removing unused db file
[policy/engine.git] / ecomp-sdk-app / src / main / webapp / app / fusion / external / ebz / sandbox / att-abs-tpls.js
1 /**
2 * FileName att-style-guide
3 * Version 2.17.0
4 * Build number 5c64ecd381d5984c483cdfaa078a1890
5 * Date 11/23/2015
6 */
7
8 (function(angular, window){
9 angular.module("att.abs", ["att.abs.tpls", "att.abs.utilities","att.abs.position","att.abs.transition","att.abs.accordion","att.abs.alert","att.abs.boardStrip","att.abs.breadCrumbs","att.abs.buttons","att.abs.checkbox","att.abs.colorselector","att.abs.datepicker","att.abs.devNotes","att.abs.dividerLines","att.abs.dragdrop","att.abs.drawer","att.abs.message","att.abs.formField","att.abs.hourpicker","att.abs.iconButtons","att.abs.links","att.abs.loading","att.abs.modal","att.abs.pagination","att.abs.paneSelector","att.abs.tooltip","att.abs.popOvers","att.abs.profileCard","att.abs.progressBars","att.abs.radio","att.abs.scrollbar","att.abs.search","att.abs.select","att.abs.slider","att.abs.splitButtonDropdown","att.abs.splitIconButton","att.abs.stepSlider","att.abs.steptracker","att.abs.table","att.abs.tableMessages","att.abs.tabs","att.abs.tagBadges","att.abs.textOverflow","att.abs.toggle","att.abs.treeview","att.abs.typeAhead","att.abs.verticalSteptracker","att.abs.videoControls"]);
10 angular.module("att.abs.tpls", ["app/scripts/ng_js_att_tpls/accordion/accordion.html","app/scripts/ng_js_att_tpls/accordion/accordion_alt.html","app/scripts/ng_js_att_tpls/accordion/attAccord.html","app/scripts/ng_js_att_tpls/accordion/attAccordBody.html","app/scripts/ng_js_att_tpls/accordion/attAccordHeader.html","app/scripts/ng_js_att_tpls/alert/alert.html","app/scripts/ng_js_att_tpls/boardStrip/attAddBoard.html","app/scripts/ng_js_att_tpls/boardStrip/attBoard.html","app/scripts/ng_js_att_tpls/boardStrip/attBoardStrip.html","app/scripts/ng_js_att_tpls/buttons/buttonDropdown.html","app/scripts/ng_js_att_tpls/colorselector/colorselector.html","app/scripts/ng_js_att_tpls/datepicker/dateFilter.html","app/scripts/ng_js_att_tpls/datepicker/dateFilterList.html","app/scripts/ng_js_att_tpls/datepicker/datepicker.html","app/scripts/ng_js_att_tpls/datepicker/datepickerPopup.html","app/scripts/ng_js_att_tpls/dividerLines/dividerLines.html","app/scripts/ng_js_att_tpls/dragdrop/fileUpload.html","app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlert.html","app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlertPrv.html","app/scripts/ng_js_att_tpls/formField/creditCardImage.html","app/scripts/ng_js_att_tpls/formField/cvcSecurityImg.html","app/scripts/ng_js_att_tpls/hourpicker/hourpicker.html","app/scripts/ng_js_att_tpls/links/readMore.html","app/scripts/ng_js_att_tpls/loading/loading.html","app/scripts/ng_js_att_tpls/modal/backdrop.html","app/scripts/ng_js_att_tpls/modal/tabbedItem.html","app/scripts/ng_js_att_tpls/modal/tabbedOverlayItem.html","app/scripts/ng_js_att_tpls/modal/window.html","app/scripts/ng_js_att_tpls/pagination/pagination.html","app/scripts/ng_js_att_tpls/paneSelector/innerPane.html","app/scripts/ng_js_att_tpls/paneSelector/paneGroup.html","app/scripts/ng_js_att_tpls/paneSelector/sidePane.html","app/scripts/ng_js_att_tpls/tooltip/tooltip-popup.html","app/scripts/ng_js_att_tpls/popOvers/popOvers.html","app/scripts/ng_js_att_tpls/profileCard/addUser.html","app/scripts/ng_js_att_tpls/profileCard/profileCard.html","app/scripts/ng_js_att_tpls/progressBars/progressBars.html","app/scripts/ng_js_att_tpls/scrollbar/scrollbar.html","app/scripts/ng_js_att_tpls/search/search.html","app/scripts/ng_js_att_tpls/select/select.html","app/scripts/ng_js_att_tpls/select/textDropdown.html","app/scripts/ng_js_att_tpls/slider/maxContent.html","app/scripts/ng_js_att_tpls/slider/minContent.html","app/scripts/ng_js_att_tpls/slider/slider.html","app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdown.html","app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdownItem.html","app/scripts/ng_js_att_tpls/splitIconButton/splitIcon.html","app/scripts/ng_js_att_tpls/splitIconButton/splitIconButton.html","app/scripts/ng_js_att_tpls/splitIconButton/splitIconButtonGroup.html","app/scripts/ng_js_att_tpls/stepSlider/attStepSlider.html","app/scripts/ng_js_att_tpls/steptracker/step-tracker.html","app/scripts/ng_js_att_tpls/steptracker/step.html","app/scripts/ng_js_att_tpls/steptracker/timeline.html","app/scripts/ng_js_att_tpls/steptracker/timelineBar.html","app/scripts/ng_js_att_tpls/steptracker/timelineDot.html","app/scripts/ng_js_att_tpls/table/attTable.html","app/scripts/ng_js_att_tpls/table/attTableBody.html","app/scripts/ng_js_att_tpls/table/attTableHeader.html","app/scripts/ng_js_att_tpls/tableMessages/attTableMessage.html","app/scripts/ng_js_att_tpls/tableMessages/attUserMessage.html","app/scripts/ng_js_att_tpls/tabs/floatingTabs.html","app/scripts/ng_js_att_tpls/tabs/genericTabs.html","app/scripts/ng_js_att_tpls/tabs/menuTab.html","app/scripts/ng_js_att_tpls/tabs/parentmenuTab.html","app/scripts/ng_js_att_tpls/tabs/simplifiedTabs.html","app/scripts/ng_js_att_tpls/tabs/submenuTab.html","app/scripts/ng_js_att_tpls/tagBadges/tagBadges.html","app/scripts/ng_js_att_tpls/toggle/demoToggle.html","app/scripts/ng_js_att_tpls/typeAhead/typeAhead.html","app/scripts/ng_js_att_tpls/verticalSteptracker/vertical-step-tracker.html","app/scripts/ng_js_att_tpls/videoControls/photoControls.html","app/scripts/ng_js_att_tpls/videoControls/videoControls.html"]);
11 angular.module('att.abs.utilities', [])
12
13 .filter('unsafe',[ '$sce', function ($sce) {
14         return function(val){
15        return $sce.trustAsHtml(val);
16     };
17 }])
18
19 .filter('highlight', function () {
20     function escapeRegexp(queryToEscape) {
21         return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1');
22     }
23     return function (matchItem, query, className) {
24         return query && matchItem ? matchItem.replace(new RegExp(escapeRegexp(query), 'gi'), '<span class=\"' + className + '\">$&</span>') : matchItem;
25     };
26 })
27
28 .filter('attLimitTo', function() {
29     return function(actualArray, _limit, _begin) {
30         var finalArray = [];
31         var limit = _limit;
32         var begin = _begin;
33         if(isNaN(begin)) {
34             begin = 0;
35         }
36         if(actualArray && !isNaN(limit)) {
37             finalArray = actualArray.slice(begin, begin+limit);
38         } else {
39             finalArray = actualArray;
40         }
41         return finalArray;
42     };
43 })
44
45 .filter('startsWith', function() {
46     if (typeof String.prototype.startsWith !== 'function') {
47         // see below for better implementation!
48         String.prototype.startsWith = function (str){
49             return this.indexOf(str) === 0;
50         };
51     }
52
53     return function(items, searchString) {
54         if (searchString === undefined || searchString === "") {
55             return items;
56         }
57
58         var filtered = [];
59         angular.forEach(items, function(item) {
60             if (item.title.toLowerCase().startsWith(searchString.toLowerCase())) {
61                 filtered.push(item);
62             }
63         });
64         return filtered;
65     };
66 })
67
68 .directive('attInputDeny', [function() {
69     return {
70         restrict: 'A',
71         require: 'ngModel',
72         link: function (scope, elem, attr, ctrl) {
73             var regexExpression = null;
74             attr.$observe('attInputDeny', function (value) {
75                 if (value) {
76                     regexExpression = new RegExp(value, 'g');
77                 }
78             });
79             elem.bind('input', function () {
80                 var inputString = ctrl.$viewValue && ctrl.$viewValue.replace(regexExpression, '');
81                 if (inputString !== ctrl.$viewValue) {
82                     ctrl.$setViewValue(inputString);
83                     ctrl.$render();
84                     scope.$apply();
85                 }
86             });
87         }
88     };
89 }])
90
91 .directive('attAccessibilityClick', [function() {
92     return {
93         restrict: 'A',
94         link: function (scope, elem, attr) {
95             var keyCode = [];
96             attr.$observe('attAccessibilityClick', function (value) {
97                 if (value) {
98                     keyCode = value.split(',');
99                 }
100             });
101             elem.bind('keydown', function (ev) {
102                 var keyCodeCondition = function(){
103                     var flag = false;
104                     if(!(ev.keyCode)){
105                         if(ev.which){
106                             ev.keyCode = ev.which;
107                         }
108                         else if(ev.charCode){
109                             ev.keyCode = ev.charCode;
110                         }
111                     }
112                     if((ev.keyCode && keyCode.indexOf(ev.keyCode.toString()) > -1)){
113                         flag = true;
114                     }
115                     return flag;
116                 };
117                 if(keyCode.length > 0 && keyCodeCondition()) {
118                     elem[0].click();
119                     ev.preventDefault();
120                 }
121             });
122         }
123     };
124 }])
125
126 .directive('attElementFocus', [function() {
127     return {
128         restrict: 'A',
129         link: function(scope, elem, attr) {
130             scope.$watch(attr.attElementFocus, function (value) {
131                 if (value) {
132                     elem[0].focus();
133                 }
134             });
135         }
136     };
137 }])
138
139 .directive('focusOn', ['$timeout',
140     function ($timeout) {
141         var checkDirectivePrerequisites = function (attrs) {
142           if (!attrs.focusOn && attrs.focusOn !== '') {
143                 throw 'FocusOnCondition missing attribute to evaluate';
144           }
145         };
146         return {            
147             restrict: 'A',
148             link: function (scope, element, attrs) {
149                 checkDirectivePrerequisites(attrs);
150
151                 scope.$watch(attrs.focusOn, function (currentValue) {
152                     if(currentValue) {
153                         $timeout(function () {                                             
154                             element[0].focus();
155                         });
156                     }
157                 });
158             }
159         };
160     }
161 ])
162 .constant('whenScrollEndsConstants', {
163     'threshold': 100,
164     'width': 0,
165     'height': 0
166 })
167 .directive('whenScrollEnds', function(whenScrollEndsConstants, $log) {
168     return {
169         restrict: 'A',
170         link: function (scope, element, attrs) {
171             /**
172             * Exposed Attributes:
173             *       threshold - integer - number of pixels before scrollbar hits end that callback is called
174             *       width - integer - override for element's width (px)
175             *       height - integer - override for element's height (px)
176             *       axis - string - x/y for scroll bar axis
177             */
178             var threshold = parseInt(attrs.threshold, 10) || whenScrollEndsConstants.threshold;
179
180             if (!attrs.axis || attrs.axis === '') {
181                 $log.warn('axis attribute must be defined for whenScrollEnds.');
182                 return;
183             }
184
185             if (attrs.axis === 'x') {
186                 visibleWidth = parseInt(attrs.width, 10) || whenScrollEndsConstants.width;
187                 if (element.css('width')) {
188                     visibleWidth = element.css('width').split('px')[0];  
189                 }
190
191                 element[0].addEventListener('scroll', function() {
192                     var scrollableWidth = element.prop('scrollWidth');
193                     if (scrollableWidth === undefined) {
194                         scrollableWidth = 1;
195                     }
196                     var hiddenContentWidth = scrollableWidth - visibleWidth;
197
198                     if (hiddenContentWidth - element[0].scrollLeft <= threshold) {
199                         /* Scroll almost at bottom, load more rows */
200                         scope.$apply(attrs.whenScrollEnds);
201                     }
202                 });
203             } else if (attrs.axis === 'y') {
204                 visibleHeight = parseInt(attrs.height, 10) || whenScrollEndsConstants.height;
205                 if (element.css('width')) {
206                     visibleHeight = element.css('height').split('px')[0]; 
207                 }
208
209                 element[0].addEventListener('scroll', function() {
210                     var scrollableHeight = element.prop('scrollHeight');
211                     if (scrollableHeight === undefined) {
212                         scrollableHeight = 1;
213                     }
214                     var hiddenContentHeight = scrollableHeight - visibleHeight;
215
216                     if (hiddenContentHeight - element[0].scrollTop <= threshold) {
217                         /* Scroll almost at bottom, load more rows */
218                         scope.$apply(attrs.whenScrollEnds);
219                     }
220                 });
221             }
222         }
223     };
224 })
225
226 .directive("validImei", function(){          
227     return {
228         restrict: 'A',
229         require: 'ngModel',
230         link: function(scope, ele, attrs, ctrl)
231         {       
232             ctrl.$parsers.unshift(function(value) 
233             {
234                 if(value){                    
235                     scope.valid = false;
236                     if (!isNaN(value) && value.length === 15)
237                     {
238                         var sumImeiVal = 0;     
239                         var posIMEI = [];
240                         for (var imeiIndex=0; imeiIndex<15; imeiIndex++)
241                         {
242                             posIMEI[imeiIndex] =  parseInt(value.substring(imeiIndex,imeiIndex + 1),10);
243                             if (imeiIndex % 2 !== 0)
244                             {
245                                 posIMEI[imeiIndex] = parseInt((posIMEI[imeiIndex] * 2),10);                                        
246                             }
247                             if (posIMEI[imeiIndex] > 9)
248                             {    
249                                 posIMEI[imeiIndex] = parseInt((posIMEI[imeiIndex] % 10),10) + parseInt((posIMEI[imeiIndex] / 10),10);                                        
250                             }
251                             sumImeiVal=sumImeiVal+parseInt((posIMEI[imeiIndex]),10);
252                         }
253
254                         if((sumImeiVal % 10) === 0)
255                         {
256                             scope.valid = true;                            
257                         }
258                         else
259                         {
260                             scope.valid = false;                            
261                         }                                
262                     }
263                     else 
264                     {
265                         scope.valid = false;                        
266                     }                    
267                     ctrl.$setValidity('invalidImei', scope.valid);
268                 }
269                 return scope.valid ? value : undefined;
270             });
271         }
272     };
273 })
274
275 .directive("togglePassword", function(){
276     return{
277         restrict:'A',        
278         transclude:false,
279         link: function(scope, element, attr, ctrl)
280         {
281             element.bind("click", function() 
282             {
283                 var ipwd = attr.togglePassword;
284                 element[0].innerHTML = element[0].innerHTML === "Show" ? "Hide" : "Show";                
285                 var e = angular.element(document.querySelector('#' + ipwd))[0].type;
286                 angular.element(document.querySelector('#' + ipwd))[0].type = e === "password"? "text" : "password";
287                 
288             });      
289                        
290         }
291     };
292 })
293
294 .factory('events', function(){
295     var _stopPropagation =  function(evt){
296         if(evt.stopPropagation) {
297             evt.stopPropagation();
298         } else {
299             evt.returnValue = false;
300         }
301     };
302     var _preventDefault = function(evt) {
303         if (evt.preventDefault) {
304             evt.preventDefault();
305         } else {
306             evt.returnValue = false;
307         }
308     }
309     return {
310         stopPropagation: _stopPropagation,
311         preventDefault: _preventDefault
312     };
313 })
314
315 .factory('$documentBind', ['$document', '$timeout', function ($document, $timeout) {
316     var _click = function (flag, callbackFunc, scope) {
317         scope.$watch(flag, function (val) {
318             $timeout(function () {
319                 if (val) {
320                     $document.bind('click', callbackFunc);
321                 } else {
322                     $document.unbind('click', callbackFunc);
323                 }
324             });
325         });
326     };
327
328     var _event = function (event, flag, callbackFunc, scope, timeoutFlag, timeoutValue) {
329         if (timeoutFlag) {
330             if (!(timeoutValue)) {
331                 timeoutValue = 0;
332             }
333             scope.$watch(flag, function (newVal, oldVal) {
334                 if (newVal !== oldVal) {
335                     $timeout(function () {
336                         if (newVal) {
337                             $document.bind(event, callbackFunc);
338                         } else {
339                             $document.unbind(event, callbackFunc);
340                         }
341                     }, timeoutValue);
342                 }
343             });
344         } else {
345             scope.$watch(flag, function (newVal, oldVal) {
346                 if (newVal !== oldVal) {
347                     if (newVal) {
348                         $document.bind(event, callbackFunc);
349                     } else {
350                         $document.unbind(event, callbackFunc);
351                     }
352                 }
353             });
354         }
355     };
356
357     return {
358         click: _click,
359         event: _event
360     };
361 }])
362
363 .factory('DOMHelper', function() {
364
365     function isTabable(node) {
366         var element = angular.element(node);
367         var hasTabindex = (parseInt(element.attr('tabindex'), 10) >= 0) ? true : false;
368         var tagName = element[0].tagName.toUpperCase();
369
370         if (hasTabindex || tagName === 'A' || tagName === 'INPUT' || tagName === 'TEXTAREA') {
371             return !(element[0].disabled || element[0].readOnly);
372         }
373         return false;
374     }
375
376     function isValidChild(child) {
377         return child.nodeType == 1 && child.nodeName != 'SCRIPT' && child.nodeName != 'STYLE';
378     }
379
380     function traverse(obj) {
381         var obj = obj || document.getElementsByTagName('body')[0];
382         if (isValidChild(obj) && isTabable(obj)) {
383             return obj;
384         } 
385         if (obj.hasChildNodes()) {
386             var child = obj.firstChild;
387             while(child) {
388                 var res =  traverse(child);
389                 if(res){
390                     return res;
391                 }
392                 else{
393                     child = child.nextSibling;
394                 }
395             }
396         }
397         else{
398             return undefined;
399         }
400     }
401
402     var _firstTabableElement = function(el) {
403         /* This will return the first tabable element from the parent el */
404         var elem = el;
405         if (el.hasOwnProperty('length')) {
406             elem = el[0];
407         }
408
409         return traverse(elem);
410     };
411
412     return {
413         firstTabableElement: _firstTabableElement
414     };
415 })
416
417 .factory('keymap', function(){
418     return {
419     KEY:{
420         TAB: 9,
421         ENTER: 13,
422         ESC: 27,
423         SPACE: 32,
424         LEFT: 37,
425         UP: 38,
426         RIGHT: 39,
427         DOWN: 40,
428         SHIFT: 16,
429         CTRL: 17,
430         ALT: 18,
431         PAGE_UP: 33,
432         PAGE_DOWN: 34,
433         HOME: 36,
434         END: 35,
435         BACKSPACE: 8,
436         DELETE: 46,
437         COMMAND: 91
438         },
439         MAP: { 91 : "COMMAND", 8 : "BACKSPACE" , 9 : "TAB" , 13 : "ENTER" , 16 : "SHIFT" , 17 : "CTRL" , 18 : "ALT" , 19 : "PAUSEBREAK" , 20 : "CAPSLOCK" , 27 : "ESC" , 32 : "SPACE" , 33 : "PAGE_UP", 34 : "PAGE_DOWN" , 35 : "END" , 36 : "HOME" , 37 : "LEFT" , 38 : "UP" , 39 : "RIGHT" , 40 : "DOWN" , 43 : "+" , 44 : "PRINTSCREEN" , 45 : "INSERT" , 46 : "DELETE", 48 : "0" , 49 : "1" , 50 : "2" , 51 : "3" , 52 : "4" , 53 : "5" , 54 : "6" , 55 : "7" , 56 : "8" , 57 : "9" , 59 : ";", 61 : "=" , 65 : "A" , 66 : "B" , 67 : "C" , 68 : "D" , 69 : "E" , 70 : "F" , 71 : "G" , 72 : "H" , 73 : "I" , 74 : "J" , 75 : "K" , 76 : "L", 77 : "M" , 78 : "N" , 79 : "O" , 80 : "P" , 81 : "Q" , 82 : "R" , 83 : "S" , 84 : "T" , 85 : "U" , 86 : "V" , 87 : "W" , 88 : "X" , 89 : "Y" , 90 : "Z", 96 : "0" , 97 : "1" , 98 : "2" , 99 : "3" , 100 : "4" , 101 : "5" , 102 : "6" , 103 : "7" , 104 : "8" , 105 : "9", 106 : "*" , 107 : "+" , 109 : "-" , 110 : "." , 111 : "/", 112 : "F1" , 113 : "F2" , 114 : "F3" , 115 : "F4" , 116 : "F5" , 117 : "F6" , 118 : "F7" , 119 : "F8" , 120 : "F9" , 121 : "F10" , 122 : "F11" , 123 : "F12", 144 : "NUMLOCK" , 145 : "SCROLLLOCK" , 186 : ";" , 187 : "=" , 188 : "," , 189 : "-" , 190 : "." , 191 : "/" , 192 : "`" , 219 : "[" , 220 : "\\" , 221 : "]" , 222 : "'"
440         },
441         isControl: function (e) {
442             var k = e.keyCode;
443             switch (k) {
444             case this.KEY.COMMAND:
445             case this.KEY.SHIFT:
446             case this.KEY.CTRL:
447             case this.KEY.ALT:
448                 return true;
449             default:;
450             }
451
452             if (e.metaKey) {
453                 return true;
454             }
455
456             return false;
457         },
458         isFunctionKey: function (k) {
459             k = k.keyCode ? k.keyCode : k;
460             return k >= 112 && k <= 123;
461         },
462         isVerticalMovement: function (k){
463           return ~[this.KEY.UP, this.KEY.DOWN].indexOf(k);
464         },
465         isHorizontalMovement: function (k){
466           return ~[this.KEY.LEFT, this.KEY.RIGHT, this.KEY.BACKSPACE, this.KEY.DELETE].indexOf(k);
467         },
468         isAllowedKey: function (k){
469           return (~[this.KEY.SPACE, this.KEY.ESC, this.KEY.ENTER].indexOf(k)) || this.isHorizontalMovement(k) || this.isVerticalMovement(k);
470         }
471     };
472 })
473
474 .factory('keyMapAc', function(){
475     return {
476             keys:{ "32":" ", "33":"!", "34":"\"", "35":"#", "36":"$", "37":"%", "38":"&", "39":"'"
477                 , "40":"(", "41":")", "42":"*", "43":"+", "44":",", "45":"-", "46":".", "47":"\/", "58":":"
478                 , "59":";", "60":"<", "61":"=", "62":">", "63":"?", "64":"@", "91":"[", "92":"\\", "93":"]"
479                 , "94":"^", "95":"_", "96":"`", "123":"{", "124":"|", "125":"}", "126":"~"
480             },
481             keyRange:{"startNum":"48","endNum":"57","startSmallLetters":"97","endSmallLetters":"122"
482                 ,"startCapitalLetters":"65","endCapitalLetters":"90"},
483             allowedKeys:{TAB:8, BACKSPACE:9, DELETE:16}
484         };
485 })
486
487 .factory('$attElementDetach', function () {
488     var _detach = function (element) {
489         if (element && element.parentNode) {
490             element.parentNode.removeChild(element);
491         }
492     };
493     return _detach;
494 })
495
496 .factory('$ieVersion', function () {
497         var ie = null;
498         
499         var loadIEVersion = function () {
500                 var isIE10 = (eval("/*@cc_on!@*/false") && document.documentMode === 10);
501                 if (isIE10) {
502                         return 10;
503                 }
504                 var v = 3,
505                         div = document.createElement('div'),
506                         all = div.getElementsByTagName('i');
507                 do {
508                         div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->';
509                 } while (all[0]);
510                 return v > 4 ? v : undefined;
511         };
512         
513         return function () {
514                 if (ie===null) {
515                         ie = loadIEVersion();
516                 }
517                 return ie;
518         };
519 });
520 (function () {
521     String.prototype.toSnakeCase = function () {
522         return this.replace(/([A-Z])/g, function ($1) {
523             return "-" + $1.toLowerCase();
524         });
525     };
526     var concat = function (character, times) {
527         character = character || '';
528         times = (!isNaN(times) && times) || 0;
529         var finalChar = '';
530         for (var i = 0; i < times; i++) {
531             finalChar += character;
532         }
533         return finalChar;
534     };
535
536     // direction: true for left and false for right
537     var pad = function (actualString, width, character, direction) {
538         actualString = actualString || '';
539         width = (!isNaN(width) && width) || 0;
540         character = character || '';
541         if (width > actualString.length) {
542             if (direction) {
543                 return concat(character, (width - actualString.length)) + actualString;
544             } else {
545                 return actualString + concat(character, (width - actualString.length));
546             }
547         }
548         return actualString;
549     };
550
551     String.prototype.lPad = function (width, character) {
552         return pad(this, width, character, true);
553     };
554
555     String.prototype.rPad = function (width, character) {
556         return pad(this, width, character, false);
557     };
558
559     if (!Array.prototype.indexOf) {
560         Array.prototype.indexOf = function (val) {
561             for (var index = 0; index < this.length; index++) {
562                 if (this[index] === val) {
563                     return index;
564                 }
565             }
566             return -1;
567         };
568     }
569 })();
570
571 angular.module('att.abs.position', [])
572
573 .factory('$position', ['$document', '$window', function ($document, $window) {
574     function getStyle(el, cssprop) {
575         if (el.currentStyle) { //IE
576             return el.currentStyle[cssprop];
577         } else if ($window.getComputedStyle) {
578             return $window.getComputedStyle(el)[cssprop];
579         }
580         // finally try and get inline style
581         return el.style[cssprop];
582     }
583
584     /**
585      * Checks if a given element is statically positioned
586      * @param element - raw DOM element
587      */
588     function isStaticPositioned(element) {
589         return (getStyle(element, "position") || 'static') === 'static';
590     }
591
592     /**
593      * returns the closest, non-statically positioned parentOffset of a given element
594      * @param element
595      */
596     var parentOffsetEl = function (element) {
597         var docDomEl = $document[0];
598         var offsetParent = element.offsetParent || docDomEl;
599         while (offsetParent && offsetParent !== docDomEl && isStaticPositioned(offsetParent)) {
600             offsetParent = offsetParent.offsetParent;
601         }
602         return offsetParent || docDomEl;
603     };
604
605     return {
606         /**
607          * Provides read-only equivalent of jQuery's position function:
608          * http://api.jquery.com/position/
609          */
610         position: function (element) {
611             var elBCR = this.offset(element);
612             var offsetParentBCR = {
613                 top: 0,
614                 left: 0
615             };
616             var offsetParentEl = parentOffsetEl(element[0]);
617             if (offsetParentEl !== $document[0]) {
618                 offsetParentBCR = this.offset(angular.element(offsetParentEl));
619                 offsetParentBCR.top += offsetParentEl.clientTop - offsetParentEl.scrollTop;
620                 offsetParentBCR.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft;
621             }
622
623             return {
624                 width: element.prop('offsetWidth'),
625                 height: element.prop('offsetHeight'),
626                 top: elBCR.top - offsetParentBCR.top,
627                 left: elBCR.left - offsetParentBCR.left
628             };
629         },
630
631         /**
632          * Provides read-only equivalent of jQuery's offset function:
633          * http://api.jquery.com/offset/
634          */
635         offset: function (element) {
636             var boundingClientRect = element[0].getBoundingClientRect();
637             return {
638                 width: element.prop('offsetWidth'),
639                 height: element.prop('offsetHeight'),
640                 top: boundingClientRect.top + ($window.pageYOffset || $document[0].body.scrollTop || $document[0].documentElement.scrollTop),
641                 left: boundingClientRect.left + ($window.pageXOffset || $document[0].body.scrollLeft || $document[0].documentElement.scrollLeft)
642             };
643         }
644     };
645 }])
646
647 .factory('$isElement', [function () {
648     var isElement = function (currentElem, targetElem, alternateElem) {
649         if (currentElem[0] === targetElem[0]) {
650             return true;
651         } else if (currentElem[0] === alternateElem[0]) {
652             return false;
653         } else {
654             return isElement((currentElem.parent()[0] && currentElem.parent()) || targetElem, targetElem, alternateElem);
655         }
656     };
657
658     return isElement;
659 }])
660
661 .directive('attPosition', ['$position', function ($position) {
662     return {
663         restrict: 'A',
664         link: function (scope, elem, attr) {
665             scope.$watchCollection(function () {
666                 return $position.position(elem);
667             }, function (value) {
668                 scope[attr.attPosition] = value;
669             });
670         }
671     };
672 }]);
673
674 /*!
675  * VERSION: 1.7.3
676  * DATE: 2014-01-14
677  * UPDATES AND DOCS AT: http://www.greensock.com
678  *
679  * @license Copyright (c) 2008-2014, GreenSock. All rights reserved.
680  * This work is subject to the terms at http://www.greensock.com/terms_of_use.html or for
681  * Club GreenSock members, the software agreement that was issued with your membership.
682  * 
683  * @author: Jack Doyle, jack@greensock.com
684  **/
685 (window._gsQueue || (window._gsQueue = [])).push( function() {
686
687         "use strict";
688
689         var _doc = document.documentElement,
690                 _window = window,
691                 _max = function(element, axis) {
692                         var dim = (axis === "x") ? "Width" : "Height",
693                                 scroll = "scroll" + dim,
694                                 client = "client" + dim,
695                                 body = document.body;
696                         return (element === _window || element === _doc || element === body) ? Math.max(_doc[scroll], body[scroll]) - (_window["inner" + dim] || Math.max(_doc[client], body[client])) : element[scroll] - element["offset" + dim];
697                 },
698
699                 ScrollToPlugin = window._gsDefine.plugin({
700                         propName: "scrollTo",
701                         API: 2,
702                         version:"1.7.3",
703
704                         //called when the tween renders for the first time. This is where initial values should be recorded and any setup routines should run.
705                         init: function(target, value, tween) {
706                                 this._wdw = (target === _window);
707                                 this._target = target;
708                                 this._tween = tween;
709                                 if (typeof(value) !== "object") {
710                                         value = {y:value}; //if we don't receive an object as the parameter, assume the user intends "y".
711                                 }
712                                 this._autoKill = (value.autoKill !== false);
713                                 this.x = this.xPrev = this.getX();
714                                 this.y = this.yPrev = this.getY();
715                                 if (value.x != null) {
716                                         this._addTween(this, "x", this.x, (value.x === "max") ? _max(target, "x") : value.x, "scrollTo_x", true);
717                                         this._overwriteProps.push("scrollTo_x");
718                                 } else {
719                                         this.skipX = true;
720                                 }
721                                 if (value.y != null) {
722                                         this._addTween(this, "y", this.y, (value.y === "max") ? _max(target, "y") : value.y, "scrollTo_y", true);
723                                         this._overwriteProps.push("scrollTo_y");
724                                 } else {
725                                         this.skipY = true;
726                                 }
727                                 return true;
728                         },
729
730                         //called each time the values should be updated, and the ratio gets passed as the only parameter (typically it's a value between 0 and 1, but it can exceed those when using an ease like Elastic.easeOut or Back.easeOut, etc.)
731                         set: function(v) {
732                                 this._super.setRatio.call(this, v);
733
734                                 var x = (this._wdw || !this.skipX) ? this.getX() : this.xPrev,
735                                         y = (this._wdw || !this.skipY) ? this.getY() : this.yPrev,
736                                         yDif = y - this.yPrev,
737                                         xDif = x - this.xPrev;
738
739                                 if (this._autoKill) {
740                                         //note: iOS has a bug that throws off the scroll by several pixels, so we need to check if it's within 7 pixels of the previous one that we set instead of just looking for an exact match.
741                                         if (!this.skipX && (xDif > 7 || xDif < -7) && x < _max(this._target, "x")) {
742                                                 this.skipX = true; //if the user scrolls separately, we should stop tweening!
743                                         }
744                                         if (!this.skipY && (yDif > 7 || yDif < -7) && y < _max(this._target, "y")) {
745                                                 this.skipY = true; //if the user scrolls separately, we should stop tweening!
746                                         }
747                                         if (this.skipX && this.skipY) {
748                                                 this._tween.kill();
749                                         }
750                                 }
751                                 if (this._wdw) {
752                                         _window.scrollTo((!this.skipX) ? this.x : x, (!this.skipY) ? this.y : y);
753                                 } else {
754                                         if (!this.skipY) {
755                                                 this._target.scrollTop = this.y;
756                                         }
757                                         if (!this.skipX) {
758                                                 this._target.scrollLeft = this.x;
759                                         }
760                                 }
761                                 this.xPrev = this.x;
762                                 this.yPrev = this.y;
763                         }
764
765                 }),
766                 p = ScrollToPlugin.prototype;
767
768         ScrollToPlugin.max = _max;
769
770         p.getX = function() {
771                 return (!this._wdw) ? this._target.scrollLeft : (_window.pageXOffset != null) ? _window.pageXOffset : (_doc.scrollLeft != null) ? _doc.scrollLeft : document.body.scrollLeft;
772         };
773
774         p.getY = function() {
775                 return (!this._wdw) ? this._target.scrollTop : (_window.pageYOffset != null) ? _window.pageYOffset : (_doc.scrollTop != null) ? _doc.scrollTop : document.body.scrollTop;
776         };
777
778         p._kill = function(lookup) {
779                 if (lookup.scrollTo_x) {
780                         this.skipX = true;
781                 }
782                 if (lookup.scrollTo_y) {
783                         this.skipY = true;
784                 }
785                 return this._super._kill.call(this, lookup);
786         };
787
788 }); if (window._gsDefine) { window._gsQueue.pop()(); }
789 /*!
790  * VERSION: 1.12.1
791  * DATE: 2014-06-26
792  * UPDATES AND DOCS AT: http://www.greensock.com
793  * 
794  * Includes all of the following: TweenLite, TweenMax, TimelineLite, TimelineMax, EasePack, CSSPlugin, RoundPropsPlugin, BezierPlugin, AttrPlugin, DirectionalRotationPlugin
795  *
796  * @license Copyright (c) 2008-2014, GreenSock. All rights reserved.
797  * This work is subject to the terms at http://www.greensock.com/terms_of_use.html or for
798  * Club GreenSock members, the software agreement that was issued with your membership.
799  * 
800  * @author: Jack Doyle, jack@greensock.com
801  **/
802
803 (window._gsQueue || (window._gsQueue = [])).push( function() {
804
805         "use strict";
806
807         window._gsDefine("TweenMax", ["core.Animation","core.SimpleTimeline","TweenLite"], function(Animation, SimpleTimeline, TweenLite) {
808
809                 var _slice = [].slice,
810                         TweenMax = function(target, duration, vars) {
811                                 TweenLite.call(this, target, duration, vars);
812                                 this._cycle = 0;
813                                 this._yoyo = (this.vars.yoyo === true);
814                                 this._repeat = this.vars.repeat || 0;
815                                 this._repeatDelay = this.vars.repeatDelay || 0;
816                                 this._dirty = true; //ensures that if there is any repeat, the totalDuration will get recalculated to accurately report it.
817                                 this.render = TweenMax.prototype.render; //speed optimization (avoid prototype lookup on this "hot" method)
818                         },
819                         _tinyNum = 0.0000000001,
820                         TweenLiteInternals = TweenLite._internals,
821                         _isSelector = TweenLiteInternals.isSelector,
822                         _isArray = TweenLiteInternals.isArray,
823                         p = TweenMax.prototype = TweenLite.to({}, 0.1, {}),
824                         _blankArray = [];
825
826                 TweenMax.version = "1.12.1";
827                 p.constructor = TweenMax;
828                 p.kill()._gc = false;
829                 TweenMax.killTweensOf = TweenMax.killDelayedCallsTo = TweenLite.killTweensOf;
830                 TweenMax.getTweensOf = TweenLite.getTweensOf;
831                 TweenMax.lagSmoothing = TweenLite.lagSmoothing;
832                 TweenMax.ticker = TweenLite.ticker;
833                 TweenMax.render = TweenLite.render;
834
835                 p.invalidate = function() {
836                         this._yoyo = (this.vars.yoyo === true);
837                         this._repeat = this.vars.repeat || 0;
838                         this._repeatDelay = this.vars.repeatDelay || 0;
839                         this._uncache(true);
840                         return TweenLite.prototype.invalidate.call(this);
841                 };
842                 
843                 p.updateTo = function(vars, resetDuration) {
844                         var curRatio = this.ratio, p;
845                         if (resetDuration && this._startTime < this._timeline._time) {
846                                 this._startTime = this._timeline._time;
847                                 this._uncache(false);
848                                 if (this._gc) {
849                                         this._enabled(true, false);
850                                 } else {
851                                         this._timeline.insert(this, this._startTime - this._delay); //ensures that any necessary re-sequencing of Animations in the timeline occurs to make sure the rendering order is correct.
852                                 }
853                         }
854                         for (p in vars) {
855                                 this.vars[p] = vars[p];
856                         }
857                         if (this._initted) {
858                                 if (resetDuration) {
859                                         this._initted = false;
860                                 } else {
861                                         if (this._gc) {
862                                                 this._enabled(true, false);
863                                         }
864                                         if (this._notifyPluginsOfEnabled && this._firstPT) {
865                                                 TweenLite._onPluginEvent("_onDisable", this); //in case a plugin like MotionBlur must perform some cleanup tasks
866                                         }
867                                         if (this._time / this._duration > 0.998) { //if the tween has finished (or come extremely close to finishing), we just need to rewind it to 0 and then render it again at the end which forces it to re-initialize (parsing the new vars). We allow tweens that are close to finishing (but haven't quite finished) to work this way too because otherwise, the values are so small when determining where to project the starting values that binary math issues creep in and can make the tween appear to render incorrectly when run backwards. 
868                                                 var prevTime = this._time;
869                                                 this.render(0, true, false);
870                                                 this._initted = false;
871                                                 this.render(prevTime, true, false);
872                                         } else if (this._time > 0) {
873                                                 this._initted = false;
874                                                 this._init();
875                                                 var inv = 1 / (1 - curRatio),
876                                                         pt = this._firstPT, endValue;
877                                                 while (pt) {
878                                                         endValue = pt.s + pt.c; 
879                                                         pt.c *= inv;
880                                                         pt.s = endValue - pt.c;
881                                                         pt = pt._next;
882                                                 }
883                                         }
884                                 }
885                         }
886                         return this;
887                 };
888                                 
889                 p.render = function(time, suppressEvents, force) {
890                         if (!this._initted) if (this._duration === 0 && this.vars.repeat) { //zero duration tweens that render immediately have render() called from TweenLite's constructor, before TweenMax's constructor has finished setting _repeat, _repeatDelay, and _yoyo which are critical in determining totalDuration() so we need to call invalidate() which is a low-kb way to get those set properly.
891                                 this.invalidate();
892                         }
893                         var totalDur = (!this._dirty) ? this._totalDuration : this.totalDuration(),
894                                 prevTime = this._time,
895                                 prevTotalTime = this._totalTime, 
896                                 prevCycle = this._cycle,
897                                 duration = this._duration,
898                                 prevRawPrevTime = this._rawPrevTime,
899                                 isComplete, callback, pt, cycleDuration, r, type, pow, rawPrevTime, i;
900                         if (time >= totalDur) {
901                                 this._totalTime = totalDur;
902                                 this._cycle = this._repeat;
903                                 if (this._yoyo && (this._cycle & 1) !== 0) {
904                                         this._time = 0;
905                                         this.ratio = this._ease._calcEnd ? this._ease.getRatio(0) : 0;
906                                 } else {
907                                         this._time = duration;
908                                         this.ratio = this._ease._calcEnd ? this._ease.getRatio(1) : 1;
909                                 }
910                                 if (!this._reversed) {
911                                         isComplete = true;
912                                         callback = "onComplete";
913                                 }
914                                 if (duration === 0) if (this._initted || !this.vars.lazy || force) { //zero-duration tweens are tricky because we must discern the momentum/direction of time in order to determine whether the starting values should be rendered or the ending values. If the "playhead" of its timeline goes past the zero-duration tween in the forward direction or lands directly on it, the end values should be rendered, but if the timeline's "playhead" moves past it in the backward direction (from a postitive time to a negative time), the starting values must be rendered.
915                                         if (this._startTime === this._timeline._duration) { //if a zero-duration tween is at the VERY end of a timeline and that timeline renders at its end, it will typically add a tiny bit of cushion to the render time to prevent rounding errors from getting in the way of tweens rendering their VERY end. If we then reverse() that timeline, the zero-duration tween will trigger its onReverseComplete even though technically the playhead didn't pass over it again. It's a very specific edge case we must accommodate.
916                                                 time = 0;
917                                         }
918                                         if (time === 0 || prevRawPrevTime < 0 || prevRawPrevTime === _tinyNum) if (prevRawPrevTime !== time) {
919                                                 force = true;
920                                                 if (prevRawPrevTime > _tinyNum) {
921                                                         callback = "onReverseComplete";
922                                                 }
923                                         }
924                                         this._rawPrevTime = rawPrevTime = (!suppressEvents || time || prevRawPrevTime === time) ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient.
925                                 }
926                                 
927                         } else if (time < 0.0000001) { //to work around occasional floating point math artifacts, round super small values to 0.
928                                 this._totalTime = this._time = this._cycle = 0;
929                                 this.ratio = this._ease._calcEnd ? this._ease.getRatio(0) : 0;
930                                 if (prevTotalTime !== 0 || (duration === 0 && prevRawPrevTime > 0 && prevRawPrevTime !== _tinyNum)) {
931                                         callback = "onReverseComplete";
932                                         isComplete = this._reversed;
933                                 }
934                                 if (time < 0) {
935                                         this._active = false;
936                                         if (duration === 0) if (this._initted || !this.vars.lazy || force) { //zero-duration tweens are tricky because we must discern the momentum/direction of time in order to determine whether the starting values should be rendered or the ending values. If the "playhead" of its timeline goes past the zero-duration tween in the forward direction or lands directly on it, the end values should be rendered, but if the timeline's "playhead" moves past it in the backward direction (from a postitive time to a negative time), the starting values must be rendered.
937                                                 if (prevRawPrevTime >= 0) {
938                                                         force = true;
939                                                 }
940                                                 this._rawPrevTime = rawPrevTime = (!suppressEvents || time || prevRawPrevTime === time) ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient.
941                                         }
942                                 } else if (!this._initted) { //if we render the very beginning (time == 0) of a fromTo(), we must force the render (normal tweens wouldn't need to render at a time of 0 when the prevTime was also 0). This is also mandatory to make sure overwriting kicks in immediately.
943                                         force = true;
944                                 }
945                         } else {
946                                 this._totalTime = this._time = time;
947                                 
948                                 if (this._repeat !== 0) {
949                                         cycleDuration = duration + this._repeatDelay;
950                                         this._cycle = (this._totalTime / cycleDuration) >> 0; //originally _totalTime % cycleDuration but floating point errors caused problems, so I normalized it. (4 % 0.8 should be 0 but Flash reports it as 0.79999999!)
951                                         if (this._cycle !== 0) if (this._cycle === this._totalTime / cycleDuration) {
952                                                 this._cycle--; //otherwise when rendered exactly at the end time, it will act as though it is repeating (at the beginning)
953                                         }
954                                         this._time = this._totalTime - (this._cycle * cycleDuration);
955                                         if (this._yoyo) if ((this._cycle & 1) !== 0) {
956                                                 this._time = duration - this._time;
957                                         }
958                                         if (this._time > duration) {
959                                                 this._time = duration;
960                                         } else if (this._time < 0) {
961                                                 this._time = 0;
962                                         }
963                                 }
964
965                                 if (this._easeType) {
966                                         r = this._time / duration;
967                                         type = this._easeType;
968                                         pow = this._easePower;
969                                         if (type === 1 || (type === 3 && r >= 0.5)) {
970                                                 r = 1 - r;
971                                         }
972                                         if (type === 3) {
973                                                 r *= 2;
974                                         }
975                                         if (pow === 1) {
976                                                 r *= r;
977                                         } else if (pow === 2) {
978                                                 r *= r * r;
979                                         } else if (pow === 3) {
980                                                 r *= r * r * r;
981                                         } else if (pow === 4) {
982                                                 r *= r * r * r * r;
983                                         }
984
985                                         if (type === 1) {
986                                                 this.ratio = 1 - r;
987                                         } else if (type === 2) {
988                                                 this.ratio = r;
989                                         } else if (this._time / duration < 0.5) {
990                                                 this.ratio = r / 2;
991                                         } else {
992                                                 this.ratio = 1 - (r / 2);
993                                         }
994
995                                 } else {
996                                         this.ratio = this._ease.getRatio(this._time / duration);
997                                 }
998                                 
999                         }
1000                                 
1001                         if (prevTime === this._time && !force && prevCycle === this._cycle) {
1002                                 if (prevTotalTime !== this._totalTime) if (this._onUpdate) if (!suppressEvents) { //so that onUpdate fires even during the repeatDelay - as long as the totalTime changed, we should trigger onUpdate.
1003                                         this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray);
1004                                 }
1005                                 return;
1006                         } else if (!this._initted) {
1007                                 this._init();
1008                                 if (!this._initted || this._gc) { //immediateRender tweens typically won't initialize until the playhead advances (_time is greater than 0) in order to ensure that overwriting occurs properly. Also, if all of the tweening properties have been overwritten (which would cause _gc to be true, as set in _init()), we shouldn't continue otherwise an onStart callback could be called for example.
1009                                         return;
1010                                 } else if (!force && this._firstPT && ((this.vars.lazy !== false && this._duration) || (this.vars.lazy && !this._duration))) { //we stick it in the queue for rendering at the very end of the tick - this is a performance optimization because browsers invalidate styles and force a recalculation if you read, write, and then read style data (so it's better to read/read/read/write/write/write than read/write/read/write/read/write). The down side, of course, is that usually you WANT things to render immediately because you may have code running right after that which depends on the change. Like imagine running TweenLite.set(...) and then immediately after that, creating a nother tween that animates the same property to another value; the starting values of that 2nd tween wouldn't be accurate if lazy is true.
1011                                         this._time = prevTime;
1012                                         this._totalTime = prevTotalTime;
1013                                         this._rawPrevTime = prevRawPrevTime;
1014                                         this._cycle = prevCycle;
1015                                         TweenLiteInternals.lazyTweens.push(this);
1016                                         this._lazy = time;
1017                                         return;
1018                                 }
1019                                 //_ease is initially set to defaultEase, so now that init() has run, _ease is set properly and we need to recalculate the ratio. Overall this is faster than using conditional logic earlier in the method to avoid having to set ratio twice because we only init() once but renderTime() gets called VERY frequently.
1020                                 if (this._time && !isComplete) {
1021                                         this.ratio = this._ease.getRatio(this._time / duration);
1022                                 } else if (isComplete && this._ease._calcEnd) {
1023                                         this.ratio = this._ease.getRatio((this._time === 0) ? 0 : 1);
1024                                 }
1025                         }
1026                         if (this._lazy !== false) {
1027                                 this._lazy = false;
1028                         }
1029
1030                         if (!this._active) if (!this._paused && this._time !== prevTime && time >= 0) {
1031                                 this._active = true; //so that if the user renders a tween (as opposed to the timeline rendering it), the timeline is forced to re-render and align it with the proper time/frame on the next rendering cycle. Maybe the tween already finished but the user manually re-renders it as halfway done.
1032                         }
1033                         if (prevTotalTime === 0) {
1034                                 if (this._initted === 2 && time > 0) {
1035                                         //this.invalidate();
1036                                         this._init(); //will just apply overwriting since _initted of (2) means it was a from() tween that had immediateRender:true
1037                                 }
1038                                 if (this._startAt) {
1039                                         if (time >= 0) {
1040                                                 this._startAt.render(time, suppressEvents, force);
1041                                         } else if (!callback) {
1042                                                 callback = "_dummyGS"; //if no callback is defined, use a dummy value just so that the condition at the end evaluates as true because _startAt should render AFTER the normal render loop when the time is negative. We could handle this in a more intuitive way, of course, but the render loop is the MOST important thing to optimize, so this technique allows us to avoid adding extra conditional logic in a high-frequency area.
1043                                         }
1044                                 }
1045                                 if (this.vars.onStart) if (this._totalTime !== 0 || duration === 0) if (!suppressEvents) {
1046                                         this.vars.onStart.apply(this.vars.onStartScope || this, this.vars.onStartParams || _blankArray);
1047                                 }
1048                         }
1049                         
1050                         pt = this._firstPT;
1051                         while (pt) {
1052                                 if (pt.f) {
1053                                         pt.t[pt.p](pt.c * this.ratio + pt.s);
1054                                 } else {
1055                                         pt.t[pt.p] = pt.c * this.ratio + pt.s;
1056                                 }
1057                                 pt = pt._next;
1058                         }
1059                         
1060                         if (this._onUpdate) {
1061                                 if (time < 0) if (this._startAt && this._startTime) { //if the tween is positioned at the VERY beginning (_startTime 0) of its parent timeline, it's illegal for the playhead to go back further, so we should not render the recorded startAt values.
1062                                         this._startAt.render(time, suppressEvents, force); //note: for performance reasons, we tuck this conditional logic inside less traveled areas (most tweens don't have an onUpdate). We'd just have it at the end before the onComplete, but the values should be updated before any onUpdate is called, so we ALSO put it here and then if it's not called, we do so later near the onComplete.
1063                                 }
1064                                 if (!suppressEvents) if (this._totalTime !== prevTotalTime || isComplete) {
1065                                         this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray);
1066                                 }
1067                         }
1068                         if (this._cycle !== prevCycle) if (!suppressEvents) if (!this._gc) if (this.vars.onRepeat) {
1069                                 this.vars.onRepeat.apply(this.vars.onRepeatScope || this, this.vars.onRepeatParams || _blankArray);
1070                         }
1071                         if (callback) if (!this._gc) { //check gc because there's a chance that kill() could be called in an onUpdate
1072                                 if (time < 0 && this._startAt && !this._onUpdate && this._startTime) { //if the tween is positioned at the VERY beginning (_startTime 0) of its parent timeline, it's illegal for the playhead to go back further, so we should not render the recorded startAt values.
1073                                         this._startAt.render(time, suppressEvents, force);
1074                                 }
1075                                 if (isComplete) {
1076                                         if (this._timeline.autoRemoveChildren) {
1077                                                 this._enabled(false, false);
1078                                         }
1079                                         this._active = false;
1080                                 }
1081                                 if (!suppressEvents && this.vars[callback]) {
1082                                         this.vars[callback].apply(this.vars[callback + "Scope"] || this, this.vars[callback + "Params"] || _blankArray);
1083                                 }
1084                                 if (duration === 0 && this._rawPrevTime === _tinyNum && rawPrevTime !== _tinyNum) { //the onComplete or onReverseComplete could trigger movement of the playhead and for zero-duration tweens (which must discern direction) that land directly back on their start time, we don't want to fire again on the next render. Think of several addPause()'s in a timeline that forces the playhead to a certain spot, but what if it's already paused and another tween is tweening the "time" of the timeline? Each time it moves [forward] past that spot, it would move back, and since suppressEvents is true, it'd reset _rawPrevTime to _tinyNum so that when it begins again, the callback would fire (so ultimately it could bounce back and forth during that tween). Again, this is a very uncommon scenario, but possible nonetheless.
1085                                         this._rawPrevTime = 0;
1086                                 }
1087                         }
1088                 };
1089                 
1090 //---- STATIC FUNCTIONS -----------------------------------------------------------------------------------------------------------
1091                 
1092                 TweenMax.to = function(target, duration, vars) {
1093                         return new TweenMax(target, duration, vars);
1094                 };
1095                 
1096                 TweenMax.from = function(target, duration, vars) {
1097                         vars.runBackwards = true;
1098                         vars.immediateRender = (vars.immediateRender != false);
1099                         return new TweenMax(target, duration, vars);
1100                 };
1101                 
1102                 TweenMax.fromTo = function(target, duration, fromVars, toVars) {
1103                         toVars.startAt = fromVars;
1104                         toVars.immediateRender = (toVars.immediateRender != false && fromVars.immediateRender != false);
1105                         return new TweenMax(target, duration, toVars);
1106                 };
1107                 
1108                 TweenMax.staggerTo = TweenMax.allTo = function(targets, duration, vars, stagger, onCompleteAll, onCompleteAllParams, onCompleteAllScope) {
1109                         stagger = stagger || 0;
1110                         var delay = vars.delay || 0,
1111                                 a = [],
1112                                 finalComplete = function() {
1113                                         if (vars.onComplete) {
1114                                                 vars.onComplete.apply(vars.onCompleteScope || this, arguments);
1115                                         }
1116                                         onCompleteAll.apply(onCompleteAllScope || this, onCompleteAllParams || _blankArray);
1117                                 },
1118                                 l, copy, i, p;
1119                         if (!_isArray(targets)) {
1120                                 if (typeof(targets) === "string") {
1121                                         targets = TweenLite.selector(targets) || targets;
1122                                 }
1123                                 if (_isSelector(targets)) {
1124                                         targets = _slice.call(targets, 0);
1125                                 }
1126                         }
1127                         l = targets.length;
1128                         for (i = 0; i < l; i++) {
1129                                 copy = {};
1130                                 for (p in vars) {
1131                                         copy[p] = vars[p];
1132                                 }
1133                                 copy.delay = delay;
1134                                 if (i === l - 1 && onCompleteAll) {
1135                                         copy.onComplete = finalComplete;
1136                                 }
1137                                 a[i] = new TweenMax(targets[i], duration, copy);
1138                                 delay += stagger;
1139                         }
1140                         return a;
1141                 };
1142                 
1143                 TweenMax.staggerFrom = TweenMax.allFrom = function(targets, duration, vars, stagger, onCompleteAll, onCompleteAllParams, onCompleteAllScope) {
1144                         vars.runBackwards = true;
1145                         vars.immediateRender = (vars.immediateRender != false);
1146                         return TweenMax.staggerTo(targets, duration, vars, stagger, onCompleteAll, onCompleteAllParams, onCompleteAllScope);
1147                 };
1148                 
1149                 TweenMax.staggerFromTo = TweenMax.allFromTo = function(targets, duration, fromVars, toVars, stagger, onCompleteAll, onCompleteAllParams, onCompleteAllScope) {
1150                         toVars.startAt = fromVars;
1151                         toVars.immediateRender = (toVars.immediateRender != false && fromVars.immediateRender != false);
1152                         return TweenMax.staggerTo(targets, duration, toVars, stagger, onCompleteAll, onCompleteAllParams, onCompleteAllScope);
1153                 };
1154                                 
1155                 TweenMax.delayedCall = function(delay, callback, params, scope, useFrames) {
1156                         return new TweenMax(callback, 0, {delay:delay, onComplete:callback, onCompleteParams:params, onCompleteScope:scope, onReverseComplete:callback, onReverseCompleteParams:params, onReverseCompleteScope:scope, immediateRender:false, useFrames:useFrames, overwrite:0});
1157                 };
1158                 
1159                 TweenMax.set = function(target, vars) {
1160                         return new TweenMax(target, 0, vars);
1161                 };
1162                 
1163                 TweenMax.isTweening = function(target) {
1164                         return (TweenLite.getTweensOf(target, true).length > 0);
1165                 };
1166                 
1167                 var _getChildrenOf = function(timeline, includeTimelines) {
1168                                 var a = [],
1169                                         cnt = 0,
1170                                         tween = timeline._first;
1171                                 while (tween) {
1172                                         if (tween instanceof TweenLite) {
1173                                                 a[cnt++] = tween;
1174                                         } else {
1175                                                 if (includeTimelines) {
1176                                                         a[cnt++] = tween;
1177                                                 }
1178                                                 a = a.concat(_getChildrenOf(tween, includeTimelines));
1179                                                 cnt = a.length;
1180                                         }
1181                                         tween = tween._next;
1182                                 }
1183                                 return a;
1184                         }, 
1185                         getAllTweens = TweenMax.getAllTweens = function(includeTimelines) {
1186                                 return _getChildrenOf(Animation._rootTimeline, includeTimelines).concat( _getChildrenOf(Animation._rootFramesTimeline, includeTimelines) );
1187                         };
1188                 
1189                 TweenMax.killAll = function(complete, tweens, delayedCalls, timelines) {
1190                         if (tweens == null) {
1191                                 tweens = true;
1192                         }
1193                         if (delayedCalls == null) {
1194                                 delayedCalls = true;
1195                         }
1196                         var a = getAllTweens((timelines != false)),
1197                                 l = a.length,
1198                                 allTrue = (tweens && delayedCalls && timelines),
1199                                 isDC, tween, i;
1200                         for (i = 0; i < l; i++) {
1201                                 tween = a[i];
1202                                 if (allTrue || (tween instanceof SimpleTimeline) || ((isDC = (tween.target === tween.vars.onComplete)) && delayedCalls) || (tweens && !isDC)) {
1203                                         if (complete) {
1204                                                 tween.totalTime(tween._reversed ? 0 : tween.totalDuration());
1205                                         } else {
1206                                                 tween._enabled(false, false);
1207                                         }
1208                                 }
1209                         }
1210                 };
1211                 
1212                 TweenMax.killChildTweensOf = function(parent, complete) {
1213                         if (parent == null) {
1214                                 return;
1215                         }
1216                         var tl = TweenLiteInternals.tweenLookup,
1217                                 a, curParent, p, i, l;
1218                         if (typeof(parent) === "string") {
1219                                 parent = TweenLite.selector(parent) || parent;
1220                         }
1221                         if (_isSelector(parent)) {
1222                                 parent = _slice.call(parent, 0);
1223                         }
1224                         if (_isArray(parent)) {
1225                                 i = parent.length;
1226                                 while (--i > -1) {
1227                                         TweenMax.killChildTweensOf(parent[i], complete);
1228                                 }
1229                                 return;
1230                         }
1231                         a = [];
1232                         for (p in tl) {
1233                                 curParent = tl[p].target.parentNode;
1234                                 while (curParent) {
1235                                         if (curParent === parent) {
1236                                                 a = a.concat(tl[p].tweens);
1237                                         }
1238                                         curParent = curParent.parentNode;
1239                                 }
1240                         }
1241                         l = a.length;
1242                         for (i = 0; i < l; i++) {
1243                                 if (complete) {
1244                                         a[i].totalTime(a[i].totalDuration());
1245                                 }
1246                                 a[i]._enabled(false, false);
1247                         }
1248                 };
1249
1250                 var _changePause = function(pause, tweens, delayedCalls, timelines) {
1251                         tweens = (tweens !== false);
1252                         delayedCalls = (delayedCalls !== false);
1253                         timelines = (timelines !== false);
1254                         var a = getAllTweens(timelines),
1255                                 allTrue = (tweens && delayedCalls && timelines),
1256                                 i = a.length,
1257                                 isDC, tween;
1258                         while (--i > -1) {
1259                                 tween = a[i];
1260                                 if (allTrue || (tween instanceof SimpleTimeline) || ((isDC = (tween.target === tween.vars.onComplete)) && delayedCalls) || (tweens && !isDC)) {
1261                                         tween.paused(pause);
1262                                 }
1263                         }
1264                 };
1265                 
1266                 TweenMax.pauseAll = function(tweens, delayedCalls, timelines) {
1267                         _changePause(true, tweens, delayedCalls, timelines);
1268                 };
1269                 
1270                 TweenMax.resumeAll = function(tweens, delayedCalls, timelines) {
1271                         _changePause(false, tweens, delayedCalls, timelines);
1272                 };
1273
1274                 TweenMax.globalTimeScale = function(value) {
1275                         var tl = Animation._rootTimeline,
1276                                 t = TweenLite.ticker.time;
1277                         if (!arguments.length) {
1278                                 return tl._timeScale;
1279                         }
1280                         value = value || _tinyNum; //can't allow zero because it'll throw the math off
1281                         tl._startTime = t - ((t - tl._startTime) * tl._timeScale / value);
1282                         tl = Animation._rootFramesTimeline;
1283                         t = TweenLite.ticker.frame;
1284                         tl._startTime = t - ((t - tl._startTime) * tl._timeScale / value);
1285                         tl._timeScale = Animation._rootTimeline._timeScale = value;
1286                         return value;
1287                 };
1288                 
1289         
1290 //---- GETTERS / SETTERS ----------------------------------------------------------------------------------------------------------
1291                 
1292                 p.progress = function(value) {
1293                         return (!arguments.length) ? this._time / this.duration() : this.totalTime( this.duration() * ((this._yoyo && (this._cycle & 1) !== 0) ? 1 - value : value) + (this._cycle * (this._duration + this._repeatDelay)), false);
1294                 };
1295                 
1296                 p.totalProgress = function(value) {
1297                         return (!arguments.length) ? this._totalTime / this.totalDuration() : this.totalTime( this.totalDuration() * value, false);
1298                 };
1299                 
1300                 p.time = function(value, suppressEvents) {
1301                         if (!arguments.length) {
1302                                 return this._time;
1303                         }
1304                         if (this._dirty) {
1305                                 this.totalDuration();
1306                         }
1307                         if (value > this._duration) {
1308                                 value = this._duration;
1309                         }
1310                         if (this._yoyo && (this._cycle & 1) !== 0) {
1311                                 value = (this._duration - value) + (this._cycle * (this._duration + this._repeatDelay));
1312                         } else if (this._repeat !== 0) {
1313                                 value += this._cycle * (this._duration + this._repeatDelay);
1314                         }
1315                         return this.totalTime(value, suppressEvents);
1316                 };
1317
1318                 p.duration = function(value) {
1319                         if (!arguments.length) {
1320                                 return this._duration; //don't set _dirty = false because there could be repeats that haven't been factored into the _totalDuration yet. Otherwise, if you create a repeated TweenMax and then immediately check its duration(), it would cache the value and the totalDuration would not be correct, thus repeats wouldn't take effect.
1321                         }
1322                         return Animation.prototype.duration.call(this, value);
1323                 };
1324
1325                 p.totalDuration = function(value) {
1326                         if (!arguments.length) {
1327                                 if (this._dirty) {
1328                                         //instead of Infinity, we use 999999999999 so that we can accommodate reverses
1329                                         this._totalDuration = (this._repeat === -1) ? 999999999999 : this._duration * (this._repeat + 1) + (this._repeatDelay * this._repeat);
1330                                         this._dirty = false;
1331                                 }
1332                                 return this._totalDuration;
1333                         }
1334                         return (this._repeat === -1) ? this : this.duration( (value - (this._repeat * this._repeatDelay)) / (this._repeat + 1) );
1335                 };
1336                 
1337                 p.repeat = function(value) {
1338                         if (!arguments.length) {
1339                                 return this._repeat;
1340                         }
1341                         this._repeat = value;
1342                         return this._uncache(true);
1343                 };
1344                 
1345                 p.repeatDelay = function(value) {
1346                         if (!arguments.length) {
1347                                 return this._repeatDelay;
1348                         }
1349                         this._repeatDelay = value;
1350                         return this._uncache(true);
1351                 };
1352                 
1353                 p.yoyo = function(value) {
1354                         if (!arguments.length) {
1355                                 return this._yoyo;
1356                         }
1357                         this._yoyo = value;
1358                         return this;
1359                 };
1360                 
1361                 
1362                 return TweenMax;
1363                 
1364         }, true);
1365
1366
1367
1368
1369
1370
1371
1372
1373 /*
1374  * ----------------------------------------------------------------
1375  * TimelineLite
1376  * ----------------------------------------------------------------
1377  */
1378         window._gsDefine("TimelineLite", ["core.Animation","core.SimpleTimeline","TweenLite"], function(Animation, SimpleTimeline, TweenLite) {
1379
1380                 var TimelineLite = function(vars) {
1381                                 SimpleTimeline.call(this, vars);
1382                                 this._labels = {};
1383                                 this.autoRemoveChildren = (this.vars.autoRemoveChildren === true);
1384                                 this.smoothChildTiming = (this.vars.smoothChildTiming === true);
1385                                 this._sortChildren = true;
1386                                 this._onUpdate = this.vars.onUpdate;
1387                                 var v = this.vars,
1388                                         val, p;
1389                                 for (p in v) {
1390                                         val = v[p];
1391                                         if (_isArray(val)) if (val.join("").indexOf("{self}") !== -1) {
1392                                                 v[p] = this._swapSelfInParams(val);
1393                                         }
1394                                 }
1395                                 if (_isArray(v.tweens)) {
1396                                         this.add(v.tweens, 0, v.align, v.stagger);
1397                                 }
1398                         },
1399                         _tinyNum = 0.0000000001,
1400                         _isSelector = TweenLite._internals.isSelector,
1401                         _isArray = TweenLite._internals.isArray,
1402                         _blankArray = [],
1403                         _globals = window._gsDefine.globals,
1404                         _copy = function(vars) {
1405                                 var copy = {}, p;
1406                                 for (p in vars) {
1407                                         copy[p] = vars[p];
1408                                 }
1409                                 return copy;
1410                         },
1411                         _pauseCallback = function(tween, callback, params, scope) {
1412                                 tween._timeline.pause(tween._startTime);
1413                                 if (callback) {
1414                                         callback.apply(scope || tween._timeline, params || _blankArray);
1415                                 }
1416                         },
1417                         _slice = _blankArray.slice,
1418                         p = TimelineLite.prototype = new SimpleTimeline();
1419
1420                 TimelineLite.version = "1.12.1";
1421                 p.constructor = TimelineLite;
1422                 p.kill()._gc = false;
1423
1424                 p.to = function(target, duration, vars, position) {
1425                         var Engine = (vars.repeat && _globals.TweenMax) || TweenLite;
1426                         return duration ? this.add( new Engine(target, duration, vars), position) : this.set(target, vars, position);
1427                 };
1428
1429                 p.from = function(target, duration, vars, position) {
1430                         return this.add( ((vars.repeat && _globals.TweenMax) || TweenLite).from(target, duration, vars), position);
1431                 };
1432
1433                 p.fromTo = function(target, duration, fromVars, toVars, position) {
1434                         var Engine = (toVars.repeat && _globals.TweenMax) || TweenLite;
1435                         return duration ? this.add( Engine.fromTo(target, duration, fromVars, toVars), position) : this.set(target, toVars, position);
1436                 };
1437
1438                 p.staggerTo = function(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope) {
1439                         var tl = new TimelineLite({onComplete:onCompleteAll, onCompleteParams:onCompleteAllParams, onCompleteScope:onCompleteAllScope, smoothChildTiming:this.smoothChildTiming}),
1440                                 i;
1441                         if (typeof(targets) === "string") {
1442                                 targets = TweenLite.selector(targets) || targets;
1443                         }
1444                         if (_isSelector(targets)) { //senses if the targets object is a selector. If it is, we should translate it into an array.
1445                                 targets = _slice.call(targets, 0);
1446                         }
1447                         stagger = stagger || 0;
1448                         for (i = 0; i < targets.length; i++) {
1449                                 if (vars.startAt) {
1450                                         vars.startAt = _copy(vars.startAt);
1451                                 }
1452                                 tl.to(targets[i], duration, _copy(vars), i * stagger);
1453                         }
1454                         return this.add(tl, position);
1455                 };
1456
1457                 p.staggerFrom = function(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope) {
1458                         vars.immediateRender = (vars.immediateRender != false);
1459                         vars.runBackwards = true;
1460                         return this.staggerTo(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope);
1461                 };
1462
1463                 p.staggerFromTo = function(targets, duration, fromVars, toVars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope) {
1464                         toVars.startAt = fromVars;
1465                         toVars.immediateRender = (toVars.immediateRender != false && fromVars.immediateRender != false);
1466                         return this.staggerTo(targets, duration, toVars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope);
1467                 };
1468
1469                 p.call = function(callback, params, scope, position) {
1470                         return this.add( TweenLite.delayedCall(0, callback, params, scope), position);
1471                 };
1472
1473                 p.set = function(target, vars, position) {
1474                         position = this._parseTimeOrLabel(position, 0, true);
1475                         if (vars.immediateRender == null) {
1476                                 vars.immediateRender = (position === this._time && !this._paused);
1477                         }
1478                         return this.add( new TweenLite(target, 0, vars), position);
1479                 };
1480
1481                 TimelineLite.exportRoot = function(vars, ignoreDelayedCalls) {
1482                         vars = vars || {};
1483                         if (vars.smoothChildTiming == null) {
1484                                 vars.smoothChildTiming = true;
1485                         }
1486                         var tl = new TimelineLite(vars),
1487                                 root = tl._timeline,
1488                                 tween, next;
1489                         if (ignoreDelayedCalls == null) {
1490                                 ignoreDelayedCalls = true;
1491                         }
1492                         root._remove(tl, true);
1493                         tl._startTime = 0;
1494                         tl._rawPrevTime = tl._time = tl._totalTime = root._time;
1495                         tween = root._first;
1496                         while (tween) {
1497                                 next = tween._next;
1498                                 if (!ignoreDelayedCalls || !(tween instanceof TweenLite && tween.target === tween.vars.onComplete)) {
1499                                         tl.add(tween, tween._startTime - tween._delay);
1500                                 }
1501                                 tween = next;
1502                         }
1503                         root.add(tl, 0);
1504                         return tl;
1505                 };
1506
1507                 p.add = function(value, position, align, stagger) {
1508                         var curTime, l, i, child, tl, beforeRawTime;
1509                         if (typeof(position) !== "number") {
1510                                 position = this._parseTimeOrLabel(position, 0, true, value);
1511                         }
1512                         if (!(value instanceof Animation)) {
1513                                 if ((value instanceof Array) || (value && value.push && _isArray(value))) {
1514                                         align = align || "normal";
1515                                         stagger = stagger || 0;
1516                                         curTime = position;
1517                                         l = value.length;
1518                                         for (i = 0; i < l; i++) {
1519                                                 if (_isArray(child = value[i])) {
1520                                                         child = new TimelineLite({tweens:child});
1521                                                 }
1522                                                 this.add(child, curTime);
1523                                                 if (typeof(child) !== "string" && typeof(child) !== "function") {
1524                                                         if (align === "sequence") {
1525                                                                 curTime = child._startTime + (child.totalDuration() / child._timeScale);
1526                                                         } else if (align === "start") {
1527                                                                 child._startTime -= child.delay();
1528                                                         }
1529                                                 }
1530                                                 curTime += stagger;
1531                                         }
1532                                         return this._uncache(true);
1533                                 } else if (typeof(value) === "string") {
1534                                         return this.addLabel(value, position);
1535                                 } else if (typeof(value) === "function") {
1536                                         value = TweenLite.delayedCall(0, value);
1537                                 } else {
1538                                         throw("Cannot add " + value + " into the timeline; it is not a tween, timeline, function, or string.");
1539                                 }
1540                         }
1541
1542                         SimpleTimeline.prototype.add.call(this, value, position);
1543
1544                         //if the timeline has already ended but the inserted tween/timeline extends the duration, we should enable this timeline again so that it renders properly. We should also align the playhead with the parent timeline's when appropriate.
1545                         if (this._gc || this._time === this._duration) if (!this._paused) if (this._duration < this.duration()) {
1546                                 //in case any of the ancestors had completed but should now be enabled...
1547                                 tl = this;
1548                                 beforeRawTime = (tl.rawTime() > value._startTime); //if the tween is placed on the timeline so that it starts BEFORE the current rawTime, we should align the playhead (move the timeline). This is because sometimes users will create a timeline, let it finish, and much later append a tween and expect it to run instead of jumping to its end state. While technically one could argue that it should jump to its end state, that's not what users intuitively expect.
1549                                 while (tl._timeline) {
1550                                         if (beforeRawTime && tl._timeline.smoothChildTiming) {
1551                                                 tl.totalTime(tl._totalTime, true); //moves the timeline (shifts its startTime) if necessary, and also enables it.
1552                                         } else if (tl._gc) {
1553                                                 tl._enabled(true, false);
1554                                         }
1555                                         tl = tl._timeline;
1556                                 }
1557                         }
1558
1559                         return this;
1560                 };
1561
1562                 p.remove = function(value) {
1563                         if (value instanceof Animation) {
1564                                 return this._remove(value, false);
1565                         } else if (value instanceof Array || (value && value.push && _isArray(value))) {
1566                                 var i = value.length;
1567                                 while (--i > -1) {
1568                                         this.remove(value[i]);
1569                                 }
1570                                 return this;
1571                         } else if (typeof(value) === "string") {
1572                                 return this.removeLabel(value);
1573                         }
1574                         return this.kill(null, value);
1575                 };
1576
1577                 p._remove = function(tween, skipDisable) {
1578                         SimpleTimeline.prototype._remove.call(this, tween, skipDisable);
1579                         var last = this._last;
1580                         if (!last) {
1581                                 this._time = this._totalTime = this._duration = this._totalDuration = 0;
1582                         } else if (this._time > last._startTime + last._totalDuration / last._timeScale) {
1583                                 this._time = this.duration();
1584                                 this._totalTime = this._totalDuration;
1585                         }
1586                         return this;
1587                 };
1588
1589                 p.append = function(value, offsetOrLabel) {
1590                         return this.add(value, this._parseTimeOrLabel(null, offsetOrLabel, true, value));
1591                 };
1592
1593                 p.insert = p.insertMultiple = function(value, position, align, stagger) {
1594                         return this.add(value, position || 0, align, stagger);
1595                 };
1596
1597                 p.appendMultiple = function(tweens, offsetOrLabel, align, stagger) {
1598                         return this.add(tweens, this._parseTimeOrLabel(null, offsetOrLabel, true, tweens), align, stagger);
1599                 };
1600
1601                 p.addLabel = function(label, position) {
1602                         this._labels[label] = this._parseTimeOrLabel(position);
1603                         return this;
1604                 };
1605
1606                 p.addPause = function(position, callback, params, scope) {
1607                         return this.call(_pauseCallback, ["{self}", callback, params, scope], this, position);
1608                 };
1609
1610                 p.removeLabel = function(label) {
1611                         delete this._labels[label];
1612                         return this;
1613                 };
1614
1615                 p.getLabelTime = function(label) {
1616                         return (this._labels[label] != null) ? this._labels[label] : -1;
1617                 };
1618
1619                 p._parseTimeOrLabel = function(timeOrLabel, offsetOrLabel, appendIfAbsent, ignore) {
1620                         var i;
1621                         //if we're about to add a tween/timeline (or an array of them) that's already a child of this timeline, we should remove it first so that it doesn't contaminate the duration().
1622                         if (ignore instanceof Animation && ignore.timeline === this) {
1623                                 this.remove(ignore);
1624                         } else if (ignore && ((ignore instanceof Array) || (ignore.push && _isArray(ignore)))) {
1625                                 i = ignore.length;
1626                                 while (--i > -1) {
1627                                         if (ignore[i] instanceof Animation && ignore[i].timeline === this) {
1628                                                 this.remove(ignore[i]);
1629                                         }
1630                                 }
1631                         }
1632                         if (typeof(offsetOrLabel) === "string") {
1633                                 return this._parseTimeOrLabel(offsetOrLabel, (appendIfAbsent && typeof(timeOrLabel) === "number" && this._labels[offsetOrLabel] == null) ? timeOrLabel - this.duration() : 0, appendIfAbsent);
1634                         }
1635                         offsetOrLabel = offsetOrLabel || 0;
1636                         if (typeof(timeOrLabel) === "string" && (isNaN(timeOrLabel) || this._labels[timeOrLabel] != null)) { //if the string is a number like "1", check to see if there's a label with that name, otherwise interpret it as a number (absolute value).
1637                                 i = timeOrLabel.indexOf("=");
1638                                 if (i === -1) {
1639                                         if (this._labels[timeOrLabel] == null) {
1640                                                 return appendIfAbsent ? (this._labels[timeOrLabel] = this.duration() + offsetOrLabel) : offsetOrLabel;
1641                                         }
1642                                         return this._labels[timeOrLabel] + offsetOrLabel;
1643                                 }
1644                                 offsetOrLabel = parseInt(timeOrLabel.charAt(i-1) + "1", 10) * Number(timeOrLabel.substr(i+1));
1645                                 timeOrLabel = (i > 1) ? this._parseTimeOrLabel(timeOrLabel.substr(0, i-1), 0, appendIfAbsent) : this.duration();
1646                         } else if (timeOrLabel == null) {
1647                                 timeOrLabel = this.duration();
1648                         }
1649                         return Number(timeOrLabel) + offsetOrLabel;
1650                 };
1651
1652                 p.seek = function(position, suppressEvents) {
1653                         return this.totalTime((typeof(position) === "number") ? position : this._parseTimeOrLabel(position), (suppressEvents !== false));
1654                 };
1655
1656                 p.stop = function() {
1657                         return this.paused(true);
1658                 };
1659
1660                 p.gotoAndPlay = function(position, suppressEvents) {
1661                         return this.play(position, suppressEvents);
1662                 };
1663
1664                 p.gotoAndStop = function(position, suppressEvents) {
1665                         return this.pause(position, suppressEvents);
1666                 };
1667
1668                 p.render = function(time, suppressEvents, force) {
1669                         if (this._gc) {
1670                                 this._enabled(true, false);
1671                         }
1672                         var totalDur = (!this._dirty) ? this._totalDuration : this.totalDuration(),
1673                                 prevTime = this._time,
1674                                 prevStart = this._startTime,
1675                                 prevTimeScale = this._timeScale,
1676                                 prevPaused = this._paused,
1677                                 tween, isComplete, next, callback, internalForce;
1678                         if (time >= totalDur) {
1679                                 this._totalTime = this._time = totalDur;
1680                                 if (!this._reversed) if (!this._hasPausedChild()) {
1681                                         isComplete = true;
1682                                         callback = "onComplete";
1683                                         if (this._duration === 0) if (time === 0 || this._rawPrevTime < 0 || this._rawPrevTime === _tinyNum) if (this._rawPrevTime !== time && this._first) {
1684                                                 internalForce = true;
1685                                                 if (this._rawPrevTime > _tinyNum) {
1686                                                         callback = "onReverseComplete";
1687                                                 }
1688                                         }
1689                                 }
1690                                 this._rawPrevTime = (this._duration || !suppressEvents || time || this._rawPrevTime === time) ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration timeline or tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient.
1691                                 time = totalDur + 0.0001; //to avoid occasional floating point rounding errors - sometimes child tweens/timelines were not being fully completed (their progress might be 0.999999999999998 instead of 1 because when _time - tween._startTime is performed, floating point errors would return a value that was SLIGHTLY off). Try (999999999999.7 - 999999999999) * 1 = 0.699951171875 instead of 0.7.
1692
1693                         } else if (time < 0.0000001) { //to work around occasional floating point math artifacts, round super small values to 0.
1694                                 this._totalTime = this._time = 0;
1695                                 if (prevTime !== 0 || (this._duration === 0 && this._rawPrevTime !== _tinyNum && (this._rawPrevTime > 0 || (time < 0 && this._rawPrevTime >= 0)))) {
1696                                         callback = "onReverseComplete";
1697                                         isComplete = this._reversed;
1698                                 }
1699                                 if (time < 0) {
1700                                         this._active = false;
1701                                         if (this._duration === 0) if (this._rawPrevTime >= 0 && this._first) { //zero-duration timelines are tricky because we must discern the momentum/direction of time in order to determine whether the starting values should be rendered or the ending values. If the "playhead" of its timeline goes past the zero-duration tween in the forward direction or lands directly on it, the end values should be rendered, but if the timeline's "playhead" moves past it in the backward direction (from a postitive time to a negative time), the starting values must be rendered.
1702                                                 internalForce = true;
1703                                         }
1704                                         this._rawPrevTime = time;
1705                                 } else {
1706                                         this._rawPrevTime = (this._duration || !suppressEvents || time || this._rawPrevTime === time) ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration timeline or tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient.
1707
1708                                         time = 0; //to avoid occasional floating point rounding errors (could cause problems especially with zero-duration tweens at the very beginning of the timeline)
1709                                         if (!this._initted) {
1710                                                 internalForce = true;
1711                                         }
1712                                 }
1713
1714                         } else {
1715                                 this._totalTime = this._time = this._rawPrevTime = time;
1716                         }
1717                         if ((this._time === prevTime || !this._first) && !force && !internalForce) {
1718                                 return;
1719                         } else if (!this._initted) {
1720                                 this._initted = true;
1721                         }
1722
1723                         if (!this._active) if (!this._paused && this._time !== prevTime && time > 0) {
1724                                 this._active = true;  //so that if the user renders the timeline (as opposed to the parent timeline rendering it), it is forced to re-render and align it with the proper time/frame on the next rendering cycle. Maybe the timeline already finished but the user manually re-renders it as halfway done, for example.
1725                         }
1726
1727                         if (prevTime === 0) if (this.vars.onStart) if (this._time !== 0) if (!suppressEvents) {
1728                                 this.vars.onStart.apply(this.vars.onStartScope || this, this.vars.onStartParams || _blankArray);
1729                         }
1730
1731                         if (this._time >= prevTime) {
1732                                 tween = this._first;
1733                                 while (tween) {
1734                                         next = tween._next; //record it here because the value could change after rendering...
1735                                         if (this._paused && !prevPaused) { //in case a tween pauses the timeline when rendering
1736                                                 break;
1737                                         } else if (tween._active || (tween._startTime <= this._time && !tween._paused && !tween._gc)) {
1738                                                 if (!tween._reversed) {
1739                                                         tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force);
1740                                                 } else {
1741                                                         tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force);
1742                                                 }
1743                                         }
1744                                         tween = next;
1745                                 }
1746                         } else {
1747                                 tween = this._last;
1748                                 while (tween) {
1749                                         next = tween._prev; //record it here because the value could change after rendering...
1750                                         if (this._paused && !prevPaused) { //in case a tween pauses the timeline when rendering
1751                                                 break;
1752                                         } else if (tween._active || (tween._startTime <= prevTime && !tween._paused && !tween._gc)) {
1753                                                 if (!tween._reversed) {
1754                                                         tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force);
1755                                                 } else {
1756                                                         tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force);
1757                                                 }
1758                                         }
1759                                         tween = next;
1760                                 }
1761                         }
1762
1763                         if (this._onUpdate) if (!suppressEvents) {
1764                                 this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray);
1765                         }
1766
1767                         if (callback) if (!this._gc) if (prevStart === this._startTime || prevTimeScale !== this._timeScale) if (this._time === 0 || totalDur >= this.totalDuration()) { //if one of the tweens that was rendered altered this timeline's startTime (like if an onComplete reversed the timeline), it probably isn't complete. If it is, don't worry, because whatever call altered the startTime would complete if it was necessary at the new time. The only exception is the timeScale property. Also check _gc because there's a chance that kill() could be called in an onUpdate
1768                                 if (isComplete) {
1769                                         if (this._timeline.autoRemoveChildren) {
1770                                                 this._enabled(false, false);
1771                                         }
1772                                         this._active = false;
1773                                 }
1774                                 if (!suppressEvents && this.vars[callback]) {
1775                                         this.vars[callback].apply(this.vars[callback + "Scope"] || this, this.vars[callback + "Params"] || _blankArray);
1776                                 }
1777                         }
1778                 };
1779
1780                 p._hasPausedChild = function() {
1781                         var tween = this._first;
1782                         while (tween) {
1783                                 if (tween._paused || ((tween instanceof TimelineLite) && tween._hasPausedChild())) {
1784                                         return true;
1785                                 }
1786                                 tween = tween._next;
1787                         }
1788                         return false;
1789                 };
1790
1791                 p.getChildren = function(nested, tweens, timelines, ignoreBeforeTime) {
1792                         ignoreBeforeTime = ignoreBeforeTime || -9999999999;
1793                         var a = [],
1794                                 tween = this._first,
1795                                 cnt = 0;
1796                         while (tween) {
1797                                 if (tween._startTime < ignoreBeforeTime) {
1798                                         //do nothing
1799                                 } else if (tween instanceof TweenLite) {
1800                                         if (tweens !== false) {
1801                                                 a[cnt++] = tween;
1802                                         }
1803                                 } else {
1804                                         if (timelines !== false) {
1805                                                 a[cnt++] = tween;
1806                                         }
1807                                         if (nested !== false) {
1808                                                 a = a.concat(tween.getChildren(true, tweens, timelines));
1809                                                 cnt = a.length;
1810                                         }
1811                                 }
1812                                 tween = tween._next;
1813                         }
1814                         return a;
1815                 };
1816
1817                 p.getTweensOf = function(target, nested) {
1818                         var disabled = this._gc,
1819                                 a = [],
1820                                 cnt = 0,
1821                                 tweens, i;
1822                         if (disabled) {
1823                                 this._enabled(true, true); //getTweensOf() filters out disabled tweens, and we have to mark them as _gc = true when the timeline completes in order to allow clean garbage collection, so temporarily re-enable the timeline here.
1824                         }
1825                         tweens = TweenLite.getTweensOf(target);
1826                         i = tweens.length;
1827                         while (--i > -1) {
1828                                 if (tweens[i].timeline === this || (nested && this._contains(tweens[i]))) {
1829                                         a[cnt++] = tweens[i];
1830                                 }
1831                         }
1832                         if (disabled) {
1833                                 this._enabled(false, true);
1834                         }
1835                         return a;
1836                 };
1837
1838                 p._contains = function(tween) {
1839                         var tl = tween.timeline;
1840                         while (tl) {
1841                                 if (tl === this) {
1842                                         return true;
1843                                 }
1844                                 tl = tl.timeline;
1845                         }
1846                         return false;
1847                 };
1848
1849                 p.shiftChildren = function(amount, adjustLabels, ignoreBeforeTime) {
1850                         ignoreBeforeTime = ignoreBeforeTime || 0;
1851                         var tween = this._first,
1852                                 labels = this._labels,
1853                                 p;
1854                         while (tween) {
1855                                 if (tween._startTime >= ignoreBeforeTime) {
1856                                         tween._startTime += amount;
1857                                 }
1858                                 tween = tween._next;
1859                         }
1860                         if (adjustLabels) {
1861                                 for (p in labels) {
1862                                         if (labels[p] >= ignoreBeforeTime) {
1863                                                 labels[p] += amount;
1864                                         }
1865                                 }
1866                         }
1867                         return this._uncache(true);
1868                 };
1869
1870                 p._kill = function(vars, target) {
1871                         if (!vars && !target) {
1872                                 return this._enabled(false, false);
1873                         }
1874                         var tweens = (!target) ? this.getChildren(true, true, false) : this.getTweensOf(target),
1875                                 i = tweens.length,
1876                                 changed = false;
1877                         while (--i > -1) {
1878                                 if (tweens[i]._kill(vars, target)) {
1879                                         changed = true;
1880                                 }
1881                         }
1882                         return changed;
1883                 };
1884
1885                 p.clear = function(labels) {
1886                         var tweens = this.getChildren(false, true, true),
1887                                 i = tweens.length;
1888                         this._time = this._totalTime = 0;
1889                         while (--i > -1) {
1890                                 tweens[i]._enabled(false, false);
1891                         }
1892                         if (labels !== false) {
1893                                 this._labels = {};
1894                         }
1895                         return this._uncache(true);
1896                 };
1897
1898                 p.invalidate = function() {
1899                         var tween = this._first;
1900                         while (tween) {
1901                                 tween.invalidate();
1902                                 tween = tween._next;
1903                         }
1904                         return this;
1905                 };
1906
1907                 p._enabled = function(enabled, ignoreTimeline) {
1908                         if (enabled === this._gc) {
1909                                 var tween = this._first;
1910                                 while (tween) {
1911                                         tween._enabled(enabled, true);
1912                                         tween = tween._next;
1913                                 }
1914                         }
1915                         return SimpleTimeline.prototype._enabled.call(this, enabled, ignoreTimeline);
1916                 };
1917
1918                 p.duration = function(value) {
1919                         if (!arguments.length) {
1920                                 if (this._dirty) {
1921                                         this.totalDuration(); //just triggers recalculation
1922                                 }
1923                                 return this._duration;
1924                         }
1925                         if (this.duration() !== 0 && value !== 0) {
1926                                 this.timeScale(this._duration / value);
1927                         }
1928                         return this;
1929                 };
1930
1931                 p.totalDuration = function(value) {
1932                         if (!arguments.length) {
1933                                 if (this._dirty) {
1934                                         var max = 0,
1935                                                 tween = this._last,
1936                                                 prevStart = 999999999999,
1937                                                 prev, end;
1938                                         while (tween) {
1939                                                 prev = tween._prev; //record it here in case the tween changes position in the sequence...
1940                                                 if (tween._dirty) {
1941                                                         tween.totalDuration(); //could change the tween._startTime, so make sure the tween's cache is clean before analyzing it.
1942                                                 }
1943                                                 if (tween._startTime > prevStart && this._sortChildren && !tween._paused) { //in case one of the tweens shifted out of order, it needs to be re-inserted into the correct position in the sequence
1944                                                         this.add(tween, tween._startTime - tween._delay);
1945                                                 } else {
1946                                                         prevStart = tween._startTime;
1947                                                 }
1948                                                 if (tween._startTime < 0 && !tween._paused) { //children aren't allowed to have negative startTimes unless smoothChildTiming is true, so adjust here if one is found.
1949                                                         max -= tween._startTime;
1950                                                         if (this._timeline.smoothChildTiming) {
1951                                                                 this._startTime += tween._startTime / this._timeScale;
1952                                                         }
1953                                                         this.shiftChildren(-tween._startTime, false, -9999999999);
1954                                                         prevStart = 0;
1955                                                 }
1956                                                 end = tween._startTime + (tween._totalDuration / tween._timeScale);
1957                                                 if (end > max) {
1958                                                         max = end;
1959                                                 }
1960                                                 tween = prev;
1961                                         }
1962                                         this._duration = this._totalDuration = max;
1963                                         this._dirty = false;
1964                                 }
1965                                 return this._totalDuration;
1966                         }
1967                         if (this.totalDuration() !== 0) if (value !== 0) {
1968                                 this.timeScale(this._totalDuration / value);
1969                         }
1970                         return this;
1971                 };
1972
1973                 p.usesFrames = function() {
1974                         var tl = this._timeline;
1975                         while (tl._timeline) {
1976                                 tl = tl._timeline;
1977                         }
1978                         return (tl === Animation._rootFramesTimeline);
1979                 };
1980
1981                 p.rawTime = function() {
1982                         return this._paused ? this._totalTime : (this._timeline.rawTime() - this._startTime) * this._timeScale;
1983                 };
1984
1985                 return TimelineLite;
1986
1987         }, true);
1988         
1989
1990
1991
1992
1993
1994
1995
1996         
1997         
1998         
1999         
2000         
2001 /*
2002  * ----------------------------------------------------------------
2003  * TimelineMax
2004  * ----------------------------------------------------------------
2005  */
2006         window._gsDefine("TimelineMax", ["TimelineLite","TweenLite","easing.Ease"], function(TimelineLite, TweenLite, Ease) {
2007
2008                 var TimelineMax = function(vars) {
2009                                 TimelineLite.call(this, vars);
2010                                 this._repeat = this.vars.repeat || 0;
2011                                 this._repeatDelay = this.vars.repeatDelay || 0;
2012                                 this._cycle = 0;
2013                                 this._yoyo = (this.vars.yoyo === true);
2014                                 this._dirty = true;
2015                         },
2016                         _tinyNum = 0.0000000001,
2017                         _blankArray = [],
2018                         _easeNone = new Ease(null, null, 1, 0),
2019                         p = TimelineMax.prototype = new TimelineLite();
2020
2021                 p.constructor = TimelineMax;
2022                 p.kill()._gc = false;
2023                 TimelineMax.version = "1.12.1";
2024
2025                 p.invalidate = function() {
2026                         this._yoyo = (this.vars.yoyo === true);
2027                         this._repeat = this.vars.repeat || 0;
2028                         this._repeatDelay = this.vars.repeatDelay || 0;
2029                         this._uncache(true);
2030                         return TimelineLite.prototype.invalidate.call(this);
2031                 };
2032
2033                 p.addCallback = function(callback, position, params, scope) {
2034                         return this.add( TweenLite.delayedCall(0, callback, params, scope), position);
2035                 };
2036
2037                 p.removeCallback = function(callback, position) {
2038                         if (callback) {
2039                                 if (position == null) {
2040                                         this._kill(null, callback);
2041                                 } else {
2042                                         var a = this.getTweensOf(callback, false),
2043                                                 i = a.length,
2044                                                 time = this._parseTimeOrLabel(position);
2045                                         while (--i > -1) {
2046                                                 if (a[i]._startTime === time) {
2047                                                         a[i]._enabled(false, false);
2048                                                 }
2049                                         }
2050                                 }
2051                         }
2052                         return this;
2053                 };
2054
2055                 p.tweenTo = function(position, vars) {
2056                         vars = vars || {};
2057                         var copy = {ease:_easeNone, overwrite:(vars.delay ? 2 : 1), useFrames:this.usesFrames(), immediateRender:false},//note: set overwrite to 1 (true/all) by default unless there's a delay so that we avoid a racing situation that could happen if, for example, an onmousemove creates the same tweenTo() over and over again.
2058                                 duration, p, t;
2059                         for (p in vars) {
2060                                 copy[p] = vars[p];
2061                         }
2062                         copy.time = this._parseTimeOrLabel(position);
2063                         duration = (Math.abs(Number(copy.time) - this._time) / this._timeScale) || 0.001;
2064                         t = new TweenLite(this, duration, copy);
2065                         copy.onStart = function() {
2066                                 t.target.paused(true);
2067                                 if (t.vars.time !== t.target.time() && duration === t.duration()) { //don't make the duration zero - if it's supposed to be zero, don't worry because it's already initting the tween and will complete immediately, effectively making the duration zero anyway. If we make duration zero, the tween won't run at all.
2068                                         t.duration( Math.abs( t.vars.time - t.target.time()) / t.target._timeScale );
2069                                 }
2070                                 if (vars.onStart) { //in case the user had an onStart in the vars - we don't want to overwrite it.
2071                                         vars.onStart.apply(vars.onStartScope || t, vars.onStartParams || _blankArray);
2072                                 }
2073                         };
2074                         return t;
2075                 };
2076
2077                 p.tweenFromTo = function(fromPosition, toPosition, vars) {
2078                         vars = vars || {};
2079                         fromPosition = this._parseTimeOrLabel(fromPosition);
2080                         vars.startAt = {onComplete:this.seek, onCompleteParams:[fromPosition], onCompleteScope:this};
2081                         vars.immediateRender = (vars.immediateRender !== false);
2082                         var t = this.tweenTo(toPosition, vars);
2083                         return t.duration((Math.abs( t.vars.time - fromPosition) / this._timeScale) || 0.001);
2084                 };
2085
2086                 p.render = function(time, suppressEvents, force) {
2087                         if (this._gc) {
2088                                 this._enabled(true, false);
2089                         }
2090                         var totalDur = (!this._dirty) ? this._totalDuration : this.totalDuration(),
2091                                 dur = this._duration,
2092                                 prevTime = this._time,
2093                                 prevTotalTime = this._totalTime,
2094                                 prevStart = this._startTime,
2095                                 prevTimeScale = this._timeScale,
2096                                 prevRawPrevTime = this._rawPrevTime,
2097                                 prevPaused = this._paused,
2098                                 prevCycle = this._cycle,
2099                                 tween, isComplete, next, callback, internalForce, cycleDuration;
2100                         if (time >= totalDur) {
2101                                 if (!this._locked) {
2102                                         this._totalTime = totalDur;
2103                                         this._cycle = this._repeat;
2104                                 }
2105                                 if (!this._reversed) if (!this._hasPausedChild()) {
2106                                         isComplete = true;
2107                                         callback = "onComplete";
2108                                         if (this._duration === 0) if (time === 0 || prevRawPrevTime < 0 || prevRawPrevTime === _tinyNum) if (prevRawPrevTime !== time && this._first) {
2109                                                 internalForce = true;
2110                                                 if (prevRawPrevTime > _tinyNum) {
2111                                                         callback = "onReverseComplete";
2112                                                 }
2113                                         }
2114                                 }
2115                                 this._rawPrevTime = (this._duration || !suppressEvents || time || this._rawPrevTime === time) ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration timeline or tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient.
2116                                 if (this._yoyo && (this._cycle & 1) !== 0) {
2117                                         this._time = time = 0;
2118                                 } else {
2119                                         this._time = dur;
2120                                         time = dur + 0.0001; //to avoid occasional floating point rounding errors - sometimes child tweens/timelines were not being fully completed (their progress might be 0.999999999999998 instead of 1 because when _time - tween._startTime is performed, floating point errors would return a value that was SLIGHTLY off). Try (999999999999.7 - 999999999999) * 1 = 0.699951171875 instead of 0.7. We cannot do less then 0.0001 because the same issue can occur when the duration is extremely large like 999999999999 in which case adding 0.00000001, for example, causes it to act like nothing was added.
2121                                 }
2122
2123                         } else if (time < 0.0000001) { //to work around occasional floating point math artifacts, round super small values to 0.
2124                                 if (!this._locked) {
2125                                         this._totalTime = this._cycle = 0;
2126                                 }
2127                                 this._time = 0;
2128                                 if (prevTime !== 0 || (dur === 0 && prevRawPrevTime !== _tinyNum && (prevRawPrevTime > 0 || (time < 0 && prevRawPrevTime >= 0)) && !this._locked)) { //edge case for checking time < 0 && prevRawPrevTime >= 0: a zero-duration fromTo() tween inside a zero-duration timeline (yeah, very rare)
2129                                         callback = "onReverseComplete";
2130                                         isComplete = this._reversed;
2131                                 }
2132                                 if (time < 0) {
2133                                         this._active = false;
2134                                         if (dur === 0) if (prevRawPrevTime >= 0 && this._first) { //zero-duration timelines are tricky because we must discern the momentum/direction of time in order to determine whether the starting values should be rendered or the ending values. If the "playhead" of its timeline goes past the zero-duration tween in the forward direction or lands directly on it, the end values should be rendered, but if the timeline's "playhead" moves past it in the backward direction (from a postitive time to a negative time), the starting values must be rendered.
2135                                                 internalForce = true;
2136                                         }
2137                                         this._rawPrevTime = time;
2138                                 } else {
2139                                         this._rawPrevTime = (dur || !suppressEvents || time || this._rawPrevTime === time) ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration timeline or tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient.
2140                                         time = 0; //to avoid occasional floating point rounding errors (could cause problems especially with zero-duration tweens at the very beginning of the timeline)
2141                                         if (!this._initted) {
2142                                                 internalForce = true;
2143                                         }
2144                                 }
2145
2146                         } else {
2147                                 if (dur === 0 && prevRawPrevTime < 0) { //without this, zero-duration repeating timelines (like with a simple callback nested at the very beginning and a repeatDelay) wouldn't render the first time through.
2148                                         internalForce = true;
2149                                 }
2150                                 this._time = this._rawPrevTime = time;
2151                                 if (!this._locked) {
2152                                         this._totalTime = time;
2153                                         if (this._repeat !== 0) {
2154                                                 cycleDuration = dur + this._repeatDelay;
2155                                                 this._cycle = (this._totalTime / cycleDuration) >> 0; //originally _totalTime % cycleDuration but floating point errors caused problems, so I normalized it. (4 % 0.8 should be 0 but it gets reported as 0.79999999!)
2156                                                 if (this._cycle !== 0) if (this._cycle === this._totalTime / cycleDuration) {
2157                                                         this._cycle--; //otherwise when rendered exactly at the end time, it will act as though it is repeating (at the beginning)
2158                                                 }
2159                                                 this._time = this._totalTime - (this._cycle * cycleDuration);
2160                                                 if (this._yoyo) if ((this._cycle & 1) !== 0) {
2161                                                         this._time = dur - this._time;
2162                                                 }
2163                                                 if (this._time > dur) {
2164                                                         this._time = dur;
2165                                                         time = dur + 0.0001; //to avoid occasional floating point rounding error
2166                                                 } else if (this._time < 0) {
2167                                                         this._time = time = 0;
2168                                                 } else {
2169                                                         time = this._time;
2170                                                 }
2171                                         }
2172                                 }
2173                         }
2174
2175                         if (this._cycle !== prevCycle) if (!this._locked) {
2176                                 /*
2177                                 make sure children at the end/beginning of the timeline are rendered properly. If, for example,
2178                                 a 3-second long timeline rendered at 2.9 seconds previously, and now renders at 3.2 seconds (which
2179                                 would get transated to 2.8 seconds if the timeline yoyos or 0.2 seconds if it just repeats), there
2180                                 could be a callback or a short tween that's at 2.95 or 3 seconds in which wouldn't render. So
2181                                 we need to push the timeline to the end (and/or beginning depending on its yoyo value). Also we must
2182                                 ensure that zero-duration tweens at the very beginning or end of the TimelineMax work.
2183                                 */
2184                                 var backwards = (this._yoyo && (prevCycle & 1) !== 0),
2185                                         wrap = (backwards === (this._yoyo && (this._cycle & 1) !== 0)),
2186                                         recTotalTime = this._totalTime,
2187                                         recCycle = this._cycle,
2188                                         recRawPrevTime = this._rawPrevTime,
2189                                         recTime = this._time;
2190
2191                                 this._totalTime = prevCycle * dur;
2192                                 if (this._cycle < prevCycle) {
2193                                         backwards = !backwards;
2194                                 } else {
2195                                         this._totalTime += dur;
2196                                 }
2197                                 this._time = prevTime; //temporarily revert _time so that render() renders the children in the correct order. Without this, tweens won't rewind correctly. We could arhictect things in a "cleaner" way by splitting out the rendering queue into a separate method but for performance reasons, we kept it all inside this method.
2198
2199                                 this._rawPrevTime = (dur === 0) ? prevRawPrevTime - 0.0001 : prevRawPrevTime;
2200                                 this._cycle = prevCycle;
2201                                 this._locked = true; //prevents changes to totalTime and skips repeat/yoyo behavior when we recursively call render()
2202                                 prevTime = (backwards) ? 0 : dur;
2203                                 this.render(prevTime, suppressEvents, (dur === 0));
2204                                 if (!suppressEvents) if (!this._gc) {
2205                                         if (this.vars.onRepeat) {
2206                                                 this.vars.onRepeat.apply(this.vars.onRepeatScope || this, this.vars.onRepeatParams || _blankArray);
2207                                         }
2208                                 }
2209                                 if (wrap) {
2210                                         prevTime = (backwards) ? dur + 0.0001 : -0.0001;
2211                                         this.render(prevTime, true, false);
2212                                 }
2213                                 this._locked = false;
2214                                 if (this._paused && !prevPaused) { //if the render() triggered callback that paused this timeline, we should abort (very rare, but possible)
2215                                         return;
2216                                 }
2217                                 this._time = recTime;
2218                                 this._totalTime = recTotalTime;
2219                                 this._cycle = recCycle;
2220                                 this._rawPrevTime = recRawPrevTime;
2221                         }
2222
2223                         if ((this._time === prevTime || !this._first) && !force && !internalForce) {
2224                                 if (prevTotalTime !== this._totalTime) if (this._onUpdate) if (!suppressEvents) { //so that onUpdate fires even during the repeatDelay - as long as the totalTime changed, we should trigger onUpdate.
2225                                         this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray);
2226                                 }
2227                                 return;
2228                         } else if (!this._initted) {
2229                                 this._initted = true;
2230                         }
2231
2232                         if (!this._active) if (!this._paused && this._totalTime !== prevTotalTime && time > 0) {
2233                                 this._active = true;  //so that if the user renders the timeline (as opposed to the parent timeline rendering it), it is forced to re-render and align it with the proper time/frame on the next rendering cycle. Maybe the timeline already finished but the user manually re-renders it as halfway done, for example.
2234                         }
2235
2236                         if (prevTotalTime === 0) if (this.vars.onStart) if (this._totalTime !== 0) if (!suppressEvents) {
2237                                 this.vars.onStart.apply(this.vars.onStartScope || this, this.vars.onStartParams || _blankArray);
2238                         }
2239
2240                         if (this._time >= prevTime) {
2241                                 tween = this._first;
2242                                 while (tween) {
2243                                         next = tween._next; //record it here because the value could change after rendering...
2244                                         if (this._paused && !prevPaused) { //in case a tween pauses the timeline when rendering
2245                                                 break;
2246                                         } else if (tween._active || (tween._startTime <= this._time && !tween._paused && !tween._gc)) {
2247                                                 if (!tween._reversed) {
2248                                                         tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force);
2249                                                 } else {
2250                                                         tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force);
2251                                                 }
2252
2253                                         }
2254                                         tween = next;
2255                                 }
2256                         } else {
2257                                 tween = this._last;
2258                                 while (tween) {
2259                                         next = tween._prev; //record it here because the value could change after rendering...
2260                                         if (this._paused && !prevPaused) { //in case a tween pauses the timeline when rendering
2261                                                 break;
2262                                         } else if (tween._active || (tween._startTime <= prevTime && !tween._paused && !tween._gc)) {
2263                                                 if (!tween._reversed) {
2264                                                         tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force);
2265                                                 } else {
2266                                                         tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force);
2267                                                 }
2268                                         }
2269                                         tween = next;
2270                                 }
2271                         }
2272
2273                         if (this._onUpdate) if (!suppressEvents) {
2274                                 this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray);
2275                         }
2276                         if (callback) if (!this._locked) if (!this._gc) if (prevStart === this._startTime || prevTimeScale !== this._timeScale) if (this._time === 0 || totalDur >= this.totalDuration()) { //if one of the tweens that was rendered altered this timeline's startTime (like if an onComplete reversed the timeline), it probably isn't complete. If it is, don't worry, because whatever call altered the startTime would complete if it was necessary at the new time. The only exception is the timeScale property. Also check _gc because there's a chance that kill() could be called in an onUpdate
2277                                 if (isComplete) {
2278                                         if (this._timeline.autoRemoveChildren) {
2279                                                 this._enabled(false, false);
2280                                         }
2281                                         this._active = false;
2282                                 }
2283                                 if (!suppressEvents && this.vars[callback]) {
2284                                         this.vars[callback].apply(this.vars[callback + "Scope"] || this, this.vars[callback + "Params"] || _blankArray);
2285                                 }
2286                         }
2287                 };
2288
2289                 p.getActive = function(nested, tweens, timelines) {
2290                         if (nested == null) {
2291                                 nested = true;
2292                         }
2293                         if (tweens == null) {
2294                                 tweens = true;
2295                         }
2296                         if (timelines == null) {
2297                                 timelines = false;
2298                         }
2299                         var a = [],
2300                                 all = this.getChildren(nested, tweens, timelines),
2301                                 cnt = 0,
2302                                 l = all.length,
2303                                 i, tween;
2304                         for (i = 0; i < l; i++) {
2305                                 tween = all[i];
2306                                 if (tween.isActive()) {
2307                                         a[cnt++] = tween;
2308                                 }
2309                         }
2310                         return a;
2311                 };
2312
2313
2314                 p.getLabelAfter = function(time) {
2315                         if (!time) if (time !== 0) { //faster than isNan()
2316                                 time = this._time;
2317                         }
2318                         var labels = this.getLabelsArray(),
2319                                 l = labels.length,
2320                                 i;
2321                         for (i = 0; i < l; i++) {
2322                                 if (labels[i].time > time) {
2323                                         return labels[i].name;
2324                                 }
2325                         }
2326                         return null;
2327                 };
2328
2329                 p.getLabelBefore = function(time) {
2330                         if (time == null) {
2331                                 time = this._time;
2332                         }
2333                         var labels = this.getLabelsArray(),
2334                                 i = labels.length;
2335                         while (--i > -1) {
2336                                 if (labels[i].time < time) {
2337                                         return labels[i].name;
2338                                 }
2339                         }
2340                         return null;
2341                 };
2342
2343                 p.getLabelsArray = function() {
2344                         var a = [],
2345                                 cnt = 0,
2346                                 p;
2347                         for (p in this._labels) {
2348                                 a[cnt++] = {time:this._labels[p], name:p};
2349                         }
2350                         a.sort(function(a,b) {
2351                                 return a.time - b.time;
2352                         });
2353                         return a;
2354                 };
2355
2356
2357 //---- GETTERS / SETTERS -------------------------------------------------------------------------------------------------------
2358
2359                 p.progress = function(value) {
2360                         return (!arguments.length) ? this._time / this.duration() : this.totalTime( this.duration() * ((this._yoyo && (this._cycle & 1) !== 0) ? 1 - value : value) + (this._cycle * (this._duration + this._repeatDelay)), false);
2361                 };
2362
2363                 p.totalProgress = function(value) {
2364                         return (!arguments.length) ? this._totalTime / this.totalDuration() : this.totalTime( this.totalDuration() * value, false);
2365                 };
2366
2367                 p.totalDuration = function(value) {
2368                         if (!arguments.length) {
2369                                 if (this._dirty) {
2370                                         TimelineLite.prototype.totalDuration.call(this); //just forces refresh
2371                                         //Instead of Infinity, we use 999999999999 so that we can accommodate reverses.
2372                                         this._totalDuration = (this._repeat === -1) ? 999999999999 : this._duration * (this._repeat + 1) + (this._repeatDelay * this._repeat);
2373                                 }
2374                                 return this._totalDuration;
2375                         }
2376                         return (this._repeat === -1) ? this : this.duration( (value - (this._repeat * this._repeatDelay)) / (this._repeat + 1) );
2377                 };
2378
2379                 p.time = function(value, suppressEvents) {
2380                         if (!arguments.length) {
2381                                 return this._time;
2382                         }
2383                         if (this._dirty) {
2384                                 this.totalDuration();
2385                         }
2386                         if (value > this._duration) {
2387                                 value = this._duration;
2388                         }
2389                         if (this._yoyo && (this._cycle & 1) !== 0) {
2390                                 value = (this._duration - value) + (this._cycle * (this._duration + this._repeatDelay));
2391                         } else if (this._repeat !== 0) {
2392                                 value += this._cycle * (this._duration + this._repeatDelay);
2393                         }
2394                         return this.totalTime(value, suppressEvents);
2395                 };
2396
2397                 p.repeat = function(value) {
2398                         if (!arguments.length) {
2399                                 return this._repeat;
2400                         }
2401                         this._repeat = value;
2402                         return this._uncache(true);
2403                 };
2404
2405                 p.repeatDelay = function(value) {
2406                         if (!arguments.length) {
2407                                 return this._repeatDelay;
2408                         }
2409                         this._repeatDelay = value;
2410                         return this._uncache(true);
2411                 };
2412
2413                 p.yoyo = function(value) {
2414                         if (!arguments.length) {
2415                                 return this._yoyo;
2416                         }
2417                         this._yoyo = value;
2418                         return this;
2419                 };
2420
2421                 p.currentLabel = function(value) {
2422                         if (!arguments.length) {
2423                                 return this.getLabelBefore(this._time + 0.00000001);
2424                         }
2425                         return this.seek(value, true);
2426                 };
2427
2428                 return TimelineMax;
2429
2430         }, true);
2431         
2432
2433
2434
2435
2436         
2437         
2438         
2439         
2440         
2441         
2442         
2443 /*
2444  * ----------------------------------------------------------------
2445  * BezierPlugin
2446  * ----------------------------------------------------------------
2447  */
2448         (function() {
2449
2450                 var _RAD2DEG = 180 / Math.PI,
2451                         _r1 = [],
2452                         _r2 = [],
2453                         _r3 = [],
2454                         _corProps = {},
2455                         Segment = function(a, b, c, d) {
2456                                 this.a = a;
2457                                 this.b = b;
2458                                 this.c = c;
2459                                 this.d = d;
2460                                 this.da = d - a;
2461                                 this.ca = c - a;
2462                                 this.ba = b - a;
2463                         },
2464                         _correlate = ",x,y,z,left,top,right,bottom,marginTop,marginLeft,marginRight,marginBottom,paddingLeft,paddingTop,paddingRight,paddingBottom,backgroundPosition,backgroundPosition_y,",
2465                         cubicToQuadratic = function(a, b, c, d) {
2466                                 var q1 = {a:a},
2467                                         q2 = {},
2468                                         q3 = {},
2469                                         q4 = {c:d},
2470                                         mab = (a + b) / 2,
2471                                         mbc = (b + c) / 2,
2472                                         mcd = (c + d) / 2,
2473                                         mabc = (mab + mbc) / 2,
2474                                         mbcd = (mbc + mcd) / 2,
2475                                         m8 = (mbcd - mabc) / 8;
2476                                 q1.b = mab + (a - mab) / 4;
2477                                 q2.b = mabc + m8;
2478                                 q1.c = q2.a = (q1.b + q2.b) / 2;
2479                                 q2.c = q3.a = (mabc + mbcd) / 2;
2480                                 q3.b = mbcd - m8;
2481                                 q4.b = mcd + (d - mcd) / 4;
2482                                 q3.c = q4.a = (q3.b + q4.b) / 2;
2483                                 return [q1, q2, q3, q4];
2484                         },
2485                         _calculateControlPoints = function(a, curviness, quad, basic, correlate) {
2486                                 var l = a.length - 1,
2487                                         ii = 0,
2488                                         cp1 = a[0].a,
2489                                         i, p1, p2, p3, seg, m1, m2, mm, cp2, qb, r1, r2, tl;
2490                                 for (i = 0; i < l; i++) {
2491                                         seg = a[ii];
2492                                         p1 = seg.a;
2493                                         p2 = seg.d;
2494                                         p3 = a[ii+1].d;
2495
2496                                         if (correlate) {
2497                                                 r1 = _r1[i];
2498                                                 r2 = _r2[i];
2499                                                 tl = ((r2 + r1) * curviness * 0.25) / (basic ? 0.5 : _r3[i] || 0.5);
2500                                                 m1 = p2 - (p2 - p1) * (basic ? curviness * 0.5 : (r1 !== 0 ? tl / r1 : 0));
2501                                                 m2 = p2 + (p3 - p2) * (basic ? curviness * 0.5 : (r2 !== 0 ? tl / r2 : 0));
2502                                                 mm = p2 - (m1 + (((m2 - m1) * ((r1 * 3 / (r1 + r2)) + 0.5) / 4) || 0));
2503                                         } else {
2504                                                 m1 = p2 - (p2 - p1) * curviness * 0.5;
2505                                                 m2 = p2 + (p3 - p2) * curviness * 0.5;
2506                                                 mm = p2 - (m1 + m2) / 2;
2507                                         }
2508                                         m1 += mm;
2509                                         m2 += mm;
2510
2511                                         seg.c = cp2 = m1;
2512                                         if (i !== 0) {
2513                                                 seg.b = cp1;
2514                                         } else {
2515                                                 seg.b = cp1 = seg.a + (seg.c - seg.a) * 0.6; //instead of placing b on a exactly, we move it inline with c so that if the user specifies an ease like Back.easeIn or Elastic.easeIn which goes BEYOND the beginning, it will do so smoothly.
2516                                         }
2517
2518                                         seg.da = p2 - p1;
2519                                         seg.ca = cp2 - p1;
2520                                         seg.ba = cp1 - p1;
2521
2522                                         if (quad) {
2523                                                 qb = cubicToQuadratic(p1, cp1, cp2, p2);
2524                                                 a.splice(ii, 1, qb[0], qb[1], qb[2], qb[3]);
2525                                                 ii += 4;
2526                                         } else {
2527                                                 ii++;
2528                                         }
2529
2530                                         cp1 = m2;
2531                                 }
2532                                 seg = a[ii];
2533                                 seg.b = cp1;
2534                                 seg.c = cp1 + (seg.d - cp1) * 0.4; //instead of placing c on d exactly, we move it inline with b so that if the user specifies an ease like Back.easeOut or Elastic.easeOut which goes BEYOND the end, it will do so smoothly.
2535                                 seg.da = seg.d - seg.a;
2536                                 seg.ca = seg.c - seg.a;
2537                                 seg.ba = cp1 - seg.a;
2538                                 if (quad) {
2539                                         qb = cubicToQuadratic(seg.a, cp1, seg.c, seg.d);
2540                                         a.splice(ii, 1, qb[0], qb[1], qb[2], qb[3]);
2541                                 }
2542                         },
2543                         _parseAnchors = function(values, p, correlate, prepend) {
2544                                 var a = [],
2545                                         l, i, p1, p2, p3, tmp;
2546                                 if (prepend) {
2547                                         values = [prepend].concat(values);
2548                                         i = values.length;
2549                                         while (--i > -1) {
2550                                                 if (typeof( (tmp = values[i][p]) ) === "string") if (tmp.charAt(1) === "=") {
2551                                                         values[i][p] = prepend[p] + Number(tmp.charAt(0) + tmp.substr(2)); //accommodate relative values. Do it inline instead of breaking it out into a function for speed reasons
2552                                                 }
2553                                         }
2554                                 }
2555                                 l = values.length - 2;
2556                                 if (l < 0) {
2557                                         a[0] = new Segment(values[0][p], 0, 0, values[(l < -1) ? 0 : 1][p]);
2558                                         return a;
2559                                 }
2560                                 for (i = 0; i < l; i++) {
2561                                         p1 = values[i][p];
2562                                         p2 = values[i+1][p];
2563                                         a[i] = new Segment(p1, 0, 0, p2);
2564                                         if (correlate) {
2565                                                 p3 = values[i+2][p];
2566                                                 _r1[i] = (_r1[i] || 0) + (p2 - p1) * (p2 - p1);
2567                                                 _r2[i] = (_r2[i] || 0) + (p3 - p2) * (p3 - p2);
2568                                         }
2569                                 }
2570                                 a[i] = new Segment(values[i][p], 0, 0, values[i+1][p]);
2571                                 return a;
2572                         },
2573                         bezierThrough = function(values, curviness, quadratic, basic, correlate, prepend) {
2574                                 var obj = {},
2575                                         props = [],
2576                                         first = prepend || values[0],
2577                                         i, p, a, j, r, l, seamless, last;
2578                                 correlate = (typeof(correlate) === "string") ? ","+correlate+"," : _correlate;
2579                                 if (curviness == null) {
2580                                         curviness = 1;
2581                                 }
2582                                 for (p in values[0]) {
2583                                         props.push(p);
2584                                 }
2585                                 //check to see if the last and first values are identical (well, within 0.05). If so, make seamless by appending the second element to the very end of the values array and the 2nd-to-last element to the very beginning (we'll remove those segments later)
2586                                 if (values.length > 1) {
2587                                         last = values[values.length - 1];
2588                                         seamless = true;
2589                                         i = props.length;
2590                                         while (--i > -1) {
2591                                                 p = props[i];
2592                                                 if (Math.abs(first[p] - last[p]) > 0.05) { //build in a tolerance of +/-0.05 to accommodate rounding errors. For example, if you set an object's position to 4.945, Flash will make it 4.9
2593                                                         seamless = false;
2594                                                         break;
2595                                                 }
2596                                         }
2597                                         if (seamless) {
2598                                                 values = values.concat(); //duplicate the array to avoid contaminating the original which the user may be reusing for other tweens
2599                                                 if (prepend) {
2600                                                         values.unshift(prepend);
2601                                                 }
2602                                                 values.push(values[1]);
2603                                                 prepend = values[values.length - 3];
2604                                         }
2605                                 }
2606                                 _r1.length = _r2.length = _r3.length = 0;
2607                                 i = props.length;
2608                                 while (--i > -1) {
2609                                         p = props[i];
2610                                         _corProps[p] = (correlate.indexOf(","+p+",") !== -1);
2611                                         obj[p] = _parseAnchors(values, p, _corProps[p], prepend);
2612                                 }
2613                                 i = _r1.length;
2614                                 while (--i > -1) {
2615                                         _r1[i] = Math.sqrt(_r1[i]);
2616                                         _r2[i] = Math.sqrt(_r2[i]);
2617                                 }
2618                                 if (!basic) {
2619                                         i = props.length;
2620                                         while (--i > -1) {
2621                                                 if (_corProps[p]) {
2622                                                         a = obj[props[i]];
2623                                                         l = a.length - 1;
2624                                                         for (j = 0; j < l; j++) {
2625                                                                 r = a[j+1].da / _r2[j] + a[j].da / _r1[j];
2626                                                                 _r3[j] = (_r3[j] || 0) + r * r;
2627                                                         }
2628                                                 }
2629                                         }
2630                                         i = _r3.length;
2631                                         while (--i > -1) {
2632                                                 _r3[i] = Math.sqrt(_r3[i]);
2633                                         }
2634                                 }
2635                                 i = props.length;
2636                                 j = quadratic ? 4 : 1;
2637                                 while (--i > -1) {
2638                                         p = props[i];
2639                                         a = obj[p];
2640                                         _calculateControlPoints(a, curviness, quadratic, basic, _corProps[p]); //this method requires that _parseAnchors() and _setSegmentRatios() ran first so that _r1, _r2, and _r3 values are populated for all properties
2641                                         if (seamless) {
2642                                                 a.splice(0, j);
2643                                                 a.splice(a.length - j, j);
2644                                         }
2645                                 }
2646                                 return obj;
2647                         },
2648                         _parseBezierData = function(values, type, prepend) {
2649                                 type = type || "soft";
2650                                 var obj = {},
2651                                         inc = (type === "cubic") ? 3 : 2,
2652                                         soft = (type === "soft"),
2653                                         props = [],
2654                                         a, b, c, d, cur, i, j, l, p, cnt, tmp;
2655                                 if (soft && prepend) {
2656                                         values = [prepend].concat(values);
2657                                 }
2658                                 if (values == null || values.length < inc + 1) { throw "invalid Bezier data"; }
2659                                 for (p in values[0]) {
2660                                         props.push(p);
2661                                 }
2662                                 i = props.length;
2663                                 while (--i > -1) {
2664                                         p = props[i];
2665                                         obj[p] = cur = [];
2666                                         cnt = 0;
2667                                         l = values.length;
2668                                         for (j = 0; j < l; j++) {
2669                                                 a = (prepend == null) ? values[j][p] : (typeof( (tmp = values[j][p]) ) === "string" && tmp.charAt(1) === "=") ? prepend[p] + Number(tmp.charAt(0) + tmp.substr(2)) : Number(tmp);
2670                                                 if (soft) if (j > 1) if (j < l - 1) {
2671                                                         cur[cnt++] = (a + cur[cnt-2]) / 2;
2672                                                 }
2673                                                 cur[cnt++] = a;
2674                                         }
2675                                         l = cnt - inc + 1;
2676                                         cnt = 0;
2677                                         for (j = 0; j < l; j += inc) {
2678                                                 a = cur[j];
2679                                                 b = cur[j+1];
2680                                                 c = cur[j+2];
2681                                                 d = (inc === 2) ? 0 : cur[j+3];
2682                                                 cur[cnt++] = tmp = (inc === 3) ? new Segment(a, b, c, d) : new Segment(a, (2 * b + a) / 3, (2 * b + c) / 3, c);
2683                                         }
2684                                         cur.length = cnt;
2685                                 }
2686                                 return obj;
2687                         },
2688                         _addCubicLengths = function(a, steps, resolution) {
2689                                 var inc = 1 / resolution,
2690                                         j = a.length,
2691                                         d, d1, s, da, ca, ba, p, i, inv, bez, index;
2692                                 while (--j > -1) {
2693                                         bez = a[j];
2694                                         s = bez.a;
2695                                         da = bez.d - s;
2696                                         ca = bez.c - s;
2697                                         ba = bez.b - s;
2698                                         d = d1 = 0;
2699                                         for (i = 1; i <= resolution; i++) {
2700                                                 p = inc * i;
2701                                                 inv = 1 - p;
2702                                                 d = d1 - (d1 = (p * p * da + 3 * inv * (p * ca + inv * ba)) * p);
2703                                                 index = j * resolution + i - 1;
2704                                                 steps[index] = (steps[index] || 0) + d * d;
2705                                         }
2706                                 }
2707                         },
2708                         _parseLengthData = function(obj, resolution) {
2709                                 resolution = resolution >> 0 || 6;
2710                                 var a = [],
2711                                         lengths = [],
2712                                         d = 0,
2713                                         total = 0,
2714                                         threshold = resolution - 1,
2715                                         segments = [],
2716                                         curLS = [], //current length segments array
2717                                         p, i, l, index;
2718                                 for (p in obj) {
2719                                         _addCubicLengths(obj[p], a, resolution);
2720                                 }
2721                                 l = a.length;
2722                                 for (i = 0; i < l; i++) {
2723                                         d += Math.sqrt(a[i]);
2724                                         index = i % resolution;
2725                                         curLS[index] = d;
2726                                         if (index === threshold) {
2727                                                 total += d;
2728                                                 index = (i / resolution) >> 0;
2729                                                 segments[index] = curLS;
2730                                                 lengths[index] = total;
2731                                                 d = 0;
2732                                                 curLS = [];
2733                                         }
2734                                 }
2735                                 return {length:total, lengths:lengths, segments:segments};
2736                         },
2737
2738
2739
2740                         BezierPlugin = window._gsDefine.plugin({
2741                                         propName: "bezier",
2742                                         priority: -1,
2743                                         version: "1.3.2",
2744                                         API: 2,
2745                                         global:true,
2746
2747                                         //gets called when the tween renders for the first time. This is where initial values should be recorded and any setup routines should run.
2748                                         init: function(target, vars, tween) {
2749                                                 this._target = target;
2750                                                 if (vars instanceof Array) {
2751                                                         vars = {values:vars};
2752                                                 }
2753                                                 this._func = {};
2754                                                 this._round = {};
2755                                                 this._props = [];
2756                                                 this._timeRes = (vars.timeResolution == null) ? 6 : parseInt(vars.timeResolution, 10);
2757                                                 var values = vars.values || [],
2758                                                         first = {},
2759                                                         second = values[0],
2760                                                         autoRotate = vars.autoRotate || tween.vars.orientToBezier,
2761                                                         p, isFunc, i, j, prepend;
2762
2763                                                 this._autoRotate = autoRotate ? (autoRotate instanceof Array) ? autoRotate : [["x","y","rotation",((autoRotate === true) ? 0 : Number(autoRotate) || 0)]] : null;
2764                                                 for (p in second) {
2765                                                         this._props.push(p);
2766                                                 }
2767
2768                                                 i = this._props.length;
2769                                                 while (--i > -1) {
2770                                                         p = this._props[i];
2771
2772                                                         this._overwriteProps.push(p);
2773                                                         isFunc = this._func[p] = (typeof(target[p]) === "function");
2774                                                         first[p] = (!isFunc) ? parseFloat(target[p]) : target[ ((p.indexOf("set") || typeof(target["get" + p.substr(3)]) !== "function") ? p : "get" + p.substr(3)) ]();
2775                                                         if (!prepend) if (first[p] !== values[0][p]) {
2776                                                                 prepend = first;
2777                                                         }
2778                                                 }
2779                                                 this._beziers = (vars.type !== "cubic" && vars.type !== "quadratic" && vars.type !== "soft") ? bezierThrough(values, isNaN(vars.curviness) ? 1 : vars.curviness, false, (vars.type === "thruBasic"), vars.correlate, prepend) : _parseBezierData(values, vars.type, first);
2780                                                 this._segCount = this._beziers[p].length;
2781
2782                                                 if (this._timeRes) {
2783                                                         var ld = _parseLengthData(this._beziers, this._timeRes);
2784                                                         this._length = ld.length;
2785                                                         this._lengths = ld.lengths;
2786                                                         this._segments = ld.segments;
2787                                                         this._l1 = this._li = this._s1 = this._si = 0;
2788                                                         this._l2 = this._lengths[0];
2789                                                         this._curSeg = this._segments[0];
2790                                                         this._s2 = this._curSeg[0];
2791                                                         this._prec = 1 / this._curSeg.length;
2792                                                 }
2793
2794                                                 if ((autoRotate = this._autoRotate)) {
2795                                                         this._initialRotations = [];
2796                                                         if (!(autoRotate[0] instanceof Array)) {
2797                                                                 this._autoRotate = autoRotate = [autoRotate];
2798                                                         }
2799                                                         i = autoRotate.length;
2800                                                         while (--i > -1) {
2801                                                                 for (j = 0; j < 3; j++) {
2802                                                                         p = autoRotate[i][j];
2803                                                                         this._func[p] = (typeof(target[p]) === "function") ? target[ ((p.indexOf("set") || typeof(target["get" + p.substr(3)]) !== "function") ? p : "get" + p.substr(3)) ] : false;
2804                                                                 }
2805                                                                 p = autoRotate[i][2];
2806                                                                 this._initialRotations[i] = this._func[p] ? this._func[p].call(this._target) : this._target[p];
2807                                                         }
2808                                                 }
2809                                                 this._startRatio = tween.vars.runBackwards ? 1 : 0; //we determine the starting ratio when the tween inits which is always 0 unless the tween has runBackwards:true (indicating it's a from() tween) in which case it's 1.
2810                                                 return true;
2811                                         },
2812
2813                                         //called each time the values should be updated, and the ratio gets passed as the only parameter (typically it's a value between 0 and 1, but it can exceed those when using an ease like Elastic.easeOut or Back.easeOut, etc.)
2814                                         set: function(v) {
2815                                                 var segments = this._segCount,
2816                                                         func = this._func,
2817                                                         target = this._target,
2818                                                         notStart = (v !== this._startRatio),
2819                                                         curIndex, inv, i, p, b, t, val, l, lengths, curSeg;
2820                                                 if (!this._timeRes) {
2821                                                         curIndex = (v < 0) ? 0 : (v >= 1) ? segments - 1 : (segments * v) >> 0;
2822                                                         t = (v - (curIndex * (1 / segments))) * segments;
2823                                                 } else {
2824                                                         lengths = this._lengths;
2825                                                         curSeg = this._curSeg;
2826                                                         v *= this._length;
2827                                                         i = this._li;
2828                                                         //find the appropriate segment (if the currently cached one isn't correct)
2829                                                         if (v > this._l2 && i < segments - 1) {
2830                                                                 l = segments - 1;
2831                                                                 while (i < l && (this._l2 = lengths[++i]) <= v) {       }
2832                                                                 this._l1 = lengths[i-1];
2833                                                                 this._li = i;
2834                                                                 this._curSeg = curSeg = this._segments[i];
2835                                                                 this._s2 = curSeg[(this._s1 = this._si = 0)];
2836                                                         } else if (v < this._l1 && i > 0) {
2837                                                                 while (i > 0 && (this._l1 = lengths[--i]) >= v) { }
2838                                                                 if (i === 0 && v < this._l1) {
2839                                                                         this._l1 = 0;
2840                                                                 } else {
2841                                                                         i++;
2842                                                                 }
2843                                                                 this._l2 = lengths[i];
2844                                                                 this._li = i;
2845                                                                 this._curSeg = curSeg = this._segments[i];
2846                                                                 this._s1 = curSeg[(this._si = curSeg.length - 1) - 1] || 0;
2847                                                                 this._s2 = curSeg[this._si];
2848                                                         }
2849                                                         curIndex = i;
2850                                                         //now find the appropriate sub-segment (we split it into the number of pieces that was defined by "precision" and measured each one)
2851                                                         v -= this._l1;
2852                                                         i = this._si;
2853                                                         if (v > this._s2 && i < curSeg.length - 1) {
2854                                                                 l = curSeg.length - 1;
2855                                                                 while (i < l && (this._s2 = curSeg[++i]) <= v) {        }
2856                                                                 this._s1 = curSeg[i-1];
2857                                                                 this._si = i;
2858                                                         } else if (v < this._s1 && i > 0) {
2859                                                                 while (i > 0 && (this._s1 = curSeg[--i]) >= v) {        }
2860                                                                 if (i === 0 && v < this._s1) {
2861                                                                         this._s1 = 0;
2862                                                                 } else {
2863                                                                         i++;
2864                                                                 }
2865                                                                 this._s2 = curSeg[i];
2866                                                                 this._si = i;
2867                                                         }
2868                                                         t = (i + (v - this._s1) / (this._s2 - this._s1)) * this._prec;
2869                                                 }
2870                                                 inv = 1 - t;
2871
2872                                                 i = this._props.length;
2873                                                 while (--i > -1) {
2874                                                         p = this._props[i];
2875                                                         b = this._beziers[p][curIndex];
2876                                                         val = (t * t * b.da + 3 * inv * (t * b.ca + inv * b.ba)) * t + b.a;
2877                                                         if (this._round[p]) {
2878                                                                 val = Math.round(val);
2879                                                         }
2880                                                         if (func[p]) {
2881                                                                 target[p](val);
2882                                                         } else {
2883                                                                 target[p] = val;
2884                                                         }
2885                                                 }
2886
2887                                                 if (this._autoRotate) {
2888                                                         var ar = this._autoRotate,
2889                                                                 b2, x1, y1, x2, y2, add, conv;
2890                                                         i = ar.length;
2891                                                         while (--i > -1) {
2892                                                                 p = ar[i][2];
2893                                                                 add = ar[i][3] || 0;
2894                                                                 conv = (ar[i][4] === true) ? 1 : _RAD2DEG;
2895                                                                 b = this._beziers[ar[i][0]];
2896                                                                 b2 = this._beziers[ar[i][1]];
2897
2898                                                                 if (b && b2) { //in case one of the properties got overwritten.
2899                                                                         b = b[curIndex];
2900                                                                         b2 = b2[curIndex];
2901
2902                                                                         x1 = b.a + (b.b - b.a) * t;
2903                                                                         x2 = b.b + (b.c - b.b) * t;
2904                                                                         x1 += (x2 - x1) * t;
2905                                                                         x2 += ((b.c + (b.d - b.c) * t) - x2) * t;
2906
2907                                                                         y1 = b2.a + (b2.b - b2.a) * t;
2908                                                                         y2 = b2.b + (b2.c - b2.b) * t;
2909                                                                         y1 += (y2 - y1) * t;
2910                                                                         y2 += ((b2.c + (b2.d - b2.c) * t) - y2) * t;
2911
2912                                                                         val = notStart ? Math.atan2(y2 - y1, x2 - x1) * conv + add : this._initialRotations[i];
2913
2914                                                                         if (func[p]) {
2915                                                                                 target[p](val);
2916                                                                         } else {
2917                                                                                 target[p] = val;
2918                                                                         }
2919                                                                 }
2920                                                         }
2921                                                 }
2922                                         }
2923                         }),
2924                         p = BezierPlugin.prototype;
2925
2926
2927                 BezierPlugin.bezierThrough = bezierThrough;
2928                 BezierPlugin.cubicToQuadratic = cubicToQuadratic;
2929                 BezierPlugin._autoCSS = true; //indicates that this plugin can be inserted into the "css" object using the autoCSS feature of TweenLite
2930                 BezierPlugin.quadraticToCubic = function(a, b, c) {
2931                         return new Segment(a, (2 * b + a) / 3, (2 * b + c) / 3, c);
2932                 };
2933
2934                 BezierPlugin._cssRegister = function() {
2935                         var CSSPlugin = window._gsDefine.globals.CSSPlugin;
2936                         if (!CSSPlugin) {
2937                                 return;
2938                         }
2939                         var _internals = CSSPlugin._internals,
2940                                 _parseToProxy = _internals._parseToProxy,
2941                                 _setPluginRatio = _internals._setPluginRatio,
2942                                 CSSPropTween = _internals.CSSPropTween;
2943                         _internals._registerComplexSpecialProp("bezier", {parser:function(t, e, prop, cssp, pt, plugin) {
2944                                 if (e instanceof Array) {
2945                                         e = {values:e};
2946                                 }
2947                                 plugin = new BezierPlugin();
2948                                 var values = e.values,
2949                                         l = values.length - 1,
2950                                         pluginValues = [],
2951                                         v = {},
2952                                         i, p, data;
2953                                 if (l < 0) {
2954                                         return pt;
2955                                 }
2956                                 for (i = 0; i <= l; i++) {
2957                                         data = _parseToProxy(t, values[i], cssp, pt, plugin, (l !== i));
2958                                         pluginValues[i] = data.end;
2959                                 }
2960                                 for (p in e) {
2961                                         v[p] = e[p]; //duplicate the vars object because we need to alter some things which would cause problems if the user plans to reuse the same vars object for another tween.
2962                                 }
2963                                 v.values = pluginValues;
2964                                 pt = new CSSPropTween(t, "bezier", 0, 0, data.pt, 2);
2965                                 pt.data = data;
2966                                 pt.plugin = plugin;
2967                                 pt.setRatio = _setPluginRatio;
2968                                 if (v.autoRotate === 0) {
2969                                         v.autoRotate = true;
2970                                 }
2971                                 if (v.autoRotate && !(v.autoRotate instanceof Array)) {
2972                                         i = (v.autoRotate === true) ? 0 : Number(v.autoRotate);
2973                                         v.autoRotate = (data.end.left != null) ? [["left","top","rotation",i,false]] : (data.end.x != null) ? [["x","y","rotation",i,false]] : false;
2974                                 }
2975                                 if (v.autoRotate) {
2976                                         if (!cssp._transform) {
2977                                                 cssp._enableTransforms(false);
2978                                         }
2979                                         data.autoRotate = cssp._target._gsTransform;
2980                                 }
2981                                 plugin._onInitTween(data.proxy, v, cssp._tween);
2982                                 return pt;
2983                         }});
2984                 };
2985
2986                 p._roundProps = function(lookup, value) {
2987                         var op = this._overwriteProps,
2988                                 i = op.length;
2989                         while (--i > -1) {
2990                                 if (lookup[op[i]] || lookup.bezier || lookup.bezierThrough) {
2991                                         this._round[op[i]] = value;
2992                                 }
2993                         }
2994                 };
2995
2996                 p._kill = function(lookup) {
2997                         var a = this._props,
2998                                 p, i;
2999                         for (p in this._beziers) {
3000                                 if (p in lookup) {
3001                                         delete this._beziers[p];
3002                                         delete this._func[p];
3003                                         i = a.length;
3004                                         while (--i > -1) {
3005                                                 if (a[i] === p) {
3006                                                         a.splice(i, 1);
3007                                                 }
3008                                         }
3009                                 }
3010                         }
3011                         return this._super._kill.call(this, lookup);
3012                 };
3013
3014         }());
3015
3016
3017
3018
3019
3020
3021         
3022         
3023         
3024         
3025         
3026         
3027         
3028         
3029 /*
3030  * ----------------------------------------------------------------
3031  * CSSPlugin
3032  * ----------------------------------------------------------------
3033  */
3034         window._gsDefine("plugins.CSSPlugin", ["plugins.TweenPlugin","TweenLite"], function(TweenPlugin, TweenLite) {
3035
3036                 /** @constructor **/
3037                 var CSSPlugin = function() {
3038                                 TweenPlugin.call(this, "css");
3039                                 this._overwriteProps.length = 0;
3040                                 this.setRatio = CSSPlugin.prototype.setRatio; //speed optimization (avoid prototype lookup on this "hot" method)
3041                         },
3042                         _hasPriority, //turns true whenever a CSSPropTween instance is created that has a priority other than 0. This helps us discern whether or not we should spend the time organizing the linked list or not after a CSSPlugin's _onInitTween() method is called.
3043                         _suffixMap, //we set this in _onInitTween() each time as a way to have a persistent variable we can use in other methods like _parse() without having to pass it around as a parameter and we keep _parse() decoupled from a particular CSSPlugin instance
3044                         _cs, //computed style (we store this in a shared variable to conserve memory and make minification tighter
3045                         _overwriteProps, //alias to the currently instantiating CSSPlugin's _overwriteProps array. We use this closure in order to avoid having to pass a reference around from method to method and aid in minification.
3046                         _specialProps = {},
3047                         p = CSSPlugin.prototype = new TweenPlugin("css");
3048
3049                 p.constructor = CSSPlugin;
3050                 CSSPlugin.version = "1.12.1";
3051                 CSSPlugin.API = 2;
3052                 CSSPlugin.defaultTransformPerspective = 0;
3053                 CSSPlugin.defaultSkewType = "compensated";
3054                 p = "px"; //we'll reuse the "p" variable to keep file size down
3055                 CSSPlugin.suffixMap = {top:p, right:p, bottom:p, left:p, width:p, height:p, fontSize:p, padding:p, margin:p, perspective:p, lineHeight:""};
3056
3057
3058                 var _numExp = /(?:\d|\-\d|\.\d|\-\.\d)+/g,
3059                         _relNumExp = /(?:\d|\-\d|\.\d|\-\.\d|\+=\d|\-=\d|\+=.\d|\-=\.\d)+/g,
3060                         _valuesExp = /(?:\+=|\-=|\-|\b)[\d\-\.]+[a-zA-Z0-9]*(?:%|\b)/gi, //finds all the values that begin with numbers or += or -= and then a number. Includes suffixes. We use this to split complex values apart like "1px 5px 20px rgb(255,102,51)"
3061                         _NaNExp = /[^\d\-\.]/g,
3062                         _suffixExp = /(?:\d|\-|\+|=|#|\.)*/g,
3063                         _opacityExp = /opacity *= *([^)]*)/i,
3064                         _opacityValExp = /opacity:([^;]*)/i,
3065                         _alphaFilterExp = /alpha\(opacity *=.+?\)/i,
3066                         _rgbhslExp = /^(rgb|hsl)/,
3067                         _capsExp = /([A-Z])/g,
3068                         _camelExp = /-([a-z])/gi,
3069                         _urlExp = /(^(?:url\(\"|url\())|(?:(\"\))$|\)$)/gi, //for pulling out urls from url(...) or url("...") strings (some browsers wrap urls in quotes, some don't when reporting things like backgroundImage)
3070                         _camelFunc = function(s, g) { return g.toUpperCase(); },
3071                         _horizExp = /(?:Left|Right|Width)/i,
3072                         _ieGetMatrixExp = /(M11|M12|M21|M22)=[\d\-\.e]+/gi,
3073                         _ieSetMatrixExp = /progid\:DXImageTransform\.Microsoft\.Matrix\(.+?\)/i,
3074                         _commasOutsideParenExp = /,(?=[^\)]*(?:\(|$))/gi, //finds any commas that are not within parenthesis
3075                         _DEG2RAD = Math.PI / 180,
3076                         _RAD2DEG = 180 / Math.PI,
3077                         _forcePT = {},
3078                         _doc = document,
3079                         _tempDiv = _doc.createElement("div"),
3080                         _tempImg = _doc.createElement("img"),
3081                         _internals = CSSPlugin._internals = {_specialProps:_specialProps}, //provides a hook to a few internal methods that we need to access from inside other plugins
3082                         _agent = navigator.userAgent,
3083                         _autoRound,
3084                         _reqSafariFix, //we won't apply the Safari transform fix until we actually come across a tween that affects a transform property (to maintain best performance).
3085
3086                         _isSafari,
3087                         _isFirefox, //Firefox has a bug that causes 3D transformed elements to randomly disappear unless a repaint is forced after each update on each element.
3088                         _isSafariLT6, //Safari (and Android 4 which uses a flavor of Safari) has a bug that prevents changes to "top" and "left" properties from rendering properly if changed on the same frame as a transform UNLESS we set the element's WebkitBackfaceVisibility to hidden (weird, I know). Doing this for Android 3 and earlier seems to actually cause other problems, though (fun!)
3089                         _ieVers,
3090                         _supportsOpacity = (function() { //we set _isSafari, _ieVers, _isFirefox, and _supportsOpacity all in one function here to reduce file size slightly, especially in the minified version.
3091                                 var i = _agent.indexOf("Android"),
3092                                         d = _doc.createElement("div"), a;
3093
3094                                 _isSafari = (_agent.indexOf("Safari") !== -1 && _agent.indexOf("Chrome") === -1 && (i === -1 || Number(_agent.substr(i+8, 1)) > 3));
3095                                 _isSafariLT6 = (_isSafari && (Number(_agent.substr(_agent.indexOf("Version/")+8, 1)) < 6));
3096                                 _isFirefox = (_agent.indexOf("Firefox") !== -1);
3097
3098                                 if ((/MSIE ([0-9]{1,}[\.0-9]{0,})/).exec(_agent)) {
3099                                         _ieVers = parseFloat( RegExp.$1 );
3100                                 }
3101
3102                                 d.innerHTML = "<a style='top:1px;opacity:.55;'>a</a>";
3103                                 a = d.getElementsByTagName("a")[0];
3104                                 return a ? /^0.55/.test(a.style.opacity) : false;
3105                         }()),
3106                         _getIEOpacity = function(v) {
3107                                 return (_opacityExp.test( ((typeof(v) === "string") ? v : (v.currentStyle ? v.currentStyle.filter : v.style.filter) || "") ) ? ( parseFloat( RegExp.$1 ) / 100 ) : 1);
3108                         },
3109                         _log = function(s) {//for logging messages, but in a way that won't throw errors in old versions of IE.
3110                                 if (window.console) {
3111                                         //console.log(s);
3112                                 }
3113                         },
3114                         _prefixCSS = "", //the non-camelCase vendor prefix like "-o-", "-moz-", "-ms-", or "-webkit-"
3115                         _prefix = "", //camelCase vendor prefix like "O", "ms", "Webkit", or "Moz".
3116
3117                         // @private feed in a camelCase property name like "transform" and it will check to see if it is valid as-is or if it needs a vendor prefix. It returns the corrected camelCase property name (i.e. "WebkitTransform" or "MozTransform" or "transform" or null if no such property is found, like if the browser is IE8 or before, "transform" won't be found at all)
3118                         _checkPropPrefix = function(p, e) {
3119                                 e = e || _tempDiv;
3120                                 var s = e.style,
3121                                         a, i;
3122                                 if (s[p] !== undefined) {
3123                                         return p;
3124                                 }
3125                                 p = p.charAt(0).toUpperCase() + p.substr(1);
3126                                 a = ["O","Moz","ms","Ms","Webkit"];
3127                                 i = 5;
3128                                 while (--i > -1 && s[a[i]+p] === undefined) { }
3129                                 if (i >= 0) {
3130                                         _prefix = (i === 3) ? "ms" : a[i];
3131                                         _prefixCSS = "-" + _prefix.toLowerCase() + "-";
3132                                         return _prefix + p;
3133                                 }
3134                                 return null;
3135                         },
3136
3137                         _getComputedStyle = _doc.defaultView ? _doc.defaultView.getComputedStyle : function() {},
3138
3139                         /**
3140                          * @private Returns the css style for a particular property of an element. For example, to get whatever the current "left" css value for an element with an ID of "myElement", you could do:
3141                          * var currentLeft = CSSPlugin.getStyle( document.getElementById("myElement"), "left");
3142                          *
3143                          * @param {!Object} t Target element whose style property you want to query
3144                          * @param {!string} p Property name (like "left" or "top" or "marginTop", etc.)
3145                          * @param {Object=} cs Computed style object. This just provides a way to speed processing if you're going to get several properties on the same element in quick succession - you can reuse the result of the getComputedStyle() call.
3146                          * @param {boolean=} calc If true, the value will not be read directly from the element's "style" property (if it exists there), but instead the getComputedStyle() result will be used. This can be useful when you want to ensure that the browser itself is interpreting the value.
3147                          * @param {string=} dflt Default value that should be returned in the place of null, "none", "auto" or "auto auto".
3148                          * @return {?string} The current property value
3149                          */
3150                         _getStyle = CSSPlugin.getStyle = function(t, p, cs, calc, dflt) {
3151                                 var rv;
3152                                 if (!_supportsOpacity) if (p === "opacity") { //several versions of IE don't use the standard "opacity" property - they use things like filter:alpha(opacity=50), so we parse that here.
3153                                         return _getIEOpacity(t);
3154                                 }
3155                                 if (!calc && t.style[p]) {
3156                                         rv = t.style[p];
3157                                 } else if ((cs = cs || _getComputedStyle(t))) {
3158                                         rv = cs[p] || cs.getPropertyValue(p) || cs.getPropertyValue(p.replace(_capsExp, "-$1").toLowerCase());
3159                                 } else if (t.currentStyle) {
3160                                         rv = t.currentStyle[p];
3161                                 }
3162                                 return (dflt != null && (!rv || rv === "none" || rv === "auto" || rv === "auto auto")) ? dflt : rv;
3163                         },
3164
3165                         /**
3166                          * @private Pass the target element, the property name, the numeric value, and the suffix (like "%", "em", "px", etc.) and it will spit back the equivalent pixel number.
3167                          * @param {!Object} t Target element
3168                          * @param {!string} p Property name (like "left", "top", "marginLeft", etc.)
3169                          * @param {!number} v Value
3170                          * @param {string=} sfx Suffix (like "px" or "%" or "em")
3171                          * @param {boolean=} recurse If true, the call is a recursive one. In some browsers (like IE7/8), occasionally the value isn't accurately reported initially, but if we run the function again it will take effect.
3172                          * @return {number} value in pixels
3173                          */
3174                         _convertToPixels = _internals.convertToPixels = function(t, p, v, sfx, recurse) {
3175                                 if (sfx === "px" || !sfx) { return v; }
3176                                 if (sfx === "auto" || !v) { return 0; }
3177                                 var horiz = _horizExp.test(p),
3178                                         node = t,
3179                                         style = _tempDiv.style,
3180                                         neg = (v < 0),
3181                                         pix, cache, time;
3182                                 if (neg) {
3183                                         v = -v;
3184                                 }
3185                                 if (sfx === "%" && p.indexOf("border") !== -1) {
3186                                         pix = (v / 100) * (horiz ? t.clientWidth : t.clientHeight);
3187                                 } else {
3188                                         style.cssText = "border:0 solid red;position:" + _getStyle(t, "position") + ";line-height:0;";
3189                                         if (sfx === "%" || !node.appendChild) {
3190                                                 node = t.parentNode || _doc.body;
3191                                                 cache = node._gsCache;
3192                                                 time = TweenLite.ticker.frame;
3193                                                 if (cache && horiz && cache.time === time) { //performance optimization: we record the width of elements along with the ticker frame so that we can quickly get it again on the same tick (seems relatively safe to assume it wouldn't change on the same tick)
3194                                                         return cache.width * v / 100;
3195                                                 }
3196                                                 style[(horiz ? "width" : "height")] = v + sfx;
3197                                         } else {
3198                                                 style[(horiz ? "borderLeftWidth" : "borderTopWidth")] = v + sfx;
3199                                         }
3200                                         node.appendChild(_tempDiv);
3201                                         pix = parseFloat(_tempDiv[(horiz ? "offsetWidth" : "offsetHeight")]);
3202                                         node.removeChild(_tempDiv);
3203                                         if (horiz && sfx === "%" && CSSPlugin.cacheWidths !== false) {
3204                                                 cache = node._gsCache = node._gsCache || {};
3205                                                 cache.time = time;
3206                                                 cache.width = pix / v * 100;
3207                                         }
3208                                         if (pix === 0 && !recurse) {
3209                                                 pix = _convertToPixels(t, p, v, sfx, true);
3210                                         }
3211                                 }
3212                                 return neg ? -pix : pix;
3213                         },
3214                         _calculateOffset = _internals.calculateOffset = function(t, p, cs) { //for figuring out "top" or "left" in px when it's "auto". We need to factor in margin with the offsetLeft/offsetTop
3215                                 if (_getStyle(t, "position", cs) !== "absolute") { return 0; }
3216                                 var dim = ((p === "left") ? "Left" : "Top"),
3217                                         v = _getStyle(t, "margin" + dim, cs);
3218                                 return t["offset" + dim] - (_convertToPixels(t, p, parseFloat(v), v.replace(_suffixExp, "")) || 0);
3219                         },
3220
3221                         // @private returns at object containing ALL of the style properties in camelCase and their associated values.
3222                         _getAllStyles = function(t, cs) {
3223                                 var s = {},
3224                                         i, tr;
3225                                 if ((cs = cs || _getComputedStyle(t, null))) {
3226                                         if ((i = cs.length)) {
3227                                                 while (--i > -1) {
3228                                                         s[cs[i].replace(_camelExp, _camelFunc)] = cs.getPropertyValue(cs[i]);
3229                                                 }
3230                                         } else { //Opera behaves differently - cs.length is always 0, so we must do a for...in loop.
3231                                                 for (i in cs) {
3232                                                         s[i] = cs[i];
3233                                                 }
3234                                         }
3235                                 } else if ((cs = t.currentStyle || t.style)) {
3236                                         for (i in cs) {
3237                                                 if (typeof(i) === "string" && s[i] === undefined) {
3238                                                         s[i.replace(_camelExp, _camelFunc)] = cs[i];
3239                                                 }
3240                                         }
3241                                 }
3242                                 if (!_supportsOpacity) {
3243                                         s.opacity = _getIEOpacity(t);
3244                                 }
3245                                 tr = _getTransform(t, cs, false);
3246                                 s.rotation = tr.rotation;
3247                                 s.skewX = tr.skewX;
3248                                 s.scaleX = tr.scaleX;
3249                                 s.scaleY = tr.scaleY;
3250                                 s.x = tr.x;
3251                                 s.y = tr.y;
3252                                 if (_supports3D) {
3253                                         s.z = tr.z;
3254                                         s.rotationX = tr.rotationX;
3255                                         s.rotationY = tr.rotationY;
3256                                         s.scaleZ = tr.scaleZ;
3257                                 }
3258                                 if (s.filters) {
3259                                         delete s.filters;
3260                                 }
3261                                 return s;
3262                         },
3263
3264                         // @private analyzes two style objects (as returned by _getAllStyles()) and only looks for differences between them that contain tweenable values (like a number or color). It returns an object with a "difs" property which refers to an object containing only those isolated properties and values for tweening, and a "firstMPT" property which refers to the first MiniPropTween instance in a linked list that recorded all the starting values of the different properties so that we can revert to them at the end or beginning of the tween - we don't want the cascading to get messed up. The forceLookup parameter is an optional generic object with properties that should be forced into the results - this is necessary for className tweens that are overwriting others because imagine a scenario where a rollover/rollout adds/removes a class and the user swipes the mouse over the target SUPER fast, thus nothing actually changed yet and the subsequent comparison of the properties would indicate they match (especially when px rounding is taken into consideration), thus no tweening is necessary even though it SHOULD tween and remove those properties after the tween (otherwise the inline styles will contaminate things). See the className SpecialProp code for details.
3265                         _cssDif = function(t, s1, s2, vars, forceLookup) {
3266                                 var difs = {},
3267                                         style = t.style,
3268                                         val, p, mpt;
3269                                 for (p in s2) {
3270                                         if (p !== "cssText") if (p !== "length") if (isNaN(p)) if (s1[p] !== (val = s2[p]) || (forceLookup && forceLookup[p])) if (p.indexOf("Origin") === -1) if (typeof(val) === "number" || typeof(val) === "string") {
3271                                                 difs[p] = (val === "auto" && (p === "left" || p === "top")) ? _calculateOffset(t, p) : ((val === "" || val === "auto" || val === "none") && typeof(s1[p]) === "string" && s1[p].replace(_NaNExp, "") !== "") ? 0 : val; //if the ending value is defaulting ("" or "auto"), we check the starting value and if it can be parsed into a number (a string which could have a suffix too, like 700px), then we swap in 0 for "" or "auto" so that things actually tween.
3272                                                 if (style[p] !== undefined) { //for className tweens, we must remember which properties already existed inline - the ones that didn't should be removed when the tween isn't in progress because they were only introduced to facilitate the transition between classes.
3273                                                         mpt = new MiniPropTween(style, p, style[p], mpt);
3274                                                 }
3275                                         }
3276                                 }
3277                                 if (vars) {
3278                                         for (p in vars) { //copy properties (except className)
3279                                                 if (p !== "className") {
3280                                                         difs[p] = vars[p];
3281                                                 }
3282                                         }
3283                                 }
3284                                 return {difs:difs, firstMPT:mpt};
3285                         },
3286                         _dimensions = {width:["Left","Right"], height:["Top","Bottom"]},
3287                         _margins = ["marginLeft","marginRight","marginTop","marginBottom"],
3288
3289                         /**
3290                          * @private Gets the width or height of an element
3291                          * @param {!Object} t Target element
3292                          * @param {!string} p Property name ("width" or "height")
3293                          * @param {Object=} cs Computed style object (if one exists). Just a speed optimization.
3294                          * @return {number} Dimension (in pixels)
3295                          */
3296                         _getDimension = function(t, p, cs) {
3297                                 var v = parseFloat((p === "width") ? t.offsetWidth : t.offsetHeight),
3298                                         a = _dimensions[p],
3299                                         i = a.length;
3300                                 cs = cs || _getComputedStyle(t, null);
3301                                 while (--i > -1) {
3302                                         v -= parseFloat( _getStyle(t, "padding" + a[i], cs, true) ) || 0;
3303                                         v -= parseFloat( _getStyle(t, "border" + a[i] + "Width", cs, true) ) || 0;
3304                                 }
3305                                 return v;
3306                         },
3307
3308                         // @private Parses position-related complex strings like "top left" or "50px 10px" or "70% 20%", etc. which are used for things like transformOrigin or backgroundPosition. Optionally decorates a supplied object (recObj) with the following properties: "ox" (offsetX), "oy" (offsetY), "oxp" (if true, "ox" is a percentage not a pixel value), and "oxy" (if true, "oy" is a percentage not a pixel value)
3309                         _parsePosition = function(v, recObj) {
3310                                 if (v == null || v === "" || v === "auto" || v === "auto auto") { //note: Firefox uses "auto auto" as default whereas Chrome uses "auto".
3311                                         v = "0 0";
3312                                 }
3313                                 var a = v.split(" "),
3314                                         x = (v.indexOf("left") !== -1) ? "0%" : (v.indexOf("right") !== -1) ? "100%" : a[0],
3315                                         y = (v.indexOf("top") !== -1) ? "0%" : (v.indexOf("bottom") !== -1) ? "100%" : a[1];
3316                                 if (y == null) {
3317                                         y = "0";
3318                                 } else if (y === "center") {
3319                                         y = "50%";
3320                                 }
3321                                 if (x === "center" || (isNaN(parseFloat(x)) && (x + "").indexOf("=") === -1)) { //remember, the user could flip-flop the values and say "bottom center" or "center bottom", etc. "center" is ambiguous because it could be used to describe horizontal or vertical, hence the isNaN(). If there's an "=" sign in the value, it's relative.
3322                                         x = "50%";
3323                                 }
3324                                 if (recObj) {
3325                                         recObj.oxp = (x.indexOf("%") !== -1);
3326                                         recObj.oyp = (y.indexOf("%") !== -1);
3327                                         recObj.oxr = (x.charAt(1) === "=");
3328                                         recObj.oyr = (y.charAt(1) === "=");
3329                                         recObj.ox = parseFloat(x.replace(_NaNExp, ""));
3330                                         recObj.oy = parseFloat(y.replace(_NaNExp, ""));
3331                                 }
3332                                 return x + " " + y + ((a.length > 2) ? " " + a[2] : "");
3333                         },
3334
3335                         /**
3336                          * @private Takes an ending value (typically a string, but can be a number) and a starting value and returns the change between the two, looking for relative value indicators like += and -= and it also ignores suffixes (but make sure the ending value starts with a number or +=/-= and that the starting value is a NUMBER!)
3337                          * @param {(number|string)} e End value which is typically a string, but could be a number
3338                          * @param {(number|string)} b Beginning value which is typically a string but could be a number
3339                          * @return {number} Amount of change between the beginning and ending values (relative values that have a "+=" or "-=" are recognized)
3340                          */
3341                         _parseChange = function(e, b) {
3342                                 return (typeof(e) === "string" && e.charAt(1) === "=") ? parseInt(e.charAt(0) + "1", 10) * parseFloat(e.substr(2)) : parseFloat(e) - parseFloat(b);
3343                         },
3344
3345                         /**
3346                          * @private Takes a value and a default number, checks if the value is relative, null, or numeric and spits back a normalized number accordingly. Primarily used in the _parseTransform() function.
3347                          * @param {Object} v Value to be parsed
3348                          * @param {!number} d Default value (which is also used for relative calculations if "+=" or "-=" is found in the first parameter)
3349                          * @return {number} Parsed value
3350                          */
3351                         _parseVal = function(v, d) {
3352                                 return (v == null) ? d : (typeof(v) === "string" && v.charAt(1) === "=") ? parseInt(v.charAt(0) + "1", 10) * Number(v.substr(2)) + d : parseFloat(v);
3353                         },
3354
3355                         /**
3356                          * @private Translates strings like "40deg" or "40" or 40rad" or "+=40deg" or "270_short" or "-90_cw" or "+=45_ccw" to a numeric radian angle. Of course a starting/default value must be fed in too so that relative values can be calculated properly.
3357                          * @param {Object} v Value to be parsed
3358                          * @param {!number} d Default value (which is also used for relative calculations if "+=" or "-=" is found in the first parameter)
3359                          * @param {string=} p property name for directionalEnd (optional - only used when the parsed value is directional ("_short", "_cw", or "_ccw" suffix). We need a way to store the uncompensated value so that at the end of the tween, we set it to exactly what was requested with no directional compensation). Property name would be "rotation", "rotationX", or "rotationY"
3360                          * @param {Object=} directionalEnd An object that will store the raw end values for directional angles ("_short", "_cw", or "_ccw" suffix). We need a way to store the uncompensated value so that at the end of the tween, we set it to exactly what was requested with no directional compensation.
3361                          * @return {number} parsed angle in radians
3362                          */
3363                         _parseAngle = function(v, d, p, directionalEnd) {
3364                                 var min = 0.000001,
3365                                         cap, split, dif, result;
3366                                 if (v == null) {
3367                                         result = d;
3368                                 } else if (typeof(v) === "number") {
3369                                         result = v;
3370                                 } else {
3371                                         cap = 360;
3372                                         split = v.split("_");
3373                                         dif = Number(split[0].replace(_NaNExp, "")) * ((v.indexOf("rad") === -1) ? 1 : _RAD2DEG) - ((v.charAt(1) === "=") ? 0 : d);
3374                                         if (split.length) {
3375                                                 if (directionalEnd) {
3376                                                         directionalEnd[p] = d + dif;
3377                                                 }
3378                                                 if (v.indexOf("short") !== -1) {
3379                                                         dif = dif % cap;
3380                                                         if (dif !== dif % (cap / 2)) {
3381                                                                 dif = (dif < 0) ? dif + cap : dif - cap;
3382                                                         }
3383                                                 }
3384                                                 if (v.indexOf("_cw") !== -1 && dif < 0) {
3385                                                         dif = ((dif + cap * 9999999999) % cap) - ((dif / cap) | 0) * cap;
3386                                                 } else if (v.indexOf("ccw") !== -1 && dif > 0) {
3387                                                         dif = ((dif - cap * 9999999999) % cap) - ((dif / cap) | 0) * cap;
3388                                                 }
3389                                         }
3390                                         result = d + dif;
3391                                 }
3392                                 if (result < min && result > -min) {
3393                                         result = 0;
3394                                 }
3395                                 return result;
3396                         },
3397
3398                         _colorLookup = {aqua:[0,255,255],
3399                                 lime:[0,255,0],
3400                                 silver:[192,192,192],
3401                                 black:[0,0,0],
3402                                 maroon:[128,0,0],
3403                                 teal:[0,128,128],
3404                                 blue:[0,0,255],
3405                                 navy:[0,0,128],
3406                                 white:[255,255,255],
3407                                 fuchsia:[255,0,255],
3408                                 olive:[128,128,0],
3409                                 yellow:[255,255,0],
3410                                 orange:[255,165,0],
3411                                 gray:[128,128,128],
3412                                 purple:[128,0,128],
3413                                 green:[0,128,0],
3414                                 red:[255,0,0],
3415                                 pink:[255,192,203],
3416                                 cyan:[0,255,255],
3417                                 transparent:[255,255,255,0]},
3418
3419                         _hue = function(h, m1, m2) {
3420                                 h = (h < 0) ? h + 1 : (h > 1) ? h - 1 : h;
3421                                 return ((((h * 6 < 1) ? m1 + (m2 - m1) * h * 6 : (h < 0.5) ? m2 : (h * 3 < 2) ? m1 + (m2 - m1) * (2 / 3 - h) * 6 : m1) * 255) + 0.5) | 0;
3422                         },
3423
3424                         /**
3425                          * @private Parses a color (like #9F0, #FF9900, or rgb(255,51,153)) into an array with 3 elements for red, green, and blue. Also handles rgba() values (splits into array of 4 elements of course)
3426                          * @param {(string|number)} v The value the should be parsed which could be a string like #9F0 or rgb(255,102,51) or rgba(255,0,0,0.5) or it could be a number like 0xFF00CC or even a named color like red, blue, purple, etc.
3427                          * @return {Array.<number>} An array containing red, green, and blue (and optionally alpha) in that order.
3428                          */
3429                         _parseColor = function(v) {
3430                                 var c1, c2, c3, h, s, l;
3431                                 if (!v || v === "") {
3432                                         return _colorLookup.black;
3433                                 }
3434                                 if (typeof(v) === "number") {
3435                                         return [v >> 16, (v >> 8) & 255, v & 255];
3436                                 }
3437                                 if (v.charAt(v.length - 1) === ",") { //sometimes a trailing commma is included and we should chop it off (typically from a comma-delimited list of values like a textShadow:"2px 2px 2px blue, 5px 5px 5px rgb(255,0,0)" - in this example "blue," has a trailing comma. We could strip it out inside parseComplex() but we'd need to do it to the beginning and ending values plus it wouldn't provide protection from other potential scenarios like if the user passes in a similar value.
3438                                         v = v.substr(0, v.length - 1);
3439                                 }
3440                                 if (_colorLookup[v]) {
3441                                         return _colorLookup[v];
3442                                 }
3443                                 if (v.charAt(0) === "#") {
3444                                         if (v.length === 4) { //for shorthand like #9F0
3445                                                 c1 = v.charAt(1),
3446                                                 c2 = v.charAt(2),
3447                                                 c3 = v.charAt(3);
3448                                                 v = "#" + c1 + c1 + c2 + c2 + c3 + c3;
3449                                         }
3450                                         v = parseInt(v.substr(1), 16);
3451                                         return [v >> 16, (v >> 8) & 255, v & 255];
3452                                 }
3453                                 if (v.substr(0, 3) === "hsl") {
3454                                         v = v.match(_numExp);
3455                                         h = (Number(v[0]) % 360) / 360;
3456                                         s = Number(v[1]) / 100;
3457                                         l = Number(v[2]) / 100;
3458                                         c2 = (l <= 0.5) ? l * (s + 1) : l + s - l * s;
3459                                         c1 = l * 2 - c2;
3460                                         if (v.length > 3) {
3461                                                 v[3] = Number(v[3]);
3462                                         }
3463                                         v[0] = _hue(h + 1 / 3, c1, c2);
3464                                         v[1] = _hue(h, c1, c2);
3465                                         v[2] = _hue(h - 1 / 3, c1, c2);
3466                                         return v;
3467                                 }
3468                                 v = v.match(_numExp) || _colorLookup.transparent;
3469                                 v[0] = Number(v[0]);
3470                                 v[1] = Number(v[1]);
3471                                 v[2] = Number(v[2]);
3472                                 if (v.length > 3) {
3473                                         v[3] = Number(v[3]);
3474                                 }
3475                                 return v;
3476                         },
3477                         _colorExp = "(?:\\b(?:(?:rgb|rgba|hsl|hsla)\\(.+?\\))|\\B#.+?\\b"; //we'll dynamically build this Regular Expression to conserve file size. After building it, it will be able to find rgb(), rgba(), # (hexadecimal), and named color values like red, blue, purple, etc.
3478
3479                 for (p in _colorLookup) {
3480                         _colorExp += "|" + p + "\\b";
3481                 }
3482                 _colorExp = new RegExp(_colorExp+")", "gi");
3483
3484                 /**
3485                  * @private Returns a formatter function that handles taking a string (or number in some cases) and returning a consistently formatted one in terms of delimiters, quantity of values, etc. For example, we may get boxShadow values defined as "0px red" or "0px 0px 10px rgb(255,0,0)" or "0px 0px 20px 20px #F00" and we need to ensure that what we get back is described with 4 numbers and a color. This allows us to feed it into the _parseComplex() method and split the values up appropriately. The neat thing about this _getFormatter() function is that the dflt defines a pattern as well as a default, so for example, _getFormatter("0px 0px 0px 0px #777", true) not only sets the default as 0px for all distances and #777 for the color, but also sets the pattern such that 4 numbers and a color will always get returned.
3486                  * @param {!string} dflt The default value and pattern to follow. So "0px 0px 0px 0px #777" will ensure that 4 numbers and a color will always get returned.
3487                  * @param {boolean=} clr If true, the values should be searched for color-related data. For example, boxShadow values typically contain a color whereas borderRadius don't.
3488                  * @param {boolean=} collapsible If true, the value is a top/left/right/bottom style one that acts like margin or padding, where if only one value is received, it's used for all 4; if 2 are received, the first is duplicated for 3rd (bottom) and the 2nd is duplicated for the 4th spot (left), etc.
3489                  * @return {Function} formatter function
3490                  */
3491                 var _getFormatter = function(dflt, clr, collapsible, multi) {
3492                                 if (dflt == null) {
3493                                         return function(v) {return v;};
3494                                 }
3495                                 var dColor = clr ? (dflt.match(_colorExp) || [""])[0] : "",
3496                                         dVals = dflt.split(dColor).join("").match(_valuesExp) || [],
3497                                         pfx = dflt.substr(0, dflt.indexOf(dVals[0])),
3498                                         sfx = (dflt.charAt(dflt.length - 1) === ")") ? ")" : "",
3499                                         delim = (dflt.indexOf(" ") !== -1) ? " " : ",",
3500                                         numVals = dVals.length,
3501                                         dSfx = (numVals > 0) ? dVals[0].replace(_numExp, "") : "",
3502                                         formatter;
3503                                 if (!numVals) {
3504                                         return function(v) {return v;};
3505                                 }
3506                                 if (clr) {
3507                                         formatter = function(v) {
3508                                                 var color, vals, i, a;
3509                                                 if (typeof(v) === "number") {
3510                                                         v += dSfx;
3511                                                 } else if (multi && _commasOutsideParenExp.test(v)) {
3512                                                         a = v.replace(_commasOutsideParenExp, "|").split("|");
3513                                                         for (i = 0; i < a.length; i++) {
3514                                                                 a[i] = formatter(a[i]);
3515                                                         }
3516                                                         return a.join(",");
3517                                                 }
3518                                                 color = (v.match(_colorExp) || [dColor])[0];
3519                                                 vals = v.split(color).join("").match(_valuesExp) || [];
3520                                                 i = vals.length;
3521                                                 if (numVals > i--) {
3522                                                         while (++i < numVals) {
3523                                                                 vals[i] = collapsible ? vals[(((i - 1) / 2) | 0)] : dVals[i];
3524                                                         }
3525                                                 }
3526                                                 return pfx + vals.join(delim) + delim + color + sfx + (v.indexOf("inset") !== -1 ? " inset" : "");
3527                                         };
3528                                         return formatter;
3529
3530                                 }
3531                                 formatter = function(v) {
3532                                         var vals, a, i;
3533                                         if (typeof(v) === "number") {
3534                                                 v += dSfx;
3535                                         } else if (multi && _commasOutsideParenExp.test(v)) {
3536                                                 a = v.replace(_commasOutsideParenExp, "|").split("|");
3537                                                 for (i = 0; i < a.length; i++) {
3538                                                         a[i] = formatter(a[i]);
3539                                                 }
3540                                                 return a.join(",");
3541                                         }
3542                                         vals = v.match(_valuesExp) || [];
3543                                         i = vals.length;
3544                                         if (numVals > i--) {
3545                                                 while (++i < numVals) {
3546                                                         vals[i] = collapsible ? vals[(((i - 1) / 2) | 0)] : dVals[i];
3547                                                 }
3548                                         }
3549                                         return pfx + vals.join(delim) + sfx;
3550                                 };
3551                                 return formatter;
3552                         },
3553
3554                         /**
3555                          * @private returns a formatter function that's used for edge-related values like marginTop, marginLeft, paddingBottom, paddingRight, etc. Just pass a comma-delimited list of property names related to the edges.
3556                          * @param {!string} props a comma-delimited list of property names in order from top to left, like "marginTop,marginRight,marginBottom,marginLeft"
3557                          * @return {Function} a formatter function
3558                          */
3559                         _getEdgeParser = function(props) {
3560                                 props = props.split(",");
3561                                 return function(t, e, p, cssp, pt, plugin, vars) {
3562                                         var a = (e + "").split(" "),
3563                                                 i;
3564                                         vars = {};
3565                                         for (i = 0; i < 4; i++) {
3566                                                 vars[props[i]] = a[i] = a[i] || a[(((i - 1) / 2) >> 0)];
3567                                         }
3568                                         return cssp.parse(t, vars, pt, plugin);
3569                                 };
3570                         },
3571
3572                         // @private used when other plugins must tween values first, like BezierPlugin or ThrowPropsPlugin, etc. That plugin's setRatio() gets called first so that the values are updated, and then we loop through the MiniPropTweens  which handle copying the values into their appropriate slots so that they can then be applied correctly in the main CSSPlugin setRatio() method. Remember, we typically create a proxy object that has a bunch of uniquely-named properties that we feed to the sub-plugin and it does its magic normally, and then we must interpret those values and apply them to the css because often numbers must get combined/concatenated, suffixes added, etc. to work with css, like boxShadow could have 4 values plus a color.
3573                         _setPluginRatio = _internals._setPluginRatio = function(v) {
3574                                 this.plugin.setRatio(v);
3575                                 var d = this.data,
3576                                         proxy = d.proxy,
3577                                         mpt = d.firstMPT,
3578                                         min = 0.000001,
3579                                         val, pt, i, str;
3580                                 while (mpt) {
3581                                         val = proxy[mpt.v];
3582                                         if (mpt.r) {
3583                                                 val = Math.round(val);
3584                                         } else if (val < min && val > -min) {
3585                                                 val = 0;
3586                                         }
3587                                         mpt.t[mpt.p] = val;
3588                                         mpt = mpt._next;
3589                                 }
3590                                 if (d.autoRotate) {
3591                                         d.autoRotate.rotation = proxy.rotation;
3592                                 }
3593                                 //at the end, we must set the CSSPropTween's "e" (end) value dynamically here because that's what is used in the final setRatio() method.
3594                                 if (v === 1) {
3595                                         mpt = d.firstMPT;
3596                                         while (mpt) {
3597                                                 pt = mpt.t;
3598                                                 if (!pt.type) {
3599                                                         pt.e = pt.s + pt.xs0;
3600                                                 } else if (pt.type === 1) {
3601                                                         str = pt.xs0 + pt.s + pt.xs1;
3602                                                         for (i = 1; i < pt.l; i++) {
3603                                                                 str += pt["xn"+i] + pt["xs"+(i+1)];
3604                                                         }
3605                                                         pt.e = str;
3606                                                 }
3607                                                 mpt = mpt._next;
3608                                         }
3609                                 }
3610                         },
3611
3612                         /**
3613                          * @private @constructor Used by a few SpecialProps to hold important values for proxies. For example, _parseToProxy() creates a MiniPropTween instance for each property that must get tweened on the proxy, and we record the original property name as well as the unique one we create for the proxy, plus whether or not the value needs to be rounded plus the original value.
3614                          * @param {!Object} t target object whose property we're tweening (often a CSSPropTween)
3615                          * @param {!string} p property name
3616                          * @param {(number|string|object)} v value
3617                          * @param {MiniPropTween=} next next MiniPropTween in the linked list
3618                          * @param {boolean=} r if true, the tweened value should be rounded to the nearest integer
3619                          */
3620                         MiniPropTween = function(t, p, v, next, r) {
3621                                 this.t = t;
3622                                 this.p = p;
3623                                 this.v = v;
3624                                 this.r = r;
3625                                 if (next) {
3626                                         next._prev = this;
3627                                         this._next = next;
3628                                 }
3629                         },
3630
3631                         /**
3632                          * @private Most other plugins (like BezierPlugin and ThrowPropsPlugin and others) can only tween numeric values, but CSSPlugin must accommodate special values that have a bunch of extra data (like a suffix or strings between numeric values, etc.). For example, boxShadow has values like "10px 10px 20px 30px rgb(255,0,0)" which would utterly confuse other plugins. This method allows us to split that data apart and grab only the numeric data and attach it to uniquely-named properties of a generic proxy object ({}) so that we can feed that to virtually any plugin to have the numbers tweened. However, we must also keep track of which properties from the proxy go with which CSSPropTween values and instances. So we create a linked list of MiniPropTweens. Each one records a target (the original CSSPropTween), property (like "s" or "xn1" or "xn2") that we're tweening and the unique property name that was used for the proxy (like "boxShadow_xn1" and "boxShadow_xn2") and whether or not they need to be rounded. That way, in the _setPluginRatio() method we can simply copy the values over from the proxy to the CSSPropTween instance(s). Then, when the main CSSPlugin setRatio() method runs and applies the CSSPropTween values accordingly, they're updated nicely. So the external plugin tweens the numbers, _setPluginRatio() copies them over, and setRatio() acts normally, applying css-specific values to the element.
3633                          * This method returns an object that has the following properties:
3634                          *  - proxy: a generic object containing the starting values for all the properties that will be tweened by the external plugin.  This is what we feed to the external _onInitTween() as the target
3635                          *  - end: a generic object containing the ending values for all the properties that will be tweened by the external plugin. This is what we feed to the external plugin's _onInitTween() as the destination values
3636                          *  - firstMPT: the first MiniPropTween in the linked list
3637                          *  - pt: the first CSSPropTween in the linked list that was created when parsing. If shallow is true, this linked list will NOT attach to the one passed into the _parseToProxy() as the "pt" (4th) parameter.
3638                          * @param {!Object} t target object to be tweened
3639                          * @param {!(Object|string)} vars the object containing the information about the tweening values (typically the end/destination values) that should be parsed
3640                          * @param {!CSSPlugin} cssp The CSSPlugin instance
3641                          * @param {CSSPropTween=} pt the next CSSPropTween in the linked list
3642                          * @param {TweenPlugin=} plugin the external TweenPlugin instance that will be handling tweening the numeric values
3643                          * @param {boolean=} shallow if true, the resulting linked list from the parse will NOT be attached to the CSSPropTween that was passed in as the "pt" (4th) parameter.
3644                          * @return An object containing the following properties: proxy, end, firstMPT, and pt (see above for descriptions)
3645                          */
3646                         _parseToProxy = _internals._parseToProxy = function(t, vars, cssp, pt, plugin, shallow) {
3647                                 var bpt = pt,
3648                                         start = {},
3649                                         end = {},
3650                                         transform = cssp._transform,
3651                                         oldForce = _forcePT,
3652                                         i, p, xp, mpt, firstPT;
3653                                 cssp._transform = null;
3654                                 _forcePT = vars;
3655                                 pt = firstPT = cssp.parse(t, vars, pt, plugin);
3656                                 _forcePT = oldForce;
3657                                 //break off from the linked list so the new ones are isolated.
3658                                 if (shallow) {
3659                                         cssp._transform = transform;
3660                                         if (bpt) {
3661                                                 bpt._prev = null;
3662                                                 if (bpt._prev) {
3663                                                         bpt._prev._next = null;
3664                                                 }
3665                                         }
3666                                 }
3667                                 while (pt && pt !== bpt) {
3668                                         if (pt.type <= 1) {
3669                                                 p = pt.p;
3670                                                 end[p] = pt.s + pt.c;
3671                                                 start[p] = pt.s;
3672                                                 if (!shallow) {
3673                                                         mpt = new MiniPropTween(pt, "s", p, mpt, pt.r);
3674                                                         pt.c = 0;
3675                                                 }
3676                                                 if (pt.type === 1) {
3677                                                         i = pt.l;
3678                                                         while (--i > 0) {
3679                                                                 xp = "xn" + i;
3680                                                                 p = pt.p + "_" + xp;
3681                                                                 end[p] = pt.data[xp];
3682                                                                 start[p] = pt[xp];
3683                                                                 if (!shallow) {
3684                                                                         mpt = new MiniPropTween(pt, xp, p, mpt, pt.rxp[xp]);
3685                                                                 }
3686                                                         }
3687                                                 }
3688                                         }
3689                                         pt = pt._next;
3690                                 }
3691                                 return {proxy:start, end:end, firstMPT:mpt, pt:firstPT};
3692                         },
3693
3694
3695
3696                         /**
3697                          * @constructor Each property that is tweened has at least one CSSPropTween associated with it. These instances store important information like the target, property, starting value, amount of change, etc. They can also optionally have a number of "extra" strings and numeric values named xs1, xn1, xs2, xn2, xs3, xn3, etc. where "s" indicates string and "n" indicates number. These can be pieced together in a complex-value tween (type:1) that has alternating types of data like a string, number, string, number, etc. For example, boxShadow could be "5px 5px 8px rgb(102, 102, 51)". In that value, there are 6 numbers that may need to tween and then pieced back together into a string again with spaces, suffixes, etc. xs0 is special in that it stores the suffix for standard (type:0) tweens, -OR- the first string (prefix) in a complex-value (type:1) CSSPropTween -OR- it can be the non-tweening value in a type:-1 CSSPropTween. We do this to conserve memory.
3698                          * CSSPropTweens have the following optional properties as well (not defined through the constructor):
3699                          *  - l: Length in terms of the number of extra properties that the CSSPropTween has (default: 0). For example, for a boxShadow we may need to tween 5 numbers in which case l would be 5; Keep in mind that the start/end values for the first number that's tweened are always stored in the s and c properties to conserve memory. All additional values thereafter are stored in xn1, xn2, etc.
3700                          *  - xfirst: The first instance of any sub-CSSPropTweens that are tweening properties of this instance. For example, we may split up a boxShadow tween so that there's a main CSSPropTween of type:1 that has various xs* and xn* values associated with the h-shadow, v-shadow, blur, color, etc. Then we spawn a CSSPropTween for each of those that has a higher priority and runs BEFORE the main CSSPropTween so that the values are all set by the time it needs to re-assemble them. The xfirst gives us an easy way to identify the first one in that chain which typically ends at the main one (because they're all prepende to the linked list)
3701                          *  - plugin: The TweenPlugin instance that will handle the tweening of any complex values. For example, sometimes we don't want to use normal subtweens (like xfirst refers to) to tween the values - we might want ThrowPropsPlugin or BezierPlugin some other plugin to do the actual tweening, so we create a plugin instance and store a reference here. We need this reference so that if we get a request to round values or disable a tween, we can pass along that request.
3702                          *  - data: Arbitrary data that needs to be stored with the CSSPropTween. Typically if we're going to have a plugin handle the tweening of a complex-value tween, we create a generic object that stores the END values that we're tweening to and the CSSPropTween's xs1, xs2, etc. have the starting values. We store that object as data. That way, we can simply pass that object to the plugin and use the CSSPropTween as the target.
3703                          *  - setRatio: Only used for type:2 tweens that require custom functionality. In this case, we call the CSSPropTween's setRatio() method and pass the ratio each time the tween updates. This isn't quite as efficient as doing things directly in the CSSPlugin's setRatio() method, but it's very convenient and flexible.
3704                          * @param {!Object} t Target object whose property will be tweened. Often a DOM element, but not always. It could be anything.
3705                          * @param {string} p Property to tween (name). For example, to tween element.width, p would be "width".
3706                          * @param {number} s Starting numeric value
3707                          * @param {number} c Change in numeric value over the course of the entire tween. For example, if element.width starts at 5 and should end at 100, c would be 95.
3708                          * @param {CSSPropTween=} next The next CSSPropTween in the linked list. If one is defined, we will define its _prev as the new instance, and the new instance's _next will be pointed at it.
3709                          * @param {number=} type The type of CSSPropTween where -1 = a non-tweening value, 0 = a standard simple tween, 1 = a complex value (like one that has multiple numbers in a comma- or space-delimited string like border:"1px solid red"), and 2 = one that uses a custom setRatio function that does all of the work of applying the values on each update.
3710                          * @param {string=} n Name of the property that should be used for overwriting purposes which is typically the same as p but not always. For example, we may need to create a subtween for the 2nd part of a "clip:rect(...)" tween in which case "p" might be xs1 but "n" is still "clip"
3711                          * @param {boolean=} r If true, the value(s) should be rounded
3712                          * @param {number=} pr Priority in the linked list order. Higher priority CSSPropTweens will be updated before lower priority ones. The default priority is 0.
3713                          * @param {string=} b Beginning value. We store this to ensure that it is EXACTLY what it was when the tween began without any risk of interpretation issues.
3714                          * @param {string=} e Ending value. We store this to ensure that it is EXACTLY what the user defined at the end of the tween without any risk of interpretation issues.
3715                          */
3716                         CSSPropTween = _internals.CSSPropTween = function(t, p, s, c, next, type, n, r, pr, b, e) {
3717                                 this.t = t; //target
3718                                 this.p = p; //property
3719                                 this.s = s; //starting value
3720                                 this.c = c; //change value
3721                                 this.n = n || p; //name that this CSSPropTween should be associated to (usually the same as p, but not always - n is what overwriting looks at)
3722                                 if (!(t instanceof CSSPropTween)) {
3723                                         _overwriteProps.push(this.n);
3724                                 }
3725                                 this.r = r; //round (boolean)
3726                                 this.type = type || 0; //0 = normal tween, -1 = non-tweening (in which case xs0 will be applied to the target's property, like tp.t[tp.p] = tp.xs0), 1 = complex-value SpecialProp, 2 = custom setRatio() that does all the work
3727                                 if (pr) {
3728                                         this.pr = pr;
3729                                         _hasPriority = true;
3730                                 }
3731                                 this.b = (b === undefined) ? s : b;
3732                                 this.e = (e === undefined) ? s + c : e;
3733                                 if (next) {
3734                                         this._next = next;
3735                                         next._prev = this;
3736                                 }
3737                         },
3738
3739                         /**
3740                          * Takes a target, the beginning value and ending value (as strings) and parses them into a CSSPropTween (possibly with child CSSPropTweens) that accommodates multiple numbers, colors, comma-delimited values, etc. For example:
3741                          * sp.parseComplex(element, "boxShadow", "5px 10px 20px rgb(255,102,51)", "0px 0px 0px red", true, "0px 0px 0px rgb(0,0,0,0)", pt);
3742                          * It will walk through the beginning and ending values (which should be in the same format with the same number and type of values) and figure out which parts are numbers, what strings separate the numeric/tweenable values, and then create the CSSPropTweens accordingly. If a plugin is defined, no child CSSPropTweens will be created. Instead, the ending values will be stored in the "data" property of the returned CSSPropTween like: {s:-5, xn1:-10, xn2:-20, xn3:255, xn4:0, xn5:0} so that it can be fed to any other plugin and it'll be plain numeric tweens but the recomposition of the complex value will be handled inside CSSPlugin's setRatio().
3743                          * If a setRatio is defined, the type of the CSSPropTween will be set to 2 and recomposition of the values will be the responsibility of that method.
3744                          *
3745                          * @param {!Object} t Target whose property will be tweened
3746                          * @param {!string} p Property that will be tweened (its name, like "left" or "backgroundColor" or "boxShadow")
3747                          * @param {string} b Beginning value
3748                          * @param {string} e Ending value
3749                          * @param {boolean} clrs If true, the value could contain a color value like "rgb(255,0,0)" or "#F00" or "red". The default is false, so no colors will be recognized (a performance optimization)
3750                          * @param {(string|number|Object)} dflt The default beginning value that should be used if no valid beginning value is defined or if the number of values inside the complex beginning and ending values don't match
3751                          * @param {?CSSPropTween} pt CSSPropTween instance that is the current head of the linked list (we'll prepend to this).
3752                          * @param {number=} pr Priority in the linked list order. Higher priority properties will be updated before lower priority ones. The default priority is 0.
3753                          * @param {TweenPlugin=} plugin If a plugin should handle the tweening of extra properties, pass the plugin instance here. If one is defined, then NO subtweens will be created for any extra properties (the properties will be created - just not additional CSSPropTween instances to tween them) because the plugin is expected to do so. However, the end values WILL be populated in the "data" property, like {s:100, xn1:50, xn2:300}
3754                          * @param {function(number)=} setRatio If values should be set in a custom function instead of being pieced together in a type:1 (complex-value) CSSPropTween, define that custom function here.
3755                          * @return {CSSPropTween} The first CSSPropTween in the linked list which includes the new one(s) added by the parseComplex() call.
3756                          */
3757                         _parseComplex = CSSPlugin.parseComplex = function(t, p, b, e, clrs, dflt, pt, pr, plugin, setRatio) {
3758                                 //DEBUG: _log("parseComplex: "+p+", b: "+b+", e: "+e);
3759                                 b = b || dflt || "";
3760                                 pt = new CSSPropTween(t, p, 0, 0, pt, (setRatio ? 2 : 1), null, false, pr, b, e);
3761                                 e += ""; //ensures it's a string
3762                                 var ba = b.split(", ").join(",").split(" "), //beginning array
3763                                         ea = e.split(", ").join(",").split(" "), //ending array
3764                                         l = ba.length,
3765                                         autoRound = (_autoRound !== false),
3766                                         i, xi, ni, bv, ev, bnums, enums, bn, rgba, temp, cv, str;
3767                                 if (e.indexOf(",") !== -1 || b.indexOf(",") !== -1) {
3768                                         ba = ba.join(" ").replace(_commasOutsideParenExp, ", ").split(" ");
3769                                         ea = ea.join(" ").replace(_commasOutsideParenExp, ", ").split(" ");
3770                                         l = ba.length;
3771                                 }
3772                                 if (l !== ea.length) {
3773                                         //DEBUG: _log("mismatched formatting detected on " + p + " (" + b + " vs " + e + ")");
3774                                         ba = (dflt || "").split(" ");
3775                                         l = ba.length;
3776                                 }
3777                                 pt.plugin = plugin;
3778                                 pt.setRatio = setRatio;
3779                                 for (i = 0; i < l; i++) {
3780                                         bv = ba[i];
3781                                         ev = ea[i];
3782                                         bn = parseFloat(bv);
3783
3784                                         //if the value begins with a number (most common). It's fine if it has a suffix like px
3785                                         if (bn || bn === 0) {
3786                                                 pt.appendXtra("", bn, _parseChange(ev, bn), ev.replace(_relNumExp, ""), (autoRound && ev.indexOf("px") !== -1), true);
3787
3788                                         //if the value is a color
3789                                         } else if (clrs && (bv.charAt(0) === "#" || _colorLookup[bv] || _rgbhslExp.test(bv))) {
3790                                                 str = ev.charAt(ev.length - 1) === "," ? ")," : ")"; //if there's a comma at the end, retain it.
3791                                                 bv = _parseColor(bv);
3792                                                 ev = _parseColor(ev);
3793                                                 rgba = (bv.length + ev.length > 6);
3794                                                 if (rgba && !_supportsOpacity && ev[3] === 0) { //older versions of IE don't support rgba(), so if the destination alpha is 0, just use "transparent" for the end color
3795                                                         pt["xs" + pt.l] += pt.l ? " transparent" : "transparent";
3796                                                         pt.e = pt.e.split(ea[i]).join("transparent");
3797                                                 } else {
3798                                                         if (!_supportsOpacity) { //old versions of IE don't support rgba().
3799                                                                 rgba = false;
3800                                                         }
3801                                                         pt.appendXtra((rgba ? "rgba(" : "rgb("), bv[0], ev[0] - bv[0], ",", true, true)
3802                                                                 .appendXtra("", bv[1], ev[1] - bv[1], ",", true)
3803                                                                 .appendXtra("", bv[2], ev[2] - bv[2], (rgba ? "," : str), true);
3804                                                         if (rgba) {
3805                                                                 bv = (bv.length < 4) ? 1 : bv[3];
3806                                                                 pt.appendXtra("", bv, ((ev.length < 4) ? 1 : ev[3]) - bv, str, false);
3807                                                         }
3808                                                 }
3809
3810                                         } else {
3811                                                 bnums = bv.match(_numExp); //gets each group of numbers in the beginning value string and drops them into an array
3812
3813                                                 //if no number is found, treat it as a non-tweening value and just append the string to the current xs.
3814                                                 if (!bnums) {
3815                                                         pt["xs" + pt.l] += pt.l ? " " + bv : bv;
3816
3817                                                 //loop through all the numbers that are found and construct the extra values on the pt.
3818                                                 } else {
3819                                                         enums = ev.match(_relNumExp); //get each group of numbers in the end value string and drop them into an array. We allow relative values too, like +=50 or -=.5
3820                                                         if (!enums || enums.length !== bnums.length) {
3821                                                                 //DEBUG: _log("mismatched formatting detected on " + p + " (" + b + " vs " + e + ")");
3822                                                                 return pt;
3823                                                         }
3824                                                         ni = 0;
3825                                                         for (xi = 0; xi < bnums.length; xi++) {
3826                                                                 cv = bnums[xi];
3827                                                                 temp = bv.indexOf(cv, ni);
3828                                                                 pt.appendXtra(bv.substr(ni, temp - ni), Number(cv), _parseChange(enums[xi], cv), "", (autoRound && bv.substr(temp + cv.length, 2) === "px"), (xi === 0));
3829                                                                 ni = temp + cv.length;
3830                                                         }
3831                                                         pt["xs" + pt.l] += bv.substr(ni);
3832                                                 }
3833                                         }
3834                                 }
3835                                 //if there are relative values ("+=" or "-=" prefix), we need to adjust the ending value to eliminate the prefixes and combine the values properly.
3836                                 if (e.indexOf("=") !== -1) if (pt.data) {
3837                                         str = pt.xs0 + pt.data.s;
3838                                         for (i = 1; i < pt.l; i++) {
3839                                                 str += pt["xs" + i] + pt.data["xn" + i];
3840                                         }
3841                                         pt.e = str + pt["xs" + i];
3842                                 }
3843                                 if (!pt.l) {
3844                                         pt.type = -1;
3845                                         pt.xs0 = pt.e;
3846                                 }
3847                                 return pt.xfirst || pt;
3848                         },
3849                         i = 9;
3850
3851
3852                 p = CSSPropTween.prototype;
3853                 p.l = p.pr = 0; //length (number of extra properties like xn1, xn2, xn3, etc.
3854                 while (--i > 0) {
3855                         p["xn" + i] = 0;
3856                         p["xs" + i] = "";
3857                 }
3858                 p.xs0 = "";
3859                 p._next = p._prev = p.xfirst = p.data = p.plugin = p.setRatio = p.rxp = null;
3860
3861
3862                 /**
3863                  * Appends and extra tweening value to a CSSPropTween and automatically manages any prefix and suffix strings. The first extra value is stored in the s and c of the main CSSPropTween instance, but thereafter any extras are stored in the xn1, xn2, xn3, etc. The prefixes and suffixes are stored in the xs0, xs1, xs2, etc. properties. For example, if I walk through a clip value like "rect(10px, 5px, 0px, 20px)", the values would be stored like this:
3864                  * xs0:"rect(", s:10, xs1:"px, ", xn1:5, xs2:"px, ", xn2:0, xs3:"px, ", xn3:20, xn4:"px)"
3865                  * And they'd all get joined together when the CSSPlugin renders (in the setRatio() method).
3866                  * @param {string=} pfx Prefix (if any)
3867                  * @param {!number} s Starting value
3868                  * @param {!number} c Change in numeric value over the course of the entire tween. For example, if the start is 5 and the end is 100, the change would be 95.
3869                  * @param {string=} sfx Suffix (if any)
3870                  * @param {boolean=} r Round (if true).
3871                  * @param {boolean=} pad If true, this extra value should be separated by the previous one by a space. If there is no previous extra and pad is true, it will automatically drop the space.
3872                  * @return {CSSPropTween} returns itself so that multiple methods can be chained together.
3873                  */
3874                 p.appendXtra = function(pfx, s, c, sfx, r, pad) {
3875                         var pt = this,
3876                                 l = pt.l;
3877                         pt["xs" + l] += (pad && l) ? " " + pfx : pfx || "";
3878                         if (!c) if (l !== 0 && !pt.plugin) { //typically we'll combine non-changing values right into the xs to optimize performance, but we don't combine them when there's a plugin that will be tweening the values because it may depend on the values being split apart, like for a bezier, if a value doesn't change between the first and second iteration but then it does on the 3rd, we'll run into trouble because there's no xn slot for that value!
3879                                 pt["xs" + l] += s + (sfx || "");
3880                                 return pt;
3881                         }
3882                         pt.l++;
3883                         pt.type = pt.setRatio ? 2 : 1;
3884                         pt["xs" + pt.l] = sfx || "";
3885                         if (l > 0) {
3886                                 pt.data["xn" + l] = s + c;
3887                                 pt.rxp["xn" + l] = r; //round extra property (we need to tap into this in the _parseToProxy() method)
3888                                 pt["xn" + l] = s;
3889                                 if (!pt.plugin) {
3890                                         pt.xfirst = new CSSPropTween(pt, "xn" + l, s, c, pt.xfirst || pt, 0, pt.n, r, pt.pr);
3891                                         pt.xfirst.xs0 = 0; //just to ensure that the property stays numeric which helps modern browsers speed up processing. Remember, in the setRatio() method, we do pt.t[pt.p] = val + pt.xs0 so if pt.xs0 is "" (the default), it'll cast the end value as a string. When a property is a number sometimes and a string sometimes, it prevents the compiler from locking in the data type, slowing things down slightly.
3892                                 }
3893                                 return pt;
3894                         }
3895                         pt.data = {s:s + c};
3896                         pt.rxp = {};
3897                         pt.s = s;
3898                         pt.c = c;
3899                         pt.r = r;
3900                         return pt;
3901                 };
3902
3903                 /**
3904                  * @constructor A SpecialProp is basically a css property that needs to be treated in a non-standard way, like if it may contain a complex value like boxShadow:"5px 10px 15px rgb(255, 102, 51)" or if it is associated with another plugin like ThrowPropsPlugin or BezierPlugin. Every SpecialProp is associated with a particular property name like "boxShadow" or "throwProps" or "bezier" and it will intercept those values in the vars object that's passed to the CSSPlugin and handle them accordingly.
3905                  * @param {!string} p Property name (like "boxShadow" or "throwProps")
3906                  * @param {Object=} options An object containing any of the following configuration options:
3907                  *                      - defaultValue: the default value
3908                  *                      - parser: A function that should be called when the associated property name is found in the vars. This function should return a CSSPropTween instance and it should ensure that it is properly inserted into the linked list. It will receive 4 paramters: 1) The target, 2) The value defined in the vars, 3) The CSSPlugin instance (whose _firstPT should be used for the linked list), and 4) A computed style object if one was calculated (this is a speed optimization that allows retrieval of starting values quicker)
3909                  *                      - formatter: a function that formats any value received for this special property (for example, boxShadow could take "5px 5px red" and format it to "5px 5px 0px 0px red" so that both the beginning and ending values have a common order and quantity of values.)
3910                  *                      - prefix: if true, we'll determine whether or not this property requires a vendor prefix (like Webkit or Moz or ms or O)
3911                  *                      - color: set this to true if the value for this SpecialProp may contain color-related values like rgb(), rgba(), etc.
3912                  *                      - priority: priority in the linked list order. Higher priority SpecialProps will be updated before lower priority ones. The default priority is 0.
3913                  *                      - multi: if true, the formatter should accommodate a comma-delimited list of values, like boxShadow could have multiple boxShadows listed out.
3914                  *                      - collapsible: if true, the formatter should treat the value like it's a top/right/bottom/left value that could be collapsed, like "5px" would apply to all, "5px, 10px" would use 5px for top/bottom and 10px for right/left, etc.
3915                  *                      - keyword: a special keyword that can [optionally] be found inside the value (like "inset" for boxShadow). This allows us to validate beginning/ending values to make sure they match (if the keyword is found in one, it'll be added to the other for consistency by default).
3916                  */
3917                 var SpecialProp = function(p, options) {
3918                                 options = options || {};
3919                                 this.p = options.prefix ? _checkPropPrefix(p) || p : p;
3920                                 _specialProps[p] = _specialProps[this.p] = this;
3921                                 this.format = options.formatter || _getFormatter(options.defaultValue, options.color, options.collapsible, options.multi);
3922                                 if (options.parser) {
3923                                         this.parse = options.parser;
3924                                 }
3925                                 this.clrs = options.color;
3926                                 this.multi = options.multi;
3927                                 this.keyword = options.keyword;
3928                                 this.dflt = options.defaultValue;
3929                                 this.pr = options.priority || 0;
3930                         },
3931
3932                         //shortcut for creating a new SpecialProp that can accept multiple properties as a comma-delimited list (helps minification). dflt can be an array for multiple values (we don't do a comma-delimited list because the default value may contain commas, like rect(0px,0px,0px,0px)). We attach this method to the SpecialProp class/object instead of using a private _createSpecialProp() method so that we can tap into it externally if necessary, like from another plugin.
3933                         _registerComplexSpecialProp = _internals._registerComplexSpecialProp = function(p, options, defaults) {
3934                                 if (typeof(options) !== "object") {
3935                                         options = {parser:defaults}; //to make backwards compatible with older versions of BezierPlugin and ThrowPropsPlugin
3936                                 }
3937                                 var a = p.split(","),
3938                                         d = options.defaultValue,
3939                                         i, temp;
3940                                 defaults = defaults || [d];
3941                                 for (i = 0; i < a.length; i++) {
3942                                         options.prefix = (i === 0 && options.prefix);
3943                                         options.defaultValue = defaults[i] || d;
3944                                         temp = new SpecialProp(a[i], options);
3945                                 }
3946                         },
3947
3948                         //creates a placeholder special prop for a plugin so that the property gets caught the first time a tween of it is attempted, and at that time it makes the plugin register itself, thus taking over for all future tweens of that property. This allows us to not mandate that things load in a particular order and it also allows us to log() an error that informs the user when they attempt to tween an external plugin-related property without loading its .js file.
3949                         _registerPluginProp = function(p) {
3950                                 if (!_specialProps[p]) {
3951                                         var pluginName = p.charAt(0).toUpperCase() + p.substr(1) + "Plugin";
3952                                         _registerComplexSpecialProp(p, {parser:function(t, e, p, cssp, pt, plugin, vars) {
3953                                                 var pluginClass = (window.GreenSockGlobals || window).com.greensock.plugins[pluginName];
3954                                                 if (!pluginClass) {
3955                                                         _log("Error: " + pluginName + " js file not loaded.");
3956                                                         return pt;
3957                                                 }
3958                                                 pluginClass._cssRegister();
3959                                                 return _specialProps[p].parse(t, e, p, cssp, pt, plugin, vars);
3960                                         }});
3961                                 }
3962                         };
3963
3964
3965                 p = SpecialProp.prototype;
3966
3967                 /**
3968                  * Alias for _parseComplex() that automatically plugs in certain values for this SpecialProp, like its property name, whether or not colors should be sensed, the default value, and priority. It also looks for any keyword that the SpecialProp defines (like "inset" for boxShadow) and ensures that the beginning and ending values have the same number of values for SpecialProps where multi is true (like boxShadow and textShadow can have a comma-delimited list)
3969                  * @param {!Object} t target element
3970                  * @param {(string|number|object)} b beginning value
3971                  * @param {(string|number|object)} e ending (destination) value
3972                  * @param {CSSPropTween=} pt next CSSPropTween in the linked list
3973                  * @param {TweenPlugin=} plugin If another plugin will be tweening the complex value, that TweenPlugin instance goes here.
3974                  * @param {function=} setRatio If a custom setRatio() method should be used to handle this complex value, that goes here.
3975                  * @return {CSSPropTween=} First CSSPropTween in the linked list
3976                  */
3977                 p.parseComplex = function(t, b, e, pt, plugin, setRatio) {
3978                         var kwd = this.keyword,
3979                                 i, ba, ea, l, bi, ei;
3980                         //if this SpecialProp's value can contain a comma-delimited list of values (like boxShadow or textShadow), we must parse them in a special way, and look for a keyword (like "inset" for boxShadow) and ensure that the beginning and ending BOTH have it if the end defines it as such. We also must ensure that there are an equal number of values specified (we can't tween 1 boxShadow to 3 for example)
3981                         if (this.multi) if (_commasOutsideParenExp.test(e) || _commasOutsideParenExp.test(b)) {
3982                                 ba = b.replace(_commasOutsideParenExp, "|").split("|");
3983                                 ea = e.replace(_commasOutsideParenExp, "|").split("|");
3984                         } else if (kwd) {
3985                                 ba = [b];
3986                                 ea = [e];
3987                         }
3988                         if (ea) {
3989                                 l = (ea.length > ba.length) ? ea.length : ba.length;
3990                                 for (i = 0; i < l; i++) {
3991                                         b = ba[i] = ba[i] || this.dflt;
3992                                         e = ea[i] = ea[i] || this.dflt;
3993                                         if (kwd) {
3994                                                 bi = b.indexOf(kwd);
3995                                                 ei = e.indexOf(kwd);
3996                                                 if (bi !== ei) {
3997                                                         e = (ei === -1) ? ea : ba;
3998                                                         e[i] += " " + kwd;
3999                                                 }
4000                                         }
4001                                 }
4002                                 b = ba.join(", ");
4003                                 e = ea.join(", ");
4004                         }
4005                         return _parseComplex(t, this.p, b, e, this.clrs, this.dflt, pt, this.pr, plugin, setRatio);
4006                 };
4007
4008                 /**
4009                  * Accepts a target and end value and spits back a CSSPropTween that has been inserted into the CSSPlugin's linked list and conforms with all the conventions we use internally, like type:-1, 0, 1, or 2, setting up any extra property tweens, priority, etc. For example, if we have a boxShadow SpecialProp and call:
4010                  * this._firstPT = sp.parse(element, "5px 10px 20px rgb(2550,102,51)", "boxShadow", this);
4011                  * It should figure out the starting value of the element's boxShadow, compare it to the provided end value and create all the necessary CSSPropTweens of the appropriate types to tween the boxShadow. The CSSPropTween that gets spit back should already be inserted into the linked list (the 4th parameter is the current head, so prepend to that).
4012                  * @param {!Object} t Target object whose property is being tweened
4013                  * @param {Object} e End value as provided in the vars object (typically a string, but not always - like a throwProps would be an object).
4014                  * @param {!string} p Property name
4015                  * @param {!CSSPlugin} cssp The CSSPlugin instance that should be associated with this tween.
4016                  * @param {?CSSPropTween} pt The CSSPropTween that is the current head of the linked list (we'll prepend to it)
4017                  * @param {TweenPlugin=} plugin If a plugin will be used to tween the parsed value, this is the plugin instance.
4018                  * @param {Object=} vars Original vars object that contains the data for parsing.
4019                  * @return {CSSPropTween} The first CSSPropTween in the linked list which includes the new one(s) added by the parse() call.
4020                  */
4021                 p.parse = function(t, e, p, cssp, pt, plugin, vars) {
4022                         return this.parseComplex(t.style, this.format(_getStyle(t, this.p, _cs, false, this.dflt)), this.format(e), pt, plugin);
4023                 };
4024
4025                 /**
4026                  * Registers a special property that should be intercepted from any "css" objects defined in tweens. This allows you to handle them however you want without CSSPlugin doing it for you. The 2nd parameter should be a function that accepts 3 parameters:
4027                  *  1) Target object whose property should be tweened (typically a DOM element)
4028                  *  2) The end/destination value (could be a string, number, object, or whatever you want)
4029                  *  3) The tween instance (you probably don't need to worry about this, but it can be useful for looking up information like the duration)
4030                  *
4031                  * Then, your function should return a function which will be called each time the tween gets rendered, passing a numeric "ratio" parameter to your function that indicates the change factor (usually between 0 and 1). For example:
4032                  *
4033                  * CSSPlugin.registerSpecialProp("myCustomProp", function(target, value, tween) {
4034                  *      var start = target.style.width;
4035                  *      return function(ratio) {
4036                  *              target.style.width = (start + value * ratio) + "px";
4037                  *              console.log("set width to " + target.style.width);
4038                  *          }
4039                  * }, 0);
4040                  *
4041                  * Then, when I do this tween, it will trigger my special property:
4042                  *
4043                  * TweenLite.to(element, 1, {css:{myCustomProp:100}});
4044                  *
4045                  * In the example, of course, we're just changing the width, but you can do anything you want.
4046                  *
4047                  * @param {!string} name Property name (or comma-delimited list of property names) that should be intercepted and handled by your function. For example, if I define "myCustomProp", then it would handle that portion of the following tween: TweenLite.to(element, 1, {css:{myCustomProp:100}})
4048                  * @param {!function(Object, Object, Object, string):function(number)} onInitTween The function that will be called when a tween of this special property is performed. The function will receive 4 parameters: 1) Target object that should be tweened, 2) Value that was passed to the tween, 3) The tween instance itself (rarely used), and 4) The property name that's being tweened. Your function should return a function that should be called on every update of the tween. That function will receive a single parameter that is a "change factor" value (typically between 0 and 1) indicating the amount of change as a ratio. You can use this to determine how to set the values appropriately in your function.
4049                  * @param {number=} priority Priority that helps the engine determine the order in which to set the properties (default: 0). Higher priority properties will be updated before lower priority ones.
4050                  */
4051                 CSSPlugin.registerSpecialProp = function(name, onInitTween, priority) {
4052                         _registerComplexSpecialProp(name, {parser:function(t, e, p, cssp, pt, plugin, vars) {
4053                                 var rv = new CSSPropTween(t, p, 0, 0, pt, 2, p, false, priority);
4054                                 rv.plugin = plugin;
4055                                 rv.setRatio = onInitTween(t, e, cssp._tween, p);
4056                                 return rv;
4057                         }, priority:priority});
4058                 };
4059
4060
4061
4062
4063
4064
4065
4066
4067                 //transform-related methods and properties
4068                 var _transformProps = ("scaleX,scaleY,scaleZ,x,y,z,skewX,skewY,rotation,rotationX,rotationY,perspective").split(","),
4069                         _transformProp = _checkPropPrefix("transform"), //the Javascript (camelCase) transform property, like msTransform, WebkitTransform, MozTransform, or OTransform.
4070                         _transformPropCSS = _prefixCSS + "transform",
4071                         _transformOriginProp = _checkPropPrefix("transformOrigin"),
4072                         _supports3D = (_checkPropPrefix("perspective") !== null),
4073                         Transform = _internals.Transform = function() {
4074                                 this.skewY = 0;
4075                         },
4076
4077                         /**
4078                          * Parses the transform values for an element, returning an object with x, y, z, scaleX, scaleY, scaleZ, rotation, rotationX, rotationY, skewX, and skewY properties. Note: by default (for performance reasons), all skewing is combined into skewX and rotation but skewY still has a place in the transform object so that we can record how much of the skew is attributed to skewX vs skewY. Remember, a skewY of 10 looks the same as a rotation of 10 and skewX of -10.
4079                          * @param {!Object} t target element
4080                          * @param {Object=} cs computed style object (optional)
4081                          * @param {boolean=} rec if true, the transform values will be recorded to the target element's _gsTransform object, like target._gsTransform = {x:0, y:0, z:0, scaleX:1...}
4082                          * @param {boolean=} parse if true, we'll ignore any _gsTransform values that already exist on the element, and force a reparsing of the css (calculated style)
4083                          * @return {object} object containing all of the transform properties/values like {x:0, y:0, z:0, scaleX:1...}
4084                          */
4085                         _getTransform = _internals.getTransform = function(t, cs, rec, parse) {
4086                                 if (t._gsTransform && rec && !parse) {
4087                                         return t._gsTransform; //if the element already has a _gsTransform, use that. Note: some browsers don't accurately return the calculated style for the transform (particularly for SVG), so it's almost always safest to just use the values we've already applied rather than re-parsing things.
4088                                 }
4089                                 var tm = rec ? t._gsTransform || new Transform() : new Transform(),
4090                                         invX = (tm.scaleX < 0), //in order to interpret things properly, we need to know if the user applied a negative scaleX previously so that we can adjust the rotation and skewX accordingly. Otherwise, if we always interpret a flipped matrix as affecting scaleY and the user only wants to tween the scaleX on multiple sequential tweens, it would keep the negative scaleY without that being the user's intent.
4091                                         min = 0.00002,
4092                                         rnd = 100000,
4093                                         minAngle = 179.99,
4094                                         minPI = minAngle * _DEG2RAD,
4095                                         zOrigin = _supports3D ? parseFloat(_getStyle(t, _transformOriginProp, cs, false, "0 0 0").split(" ")[2]) || tm.zOrigin  || 0 : 0,
4096                                         s, m, i, n, dec, scaleX, scaleY, rotation, skewX, difX, difY, difR, difS;
4097                                 if (_transformProp) {
4098                                         s = _getStyle(t, _transformPropCSS, cs, true);
4099                                 } else if (t.currentStyle) {
4100                                         //for older versions of IE, we need to interpret the filter portion that is in the format: progid:DXImageTransform.Microsoft.Matrix(M11=6.123233995736766e-17, M12=-1, M21=1, M22=6.123233995736766e-17, sizingMethod='auto expand') Notice that we need to swap b and c compared to a normal matrix.
4101                                         s = t.currentStyle.filter.match(_ieGetMatrixExp);
4102                                         s = (s && s.length === 4) ? [s[0].substr(4), Number(s[2].substr(4)), Number(s[1].substr(4)), s[3].substr(4), (tm.x || 0), (tm.y || 0)].join(",") : "";
4103                                 }
4104                                 //split the matrix values out into an array (m for matrix)
4105                                 m = (s || "").match(/(?:\-|\b)[\d\-\.e]+\b/gi) || [];
4106                                 i = m.length;
4107                                 while (--i > -1) {
4108                                         n = Number(m[i]);
4109                                         m[i] = (dec = n - (n |= 0)) ? ((dec * rnd + (dec < 0 ? -0.5 : 0.5)) | 0) / rnd + n : n; //convert strings to Numbers and round to 5 decimal places to avoid issues with tiny numbers. Roughly 20x faster than Number.toFixed(). We also must make sure to round before dividing so that values like 0.9999999999 become 1 to avoid glitches in browser rendering and interpretation of flipped/rotated 3D matrices. And don't just multiply the number by rnd, floor it, and then divide by rnd because the bitwise operations max out at a 32-bit signed integer, thus it could get clipped at a relatively low value (like 22,000.00000 for example).
4110                                 }
4111                                 if (m.length === 16) {
4112
4113                                         //we'll only look at these position-related 6 variables first because if x/y/z all match, it's relatively safe to assume we don't need to re-parse everything which risks losing important rotational information (like rotationX:180 plus rotationY:180 would look the same as rotation:180 - there's no way to know for sure which direction was taken based solely on the matrix3d() values)
4114                                         var a13 = m[8], a23 = m[9], a33 = m[10],
4115                                                 a14 = m[12], a24 = m[13], a34 = m[14];
4116
4117                                         //we manually compensate for non-zero z component of transformOrigin to work around bugs in Safari
4118                                         if (tm.zOrigin) {
4119                                                 a34 = -tm.zOrigin;
4120                                                 a14 = a13*a34-m[12];
4121                                                 a24 = a23*a34-m[13];
4122                                                 a34 = a33*a34+tm.zOrigin-m[14];
4123                                         }
4124
4125                                         //only parse from the matrix if we MUST because not only is it usually unnecessary due to the fact that we store the values in the _gsTransform object, but also because it's impossible to accurately interpret rotationX, rotationY, rotationZ, scaleX, and scaleY if all are applied, so it's much better to rely on what we store. However, we must parse the first time that an object is tweened. We also assume that if the position has changed, the user must have done some styling changes outside of CSSPlugin, thus we force a parse in that scenario.
4126                                         if (!rec || parse || tm.rotationX == null) {
4127                                                 var a11 = m[0], a21 = m[1], a31 = m[2], a41 = m[3],
4128                                                         a12 = m[4], a22 = m[5], a32 = m[6], a42 = m[7],
4129                                                         a43 = m[11],
4130                                                         angle = Math.atan2(a32, a33),
4131                                                         xFlip = (angle < -minPI || angle > minPI),
4132                                                         t1, t2, t3, cos, sin, yFlip, zFlip;
4133                                                 tm.rotationX = angle * _RAD2DEG;
4134                                                 //rotationX
4135                                                 if (angle) {
4136                                                         cos = Math.cos(-angle);
4137                                                         sin = Math.sin(-angle);
4138                                                         t1 = a12*cos+a13*sin;
4139                                                         t2 = a22*cos+a23*sin;
4140                                                         t3 = a32*cos+a33*sin;
4141                                                         a13 = a12*-sin+a13*cos;
4142                                                         a23 = a22*-sin+a23*cos;
4143                                                         a33 = a32*-sin+a33*cos;
4144                                                         a43 = a42*-sin+a43*cos;
4145                                                         a12 = t1;
4146                                                         a22 = t2;
4147                                                         a32 = t3;
4148                                                 }
4149                                                 //rotationY
4150                                                 angle = Math.atan2(a13, a11);
4151                                                 tm.rotationY = angle * _RAD2DEG;
4152                                                 if (angle) {
4153                                                         yFlip = (angle < -minPI || angle > minPI);
4154                                                         cos = Math.cos(-angle);
4155                                                         sin = Math.sin(-angle);
4156                                                         t1 = a11*cos-a13*sin;
4157                                                         t2 = a21*cos-a23*sin;
4158                                                         t3 = a31*cos-a33*sin;
4159                                                         a23 = a21*sin+a23*cos;
4160                                                         a33 = a31*sin+a33*cos;
4161                                                         a43 = a41*sin+a43*cos;
4162                                                         a11 = t1;
4163                                                         a21 = t2;
4164                                                         a31 = t3;
4165                                                 }
4166                                                 //rotationZ
4167                                                 angle = Math.atan2(a21, a22);
4168                                                 tm.rotation = angle * _RAD2DEG;
4169                                                 if (angle) {
4170                                                         zFlip = (angle < -minPI || angle > minPI);
4171                                                         cos = Math.cos(-angle);
4172                                                         sin = Math.sin(-angle);
4173                                                         a11 = a11*cos+a12*sin;
4174                                                         t2 = a21*cos+a22*sin;
4175                                                         a22 = a21*-sin+a22*cos;
4176                                                         a32 = a31*-sin+a32*cos;
4177                                                         a21 = t2;
4178                                                 }
4179
4180                                                 if (zFlip && xFlip) {
4181                                                         tm.rotation = tm.rotationX = 0;
4182                                                 } else if (zFlip && yFlip) {
4183                                                         tm.rotation = tm.rotationY = 0;
4184                                                 } else if (yFlip && xFlip) {
4185                                                         tm.rotationY = tm.rotationX = 0;
4186                                                 }
4187
4188                                                 tm.scaleX = ((Math.sqrt(a11 * a11 + a21 * a21) * rnd + 0.5) | 0) / rnd;
4189                                                 tm.scaleY = ((Math.sqrt(a22 * a22 + a23 * a23) * rnd + 0.5) | 0) / rnd;
4190                                                 tm.scaleZ = ((Math.sqrt(a32 * a32 + a33 * a33) * rnd + 0.5) | 0) / rnd;
4191                                                 tm.skewX = 0;
4192                                                 tm.perspective = a43 ? 1 / ((a43 < 0) ? -a43 : a43) : 0;
4193                                                 tm.x = a14;
4194                                                 tm.y = a24;
4195                                                 tm.z = a34;
4196                                         }
4197
4198                                 } else if ((!_supports3D || parse || !m.length || tm.x !== m[4] || tm.y !== m[5] || (!tm.rotationX && !tm.rotationY)) && !(tm.x !== undefined && _getStyle(t, "display", cs) === "none")) { //sometimes a 6-element matrix is returned even when we performed 3D transforms, like if rotationX and rotationY are 180. In cases like this, we still need to honor the 3D transforms. If we just rely on the 2D info, it could affect how the data is interpreted, like scaleY might get set to -1 or rotation could get offset by 180 degrees. For example, do a TweenLite.to(element, 1, {css:{rotationX:180, rotationY:180}}) and then later, TweenLite.to(element, 1, {css:{rotationX:0}}) and without this conditional logic in place, it'd jump to a state of being unrotated when the 2nd tween starts. Then again, we need to honor the fact that the user COULD alter the transforms outside of CSSPlugin, like by manually applying new css, so we try to sense that by looking at x and y because if those changed, we know the changes were made outside CSSPlugin and we force a reinterpretation of the matrix values. Also, in Webkit browsers, if the element's "display" is "none", its calculated style value will always return empty, so if we've already recorded the values in the _gsTransform object, we'll just rely on those.
4199                                         var k = (m.length >= 6),
4200                                                 a = k ? m[0] : 1,
4201                                                 b = m[1] || 0,
4202                                                 c = m[2] || 0,
4203                                                 d = k ? m[3] : 1;
4204                                         tm.x = m[4] || 0;
4205                                         tm.y = m[5] || 0;
4206                                         scaleX = Math.sqrt(a * a + b * b);
4207                                         scaleY = Math.sqrt(d * d + c * c);
4208                                         rotation = (a || b) ? Math.atan2(b, a) * _RAD2DEG : tm.rotation || 0; //note: if scaleX is 0, we cannot accurately measure rotation. Same for skewX with a scaleY of 0. Therefore, we default to the previously recorded value (or zero if that doesn't exist).
4209                                         skewX = (c || d) ? Math.atan2(c, d) * _RAD2DEG + rotation : tm.skewX || 0;
4210                                         difX = scaleX - Math.abs(tm.scaleX || 0);
4211                                         difY = scaleY - Math.abs(tm.scaleY || 0);
4212                                         if (Math.abs(skewX) > 90 && Math.abs(skewX) < 270) {
4213                                                 if (invX) {
4214                                                         scaleX *= -1;
4215                                                         skewX += (rotation <= 0) ? 180 : -180;
4216                                                         rotation += (rotation <= 0) ? 180 : -180;
4217                                                 } else {
4218                                                         scaleY *= -1;
4219                                                         skewX += (skewX <= 0) ? 180 : -180;
4220                                                 }
4221                                         }
4222                                         difR = (rotation - tm.rotation) % 180; //note: matching ranges would be very small (+/-0.0001) or very close to 180.
4223                                         difS = (skewX - tm.skewX) % 180;
4224                                         //if there's already a recorded _gsTransform in place for the target, we should leave those values in place unless we know things changed for sure (beyond a super small amount). This gets around ambiguous interpretations, like if scaleX and scaleY are both -1, the matrix would be the same as if the rotation was 180 with normal scaleX/scaleY. If the user tweened to particular values, those must be prioritized to ensure animation is consistent.
4225                                         if (tm.skewX === undefined || difX > min || difX < -min || difY > min || difY < -min || (difR > -minAngle && difR < minAngle && (difR * rnd) | 0 !== 0) || (difS > -minAngle && difS < minAngle && (difS * rnd) | 0 !== 0)) {
4226                                                 tm.scaleX = scaleX;
4227                                                 tm.scaleY = scaleY;
4228                                                 tm.rotation = rotation;
4229                                                 tm.skewX = skewX;
4230                                         }
4231                                         if (_supports3D) {
4232                                                 tm.rotationX = tm.rotationY = tm.z = 0;
4233                                                 tm.perspective = parseFloat(CSSPlugin.defaultTransformPerspective) || 0;
4234                                                 tm.scaleZ = 1;
4235                                         }
4236                                 }
4237                                 tm.zOrigin = zOrigin;
4238
4239                                 //some browsers have a hard time with very small values like 2.4492935982947064e-16 (notice the "e-" towards the end) and would render the object slightly off. So we round to 0 in these cases. The conditional logic here is faster than calling Math.abs(). Also, browsers tend to render a SLIGHTLY rotated object in a fuzzy way, so we need to snap to exactly 0 when appropriate.
4240                                 for (i in tm) {
4241                                         if (tm[i] < min) if (tm[i] > -min) {
4242                                                 tm[i] = 0;
4243                                         }
4244                                 }
4245                                 //DEBUG: _log("parsed rotation: "+(tm.rotationX)+", "+(tm.rotationY)+", "+(tm.rotation)+", scale: "+tm.scaleX+", "+tm.scaleY+", "+tm.scaleZ+", position: "+tm.x+", "+tm.y+", "+tm.z+", perspective: "+tm.perspective);
4246                                 if (rec) {
4247                                         t._gsTransform = tm; //record to the object's _gsTransform which we use so that tweens can control individual properties independently (we need all the properties to accurately recompose the matrix in the setRatio() method)
4248                                 }
4249                                 return tm;
4250                         },
4251
4252                         //for setting 2D transforms in IE6, IE7, and IE8 (must use a "filter" to emulate the behavior of modern day browser transforms)
4253                         _setIETransformRatio = function(v) {
4254                                 var t = this.data, //refers to the element's _gsTransform object
4255                                         ang = -t.rotation * _DEG2RAD,
4256                                         skew = ang + t.skewX * _DEG2RAD,
4257                                         rnd = 100000,
4258                                         a = ((Math.cos(ang) * t.scaleX * rnd) | 0) / rnd,
4259                                         b = ((Math.sin(ang) * t.scaleX * rnd) | 0) / rnd,
4260                                         c = ((Math.sin(skew) * -t.scaleY * rnd) | 0) / rnd,
4261                                         d = ((Math.cos(skew) * t.scaleY * rnd) | 0) / rnd,
4262                                         style = this.t.style,
4263                                         cs = this.t.currentStyle,
4264                                         filters, val;
4265                                 if (!cs) {
4266                                         return;
4267                                 }
4268                                 val = b; //just for swapping the variables an inverting them (reused "val" to avoid creating another variable in memory). IE's filter matrix uses a non-standard matrix configuration (angle goes the opposite way, and b and c are reversed and inverted)
4269                                 b = -c;
4270                                 c = -val;
4271                                 filters = cs.filter;
4272                                 style.filter = ""; //remove filters so that we can accurately measure offsetWidth/offsetHeight
4273                                 var w = this.t.offsetWidth,
4274                                         h = this.t.offsetHeight,
4275                                         clip = (cs.position !== "absolute"),
4276                                         m = "progid:DXImageTransform.Microsoft.Matrix(M11=" + a + ", M12=" + b + ", M21=" + c + ", M22=" + d,
4277                                         ox = t.x,
4278                                         oy = t.y,
4279                                         dx, dy;
4280
4281                                 //if transformOrigin is being used, adjust the offset x and y
4282                                 if (t.ox != null) {
4283                                         dx = ((t.oxp) ? w * t.ox * 0.01 : t.ox) - w / 2;
4284                                         dy = ((t.oyp) ? h * t.oy * 0.01 : t.oy) - h / 2;
4285                                         ox += dx - (dx * a + dy * b);
4286                                         oy += dy - (dx * c + dy * d);
4287                                 }
4288
4289                                 if (!clip) {
4290                                         m += ", sizingMethod='auto expand')";
4291                                 } else {
4292                                         dx = (w / 2);
4293                                         dy = (h / 2);
4294                                         //translate to ensure that transformations occur around the correct origin (default is center).
4295                                         m += ", Dx=" + (dx - (dx * a + dy * b) + ox) + ", Dy=" + (dy - (dx * c + dy * d) + oy) + ")";
4296                                 }
4297                                 if (filters.indexOf("DXImageTransform.Microsoft.Matrix(") !== -1) {
4298                                         style.filter = filters.replace(_ieSetMatrixExp, m);
4299                                 } else {
4300                                         style.filter = m + " " + filters; //we must always put the transform/matrix FIRST (before alpha(opacity=xx)) to avoid an IE bug that slices part of the object when rotation is applied with alpha.
4301                                 }
4302
4303                                 //at the end or beginning of the tween, if the matrix is normal (1, 0, 0, 1) and opacity is 100 (or doesn't exist), remove the filter to improve browser performance.
4304                                 if (v === 0 || v === 1) if (a === 1) if (b === 0) if (c === 0) if (d === 1) if (!clip || m.indexOf("Dx=0, Dy=0") !== -1) if (!_opacityExp.test(filters) || parseFloat(RegExp.$1) === 100) if (filters.indexOf("gradient(" && filters.indexOf("Alpha")) === -1) {
4305                                         style.removeAttribute("filter");
4306                                 }
4307
4308                                 //we must set the margins AFTER applying the filter in order to avoid some bugs in IE8 that could (in rare scenarios) cause them to be ignored intermittently (vibration).
4309                                 if (!clip) {
4310                                         var mult = (_ieVers < 8) ? 1 : -1, //in Internet Explorer 7 and before, the box model is broken, causing the browser to treat the width/height of the actual rotated filtered image as the width/height of the box itself, but Microsoft corrected that in IE8. We must use a negative offset in IE8 on the right/bottom
4311                                                 marg, prop, dif;
4312                                         dx = t.ieOffsetX || 0;
4313                                         dy = t.ieOffsetY || 0;
4314                                         t.ieOffsetX = Math.round((w - ((a < 0 ? -a : a) * w + (b < 0 ? -b : b) * h)) / 2 + ox);
4315                                         t.ieOffsetY = Math.round((h - ((d < 0 ? -d : d) * h + (c < 0 ? -c : c) * w)) / 2 + oy);
4316                                         for (i = 0; i < 4; i++) {
4317                                                 prop = _margins[i];
4318                                                 marg = cs[prop];
4319                                                 //we need to get the current margin in case it is being tweened separately (we want to respect that tween's changes)
4320                                                 val = (marg.indexOf("px") !== -1) ? parseFloat(marg) : _convertToPixels(this.t, prop, parseFloat(marg), marg.replace(_suffixExp, "")) || 0;
4321                                                 if (val !== t[prop]) {
4322                                                         dif = (i < 2) ? -t.ieOffsetX : -t.ieOffsetY; //if another tween is controlling a margin, we cannot only apply the difference in the ieOffsets, so we essentially zero-out the dx and dy here in that case. We record the margin(s) later so that we can keep comparing them, making this code very flexible.
4323                                                 } else {
4324                                                         dif = (i < 2) ? dx - t.ieOffsetX : dy - t.ieOffsetY;
4325                                                 }
4326                                                 style[prop] = (t[prop] = Math.round( val - dif * ((i === 0 || i === 2) ? 1 : mult) )) + "px";
4327                                         }
4328                                 }
4329                         },
4330
4331                         _set3DTransformRatio = _internals.set3DTransformRatio = function(v) {
4332                                 var t = this.data, //refers to the element's _gsTransform object
4333                                         style = this.t.style,
4334                                         angle = t.rotation * _DEG2RAD,
4335                                         sx = t.scaleX,
4336                                         sy = t.scaleY,
4337                                         sz = t.scaleZ,
4338                                         perspective = t.perspective,
4339                                         a11, a12, a13, a14,     a21, a22, a23, a24, a31, a32, a33, a34, a41, a42, a43,
4340                                         zOrigin, rnd, cos, sin, t1, t2, t3, t4;
4341                                 if (v === 1 || v === 0) if (t.force3D === "auto") if (!t.rotationY && !t.rotationX && sz === 1 && !perspective && !t.z) { //on the final render (which could be 0 for a from tween), if there are no 3D aspects, render in 2D to free up memory and improve performance especially on mobile devices
4342                                         _set2DTransformRatio.call(this, v);
4343                                         return;
4344                                 }
4345                                 if (_isFirefox) {
4346                                         var n = 0.0001;
4347                                         if (sx < n && sx > -n) { //Firefox has a bug (at least in v25) that causes it to render the transparent part of 32-bit PNG images as black when displayed inside an iframe and the 3D scale is very small and doesn't change sufficiently enough between renders (like if you use a Power4.easeInOut to scale from 0 to 1 where the beginning values only change a tiny amount to begin the tween before accelerating). In this case, we force the scale to be 0.00002 instead which is visually the same but works around the Firefox issue.
4348                                                 sx = sz = 0.00002;
4349                                         }
4350                                         if (sy < n && sy > -n) {
4351                                                 sy = sz = 0.00002;
4352                                         }
4353                                         if (perspective && !t.z && !t.rotationX && !t.rotationY) { //Firefox has a bug that causes elements to have an odd super-thin, broken/dotted black border on elements that have a perspective set but aren't utilizing 3D space (no rotationX, rotationY, or z).
4354                                                 perspective = 0;
4355                                         }
4356                                 }
4357                                 if (angle || t.skewX) {
4358                                         cos = Math.cos(angle);
4359                                         sin = Math.sin(angle);
4360                                         a11 = cos;
4361                                         a21 = sin;
4362                                         if (t.skewX) {
4363                                                 angle -= t.skewX * _DEG2RAD;
4364                                                 cos = Math.cos(angle);
4365                                                 sin = Math.sin(angle);
4366                                                 if (t.skewType === "simple") { //by default, we compensate skewing on the other axis to make it look more natural, but you can set the skewType to "simple" to use the uncompensated skewing that CSS does
4367                                                         t1 = Math.tan(t.skewX * _DEG2RAD);
4368                                                         t1 = Math.sqrt(1 + t1 * t1);
4369                                                         cos *= t1;
4370                                                         sin *= t1;
4371                                                 }
4372                                         }
4373                                         a12 = -sin;
4374                                         a22 = cos;
4375
4376                                 } else if (!t.rotationY && !t.rotationX && sz === 1 && !perspective) { //if we're only translating and/or 2D scaling, this is faster...
4377                                         style[_transformProp] = "translate3d(" + t.x + "px," + t.y + "px," + t.z +"px)" + ((sx !== 1 || sy !== 1) ? " scale(" + sx + "," + sy + ")" : "");
4378                                         return;
4379                                 } else {
4380                                         a11 = a22 = 1;
4381                                         a12 = a21 = 0;
4382                                 }
4383                                 a33 = 1;
4384                                 a13 = a14 = a23 = a24 = a31 = a32 = a34 = a41 = a42 = 0;
4385                                 a43 = (perspective) ? -1 / perspective : 0;
4386                                 zOrigin = t.zOrigin;
4387                                 rnd = 100000;
4388                                 angle = t.rotationY * _DEG2RAD;
4389                                 if (angle) {
4390                                         cos = Math.cos(angle);
4391                                         sin = Math.sin(angle);
4392                                         a31 = a33*-sin;
4393                                         a41 = a43*-sin;
4394                                         a13 = a11*sin;
4395                                         a23 = a21*sin;
4396                                         a33 *= cos;
4397                                         a43 *= cos;
4398                                         a11 *= cos;
4399                                         a21 *= cos;
4400                                 }
4401                                 angle = t.rotationX * _DEG2RAD;
4402                                 if (angle) {
4403                                         cos = Math.cos(angle);
4404                                         sin = Math.sin(angle);
4405                                         t1 = a12*cos+a13*sin;
4406                                         t2 = a22*cos+a23*sin;
4407                                         t3 = a32*cos+a33*sin;
4408                                         t4 = a42*cos+a43*sin;
4409                                         a13 = a12*-sin+a13*cos;
4410                                         a23 = a22*-sin+a23*cos;
4411                                         a33 = a32*-sin+a33*cos;
4412                                         a43 = a42*-sin+a43*cos;
4413                                         a12 = t1;
4414                                         a22 = t2;
4415                                         a32 = t3;
4416                                         a42 = t4;
4417                                 }
4418                                 if (sz !== 1) {
4419                                         a13*=sz;
4420                                         a23*=sz;
4421                                         a33*=sz;
4422                                         a43*=sz;
4423                                 }
4424                                 if (sy !== 1) {
4425                                         a12*=sy;
4426                                         a22*=sy;
4427                                         a32*=sy;
4428                                         a42*=sy;
4429                                 }
4430                                 if (sx !== 1) {
4431                                         a11*=sx;
4432                                         a21*=sx;
4433                                         a31*=sx;
4434                                         a41*=sx;
4435                                 }
4436                                 if (zOrigin) {
4437                                         a34 -= zOrigin;
4438                                         a14 = a13*a34;
4439                                         a24 = a23*a34;
4440                                         a34 = a33*a34+zOrigin;
4441                                 }
4442                                 //we round the x, y, and z slightly differently to allow even larger values.
4443                                 a14 = (t1 = (a14 += t.x) - (a14 |= 0)) ? ((t1 * rnd + (t1 < 0 ? -0.5 : 0.5)) | 0) / rnd + a14 : a14;
4444                                 a24 = (t1 = (a24 += t.y) - (a24 |= 0)) ? ((t1 * rnd + (t1 < 0 ? -0.5 : 0.5)) | 0) / rnd + a24 : a24;
4445                                 a34 = (t1 = (a34 += t.z) - (a34 |= 0)) ? ((t1 * rnd + (t1 < 0 ? -0.5 : 0.5)) | 0) / rnd + a34 : a34;
4446                                 style[_transformProp] = "matrix3d(" + [ (((a11 * rnd) | 0) / rnd), (((a21 * rnd) | 0) / rnd), (((a31 * rnd) | 0) / rnd), (((a41 * rnd) | 0) / rnd), (((a12 * rnd) | 0) / rnd), (((a22 * rnd) | 0) / rnd), (((a32 * rnd) | 0) / rnd), (((a42 * rnd) | 0) / rnd), (((a13 * rnd) | 0) / rnd), (((a23 * rnd) | 0) / rnd), (((a33 * rnd) | 0) / rnd), (((a43 * rnd) | 0) / rnd), a14, a24, a34, (perspective ? (1 + (-a34 / perspective)) : 1) ].join(",") + ")";
4447                         },
4448
4449                         _set2DTransformRatio = _internals.set2DTransformRatio = function(v) {
4450                                 var t = this.data, //refers to the element's _gsTransform object
4451                                         targ = this.t,
4452                                         style = targ.style,
4453                                         ang, skew, rnd, sx, sy;
4454                                 if (t.rotationX || t.rotationY || t.z || t.force3D === true || (t.force3D === "auto" && v !== 1 && v !== 0)) { //if a 3D tween begins while a 2D one is running, we need to kick the rendering over to the 3D method. For example, imagine a yoyo-ing, infinitely repeating scale tween running, and then the object gets rotated in 3D space with a different tween.
4455                                         this.setRatio = _set3DTransformRatio;
4456                                         _set3DTransformRatio.call(this, v);
4457                                         return;
4458                                 }
4459                                 if (!t.rotation && !t.skewX) {
4460                                         style[_transformProp] = "matrix(" + t.scaleX + ",0,0," + t.scaleY + "," + t.x + "," + t.y + ")";
4461                                 } else {
4462                                         ang = t.rotation * _DEG2RAD;
4463                                         skew = ang - t.skewX * _DEG2RAD;
4464                                         rnd = 100000;
4465                                         sx = t.scaleX * rnd;
4466                                         sy = t.scaleY * rnd;
4467                                         //some browsers have a hard time with very small values like 2.4492935982947064e-16 (notice the "e-" towards the end) and would render the object slightly off. So we round to 5 decimal places.
4468                                         style[_transformProp] = "matrix(" + (((Math.cos(ang) * sx) | 0) / rnd) + "," + (((Math.sin(ang) * sx) | 0) / rnd) + "," + (((Math.sin(skew) * -sy) | 0) / rnd) + "," + (((Math.cos(skew) * sy) | 0) / rnd) + "," + t.x + "," + t.y + ")";
4469                                 }
4470                         };
4471
4472                 _registerComplexSpecialProp("transform,scale,scaleX,scaleY,scaleZ,x,y,z,rotation,rotationX,rotationY,rotationZ,skewX,skewY,shortRotation,shortRotationX,shortRotationY,shortRotationZ,transformOrigin,transformPerspective,directionalRotation,parseTransform,force3D,skewType", {parser:function(t, e, p, cssp, pt, plugin, vars) {
4473                         if (cssp._transform) { return pt; } //only need to parse the transform once, and only if the browser supports it.
4474                         var m1 = cssp._transform = _getTransform(t, _cs, true, vars.parseTransform),
4475                                 style = t.style,
4476                                 min = 0.000001,
4477                                 i = _transformProps.length,
4478                                 v = vars,
4479                                 endRotations = {},
4480                                 m2, skewY, copy, orig, has3D, hasChange, dr;
4481                         if (typeof(v.transform) === "string" && _transformProp) { //for values like transform:"rotate(60deg) scale(0.5, 0.8)"
4482                                 copy = _tempDiv.style; //don't use the original target because it might be SVG in which case some browsers don't report computed style correctly.
4483                                 copy[_transformProp] = v.transform;
4484                                 copy.display = "block"; //if display is "none", the browser often refuses to report the transform properties correctly.
4485                                 copy.position = "absolute";
4486                                 _doc.body.appendChild(_tempDiv);
4487                                 m2 = _getTransform(_tempDiv, null, false);
4488                                 _doc.body.removeChild(_tempDiv);
4489                         } else if (typeof(v) === "object") { //for values like scaleX, scaleY, rotation, x, y, skewX, and skewY or transform:{...} (object)
4490                                 m2 = {scaleX:_parseVal((v.scaleX != null) ? v.scaleX : v.scale, m1.scaleX),
4491                                         scaleY:_parseVal((v.scaleY != null) ? v.scaleY : v.scale, m1.scaleY),
4492                                         scaleZ:_parseVal(v.scaleZ, m1.scaleZ),
4493                                         x:_parseVal(v.x, m1.x),
4494                                         y:_parseVal(v.y, m1.y),
4495                                         z:_parseVal(v.z, m1.z),
4496                                         perspective:_parseVal(v.transformPerspective, m1.perspective)};
4497                                 dr = v.directionalRotation;
4498                                 if (dr != null) {
4499                                         if (typeof(dr) === "object") {
4500                                                 for (copy in dr) {
4501                                                         v[copy] = dr[copy];
4502                                                 }
4503                                         } else {
4504                                                 v.rotation = dr;
4505                                         }
4506                                 }
4507                                 m2.rotation = _parseAngle(("rotation" in v) ? v.rotation : ("shortRotation" in v) ? v.shortRotation + "_short" : ("rotationZ" in v) ? v.rotationZ : m1.rotation, m1.rotation, "rotation", endRotations);
4508                                 if (_supports3D) {
4509                                         m2.rotationX = _parseAngle(("rotationX" in v) ? v.rotationX : ("shortRotationX" in v) ? v.shortRotationX + "_short" : m1.rotationX || 0, m1.rotationX, "rotationX", endRotations);
4510                                         m2.rotationY = _parseAngle(("rotationY" in v) ? v.rotationY : ("shortRotationY" in v) ? v.shortRotationY + "_short" : m1.rotationY || 0, m1.rotationY, "rotationY", endRotations);
4511                                 }
4512                                 m2.skewX = (v.skewX == null) ? m1.skewX : _parseAngle(v.skewX, m1.skewX);
4513
4514                                 //note: for performance reasons, we combine all skewing into the skewX and rotation values, ignoring skewY but we must still record it so that we can discern how much of the overall skew is attributed to skewX vs. skewY. Otherwise, if the skewY would always act relative (tween skewY to 10deg, for example, multiple times and if we always combine things into skewX, we can't remember that skewY was 10 from last time). Remember, a skewY of 10 degrees looks the same as a rotation of 10 degrees plus a skewX of -10 degrees.
4515                                 m2.skewY = (v.skewY == null) ? m1.skewY : _parseAngle(v.skewY, m1.skewY);
4516                                 if ((skewY = m2.skewY - m1.skewY)) {
4517                                         m2.skewX += skewY;
4518                                         m2.rotation += skewY;
4519                                 }
4520                         }
4521
4522                         if (_supports3D && v.force3D != null) {
4523                                 m1.force3D = v.force3D;
4524                                 hasChange = true;
4525                         }
4526
4527                         m1.skewType = v.skewType || m1.skewType || CSSPlugin.defaultSkewType;
4528
4529                         has3D = (m1.force3D || m1.z || m1.rotationX || m1.rotationY || m2.z || m2.rotationX || m2.rotationY || m2.perspective);
4530                         if (!has3D && v.scale != null) {
4531                                 m2.scaleZ = 1; //no need to tween scaleZ.
4532                         }
4533
4534                         while (--i > -1) {
4535                                 p = _transformProps[i];
4536                                 orig = m2[p] - m1[p];
4537                                 if (orig > min || orig < -min || _forcePT[p] != null) {
4538                                         hasChange = true;
4539                                         pt = new CSSPropTween(m1, p, m1[p], orig, pt);
4540                                         if (p in endRotations) {
4541                                                 pt.e = endRotations[p]; //directional rotations typically have compensated values during the tween, but we need to make sure they end at exactly what the user requested
4542                                         }
4543                                         pt.xs0 = 0; //ensures the value stays numeric in setRatio()
4544                                         pt.plugin = plugin;
4545                                         cssp._overwriteProps.push(pt.n);
4546                                 }
4547                         }
4548
4549                         orig = v.transformOrigin;
4550                         if (orig || (_supports3D && has3D && m1.zOrigin)) { //if anything 3D is happening and there's a transformOrigin with a z component that's non-zero, we must ensure that the transformOrigin's z-component is set to 0 so that we can manually do those calculations to get around Safari bugs. Even if the user didn't specifically define a "transformOrigin" in this particular tween (maybe they did it via css directly).
4551                                 if (_transformProp) {
4552                                         hasChange = true;
4553                                         p = _transformOriginProp;
4554                                         orig = (orig || _getStyle(t, p, _cs, false, "50% 50%")) + ""; //cast as string to avoid errors
4555                                         pt = new CSSPropTween(style, p, 0, 0, pt, -1, "transformOrigin");
4556                                         pt.b = style[p];
4557                                         pt.plugin = plugin;
4558                                         if (_supports3D) {
4559                                                 copy = m1.zOrigin;
4560                                                 orig = orig.split(" ");
4561                                                 m1.zOrigin = ((orig.length > 2 && !(copy !== 0 && orig[2] === "0px")) ? parseFloat(orig[2]) : copy) || 0; //Safari doesn't handle the z part of transformOrigin correctly, so we'll manually handle it in the _set3DTransformRatio() method.
4562                                                 pt.xs0 = pt.e = orig[0] + " " + (orig[1] || "50%") + " 0px"; //we must define a z value of 0px specifically otherwise iOS 5 Safari will stick with the old one (if one was defined)!
4563                                                 pt = new CSSPropTween(m1, "zOrigin", 0, 0, pt, -1, pt.n); //we must create a CSSPropTween for the _gsTransform.zOrigin so that it gets reset properly at the beginning if the tween runs backward (as opposed to just setting m1.zOrigin here)
4564                                                 pt.b = copy;
4565                                                 pt.xs0 = pt.e = m1.zOrigin;
4566                                         } else {
4567                                                 pt.xs0 = pt.e = orig;
4568                                         }
4569
4570                                 //for older versions of IE (6-8), we need to manually calculate things inside the setRatio() function. We record origin x and y (ox and oy) and whether or not the values are percentages (oxp and oyp).
4571                                 } else {
4572                                         _parsePosition(orig + "", m1);
4573                                 }
4574                         }
4575
4576                         if (hasChange) {
4577                                 cssp._transformType = (has3D || this._transformType === 3) ? 3 : 2; //quicker than calling cssp._enableTransforms();
4578                         }
4579                         return pt;
4580                 }, prefix:true});
4581
4582                 _registerComplexSpecialProp("boxShadow", {defaultValue:"0px 0px 0px 0px #999", prefix:true, color:true, multi:true, keyword:"inset"});
4583
4584                 _registerComplexSpecialProp("borderRadius", {defaultValue:"0px", parser:function(t, e, p, cssp, pt, plugin) {
4585                         e = this.format(e);
4586                         var props = ["borderTopLeftRadius","borderTopRightRadius","borderBottomRightRadius","borderBottomLeftRadius"],
4587                                 style = t.style,
4588                                 ea1, i, es2, bs2, bs, es, bn, en, w, h, esfx, bsfx, rel, hn, vn, em;
4589                         w = parseFloat(t.offsetWidth);
4590                         h = parseFloat(t.offsetHeight);
4591                         ea1 = e.split(" ");
4592                         for (i = 0; i < props.length; i++) { //if we're dealing with percentages, we must convert things separately for the horizontal and vertical axis!
4593                                 if (this.p.indexOf("border")) { //older browsers used a prefix
4594                                         props[i] = _checkPropPrefix(props[i]);
4595                                 }
4596                                 bs = bs2 = _getStyle(t, props[i], _cs, false, "0px");
4597                                 if (bs.indexOf(" ") !== -1) {
4598                                         bs2 = bs.split(" ");
4599                                         bs = bs2[0];
4600                                         bs2 = bs2[1];
4601                                 }
4602                                 es = es2 = ea1[i];
4603                                 bn = parseFloat(bs);
4604                                 bsfx = bs.substr((bn + "").length);
4605                                 rel = (es.charAt(1) === "=");
4606                                 if (rel) {
4607                                         en = parseInt(es.charAt(0)+"1", 10);
4608                                         es = es.substr(2);
4609                                         en *= parseFloat(es);
4610                                         esfx = es.substr((en + "").length - (en < 0 ? 1 : 0)) || "";
4611                                 } else {
4612                                         en = parseFloat(es);
4613                                         esfx = es.substr((en + "").length);
4614                                 }
4615                                 if (esfx === "") {
4616                                         esfx = _suffixMap[p] || bsfx;
4617                                 }
4618                                 if (esfx !== bsfx) {
4619                                         hn = _convertToPixels(t, "borderLeft", bn, bsfx); //horizontal number (we use a bogus "borderLeft" property just because the _convertToPixels() method searches for the keywords "Left", "Right", "Top", and "Bottom" to determine of it's a horizontal or vertical property, and we need "border" in the name so that it knows it should measure relative to the element itself, not its parent.
4620                                         vn = _convertToPixels(t, "borderTop", bn, bsfx); //vertical number
4621                                         if (esfx === "%") {
4622                                                 bs = (hn / w * 100) + "%";
4623                                                 bs2 = (vn / h * 100) + "%";
4624                                         } else if (esfx === "em") {
4625                                                 em = _convertToPixels(t, "borderLeft", 1, "em");
4626                                                 bs = (hn / em) + "em";
4627                                                 bs2 = (vn / em) + "em";
4628                                         } else {
4629                                                 bs = hn + "px";
4630                                                 bs2 = vn + "px";
4631                                         }
4632                                         if (rel) {
4633                                                 es = (parseFloat(bs) + en) + esfx;
4634                                                 es2 = (parseFloat(bs2) + en) + esfx;
4635                                         }
4636                                 }
4637                                 pt = _parseComplex(style, props[i], bs + " " + bs2, es + " " + es2, false, "0px", pt);
4638                         }
4639                         return pt;
4640                 }, prefix:true, formatter:_getFormatter("0px 0px 0px 0px", false, true)});
4641                 _registerComplexSpecialProp("backgroundPosition", {defaultValue:"0 0", parser:function(t, e, p, cssp, pt, plugin) {
4642                         var bp = "background-position",
4643                                 cs = (_cs || _getComputedStyle(t, null)),
4644                                 bs = this.format( ((cs) ? _ieVers ? cs.getPropertyValue(bp + "-x") + " " + cs.getPropertyValue(bp + "-y") : cs.getPropertyValue(bp) : t.currentStyle.backgroundPositionX + " " + t.currentStyle.backgroundPositionY) || "0 0"), //Internet Explorer doesn't report background-position correctly - we must query background-position-x and background-position-y and combine them (even in IE10). Before IE9, we must do the same with the currentStyle object and use camelCase
4645                                 es = this.format(e),
4646                                 ba, ea, i, pct, overlap, src;
4647                         if ((bs.indexOf("%") !== -1) !== (es.indexOf("%") !== -1)) {
4648                                 src = _getStyle(t, "backgroundImage").replace(_urlExp, "");
4649                                 if (src && src !== "none") {
4650                                         ba = bs.split(" ");
4651                                         ea = es.split(" ");
4652                                         _tempImg.setAttribute("src", src); //set the temp <img>'s src to the background-image so that we can measure its width/height
4653                                         i = 2;
4654                                         while (--i > -1) {
4655                                                 bs = ba[i];
4656                                                 pct = (bs.indexOf("%") !== -1);
4657                                                 if (pct !== (ea[i].indexOf("%") !== -1)) {
4658                                                         overlap = (i === 0) ? t.offsetWidth - _tempImg.width : t.offsetHeight - _tempImg.height;
4659                                                         ba[i] = pct ? (parseFloat(bs) / 100 * overlap) + "px" : (parseFloat(bs) / overlap * 100) + "%";
4660                                                 }
4661                                         }
4662                                         bs = ba.join(" ");
4663                                 }
4664                         }
4665                         return this.parseComplex(t.style, bs, es, pt, plugin);
4666                 }, formatter:_parsePosition});
4667                 _registerComplexSpecialProp("backgroundSize", {defaultValue:"0 0", formatter:_parsePosition});
4668                 _registerComplexSpecialProp("perspective", {defaultValue:"0px", prefix:true});
4669                 _registerComplexSpecialProp("perspectiveOrigin", {defaultValue:"50% 50%", prefix:true});
4670                 _registerComplexSpecialProp("transformStyle", {prefix:true});
4671                 _registerComplexSpecialProp("backfaceVisibility", {prefix:true});
4672                 _registerComplexSpecialProp("userSelect", {prefix:true});
4673                 _registerComplexSpecialProp("margin", {parser:_getEdgeParser("marginTop,marginRight,marginBottom,marginLeft")});
4674                 _registerComplexSpecialProp("padding", {parser:_getEdgeParser("paddingTop,paddingRight,paddingBottom,paddingLeft")});
4675                 _registerComplexSpecialProp("clip", {defaultValue:"rect(0px,0px,0px,0px)", parser:function(t, e, p, cssp, pt, plugin){
4676                         var b, cs, delim;
4677                         if (_ieVers < 9) { //IE8 and earlier don't report a "clip" value in the currentStyle - instead, the values are split apart into clipTop, clipRight, clipBottom, and clipLeft. Also, in IE7 and earlier, the values inside rect() are space-delimited, not comma-delimited.
4678                                 cs = t.currentStyle;
4679                                 delim = _ieVers < 8 ? " " : ",";
4680                                 b = "rect(" + cs.clipTop + delim + cs.clipRight + delim + cs.clipBottom + delim + cs.clipLeft + ")";
4681                                 e = this.format(e).split(",").join(delim);
4682                         } else {
4683                                 b = this.format(_getStyle(t, this.p, _cs, false, this.dflt));
4684                                 e = this.format(e);
4685                         }
4686                         return this.parseComplex(t.style, b, e, pt, plugin);
4687                 }});
4688                 _registerComplexSpecialProp("textShadow", {defaultValue:"0px 0px 0px #999", color:true, multi:true});
4689                 _registerComplexSpecialProp("autoRound,strictUnits", {parser:function(t, e, p, cssp, pt) {return pt;}}); //just so that we can ignore these properties (not tween them)
4690                 _registerComplexSpecialProp("border", {defaultValue:"0px solid #000", parser:function(t, e, p, cssp, pt, plugin) {
4691                                 return this.parseComplex(t.style, this.format(_getStyle(t, "borderTopWidth", _cs, false, "0px") + " " + _getStyle(t, "borderTopStyle", _cs, false, "solid") + " " + _getStyle(t, "borderTopColor", _cs, false, "#000")), this.format(e), pt, plugin);
4692                         }, color:true, formatter:function(v) {
4693                                 var a = v.split(" ");
4694                                 return a[0] + " " + (a[1] || "solid") + " " + (v.match(_colorExp) || ["#000"])[0];
4695                         }});
4696                 _registerComplexSpecialProp("borderWidth", {parser:_getEdgeParser("borderTopWidth,borderRightWidth,borderBottomWidth,borderLeftWidth")}); //Firefox doesn't pick up on borderWidth set in style sheets (only inline).
4697                 _registerComplexSpecialProp("float,cssFloat,styleFloat", {parser:function(t, e, p, cssp, pt, plugin) {
4698                         var s = t.style,
4699                                 prop = ("cssFloat" in s) ? "cssFloat" : "styleFloat";
4700                         return new CSSPropTween(s, prop, 0, 0, pt, -1, p, false, 0, s[prop], e);
4701                 }});
4702
4703                 //opacity-related
4704                 var _setIEOpacityRatio = function(v) {
4705                                 var t = this.t, //refers to the element's style property
4706                                         filters = t.filter || _getStyle(this.data, "filter"),
4707                                         val = (this.s + this.c * v) | 0,
4708                                         skip;
4709                                 if (val === 100) { //for older versions of IE that need to use a filter to apply opacity, we should remove the filter if opacity hits 1 in order to improve performance, but make sure there isn't a transform (matrix) or gradient in the filters.
4710                                         if (filters.indexOf("atrix(") === -1 && filters.indexOf("radient(") === -1 && filters.indexOf("oader(") === -1) {
4711                                                 t.removeAttribute("filter");
4712                                                 skip = (!_getStyle(this.data, "filter")); //if a class is applied that has an alpha filter, it will take effect (we don't want that), so re-apply our alpha filter in that case. We must first remove it and then check.
4713                                         } else {
4714                                                 t.filter = filters.replace(_alphaFilterExp, "");
4715                                                 skip = true;
4716                                         }
4717                                 }
4718                                 if (!skip) {
4719                                         if (this.xn1) {
4720                                                 t.filter = filters = filters || ("alpha(opacity=" + val + ")"); //works around bug in IE7/8 that prevents changes to "visibility" from being applied properly if the filter is changed to a different alpha on the same frame.
4721                                         }
4722                                         if (filters.indexOf("pacity") === -1) { //only used if browser doesn't support the standard opacity style property (IE 7 and 8). We omit the "O" to avoid case-sensitivity issues
4723                                                 if (val !== 0 || !this.xn1) { //bugs in IE7/8 won't render the filter properly if opacity is ADDED on the same frame/render as "visibility" changes (this.xn1 is 1 if this tween is an "autoAlpha" tween)
4724                                                         t.filter = filters + " alpha(opacity=" + val + ")"; //we round the value because otherwise, bugs in IE7/8 can prevent "visibility" changes from being applied properly.
4725                                                 }
4726                                         } else {
4727                                                 t.filter = filters.replace(_opacityExp, "opacity=" + val);
4728                                         }
4729                                 }
4730                         };
4731                 _registerComplexSpecialProp("opacity,alpha,autoAlpha", {defaultValue:"1", parser:function(t, e, p, cssp, pt, plugin) {
4732                         var b = parseFloat(_getStyle(t, "opacity", _cs, false, "1")),
4733                                 style = t.style,
4734                                 isAutoAlpha = (p === "autoAlpha");
4735                         if (typeof(e) === "string" && e.charAt(1) === "=") {
4736                                 e = ((e.charAt(0) === "-") ? -1 : 1) * parseFloat(e.substr(2)) + b;
4737                         }
4738                         if (isAutoAlpha && b === 1 && _getStyle(t, "visibility", _cs) === "hidden" && e !== 0) { //if visibility is initially set to "hidden", we should interpret that as intent to make opacity 0 (a convenience)
4739                                 b = 0;
4740                         }
4741                         if (_supportsOpacity) {
4742                                 pt = new CSSPropTween(style, "opacity", b, e - b, pt);
4743                         } else {
4744                                 pt = new CSSPropTween(style, "opacity", b * 100, (e - b) * 100, pt);
4745                                 pt.xn1 = isAutoAlpha ? 1 : 0; //we need to record whether or not this is an autoAlpha so that in the setRatio(), we know to duplicate the setting of the alpha in order to work around a bug in IE7 and IE8 that prevents changes to "visibility" from taking effect if the filter is changed to a different alpha(opacity) at the same time. Setting it to the SAME value first, then the new value works around the IE7/8 bug.
4746                                 style.zoom = 1; //helps correct an IE issue.
4747                                 pt.type = 2;
4748                                 pt.b = "alpha(opacity=" + pt.s + ")";
4749                                 pt.e = "alpha(opacity=" + (pt.s + pt.c) + ")";
4750                                 pt.data = t;
4751                                 pt.plugin = plugin;
4752                                 pt.setRatio = _setIEOpacityRatio;
4753                         }
4754                         if (isAutoAlpha) { //we have to create the "visibility" PropTween after the opacity one in the linked list so that they run in the order that works properly in IE8 and earlier
4755                                 pt = new CSSPropTween(style, "visibility", 0, 0, pt, -1, null, false, 0, ((b !== 0) ? "inherit" : "hidden"), ((e === 0) ? "hidden" : "inherit"));
4756                                 pt.xs0 = "inherit";
4757                                 cssp._overwriteProps.push(pt.n);
4758                                 cssp._overwriteProps.push(p);
4759                         }
4760                         return pt;
4761                 }});
4762
4763
4764                 var _removeProp = function(s, p) {
4765                                 if (p) {
4766                                         if (s.removeProperty) {
4767                                                 if (p.substr(0,2) === "ms") { //Microsoft browsers don't conform to the standard of capping the first prefix character, so we adjust so that when we prefix the caps with a dash, it's correct (otherwise it'd be "ms-transform" instead of "-ms-transform" for IE9, for example)
4768                                                         p = "M" + p.substr(1);
4769                                                 }
4770                                                 s.removeProperty(p.replace(_capsExp, "-$1").toLowerCase());
4771                                         } else { //note: old versions of IE use "removeAttribute()" instead of "removeProperty()"
4772                                                 s.removeAttribute(p);
4773                                         }
4774                                 }
4775                         },
4776                         _setClassNameRatio = function(v) {
4777                                 this.t._gsClassPT = this;
4778                                 if (v === 1 || v === 0) {
4779                                         this.t.setAttribute("class", (v === 0) ? this.b : this.e);
4780                                         var mpt = this.data, //first MiniPropTween
4781                                                 s = this.t.style;
4782                                         while (mpt) {
4783                                                 if (!mpt.v) {
4784                                                         _removeProp(s, mpt.p);
4785                                                 } else {
4786                                                         s[mpt.p] = mpt.v;
4787                                                 }
4788                                                 mpt = mpt._next;
4789                                         }
4790                                         if (v === 1 && this.t._gsClassPT === this) {
4791                                                 this.t._gsClassPT = null;
4792                                         }
4793                                 } else if (this.t.getAttribute("class") !== this.e) {
4794                                         this.t.setAttribute("class", this.e);
4795                                 }
4796                         };
4797                 _registerComplexSpecialProp("className", {parser:function(t, e, p, cssp, pt, plugin, vars) {
4798                         var b = t.getAttribute("class") || "", //don't use t.className because it doesn't work consistently on SVG elements; getAttribute("class") and setAttribute("class", value") is more reliable.
4799                                 cssText = t.style.cssText,
4800                                 difData, bs, cnpt, cnptLookup, mpt;
4801                         pt = cssp._classNamePT = new CSSPropTween(t, p, 0, 0, pt, 2);
4802                         pt.setRatio = _setClassNameRatio;
4803                         pt.pr = -11;
4804                         _hasPriority = true;
4805                         pt.b = b;
4806                         bs = _getAllStyles(t, _cs);
4807                         //if there's a className tween already operating on the target, force it to its end so that the necessary inline styles are removed and the class name is applied before we determine the end state (we don't want inline styles interfering that were there just for class-specific values)
4808                         cnpt = t._gsClassPT;
4809                         if (cnpt) {
4810                                 cnptLookup = {};
4811                                 mpt = cnpt.data; //first MiniPropTween which stores the inline styles - we need to force these so that the inline styles don't contaminate things. Otherwise, there's a small chance that a tween could start and the inline values match the destination values and they never get cleaned.
4812                                 while (mpt) {
4813                                         cnptLookup[mpt.p] = 1;
4814                                         mpt = mpt._next;
4815                                 }
4816                                 cnpt.setRatio(1);
4817                         }
4818                         t._gsClassPT = pt;
4819                         pt.e = (e.charAt(1) !== "=") ? e : b.replace(new RegExp("\\s*\\b" + e.substr(2) + "\\b"), "") + ((e.charAt(0) === "+") ? " " + e.substr(2) : "");
4820                         if (cssp._tween._duration) { //if it's a zero-duration tween, there's no need to tween anything or parse the data. In fact, if we switch classes temporarily (which we must do for proper parsing) and the class has a transition applied, it could cause a quick flash to the end state and back again initially in some browsers.
4821                                 t.setAttribute("class", pt.e);
4822                                 difData = _cssDif(t, bs, _getAllStyles(t), vars, cnptLookup);
4823                                 t.setAttribute("class", b);
4824                                 pt.data = difData.firstMPT;
4825                                 t.style.cssText = cssText; //we recorded cssText before we swapped classes and ran _getAllStyles() because in cases when a className tween is overwritten, we remove all the related tweening properties from that class change (otherwise class-specific stuff can't override properties we've directly set on the target's style object due to specificity).
4826                                 pt = pt.xfirst = cssp.parse(t, difData.difs, pt, plugin); //we record the CSSPropTween as the xfirst so that we can handle overwriting propertly (if "className" gets overwritten, we must kill all the properties associated with the className part of the tween, so we can loop through from xfirst to the pt itself)
4827                         }
4828                         return pt;
4829                 }});
4830
4831
4832                 var _setClearPropsRatio = function(v) {
4833                         if (v === 1 || v === 0) if (this.data._totalTime === this.data._totalDuration && this.data.data !== "isFromStart") { //this.data refers to the tween. Only clear at the END of the tween (remember, from() tweens make the ratio go from 1 to 0, so we can't just check that and if the tween is the zero-duration one that's created internally to render the starting values in a from() tween, ignore that because otherwise, for example, from(...{height:100, clearProps:"height", delay:1}) would wipe the height at the beginning of the tween and after 1 second, it'd kick back in).
4834                                 var s = this.t.style,
4835                                         transformParse = _specialProps.transform.parse,
4836                                         a, p, i, clearTransform;
4837                                 if (this.e === "all") {
4838                                         s.cssText = "";
4839                                         clearTransform = true;
4840                                 } else {
4841                                         a = this.e.split(",");
4842                                         i = a.length;
4843                                         while (--i > -1) {
4844                                                 p = a[i];
4845                                                 if (_specialProps[p]) {
4846                                                         if (_specialProps[p].parse === transformParse) {
4847                                                                 clearTransform = true;
4848                                                         } else {
4849                                                                 p = (p === "transformOrigin") ? _transformOriginProp : _specialProps[p].p; //ensures that special properties use the proper browser-specific property name, like "scaleX" might be "-webkit-transform" or "boxShadow" might be "-moz-box-shadow"
4850                                                         }
4851                                                 }
4852                                                 _removeProp(s, p);
4853                                         }
4854                                 }
4855                                 if (clearTransform) {
4856                                         _removeProp(s, _transformProp);
4857                                         if (this.t._gsTransform) {
4858                                                 delete this.t._gsTransform;
4859                                         }
4860                                 }
4861
4862                         }
4863                 };
4864                 _registerComplexSpecialProp("clearProps", {parser:function(t, e, p, cssp, pt) {
4865                         pt = new CSSPropTween(t, p, 0, 0, pt, 2);
4866                         pt.setRatio = _setClearPropsRatio;
4867                         pt.e = e;
4868                         pt.pr = -10;
4869                         pt.data = cssp._tween;
4870                         _hasPriority = true;
4871                         return pt;
4872                 }});
4873
4874                 p = "bezier,throwProps,physicsProps,physics2D".split(",");
4875                 i = p.length;
4876                 while (i--) {
4877                         _registerPluginProp(p[i]);
4878                 }
4879
4880
4881
4882
4883
4884
4885
4886
4887                 p = CSSPlugin.prototype;
4888                 p._firstPT = null;
4889
4890                 //gets called when the tween renders for the first time. This kicks everything off, recording start/end values, etc.
4891                 p._onInitTween = function(target, vars, tween) {
4892                         if (!target.nodeType) { //css is only for dom elements
4893                                 return false;
4894                         }
4895                         this._target = target;
4896                         this._tween = tween;
4897                         this._vars = vars;
4898                         _autoRound = vars.autoRound;
4899                         _hasPriority = false;
4900                         _suffixMap = vars.suffixMap || CSSPlugin.suffixMap;
4901                         _cs = _getComputedStyle(target, "");
4902                         _overwriteProps = this._overwriteProps;
4903                         var style = target.style,
4904                                 v, pt, pt2, first, last, next, zIndex, tpt, threeD;
4905                         if (_reqSafariFix) if (style.zIndex === "") {
4906                                 v = _getStyle(target, "zIndex", _cs);
4907                                 if (v === "auto" || v === "") {
4908                                         //corrects a bug in [non-Android] Safari that prevents it from repainting elements in their new positions if they don't have a zIndex set. We also can't just apply this inside _parseTransform() because anything that's moved in any way (like using "left" or "top" instead of transforms like "x" and "y") can be affected, so it is best to ensure that anything that's tweening has a z-index. Setting "WebkitPerspective" to a non-zero value worked too except that on iOS Safari things would flicker randomly. Plus zIndex is less memory-intensive.
4909                                         this._addLazySet(style, "zIndex", 0);
4910                                 }
4911                         }
4912
4913                         if (typeof(vars) === "string") {
4914                                 first = style.cssText;
4915                                 v = _getAllStyles(target, _cs);
4916                                 style.cssText = first + ";" + vars;
4917                                 v = _cssDif(target, v, _getAllStyles(target)).difs;
4918                                 if (!_supportsOpacity && _opacityValExp.test(vars)) {
4919                                         v.opacity = parseFloat( RegExp.$1 );
4920                                 }
4921                                 vars = v;
4922                                 style.cssText = first;
4923                         }
4924                         this._firstPT = pt = this.parse(target, vars, null);
4925
4926                         if (this._transformType) {
4927                                 threeD = (this._transformType === 3);
4928                                 if (!_transformProp) {
4929                                         style.zoom = 1; //helps correct an IE issue.
4930                                 } else if (_isSafari) {
4931                                         _reqSafariFix = true;
4932                                         //if zIndex isn't set, iOS Safari doesn't repaint things correctly sometimes (seemingly at random).
4933                                         if (style.zIndex === "") {
4934                                                 zIndex = _getStyle(target, "zIndex", _cs);
4935                                                 if (zIndex === "auto" || zIndex === "") {
4936                                                         this._addLazySet(style, "zIndex", 0);
4937                                                 }
4938                                         }
4939                                         //Setting WebkitBackfaceVisibility corrects 3 bugs:
4940                                         // 1) [non-Android] Safari skips rendering changes to "top" and "left" that are made on the same frame/render as a transform update.
4941                                         // 2) iOS Safari sometimes neglects to repaint elements in their new positions. Setting "WebkitPerspective" to a non-zero value worked too except that on iOS Safari things would flicker randomly.
4942                                         // 3) Safari sometimes displayed odd artifacts when tweening the transform (or WebkitTransform) property, like ghosts of the edges of the element remained. Definitely a browser bug.
4943                                         //Note: we allow the user to override the auto-setting by defining WebkitBackfaceVisibility in the vars of the tween.
4944                                         if (_isSafariLT6) {
4945                                                 this._addLazySet(style, "WebkitBackfaceVisibility", this._vars.WebkitBackfaceVisibility || (threeD ? "visible" : "hidden"));
4946                                         }
4947                                 }
4948                                 pt2 = pt;
4949                                 while (pt2 && pt2._next) {
4950                                         pt2 = pt2._next;
4951                                 }
4952                                 tpt = new CSSPropTween(target, "transform", 0, 0, null, 2);
4953                                 this._linkCSSP(tpt, null, pt2);
4954                                 tpt.setRatio = (threeD && _supports3D) ? _set3DTransformRatio : _transformProp ? _set2DTransformRatio : _setIETransformRatio;
4955                                 tpt.data = this._transform || _getTransform(target, _cs, true);
4956                                 _overwriteProps.pop(); //we don't want to force the overwrite of all "transform" tweens of the target - we only care about individual transform properties like scaleX, rotation, etc. The CSSPropTween constructor automatically adds the property to _overwriteProps which is why we need to pop() here.
4957                         }
4958
4959                         if (_hasPriority) {
4960                                 //reorders the linked list in order of pr (priority)
4961                                 while (pt) {
4962                                         next = pt._next;
4963                                         pt2 = first;
4964                                         while (pt2 && pt2.pr > pt.pr) {
4965                                                 pt2 = pt2._next;
4966                                         }
4967                                         if ((pt._prev = pt2 ? pt2._prev : last)) {
4968                                                 pt._prev._next = pt;
4969                                         } else {
4970                                                 first = pt;
4971                                         }
4972                                         if ((pt._next = pt2)) {
4973                                                 pt2._prev = pt;
4974                                         } else {
4975                                                 last = pt;
4976                                         }
4977                                         pt = next;
4978                                 }
4979                                 this._firstPT = first;
4980                         }
4981                         return true;
4982                 };
4983
4984
4985                 p.parse = function(target, vars, pt, plugin) {
4986                         var style = target.style,
4987                                 p, sp, bn, en, bs, es, bsfx, esfx, isStr, rel;
4988                         for (p in vars) {
4989                                 es = vars[p]; //ending value string
4990                                 sp = _specialProps[p]; //SpecialProp lookup.
4991                                 if (sp) {
4992                                         pt = sp.parse(target, es, p, this, pt, plugin, vars);
4993
4994                                 } else {
4995                                         bs = _getStyle(target, p, _cs) + "";
4996                                         isStr = (typeof(es) === "string");
4997                                         if (p === "color" || p === "fill" || p === "stroke" || p.indexOf("Color") !== -1 || (isStr && _rgbhslExp.test(es))) { //Opera uses background: to define color sometimes in addition to backgroundColor:
4998                                                 if (!isStr) {
4999                                                         es = _parseColor(es);
5000                                                         es = ((es.length > 3) ? "rgba(" : "rgb(") + es.join(",") + ")";
5001                                                 }
5002                                                 pt = _parseComplex(style, p, bs, es, true, "transparent", pt, 0, plugin);
5003
5004                                         } else if (isStr && (es.indexOf(" ") !== -1 || es.indexOf(",") !== -1)) {
5005                                                 pt = _parseComplex(style, p, bs, es, true, null, pt, 0, plugin);
5006
5007                                         } else {
5008                                                 bn = parseFloat(bs);
5009                                                 bsfx = (bn || bn === 0) ? bs.substr((bn + "").length) : ""; //remember, bs could be non-numeric like "normal" for fontWeight, so we should default to a blank suffix in that case.
5010
5011                                                 if (bs === "" || bs === "auto") {
5012                                                         if (p === "width" || p === "height") {
5013                                                                 bn = _getDimension(target, p, _cs);
5014                                                                 bsfx = "px";
5015                                                         } else if (p === "left" || p === "top") {
5016                                                                 bn = _calculateOffset(target, p, _cs);
5017                                                                 bsfx = "px";
5018                                                         } else {
5019                                                                 bn = (p !== "opacity") ? 0 : 1;
5020                                                                 bsfx = "";
5021                                                         }
5022                                                 }
5023
5024                                                 rel = (isStr && es.charAt(1) === "=");
5025                                                 if (rel) {
5026                                                         en = parseInt(es.charAt(0) + "1", 10);
5027                                                         es = es.substr(2);
5028                                                         en *= parseFloat(es);
5029                                                         esfx = es.replace(_suffixExp, "");
5030                                                 } else {
5031                                                         en = parseFloat(es);
5032                                                         esfx = isStr ? es.substr((en + "").length) || "" : "";
5033                                                 }
5034
5035                                                 if (esfx === "") {
5036                                                         esfx = (p in _suffixMap) ? _suffixMap[p] : bsfx; //populate the end suffix, prioritizing the map, then if none is found, use the beginning suffix.
5037                                                 }
5038
5039                                                 es = (en || en === 0) ? (rel ? en + bn : en) + esfx : vars[p]; //ensures that any += or -= prefixes are taken care of. Record the end value before normalizing the suffix because we always want to end the tween on exactly what they intended even if it doesn't match the beginning value's suffix.
5040
5041                                                 //if the beginning/ending suffixes don't match, normalize them...
5042                                                 if (bsfx !== esfx) if (esfx !== "") if (en || en === 0) if (bn) { //note: if the beginning value (bn) is 0, we don't need to convert units!
5043                                                         bn = _convertToPixels(target, p, bn, bsfx);
5044                                                         if (esfx === "%") {
5045                                                                 bn /= _convertToPixels(target, p, 100, "%") / 100;
5046                                                                 if (vars.strictUnits !== true) { //some browsers report only "px" values instead of allowing "%" with getComputedStyle(), so we assume that if we're tweening to a %, we should start there too unless strictUnits:true is defined. This approach is particularly useful for responsive designs that use from() tweens.
5047                                                                         bs = bn + "%";
5048                                                                 }
5049
5050                                                         } else if (esfx === "em") {
5051                                                                 bn /= _convertToPixels(target, p, 1, "em");
5052
5053                                                         //otherwise convert to pixels.
5054                                                         } else if (esfx !== "px") {
5055                                                                 en = _convertToPixels(target, p, en, esfx);
5056                                                                 esfx = "px"; //we don't use bsfx after this, so we don't need to set it to px too.
5057                                                         }
5058                                                         if (rel) if (en || en === 0) {
5059                                                                 es = (en + bn) + esfx; //the changes we made affect relative calculations, so adjust the end value here.
5060                                                         }
5061                                                 }
5062
5063                                                 if (rel) {
5064                                                         en += bn;
5065                                                 }
5066
5067                                                 if ((bn || bn === 0) && (en || en === 0)) { //faster than isNaN(). Also, previously we required en !== bn but that doesn't really gain much performance and it prevents _parseToProxy() from working properly if beginning and ending values match but need to get tweened by an external plugin anyway. For example, a bezier tween where the target starts at left:0 and has these points: [{left:50},{left:0}] wouldn't work properly because when parsing the last point, it'd match the first (current) one and a non-tweening CSSPropTween would be recorded when we actually need a normal tween (type:0) so that things get updated during the tween properly.
5068                                                         pt = new CSSPropTween(style, p, bn, en - bn, pt, 0, p, (_autoRound !== false && (esfx === "px" || p === "zIndex")), 0, bs, es);
5069                                                         pt.xs0 = esfx;
5070                                                         //DEBUG: _log("tween "+p+" from "+pt.b+" ("+bn+esfx+") to "+pt.e+" with suffix: "+pt.xs0);
5071                                                 } else if (style[p] === undefined || !es && (es + "" === "NaN" || es == null)) {
5072                                                         _log("invalid " + p + " tween value: " + vars[p]);
5073                                                 } else {
5074                                                         pt = new CSSPropTween(style, p, en || bn || 0, 0, pt, -1, p, false, 0, bs, es);
5075                                                         pt.xs0 = (es === "none" && (p === "display" || p.indexOf("Style") !== -1)) ? bs : es; //intermediate value should typically be set immediately (end value) except for "display" or things like borderTopStyle, borderBottomStyle, etc. which should use the beginning value during the tween.
5076                                                         //DEBUG: _log("non-tweening value "+p+": "+pt.xs0);
5077                                                 }
5078                                         }
5079                                 }
5080                                 if (plugin) if (pt && !pt.plugin) {
5081                                         pt.plugin = plugin;
5082                                 }
5083                         }
5084                         return pt;
5085                 };
5086
5087
5088                 //gets called every time the tween updates, passing the new ratio (typically a value between 0 and 1, but not always (for example, if an Elastic.easeOut is used, the value can jump above 1 mid-tween). It will always start and 0 and end at 1.
5089                 p.setRatio = function(v) {
5090                         var pt = this._firstPT,
5091                                 min = 0.000001,
5092                                 val, str, i;
5093
5094                         //at the end of the tween, we set the values to exactly what we received in order to make sure non-tweening values (like "position" or "float" or whatever) are set and so that if the beginning/ending suffixes (units) didn't match and we normalized to px, the value that the user passed in is used here. We check to see if the tween is at its beginning in case it's a from() tween in which case the ratio will actually go from 1 to 0 over the course of the tween (backwards).
5095                         if (v === 1 && (this._tween._time === this._tween._duration || this._tween._time === 0)) {
5096                                 while (pt) {
5097                                         if (pt.type !== 2) {
5098                                                 pt.t[pt.p] = pt.e;
5099                                         } else {
5100                                                 pt.setRatio(v);
5101                                         }
5102                                         pt = pt._next;
5103                                 }
5104
5105                         } else if (v || !(this._tween._time === this._tween._duration || this._tween._time === 0) || this._tween._rawPrevTime === -0.000001) {
5106                                 while (pt) {
5107                                         val = pt.c * v + pt.s;
5108                                         if (pt.r) {
5109                                                 val = Math.round(val);
5110                                         } else if (val < min) if (val > -min) {
5111                                                 val = 0;
5112                                         }
5113                                         if (!pt.type) {
5114                                                 pt.t[pt.p] = val + pt.xs0;
5115                                         } else if (pt.type === 1) { //complex value (one that typically has multiple numbers inside a string, like "rect(5px,10px,20px,25px)"
5116                                                 i = pt.l;
5117                                                 if (i === 2) {
5118                                                         pt.t[pt.p] = pt.xs0 + val + pt.xs1 + pt.xn1 + pt.xs2;
5119                                                 } else if (i === 3) {
5120                                                         pt.t[pt.p] = pt.xs0 + val + pt.xs1 + pt.xn1 + pt.xs2 + pt.xn2 + pt.xs3;
5121                                                 } else if (i === 4) {
5122                                                         pt.t[pt.p] = pt.xs0 + val + pt.xs1 + pt.xn1 + pt.xs2 + pt.xn2 + pt.xs3 + pt.xn3 + pt.xs4;
5123                                                 } else if (i === 5) {
5124                                                         pt.t[pt.p] = pt.xs0 + val + pt.xs1 + pt.xn1 + pt.xs2 + pt.xn2 + pt.xs3 + pt.xn3 + pt.xs4 + pt.xn4 + pt.xs5;
5125                                                 } else {
5126                                                         str = pt.xs0 + val + pt.xs1;
5127                                                         for (i = 1; i < pt.l; i++) {
5128                                                                 str += pt["xn"+i] + pt["xs"+(i+1)];
5129                                                         }
5130                                                         pt.t[pt.p] = str;
5131                                                 }
5132
5133                                         } else if (pt.type === -1) { //non-tweening value
5134                                                 pt.t[pt.p] = pt.xs0;
5135
5136                                         } else if (pt.setRatio) { //custom setRatio() for things like SpecialProps, external plugins, etc.
5137                                                 pt.setRatio(v);
5138                                         }
5139                                         pt = pt._next;
5140                                 }
5141
5142                         //if the tween is reversed all the way back to the beginning, we need to restore the original values which may have different units (like % instead of px or em or whatever).
5143                         } else {
5144                                 while (pt) {
5145                                         if (pt.type !== 2) {
5146                                                 pt.t[pt.p] = pt.b;
5147                                         } else {
5148                                                 pt.setRatio(v);
5149                                         }
5150                                         pt = pt._next;
5151                                 }
5152                         }
5153                 };
5154
5155                 /**
5156                  * @private
5157                  * Forces rendering of the target's transforms (rotation, scale, etc.) whenever the CSSPlugin's setRatio() is called.
5158                  * Basically, this tells the CSSPlugin to create a CSSPropTween (type 2) after instantiation that runs last in the linked
5159                  * list and calls the appropriate (3D or 2D) rendering function. We separate this into its own method so that we can call
5160                  * it from other plugins like BezierPlugin if, for example, it needs to apply an autoRotation and this CSSPlugin
5161                  * doesn't have any transform-related properties of its own. You can call this method as many times as you
5162                  * want and it won't create duplicate CSSPropTweens.
5163                  *
5164                  * @param {boolean} threeD if true, it should apply 3D tweens (otherwise, just 2D ones are fine and typically faster)
5165                  */
5166                 p._enableTransforms = function(threeD) {
5167                         this._transformType = (threeD || this._transformType === 3) ? 3 : 2;
5168                         this._transform = this._transform || _getTransform(this._target, _cs, true); //ensures that the element has a _gsTransform property with the appropriate values.
5169                 };
5170
5171                 var lazySet = function(v) {
5172                         this.t[this.p] = this.e;
5173                         this.data._linkCSSP(this, this._next, null, true); //we purposefully keep this._next even though it'd make sense to null it, but this is a performance optimization, as this happens during the while (pt) {} loop in setRatio() at the bottom of which it sets pt = pt._next, so if we null it, the linked list will be broken in that loop.
5174                 };
5175                 /** @private Gives us a way to set a value on the first render (and only the first render). **/
5176                 p._addLazySet = function(t, p, v) {
5177                         var pt = this._firstPT = new CSSPropTween(t, p, 0, 0, this._firstPT, 2);
5178                         pt.e = v;
5179                         pt.setRatio = lazySet;
5180                         pt.data = this;
5181                 };
5182
5183                 /** @private **/
5184                 p._linkCSSP = function(pt, next, prev, remove) {
5185                         if (pt) {
5186                                 if (next) {
5187                                         next._prev = pt;
5188                                 }
5189                                 if (pt._next) {
5190                                         pt._next._prev = pt._prev;
5191                                 }
5192                                 if (pt._prev) {
5193                                         pt._prev._next = pt._next;
5194                                 } else if (this._firstPT === pt) {
5195                                         this._firstPT = pt._next;
5196                                         remove = true; //just to prevent resetting this._firstPT 5 lines down in case pt._next is null. (optimized for speed)
5197                                 }
5198                                 if (prev) {
5199                                         prev._next = pt;
5200                                 } else if (!remove && this._firstPT === null) {
5201                                         this._firstPT = pt;
5202                                 }
5203                                 pt._next = next;
5204                                 pt._prev = prev;
5205                         }
5206                         return pt;
5207                 };
5208
5209                 //we need to make sure that if alpha or autoAlpha is killed, opacity is too. And autoAlpha affects the "visibility" property.
5210                 p._kill = function(lookup) {
5211                         var copy = lookup,
5212                                 pt, p, xfirst;
5213                         if (lookup.autoAlpha || lookup.alpha) {
5214                                 copy = {};
5215                                 for (p in lookup) { //copy the lookup so that we're not changing the original which may be passed elsewhere.
5216                                         copy[p] = lookup[p];
5217                                 }
5218                                 copy.opacity = 1;
5219                                 if (copy.autoAlpha) {
5220                                         copy.visibility = 1;
5221                                 }
5222                         }
5223                         if (lookup.className && (pt = this._classNamePT)) { //for className tweens, we need to kill any associated CSSPropTweens too; a linked list starts at the className's "xfirst".
5224                                 xfirst = pt.xfirst;
5225                                 if (xfirst && xfirst._prev) {
5226                                         this._linkCSSP(xfirst._prev, pt._next, xfirst._prev._prev); //break off the prev
5227                                 } else if (xfirst === this._firstPT) {
5228                                         this._firstPT = pt._next;
5229                                 }
5230                                 if (pt._next) {
5231                                         this._linkCSSP(pt._next, pt._next._next, xfirst._prev);
5232                                 }
5233                                 this._classNamePT = null;
5234                         }
5235                         return TweenPlugin.prototype._kill.call(this, copy);
5236                 };
5237
5238
5239
5240                 //used by cascadeTo() for gathering all the style properties of each child element into an array for comparison.
5241                 var _getChildStyles = function(e, props, targets) {
5242                                 var children, i, child, type;
5243                                 if (e.slice) {
5244                                         i = e.length;
5245                                         while (--i > -1) {
5246                                                 _getChildStyles(e[i], props, targets);
5247                                         }
5248                                         return;
5249                                 }
5250                                 children = e.childNodes;
5251                                 i = children.length;
5252                                 while (--i > -1) {
5253                                         child = children[i];
5254                                         type = child.type;
5255                                         if (child.style) {
5256                                                 props.push(_getAllStyles(child));
5257                                                 if (targets) {
5258                                                         targets.push(child);
5259                                                 }
5260                                         }
5261                                         if ((type === 1 || type === 9 || type === 11) && child.childNodes.length) {
5262                                                 _getChildStyles(child, props, targets);
5263                                         }
5264                                 }
5265                         };
5266
5267                 /**
5268                  * Typically only useful for className tweens that may affect child elements, this method creates a TweenLite
5269                  * and then compares the style properties of all the target's child elements at the tween's start and end, and
5270                  * if any are different, it also creates tweens for those and returns an array containing ALL of the resulting
5271                  * tweens (so that you can easily add() them to a TimelineLite, for example). The reason this functionality is
5272                  * wrapped into a separate static method of CSSPlugin instead of being integrated into all regular className tweens
5273                  * is because it creates entirely new tweens that may have completely different targets than the original tween,
5274                  * so if they were all lumped into the original tween instance, it would be inconsistent with the rest of the API
5275                  * and it would create other problems. For example:
5276                  *  - If I create a tween of elementA, that tween instance may suddenly change its target to include 50 other elements (unintuitive if I specifically defined the target I wanted)
5277                  *  - We can't just create new independent tweens because otherwise, what happens if the original/parent tween is reversed or pause or dropped into a TimelineLite for tight control? You'd expect that tween's behavior to affect all the others.
5278                  *  - Analyzing every style property of every child before and after the tween is an expensive operation when there are many children, so this behavior shouldn't be imposed on all className tweens by default, especially since it's probably rare that this extra functionality is needed.
5279                  *
5280                  * @param {Object} target object to be tweened
5281                  * @param {number} Duration in seconds (or frames for frames-based tweens)
5282                  * @param {Object} Object containing the end values, like {className:"newClass", ease:Linear.easeNone}
5283                  * @return {Array} An array of TweenLite instances
5284                  */
5285                 CSSPlugin.cascadeTo = function(target, duration, vars) {
5286                         var tween = TweenLite.to(target, duration, vars),
5287                                 results = [tween],
5288                                 b = [],
5289                                 e = [],
5290                                 targets = [],
5291                                 _reservedProps = TweenLite._internals.reservedProps,
5292                                 i, difs, p;
5293                         target = tween._targets || tween.target;
5294                         _getChildStyles(target, b, targets);
5295                         tween.render(duration, true);
5296                         _getChildStyles(target, e);
5297                         tween.render(0, true);
5298                         tween._enabled(true);
5299                         i = targets.length;
5300                         while (--i > -1) {
5301                                 difs = _cssDif(targets[i], b[i], e[i]);
5302                                 if (difs.firstMPT) {
5303                                         difs = difs.difs;
5304                                         for (p in vars) {
5305                                                 if (_reservedProps[p]) {
5306                                                         difs[p] = vars[p];
5307                                                 }
5308                                         }
5309                                         results.push( TweenLite.to(targets[i], duration, difs) );
5310                                 }
5311                         }
5312                         return results;
5313                 };
5314
5315                 TweenPlugin.activate([CSSPlugin]);
5316                 return CSSPlugin;
5317
5318         }, true);
5319
5320         
5321         
5322         
5323         
5324         
5325         
5326         
5327         
5328         
5329         
5330 /*
5331  * ----------------------------------------------------------------
5332  * RoundPropsPlugin
5333  * ----------------------------------------------------------------
5334  */
5335         (function() {
5336
5337                 var RoundPropsPlugin = window._gsDefine.plugin({
5338                                 propName: "roundProps",
5339                                 priority: -1,
5340                                 API: 2,
5341
5342                                 //called when the tween renders for the first time. This is where initial values should be recorded and any setup routines should run.
5343                                 init: function(target, value, tween) {
5344                                         this._tween = tween;
5345                                         return true;
5346                                 }
5347
5348                         }),
5349                         p = RoundPropsPlugin.prototype;
5350
5351                 p._onInitAllProps = function() {
5352                         var tween = this._tween,
5353                                 rp = (tween.vars.roundProps instanceof Array) ? tween.vars.roundProps : tween.vars.roundProps.split(","),
5354                                 i = rp.length,
5355                                 lookup = {},
5356                                 rpt = tween._propLookup.roundProps,
5357                                 prop, pt, next;
5358                         while (--i > -1) {
5359                                 lookup[rp[i]] = 1;
5360                         }
5361                         i = rp.length;
5362                         while (--i > -1) {
5363                                 prop = rp[i];
5364                                 pt = tween._firstPT;
5365                                 while (pt) {
5366                                         next = pt._next; //record here, because it may get removed
5367                                         if (pt.pg) {
5368                                                 pt.t._roundProps(lookup, true);
5369                                         } else if (pt.n === prop) {
5370                                                 this._add(pt.t, prop, pt.s, pt.c);
5371                                                 //remove from linked list
5372                                                 if (next) {
5373                                                         next._prev = pt._prev;
5374                                                 }
5375                                                 if (pt._prev) {
5376                                                         pt._prev._next = next;
5377                                                 } else if (tween._firstPT === pt) {
5378                                                         tween._firstPT = next;
5379                                                 }
5380                                                 pt._next = pt._prev = null;
5381                                                 tween._propLookup[prop] = rpt;
5382                                         }
5383                                         pt = next;
5384                                 }
5385                         }
5386                         return false;
5387                 };
5388
5389                 p._add = function(target, p, s, c) {
5390                         this._addTween(target, p, s, s + c, p, true);
5391                         this._overwriteProps.push(p);
5392                 };
5393
5394         }());
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405 /*
5406  * ----------------------------------------------------------------
5407  * AttrPlugin
5408  * ----------------------------------------------------------------
5409  */
5410         window._gsDefine.plugin({
5411                 propName: "attr",
5412                 API: 2,
5413                 version: "0.3.2",
5414
5415                 //called when the tween renders for the first time. This is where initial values should be recorded and any setup routines should run.
5416                 init: function(target, value, tween) {
5417                         var p, start, end;
5418                         if (typeof(target.setAttribute) !== "function") {
5419                                 return false;
5420                         }
5421                         this._target = target;
5422                         this._proxy = {};
5423                         this._start = {}; // we record start and end values exactly as they are in case they're strings (not numbers) - we need to be able to revert to them cleanly.
5424                         this._end = {};
5425                         for (p in value) {
5426                                 this._start[p] = this._proxy[p] = start = target.getAttribute(p);
5427                                 end = this._addTween(this._proxy, p, parseFloat(start), value[p], p);
5428                                 this._end[p] = end ? end.s + end.c : value[p];
5429                                 this._overwriteProps.push(p);
5430                         }
5431                         return true;
5432                 },
5433
5434                 //called each time the values should be updated, and the ratio gets passed as the only parameter (typically it's a value between 0 and 1, but it can exceed those when using an ease like Elastic.easeOut or Back.easeOut, etc.)
5435                 set: function(ratio) {
5436                         this._super.setRatio.call(this, ratio);
5437                         var props = this._overwriteProps,
5438                                 i = props.length,
5439                                 lookup = (ratio === 1) ? this._end : ratio ? this._proxy : this._start,
5440                                 p;
5441                         while (--i > -1) {
5442                                 p = props[i];
5443                                 this._target.setAttribute(p, lookup[p] + "");
5444                         }
5445                 }
5446
5447         });
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458 /*
5459  * ----------------------------------------------------------------
5460  * DirectionalRotationPlugin
5461  * ----------------------------------------------------------------
5462  */
5463         window._gsDefine.plugin({
5464                 propName: "directionalRotation",
5465                 API: 2,
5466                 version: "0.2.0",
5467
5468                 //called when the tween renders for the first time. This is where initial values should be recorded and any setup routines should run.
5469                 init: function(target, value, tween) {
5470                         if (typeof(value) !== "object") {
5471                                 value = {rotation:value};
5472                         }
5473                         this.finals = {};
5474                         var cap = (value.useRadians === true) ? Math.PI * 2 : 360,
5475                                 min = 0.000001,
5476                                 p, v, start, end, dif, split;
5477                         for (p in value) {
5478                                 if (p !== "useRadians") {
5479                                         split = (value[p] + "").split("_");
5480                                         v = split[0];
5481                                         start = parseFloat( (typeof(target[p]) !== "function") ? target[p] : target[ ((p.indexOf("set") || typeof(target["get" + p.substr(3)]) !== "function") ? p : "get" + p.substr(3)) ]() );
5482                                         end = this.finals[p] = (typeof(v) === "string" && v.charAt(1) === "=") ? start + parseInt(v.charAt(0) + "1", 10) * Number(v.substr(2)) : Number(v) || 0;
5483                                         dif = end - start;
5484                                         if (split.length) {
5485                                                 v = split.join("_");
5486                                                 if (v.indexOf("short") !== -1) {
5487                                                         dif = dif % cap;
5488                                                         if (dif !== dif % (cap / 2)) {
5489                                                                 dif = (dif < 0) ? dif + cap : dif - cap;
5490                                                         }
5491                                                 }
5492                                                 if (v.indexOf("_cw") !== -1 && dif < 0) {
5493                                                         dif = ((dif + cap * 9999999999) % cap) - ((dif / cap) | 0) * cap;
5494                                                 } else if (v.indexOf("ccw") !== -1 && dif > 0) {
5495                                                         dif = ((dif - cap * 9999999999) % cap) - ((dif / cap) | 0) * cap;
5496                                                 }
5497                                         }
5498                                         if (dif > min || dif < -min) {
5499                                                 this._addTween(target, p, start, start + dif, p);
5500                                                 this._overwriteProps.push(p);
5501                                         }
5502                                 }
5503                         }
5504                         return true;
5505                 },
5506
5507                 //called each time the values should be updated, and the ratio gets passed as the only parameter (typically it's a value between 0 and 1, but it can exceed those when using an ease like Elastic.easeOut or Back.easeOut, etc.)
5508                 set: function(ratio) {
5509                         var pt;
5510                         if (ratio !== 1) {
5511                                 this._super.setRatio.call(this, ratio);
5512                         } else {
5513                                 pt = this._firstPT;
5514                                 while (pt) {
5515                                         if (pt.f) {
5516                                                 pt.t[pt.p](this.finals[pt.p]);
5517                                         } else {
5518                                                 pt.t[pt.p] = this.finals[pt.p];
5519                                         }
5520                                         pt = pt._next;
5521                                 }
5522                         }
5523                 }
5524
5525         })._autoCSS = true;
5526
5527
5528
5529
5530
5531
5532
5533         
5534         
5535         
5536         
5537 /*
5538  * ----------------------------------------------------------------
5539  * EasePack
5540  * ----------------------------------------------------------------
5541  */
5542         window._gsDefine("easing.Back", ["easing.Ease"], function(Ease) {
5543                 
5544                 var w = (window.GreenSockGlobals || window),
5545                         gs = w.com.greensock,
5546                         _2PI = Math.PI * 2,
5547                         _HALF_PI = Math.PI / 2,
5548                         _class = gs._class,
5549                         _create = function(n, f) {
5550                                 var C = _class("easing." + n, function(){}, true),
5551                                         p = C.prototype = new Ease();
5552                                 p.constructor = C;
5553                                 p.getRatio = f;
5554                                 return C;
5555                         },
5556                         _easeReg = Ease.register || function(){}, //put an empty function in place just as a safety measure in case someone loads an OLD version of TweenLite.js where Ease.register doesn't exist.
5557                         _wrap = function(name, EaseOut, EaseIn, EaseInOut, aliases) {
5558                                 var C = _class("easing."+name, {
5559                                         easeOut:new EaseOut(),
5560                                         easeIn:new EaseIn(),
5561                                         easeInOut:new EaseInOut()
5562                                 }, true);
5563                                 _easeReg(C, name);
5564                                 return C;
5565                         },
5566                         EasePoint = function(time, value, next) {
5567                                 this.t = time;
5568                                 this.v = value;
5569                                 if (next) {
5570                                         this.next = next;
5571                                         next.prev = this;
5572                                         this.c = next.v - value;
5573                                         this.gap = next.t - time;
5574                                 }
5575                         },
5576
5577                         //Back
5578                         _createBack = function(n, f) {
5579                                 var C = _class("easing." + n, function(overshoot) {
5580                                                 this._p1 = (overshoot || overshoot === 0) ? overshoot : 1.70158;
5581                                                 this._p2 = this._p1 * 1.525;
5582                                         }, true),
5583                                         p = C.prototype = new Ease();
5584                                 p.constructor = C;
5585                                 p.getRatio = f;
5586                                 p.config = function(overshoot) {
5587                                         return new C(overshoot);
5588                                 };
5589                                 return C;
5590                         },
5591
5592                         Back = _wrap("Back",
5593                                 _createBack("BackOut", function(p) {
5594                                         return ((p = p - 1) * p * ((this._p1 + 1) * p + this._p1) + 1);
5595                                 }),
5596                                 _createBack("BackIn", function(p) {
5597                                         return p * p * ((this._p1 + 1) * p - this._p1);
5598                                 }),
5599                                 _createBack("BackInOut", function(p) {
5600                                         return ((p *= 2) < 1) ? 0.5 * p * p * ((this._p2 + 1) * p - this._p2) : 0.5 * ((p -= 2) * p * ((this._p2 + 1) * p + this._p2) + 2);
5601                                 })
5602                         ),
5603
5604
5605                         //SlowMo
5606                         SlowMo = _class("easing.SlowMo", function(linearRatio, power, yoyoMode) {
5607                                 power = (power || power === 0) ? power : 0.7;
5608                                 if (linearRatio == null) {
5609                                         linearRatio = 0.7;
5610                                 } else if (linearRatio > 1) {
5611                                         linearRatio = 1;
5612                                 }
5613                                 this._p = (linearRatio !== 1) ? power : 0;
5614                                 this._p1 = (1 - linearRatio) / 2;
5615                                 this._p2 = linearRatio;
5616                                 this._p3 = this._p1 + this._p2;
5617                                 this._calcEnd = (yoyoMode === true);
5618                         }, true),
5619                         p = SlowMo.prototype = new Ease(),
5620                         SteppedEase, RoughEase, _createElastic;
5621
5622                 p.constructor = SlowMo;
5623                 p.getRatio = function(p) {
5624                         var r = p + (0.5 - p) * this._p;
5625                         if (p < this._p1) {
5626                                 return this._calcEnd ? 1 - ((p = 1 - (p / this._p1)) * p) : r - ((p = 1 - (p / this._p1)) * p * p * p * r);
5627                         } else if (p > this._p3) {
5628                                 return this._calcEnd ? 1 - (p = (p - this._p3) / this._p1) * p : r + ((p - r) * (p = (p - this._p3) / this._p1) * p * p * p);
5629                         }
5630                         return this._calcEnd ? 1 : r;
5631                 };
5632                 SlowMo.ease = new SlowMo(0.7, 0.7);
5633
5634                 p.config = SlowMo.config = function(linearRatio, power, yoyoMode) {
5635                         return new SlowMo(linearRatio, power, yoyoMode);
5636                 };
5637
5638
5639                 //SteppedEase
5640                 SteppedEase = _class("easing.SteppedEase", function(steps) {
5641                                 steps = steps || 1;
5642                                 this._p1 = 1 / steps;
5643                                 this._p2 = steps + 1;
5644                         }, true);
5645                 p = SteppedEase.prototype = new Ease();
5646                 p.constructor = SteppedEase;
5647                 p.getRatio = function(p) {
5648                         if (p < 0) {
5649                                 p = 0;
5650                         } else if (p >= 1) {
5651                                 p = 0.999999999;
5652                         }
5653                         return ((this._p2 * p) >> 0) * this._p1;
5654                 };
5655                 p.config = SteppedEase.config = function(steps) {
5656                         return new SteppedEase(steps);
5657                 };
5658
5659
5660                 //RoughEase
5661                 RoughEase = _class("easing.RoughEase", function(vars) {
5662                         vars = vars || {};
5663                         var taper = vars.taper || "none",
5664                                 a = [],
5665                                 cnt = 0,
5666                                 points = (vars.points || 20) | 0,
5667                                 i = points,
5668                                 randomize = (vars.randomize !== false),
5669                                 clamp = (vars.clamp === true),
5670                                 template = (vars.template instanceof Ease) ? vars.template : null,
5671                                 strength = (typeof(vars.strength) === "number") ? vars.strength * 0.4 : 0.4,
5672                                 x, y, bump, invX, obj, pnt;
5673                         while (--i > -1) {
5674                                 x = randomize ? Math.random() : (1 / points) * i;
5675                                 y = template ? template.getRatio(x) : x;
5676                                 if (taper === "none") {
5677                                         bump = strength;
5678                                 } else if (taper === "out") {
5679                                         invX = 1 - x;
5680                                         bump = invX * invX * strength;
5681                                 } else if (taper === "in") {
5682                                         bump = x * x * strength;
5683                                 } else if (x < 0.5) {  //"both" (start)
5684                                         invX = x * 2;
5685                                         bump = invX * invX * 0.5 * strength;
5686                                 } else {                                //"both" (end)
5687                                         invX = (1 - x) * 2;
5688                                         bump = invX * invX * 0.5 * strength;
5689                                 }
5690                                 if (randomize) {
5691                                         y += (Math.random() * bump) - (bump * 0.5);
5692                                 } else if (i % 2) {
5693                                         y += bump * 0.5;
5694                                 } else {
5695                                         y -= bump * 0.5;
5696                                 }
5697                                 if (clamp) {
5698                                         if (y > 1) {
5699                                                 y = 1;
5700                                         } else if (y < 0) {
5701                                                 y = 0;
5702                                         }
5703                                 }
5704                                 a[cnt++] = {x:x, y:y};
5705                         }
5706                         a.sort(function(a, b) {
5707                                 return a.x - b.x;
5708                         });
5709
5710                         pnt = new EasePoint(1, 1, null);
5711                         i = points;
5712                         while (--i > -1) {
5713                                 obj = a[i];
5714                                 pnt = new EasePoint(obj.x, obj.y, pnt);
5715                         }
5716
5717                         this._prev = new EasePoint(0, 0, (pnt.t !== 0) ? pnt : pnt.next);
5718                 }, true);
5719                 p = RoughEase.prototype = new Ease();
5720                 p.constructor = RoughEase;
5721                 p.getRatio = function(p) {
5722                         var pnt = this._prev;
5723                         if (p > pnt.t) {
5724                                 while (pnt.next && p >= pnt.t) {
5725                                         pnt = pnt.next;
5726                                 }
5727                                 pnt = pnt.prev;
5728                         } else {
5729                                 while (pnt.prev && p <= pnt.t) {
5730                                         pnt = pnt.prev;
5731                                 }
5732                         }
5733                         this._prev = pnt;
5734                         return (pnt.v + ((p - pnt.t) / pnt.gap) * pnt.c);
5735                 };
5736                 p.config = function(vars) {
5737                         return new RoughEase(vars);
5738                 };
5739                 RoughEase.ease = new RoughEase();
5740
5741
5742                 //Bounce
5743                 _wrap("Bounce",
5744                         _create("BounceOut", function(p) {
5745                                 if (p < 1 / 2.75) {
5746                                         return 7.5625 * p * p;
5747                                 } else if (p < 2 / 2.75) {
5748                                         return 7.5625 * (p -= 1.5 / 2.75) * p + 0.75;
5749                                 } else if (p < 2.5 / 2.75) {
5750                                         return 7.5625 * (p -= 2.25 / 2.75) * p + 0.9375;
5751                                 }
5752                                 return 7.5625 * (p -= 2.625 / 2.75) * p + 0.984375;
5753                         }),
5754                         _create("BounceIn", function(p) {
5755                                 if ((p = 1 - p) < 1 / 2.75) {
5756                                         return 1 - (7.5625 * p * p);
5757                                 } else if (p < 2 / 2.75) {
5758                                         return 1 - (7.5625 * (p -= 1.5 / 2.75) * p + 0.75);
5759                                 } else if (p < 2.5 / 2.75) {
5760                                         return 1 - (7.5625 * (p -= 2.25 / 2.75) * p + 0.9375);
5761                                 }
5762                                 return 1 - (7.5625 * (p -= 2.625 / 2.75) * p + 0.984375);
5763                         }),
5764                         _create("BounceInOut", function(p) {
5765                                 var invert = (p < 0.5);
5766                                 if (invert) {
5767                                         p = 1 - (p * 2);
5768                                 } else {
5769                                         p = (p * 2) - 1;
5770                                 }
5771                                 if (p < 1 / 2.75) {
5772                                         p = 7.5625 * p * p;
5773                                 } else if (p < 2 / 2.75) {
5774                                         p = 7.5625 * (p -= 1.5 / 2.75) * p + 0.75;
5775                                 } else if (p < 2.5 / 2.75) {
5776                                         p = 7.5625 * (p -= 2.25 / 2.75) * p + 0.9375;
5777                                 } else {
5778                                         p = 7.5625 * (p -= 2.625 / 2.75) * p + 0.984375;
5779                                 }
5780                                 return invert ? (1 - p) * 0.5 : p * 0.5 + 0.5;
5781                         })
5782                 );
5783
5784
5785                 //CIRC
5786                 _wrap("Circ",
5787                         _create("CircOut", function(p) {
5788                                 return Math.sqrt(1 - (p = p - 1) * p);
5789                         }),
5790                         _create("CircIn", function(p) {
5791                                 return -(Math.sqrt(1 - (p * p)) - 1);
5792                         }),
5793                         _create("CircInOut", function(p) {
5794                                 return ((p*=2) < 1) ? -0.5 * (Math.sqrt(1 - p * p) - 1) : 0.5 * (Math.sqrt(1 - (p -= 2) * p) + 1);
5795                         })
5796                 );
5797
5798
5799                 //Elastic
5800                 _createElastic = function(n, f, def) {
5801                         var C = _class("easing." + n, function(amplitude, period) {
5802                                         this._p1 = amplitude || 1;
5803                                         this._p2 = period || def;
5804                                         this._p3 = this._p2 / _2PI * (Math.asin(1 / this._p1) || 0);
5805                                 }, true),
5806                                 p = C.prototype = new Ease();
5807                         p.constructor = C;
5808                         p.getRatio = f;
5809                         p.config = function(amplitude, period) {
5810                                 return new C(amplitude, period);
5811                         };
5812                         return C;
5813                 };
5814                 _wrap("Elastic",
5815                         _createElastic("ElasticOut", function(p) {
5816                                 return this._p1 * Math.pow(2, -10 * p) * Math.sin( (p - this._p3) * _2PI / this._p2 ) + 1;
5817                         }, 0.3),
5818                         _createElastic("ElasticIn", function(p) {
5819                                 return -(this._p1 * Math.pow(2, 10 * (p -= 1)) * Math.sin( (p - this._p3) * _2PI / this._p2 ));
5820                         }, 0.3),
5821                         _createElastic("ElasticInOut", function(p) {
5822                                 return ((p *= 2) < 1) ? -0.5 * (this._p1 * Math.pow(2, 10 * (p -= 1)) * Math.sin( (p - this._p3) * _2PI / this._p2)) : this._p1 * Math.pow(2, -10 *(p -= 1)) * Math.sin( (p - this._p3) * _2PI / this._p2 ) *0.5 + 1;
5823                         }, 0.45)
5824                 );
5825
5826
5827                 //Expo
5828                 _wrap("Expo",
5829                         _create("ExpoOut", function(p) {
5830                                 return 1 - Math.pow(2, -10 * p);
5831                         }),
5832                         _create("ExpoIn", function(p) {
5833                                 return Math.pow(2, 10 * (p - 1)) - 0.001;
5834                         }),
5835                         _create("ExpoInOut", function(p) {
5836                                 return ((p *= 2) < 1) ? 0.5 * Math.pow(2, 10 * (p - 1)) : 0.5 * (2 - Math.pow(2, -10 * (p - 1)));
5837                         })
5838                 );
5839
5840
5841                 //Sine
5842                 _wrap("Sine",
5843                         _create("SineOut", function(p) {
5844                                 return Math.sin(p * _HALF_PI);
5845                         }),
5846                         _create("SineIn", function(p) {
5847                                 return -Math.cos(p * _HALF_PI) + 1;
5848                         }),
5849                         _create("SineInOut", function(p) {
5850                                 return -0.5 * (Math.cos(Math.PI * p) - 1);
5851                         })
5852                 );
5853
5854                 _class("easing.EaseLookup", {
5855                                 find:function(s) {
5856                                         return Ease.map[s];
5857                                 }
5858                         }, true);
5859
5860                 //register the non-standard eases
5861                 _easeReg(w.SlowMo, "SlowMo", "ease,");
5862                 _easeReg(RoughEase, "RoughEase", "ease,");
5863                 _easeReg(SteppedEase, "SteppedEase", "ease,");
5864
5865                 return Back;
5866                 
5867         }, true);
5868
5869
5870 }); 
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882 /*
5883  * ----------------------------------------------------------------
5884  * Base classes like TweenLite, SimpleTimeline, Ease, Ticker, etc.
5885  * ----------------------------------------------------------------
5886  */
5887 (function(window) {
5888
5889                 "use strict";
5890                 var _globals = window.GreenSockGlobals || window;
5891                 if (_globals.TweenLite) {
5892                         return; //in case the core set of classes is already loaded, don't instantiate twice.
5893                 }
5894                 var _namespace = function(ns) {
5895                                 var a = ns.split("."),
5896                                         p = _globals, i;
5897                                 for (i = 0; i < a.length; i++) {
5898                                         p[a[i]] = p = p[a[i]] || {};
5899                                 }
5900                                 return p;
5901                         },
5902                         gs = _namespace("com.greensock"),
5903                         _tinyNum = 0.0000000001,
5904                         _slice = [].slice,
5905                         _emptyFunc = function() {},
5906                         _isArray = (function() { //works around issues in iframe environments where the Array global isn't shared, thus if the object originates in a different window/iframe, "(obj instanceof Array)" will evaluate false. We added some speed optimizations to avoid Object.prototype.toString.call() unless it's absolutely necessary because it's VERY slow (like 20x slower)
5907                                 var toString = Object.prototype.toString,
5908                                         array = toString.call([]);
5909                                 return function(obj) {
5910                                         return obj != null && (obj instanceof Array || (typeof(obj) === "object" && !!obj.push && toString.call(obj) === array));
5911                                 };
5912                         }()),
5913                         a, i, p, _ticker, _tickerActive,
5914                         _defLookup = {},
5915
5916                         /**
5917                          * @constructor
5918                          * Defines a GreenSock class, optionally with an array of dependencies that must be instantiated first and passed into the definition.
5919                          * This allows users to load GreenSock JS files in any order even if they have interdependencies (like CSSPlugin extends TweenPlugin which is
5920                          * inside TweenLite.js, but if CSSPlugin is loaded first, it should wait to run its code until TweenLite.js loads and instantiates TweenPlugin
5921                          * and then pass TweenPlugin to CSSPlugin's definition). This is all done automatically and internally.
5922                          *
5923                          * Every definition will be added to a "com.greensock" global object (typically window, but if a window.GreenSockGlobals object is found,
5924                          * it will go there as of v1.7). For example, TweenLite will be found at window.com.greensock.TweenLite and since it's a global class that should be available anywhere,
5925                          * it is ALSO referenced at window.TweenLite. However some classes aren't considered global, like the base com.greensock.core.Animation class, so
5926                          * those will only be at the package like window.com.greensock.core.Animation. Again, if you define a GreenSockGlobals object on the window, everything
5927                          * gets tucked neatly inside there instead of on the window directly. This allows you to do advanced things like load multiple versions of GreenSock
5928                          * files and put them into distinct objects (imagine a banner ad uses a newer version but the main site uses an older one). In that case, you could
5929                          * sandbox the banner one like:
5930                          *
5931                          * <script>
5932                          *     var gs = window.GreenSockGlobals = {}; //the newer version we're about to load could now be referenced in a "gs" object, like gs.TweenLite.to(...). Use whatever alias you want as long as it's unique, "gs" or "banner" or whatever.
5933                          * </script>
5934                          * <script src="js/greensock/v1.7/TweenMax.js"></script>
5935                          * <script>
5936                          *     window.GreenSockGlobals = null; //reset it back to null so that the next load of TweenMax affects the window and we can reference things directly like TweenLite.to(...)
5937                          * </script>
5938                          * <script src="js/greensock/v1.6/TweenMax.js"></script>
5939                          * <script>
5940                          *     gs.TweenLite.to(...); //would use v1.7
5941                          *     TweenLite.to(...); //would use v1.6
5942                          * </script>
5943                          *
5944                          * @param {!string} ns The namespace of the class definition, leaving off "com.greensock." as that's assumed. For example, "TweenLite" or "plugins.CSSPlugin" or "easing.Back".
5945                          * @param {!Array.<string>} dependencies An array of dependencies (described as their namespaces minus "com.greensock." prefix). For example ["TweenLite","plugins.TweenPlugin","core.Animation"]
5946                          * @param {!function():Object} func The function that should be called and passed the resolved dependencies which will return the actual class for this definition.
5947                          * @param {boolean=} global If true, the class will be added to the global scope (typically window unless you define a window.GreenSockGlobals object)
5948                          */
5949                         Definition = function(ns, dependencies, func, global) {
5950                                 this.sc = (_defLookup[ns]) ? _defLookup[ns].sc : []; //subclasses
5951                                 _defLookup[ns] = this;
5952                                 this.gsClass = null;
5953                                 this.func = func;
5954                                 var _classes = [];
5955                                 this.check = function(init) {
5956                                         var i = dependencies.length,
5957                                                 missing = i,
5958                                                 cur, a, n, cl;
5959                                         while (--i > -1) {
5960                                                 if ((cur = _defLookup[dependencies[i]] || new Definition(dependencies[i], [])).gsClass) {
5961                                                         _classes[i] = cur.gsClass;
5962                                                         missing--;
5963                                                 } else if (init) {
5964                                                         cur.sc.push(this);
5965                                                 }
5966                                         }
5967                                         if (missing === 0 && func) {
5968                                                 a = ("com.greensock." + ns).split(".");
5969                                                 n = a.pop();
5970                                                 cl = _namespace(a.join("."))[n] = this.gsClass = func.apply(func, _classes);
5971
5972                                                 //exports to multiple environments
5973                                                 if (global) {
5974                                                         _globals[n] = cl; //provides a way to avoid global namespace pollution. By default, the main classes like TweenLite, Power1, Strong, etc. are added to window unless a GreenSockGlobals is defined. So if you want to have things added to a custom object instead, just do something like window.GreenSockGlobals = {} before loading any GreenSock files. You can even set up an alias like window.GreenSockGlobals = windows.gs = {} so that you can access everything like gs.TweenLite. Also remember that ALL classes are added to the window.com.greensock object (in their respective packages, like com.greensock.easing.Power1, com.greensock.TweenLite, etc.)
5975                                                         if (typeof(define) === "function" && define.amd){ //AMD
5976                                                                 define((window.GreenSockAMDPath ? window.GreenSockAMDPath + "/" : "") + ns.split(".").join("/"), [], function() { return cl; });
5977                                                         } else if (typeof(module) !== "undefined" && module.exports){ //node
5978                                                                 module.exports = cl;
5979                                                         }
5980                                                 }
5981                                                 for (i = 0; i < this.sc.length; i++) {
5982                                                         this.sc[i].check();
5983                                                 }
5984                                         }
5985                                 };
5986                                 this.check(true);
5987                         },
5988
5989                         //used to create Definition instances (which basically registers a class that has dependencies).
5990                         _gsDefine = window._gsDefine = function(ns, dependencies, func, global) {
5991                                 return new Definition(ns, dependencies, func, global);
5992                         },
5993
5994                         //a quick way to create a class that doesn't have any dependencies. Returns the class, but first registers it in the GreenSock namespace so that other classes can grab it (other classes might be dependent on the class).
5995                         _class = gs._class = function(ns, func, global) {
5996                                 func = func || function() {};
5997                                 _gsDefine(ns, [], function(){ return func; }, global);
5998                                 return func;
5999                         };
6000
6001                 _gsDefine.globals = _globals;
6002
6003
6004
6005 /*
6006  * ----------------------------------------------------------------
6007  * Ease
6008  * ----------------------------------------------------------------
6009  */
6010                 var _baseParams = [0, 0, 1, 1],
6011                         _blankArray = [],
6012                         Ease = _class("easing.Ease", function(func, extraParams, type, power) {
6013                                 this._func = func;
6014                                 this._type = type || 0;
6015                                 this._power = power || 0;
6016                                 this._params = extraParams ? _baseParams.concat(extraParams) : _baseParams;
6017                         }, true),
6018                         _easeMap = Ease.map = {},
6019                         _easeReg = Ease.register = function(ease, names, types, create) {
6020                                 var na = names.split(","),
6021                                         i = na.length,
6022                                         ta = (types || "easeIn,easeOut,easeInOut").split(","),
6023                                         e, name, j, type;
6024                                 while (--i > -1) {
6025                                         name = na[i];
6026                                         e = create ? _class("easing."+name, null, true) : gs.easing[name] || {};
6027                                         j = ta.length;
6028                                         while (--j > -1) {
6029                                                 type = ta[j];
6030                                                 _easeMap[name + "." + type] = _easeMap[type + name] = e[type] = ease.getRatio ? ease : ease[type] || new ease();
6031                                         }
6032                                 }
6033                         };
6034
6035                 p = Ease.prototype;
6036                 p._calcEnd = false;
6037                 p.getRatio = function(p) {
6038                         if (this._func) {
6039                                 this._params[0] = p;
6040                                 return this._func.apply(null, this._params);
6041                         }
6042                         var t = this._type,
6043                                 pw = this._power,
6044                                 r = (t === 1) ? 1 - p : (t === 2) ? p : (p < 0.5) ? p * 2 : (1 - p) * 2;
6045                         if (pw === 1) {
6046                                 r *= r;
6047                         } else if (pw === 2) {
6048                                 r *= r * r;
6049                         } else if (pw === 3) {
6050                                 r *= r * r * r;
6051                         } else if (pw === 4) {
6052                                 r *= r * r * r * r;
6053                         }
6054                         return (t === 1) ? 1 - r : (t === 2) ? r : (p < 0.5) ? r / 2 : 1 - (r / 2);
6055                 };
6056
6057                 //create all the standard eases like Linear, Quad, Cubic, Quart, Quint, Strong, Power0, Power1, Power2, Power3, and Power4 (each with easeIn, easeOut, and easeInOut)
6058                 a = ["Linear","Quad","Cubic","Quart","Quint,Strong"];
6059                 i = a.length;
6060                 while (--i > -1) {
6061                         p = a[i]+",Power"+i;
6062                         _easeReg(new Ease(null,null,1,i), p, "easeOut", true);
6063                         _easeReg(new Ease(null,null,2,i), p, "easeIn" + ((i === 0) ? ",easeNone" : ""));
6064                         _easeReg(new Ease(null,null,3,i), p, "easeInOut");
6065                 }
6066                 _easeMap.linear = gs.easing.Linear.easeIn;
6067                 _easeMap.swing = gs.easing.Quad.easeInOut; //for jQuery folks
6068
6069
6070 /*
6071  * ----------------------------------------------------------------
6072  * EventDispatcher
6073  * ----------------------------------------------------------------
6074  */
6075                 var EventDispatcher = _class("events.EventDispatcher", function(target) {
6076                         this._listeners = {};
6077                         this._eventTarget = target || this;
6078                 });
6079                 p = EventDispatcher.prototype;
6080
6081                 p.addEventListener = function(type, callback, scope, useParam, priority) {
6082                         priority = priority || 0;
6083                         var list = this._listeners[type],
6084                                 index = 0,
6085                                 listener, i;
6086                         if (list == null) {
6087                                 this._listeners[type] = list = [];
6088                         }
6089                         i = list.length;
6090                         while (--i > -1) {
6091                                 listener = list[i];
6092                                 if (listener.c === callback && listener.s === scope) {
6093                                         list.splice(i, 1);
6094                                 } else if (index === 0 && listener.pr < priority) {
6095                                         index = i + 1;
6096                                 }
6097                         }
6098                         list.splice(index, 0, {c:callback, s:scope, up:useParam, pr:priority});
6099                         if (this === _ticker && !_tickerActive) {
6100                                 _ticker.wake();
6101                         }
6102                 };
6103
6104                 p.removeEventListener = function(type, callback) {
6105                         var list = this._listeners[type], i;
6106                         if (list) {
6107                                 i = list.length;
6108                                 while (--i > -1) {
6109                                         if (list[i].c === callback) {
6110                                                 list.splice(i, 1);
6111                                                 return;
6112                                         }
6113                                 }
6114                         }
6115                 };
6116
6117                 p.dispatchEvent = function(type) {
6118                         var list = this._listeners[type],
6119                                 i, t, listener;
6120                         if (list) {
6121                                 i = list.length;
6122                                 t = this._eventTarget;
6123                                 while (--i > -1) {
6124                                         listener = list[i];
6125                                         if (listener.up) {
6126                                                 listener.c.call(listener.s || t, {type:type, target:t});
6127                                         } else {
6128                                                 listener.c.call(listener.s || t);
6129                                         }
6130                                 }
6131                         }
6132                 };
6133
6134
6135 /*
6136  * ----------------------------------------------------------------
6137  * Ticker
6138  * ----------------------------------------------------------------
6139  */
6140                 var _reqAnimFrame = window.requestAnimationFrame,
6141                         _cancelAnimFrame = window.cancelAnimationFrame,
6142                         _getTime = Date.now || function() {return new Date().getTime();},
6143                         _lastUpdate = _getTime();
6144
6145                 //now try to determine the requestAnimationFrame and cancelAnimationFrame functions and if none are found, we'll use a setTimeout()/clearTimeout() polyfill.
6146                 a = ["ms","moz","webkit","o"];
6147                 i = a.length;
6148                 while (--i > -1 && !_reqAnimFrame) {
6149                         _reqAnimFrame = window[a[i] + "RequestAnimationFrame"];
6150                         _cancelAnimFrame = window[a[i] + "CancelAnimationFrame"] || window[a[i] + "CancelRequestAnimationFrame"];
6151                 }
6152
6153                 _class("Ticker", function(fps, useRAF) {
6154                         var _self = this,
6155                                 _startTime = _getTime(),
6156                                 _useRAF = (useRAF !== false && _reqAnimFrame),
6157                                 _lagThreshold = 500,
6158                                 _adjustedLag = 33,
6159                                 _fps, _req, _id, _gap, _nextTime,
6160                                 _tick = function(manual) {
6161                                         var elapsed = _getTime() - _lastUpdate,
6162                                                 overlap, dispatch;
6163                                         if (elapsed > _lagThreshold) {
6164                                                 _startTime += elapsed - _adjustedLag;
6165                                         }
6166                                         _lastUpdate += elapsed;
6167                                         _self.time = (_lastUpdate - _startTime) / 1000;
6168                                         overlap = _self.time - _nextTime;
6169                                         if (!_fps || overlap > 0 || manual === true) {
6170                                                 _self.frame++;
6171                                                 _nextTime += overlap + (overlap >= _gap ? 0.004 : _gap - overlap);
6172                                                 dispatch = true;
6173                                         }
6174                                         if (manual !== true) { //make sure the request is made before we dispatch the "tick" event so that timing is maintained. Otherwise, if processing the "tick" requires a bunch of time (like 15ms) and we're using a setTimeout() that's based on 16.7ms, it'd technically take 31.7ms between frames otherwise.
6175                                                 _id = _req(_tick);
6176                                         }
6177                                         if (dispatch) {
6178                                                 _self.dispatchEvent("tick");
6179                                         }
6180                                 };
6181
6182                         EventDispatcher.call(_self);
6183                         _self.time = _self.frame = 0;
6184                         _self.tick = function() {
6185                                 _tick(true);
6186                         };
6187
6188                         _self.lagSmoothing = function(threshold, adjustedLag) {
6189                                 _lagThreshold = threshold || (1 / _tinyNum); //zero should be interpreted as basically unlimited
6190                                 _adjustedLag = Math.min(adjustedLag, _lagThreshold, 0);
6191                         };
6192
6193                         _self.sleep = function() {
6194                                 if (_id == null) {
6195                                         return;
6196                                 }
6197                                 if (!_useRAF || !_cancelAnimFrame) {
6198                                         clearTimeout(_id);
6199                                 } else {
6200                                         _cancelAnimFrame(_id);
6201                                 }
6202                                 _req = _emptyFunc;
6203                                 _id = null;
6204                                 if (_self === _ticker) {
6205                                         _tickerActive = false;
6206                                 }
6207                         };
6208
6209                         _self.wake = function() {
6210                                 if (_id !== null) {
6211                                         _self.sleep();
6212                                 } else if (_self.frame > 10) { //don't trigger lagSmoothing if we're just waking up, and make sure that at least 10 frames have elapsed because of the iOS bug that we work around below with the 1.5-second setTimout().
6213                                         _lastUpdate = _getTime() - _lagThreshold + 5;
6214                                 }
6215                                 _req = (_fps === 0) ? _emptyFunc : (!_useRAF || !_reqAnimFrame) ? function(f) { return setTimeout(f, ((_nextTime - _self.time) * 1000 + 1) | 0); } : _reqAnimFrame;
6216                                 if (_self === _ticker) {
6217                                         _tickerActive = true;
6218                                 }
6219                                 _tick(2);
6220                         };
6221
6222                         _self.fps = function(value) {
6223                                 if (!arguments.length) {
6224                                         return _fps;
6225                                 }
6226                                 _fps = value;
6227                                 _gap = 1 / (_fps || 60);
6228                                 _nextTime = this.time + _gap;
6229                                 _self.wake();
6230                         };
6231
6232                         _self.useRAF = function(value) {
6233                                 if (!arguments.length) {
6234                                         return _useRAF;
6235                                 }
6236                                 _self.sleep();
6237                                 _useRAF = value;
6238                                 _self.fps(_fps);
6239                         };
6240                         _self.fps(fps);
6241
6242                         //a bug in iOS 6 Safari occasionally prevents the requestAnimationFrame from working initially, so we use a 1.5-second timeout that automatically falls back to setTimeout() if it senses this condition.
6243                         setTimeout(function() {
6244                                 if (_useRAF && (!_id || _self.frame < 5)) {
6245                                         _self.useRAF(false);
6246                                 }
6247                         }, 1500);
6248                 });
6249
6250                 p = gs.Ticker.prototype = new gs.events.EventDispatcher();
6251                 p.constructor = gs.Ticker;
6252
6253
6254 /*
6255  * ----------------------------------------------------------------
6256  * Animation
6257  * ----------------------------------------------------------------
6258  */
6259                 var Animation = _class("core.Animation", function(duration, vars) {
6260                                 this.vars = vars = vars || {};
6261                                 this._duration = this._totalDuration = duration || 0;
6262                                 this._delay = Number(vars.delay) || 0;
6263                                 this._timeScale = 1;
6264                                 this._active = (vars.immediateRender === true);
6265                                 this.data = vars.data;
6266                                 this._reversed = (vars.reversed === true);
6267
6268                                 if (!_rootTimeline) {
6269                                         return;
6270                                 }
6271                                 if (!_tickerActive) { //some browsers (like iOS 6 Safari) shut down JavaScript execution when the tab is disabled and they [occasionally] neglect to start up requestAnimationFrame again when returning - this code ensures that the engine starts up again properly.
6272                                         _ticker.wake();
6273                                 }
6274
6275                                 var tl = this.vars.useFrames ? _rootFramesTimeline : _rootTimeline;
6276                                 tl.add(this, tl._time);
6277
6278                                 if (this.vars.paused) {
6279                                         this.paused(true);
6280                                 }
6281                         });
6282
6283                 _ticker = Animation.ticker = new gs.Ticker();
6284                 p = Animation.prototype;
6285                 p._dirty = p._gc = p._initted = p._paused = false;
6286                 p._totalTime = p._time = 0;
6287                 p._rawPrevTime = -1;
6288                 p._next = p._last = p._onUpdate = p._timeline = p.timeline = null;
6289                 p._paused = false;
6290
6291
6292                 //some browsers (like iOS) occasionally drop the requestAnimationFrame event when the user switches to a different tab and then comes back again, so we use a 2-second setTimeout() to sense if/when that condition occurs and then wake() the ticker.
6293                 var _checkTimeout = function() {
6294                                 if (_tickerActive && _getTime() - _lastUpdate > 2000) {
6295                                         _ticker.wake();
6296                                 }
6297                                 setTimeout(_checkTimeout, 2000);
6298                         };
6299                 _checkTimeout();
6300
6301
6302                 p.play = function(from, suppressEvents) {
6303                         if (from != null) {
6304                                 this.seek(from, suppressEvents);
6305                         }
6306                         return this.reversed(false).paused(false);
6307                 };
6308
6309                 p.pause = function(atTime, suppressEvents) {
6310                         if (atTime != null) {
6311                                 this.seek(atTime, suppressEvents);
6312                         }
6313                         return this.paused(true);
6314                 };
6315
6316                 p.resume = function(from, suppressEvents) {
6317                         if (from != null) {
6318                                 this.seek(from, suppressEvents);
6319                         }
6320                         return this.paused(false);
6321                 };
6322
6323                 p.seek = function(time, suppressEvents) {
6324                         return this.totalTime(Number(time), suppressEvents !== false);
6325                 };
6326
6327                 p.restart = function(includeDelay, suppressEvents) {
6328                         return this.reversed(false).paused(false).totalTime(includeDelay ? -this._delay : 0, (suppressEvents !== false), true);
6329                 };
6330
6331                 p.reverse = function(from, suppressEvents) {
6332                         if (from != null) {
6333                                 this.seek((from || this.totalDuration()), suppressEvents);
6334                         }
6335                         return this.reversed(true).paused(false);
6336                 };
6337
6338                 p.render = function(time, suppressEvents, force) {
6339                         //stub - we override this method in subclasses.
6340                 };
6341
6342                 p.invalidate = function() {
6343                         return this;
6344                 };
6345
6346                 p.isActive = function() {
6347                         var tl = this._timeline, //the 2 root timelines won't have a _timeline; they're always active.
6348                                 startTime = this._startTime,
6349                                 rawTime;
6350                         return (!tl || (!this._gc && !this._paused && tl.isActive() && (rawTime = tl.rawTime()) >= startTime && rawTime < startTime + this.totalDuration() / this._timeScale));
6351                 };
6352
6353                 p._enabled = function (enabled, ignoreTimeline) {
6354                         if (!_tickerActive) {
6355                                 _ticker.wake();
6356                         }
6357                         this._gc = !enabled;
6358                         this._active = this.isActive();
6359                         if (ignoreTimeline !== true) {
6360                                 if (enabled && !this.timeline) {
6361                                         this._timeline.add(this, this._startTime - this._delay);
6362                                 } else if (!enabled && this.timeline) {
6363                                         this._timeline._remove(this, true);
6364                                 }
6365                         }
6366                         return false;
6367                 };
6368
6369
6370                 p._kill = function(vars, target) {
6371                         return this._enabled(false, false);
6372                 };
6373
6374                 p.kill = function(vars, target) {
6375                         this._kill(vars, target);
6376                         return this;
6377                 };
6378
6379                 p._uncache = function(includeSelf) {
6380                         var tween = includeSelf ? this : this.timeline;
6381                         while (tween) {
6382                                 tween._dirty = true;
6383                                 tween = tween.timeline;
6384                         }
6385                         return this;
6386                 };
6387
6388                 p._swapSelfInParams = function(params) {
6389                         var i = params.length,
6390                                 copy = params.concat();
6391                         while (--i > -1) {
6392                                 if (params[i] === "{self}") {
6393                                         copy[i] = this;
6394                                 }
6395                         }
6396                         return copy;
6397                 };
6398
6399 //----Animation getters/setters --------------------------------------------------------
6400
6401                 p.eventCallback = function(type, callback, params, scope) {
6402                         if ((type || "").substr(0,2) === "on") {
6403                                 var v = this.vars;
6404                                 if (arguments.length === 1) {
6405                                         return v[type];
6406                                 }
6407                                 if (callback == null) {
6408                                         delete v[type];
6409                                 } else {
6410                                         v[type] = callback;
6411                                         v[type + "Params"] = (_isArray(params) && params.join("").indexOf("{self}") !== -1) ? this._swapSelfInParams(params) : params;
6412                                         v[type + "Scope"] = scope;
6413                                 }
6414                                 if (type === "onUpdate") {
6415                                         this._onUpdate = callback;
6416                                 }
6417                         }
6418                         return this;
6419                 };
6420
6421                 p.delay = function(value) {
6422                         if (!arguments.length) {
6423                                 return this._delay;
6424                         }
6425                         if (this._timeline.smoothChildTiming) {
6426                                 this.startTime( this._startTime + value - this._delay );
6427                         }
6428                         this._delay = value;
6429                         return this;
6430                 };
6431
6432                 p.duration = function(value) {
6433                         if (!arguments.length) {
6434                                 this._dirty = false;
6435                                 return this._duration;
6436                         }
6437                         this._duration = this._totalDuration = value;
6438                         this._uncache(true); //true in case it's a TweenMax or TimelineMax that has a repeat - we'll need to refresh the totalDuration.
6439                         if (this._timeline.smoothChildTiming) if (this._time > 0) if (this._time < this._duration) if (value !== 0) {
6440                                 this.totalTime(this._totalTime * (value / this._duration), true);
6441                         }
6442                         return this;
6443                 };
6444
6445                 p.totalDuration = function(value) {
6446                         this._dirty = false;
6447                         return (!arguments.length) ? this._totalDuration : this.duration(value);
6448                 };
6449
6450                 p.time = function(value, suppressEvents) {
6451                         if (!arguments.length) {
6452                                 return this._time;
6453                         }
6454                         if (this._dirty) {
6455                                 this.totalDuration();
6456                         }
6457                         return this.totalTime((value > this._duration) ? this._duration : value, suppressEvents);
6458                 };
6459
6460                 p.totalTime = function(time, suppressEvents, uncapped) {
6461                         if (!_tickerActive) {
6462                                 _ticker.wake();
6463                         }
6464                         if (!arguments.length) {
6465                                 return this._totalTime;
6466                         }
6467                         if (this._timeline) {
6468                                 if (time < 0 && !uncapped) {
6469                                         time += this.totalDuration();
6470                                 }
6471                                 if (this._timeline.smoothChildTiming) {
6472                                         if (this._dirty) {
6473                                                 this.totalDuration();
6474                                         }
6475                                         var totalDuration = this._totalDuration,
6476                                                 tl = this._timeline;
6477                                         if (time > totalDuration && !uncapped) {
6478                                                 time = totalDuration;
6479                                         }
6480                                         this._startTime = (this._paused ? this._pauseTime : tl._time) - ((!this._reversed ? time : totalDuration - time) / this._timeScale);
6481                                         if (!tl._dirty) { //for performance improvement. If the parent's cache is already dirty, it already took care of marking the ancestors as dirty too, so skip the function call here.
6482                                                 this._uncache(false);
6483                                         }
6484                                         //in case any of the ancestor timelines had completed but should now be enabled, we should reset their totalTime() which will also ensure that they're lined up properly and enabled. Skip for animations that are on the root (wasteful). Example: a TimelineLite.exportRoot() is performed when there's a paused tween on the root, the export will not complete until that tween is unpaused, but imagine a child gets restarted later, after all [unpaused] tweens have completed. The startTime of that child would get pushed out, but one of the ancestors may have completed.
6485                                         if (tl._timeline) {
6486                                                 while (tl._timeline) {
6487                                                         if (tl._timeline._time !== (tl._startTime + tl._totalTime) / tl._timeScale) {
6488                                                                 tl.totalTime(tl._totalTime, true);
6489                                                         }
6490                                                         tl = tl._timeline;
6491                                                 }
6492                                         }
6493                                 }
6494                                 if (this._gc) {
6495                                         this._enabled(true, false);
6496                                 }
6497                                 if (this._totalTime !== time || this._duration === 0) {
6498                                         this.render(time, suppressEvents, false);
6499                                         if (_lazyTweens.length) { //in case rendering caused any tweens to lazy-init, we should render them because typically when someone calls seek() or time() or progress(), they expect an immediate render.
6500                                                 _lazyRender();
6501                                         }
6502                                 }
6503                         }
6504                         return this;
6505                 };
6506
6507                 p.progress = p.totalProgress = function(value, suppressEvents) {
6508                         return (!arguments.length) ? this._time / this.duration() : this.totalTime(this.duration() * value, suppressEvents);
6509                 };
6510
6511                 p.startTime = function(value) {
6512                         if (!arguments.length) {
6513                                 return this._startTime;
6514                         }
6515                         if (value !== this._startTime) {
6516                                 this._startTime = value;
6517                                 if (this.timeline) if (this.timeline._sortChildren) {
6518                                         this.timeline.add(this, value - this._delay); //ensures that any necessary re-sequencing of Animations in the timeline occurs to make sure the rendering order is correct.
6519                                 }
6520                         }
6521                         return this;
6522                 };
6523
6524                 p.timeScale = function(value) {
6525                         if (!arguments.length) {
6526                                 return this._timeScale;
6527                         }
6528                         value = value || _tinyNum; //can't allow zero because it'll throw the math off
6529                         if (this._timeline && this._timeline.smoothChildTiming) {
6530                                 var pauseTime = this._pauseTime,
6531                                         t = (pauseTime || pauseTime === 0) ? pauseTime : this._timeline.totalTime();
6532                                 this._startTime = t - ((t - this._startTime) * this._timeScale / value);
6533                         }
6534                         this._timeScale = value;
6535                         return this._uncache(false);
6536                 };
6537
6538                 p.reversed = function(value) {
6539                         if (!arguments.length) {
6540                                 return this._reversed;
6541                         }
6542                         if (value != this._reversed) {
6543                                 this._reversed = value;
6544                                 this.totalTime(((this._timeline && !this._timeline.smoothChildTiming) ? this.totalDuration() - this._totalTime : this._totalTime), true);
6545                         }
6546                         return this;
6547                 };
6548
6549                 p.paused = function(value) {
6550                         if (!arguments.length) {
6551                                 return this._paused;
6552                         }
6553                         if (value != this._paused) if (this._timeline) {
6554                                 if (!_tickerActive && !value) {
6555                                         _ticker.wake();
6556                                 }
6557                                 var tl = this._timeline,
6558                                         raw = tl.rawTime(),
6559                                         elapsed = raw - this._pauseTime;
6560                                 if (!value && tl.smoothChildTiming) {
6561                                         this._startTime += elapsed;
6562                                         this._uncache(false);
6563                                 }
6564                                 this._pauseTime = value ? raw : null;
6565                                 this._paused = value;
6566                                 this._active = this.isActive();
6567                                 if (!value && elapsed !== 0 && this._initted && this.duration()) {
6568                                         this.render((tl.smoothChildTiming ? this._totalTime : (raw - this._startTime) / this._timeScale), true, true); //in case the target's properties changed via some other tween or manual update by the user, we should force a render.
6569                                 }
6570                         }
6571                         if (this._gc && !value) {
6572                                 this._enabled(true, false);
6573                         }
6574                         return this;
6575                 };
6576
6577
6578 /*
6579  * ----------------------------------------------------------------
6580  * SimpleTimeline
6581  * ----------------------------------------------------------------
6582  */
6583                 var SimpleTimeline = _class("core.SimpleTimeline", function(vars) {
6584                         Animation.call(this, 0, vars);
6585                         this.autoRemoveChildren = this.smoothChildTiming = true;
6586                 });
6587
6588                 p = SimpleTimeline.prototype = new Animation();
6589                 p.constructor = SimpleTimeline;
6590                 p.kill()._gc = false;
6591                 p._first = p._last = null;
6592                 p._sortChildren = false;
6593
6594                 p.add = p.insert = function(child, position, align, stagger) {
6595                         var prevTween, st;
6596                         child._startTime = Number(position || 0) + child._delay;
6597                         if (child._paused) if (this !== child._timeline) { //we only adjust the _pauseTime if it wasn't in this timeline already. Remember, sometimes a tween will be inserted again into the same timeline when its startTime is changed so that the tweens in the TimelineLite/Max are re-ordered properly in the linked list (so everything renders in the proper order).
6598                                 child._pauseTime = child._startTime + ((this.rawTime() - child._startTime) / child._timeScale);
6599                         }
6600                         if (child.timeline) {
6601                                 child.timeline._remove(child, true); //removes from existing timeline so that it can be properly added to this one.
6602                         }
6603                         child.timeline = child._timeline = this;
6604                         if (child._gc) {
6605                                 child._enabled(true, true);
6606                         }
6607                         prevTween = this._last;
6608                         if (this._sortChildren) {
6609                                 st = child._startTime;
6610                                 while (prevTween && prevTween._startTime > st) {
6611                                         prevTween = prevTween._prev;
6612                                 }
6613                         }
6614                         if (prevTween) {
6615                                 child._next = prevTween._next;
6616                                 prevTween._next = child;
6617                         } else {
6618                                 child._next = this._first;
6619                                 this._first = child;
6620                         }
6621                         if (child._next) {
6622                                 child._next._prev = child;
6623                         } else {
6624                                 this._last = child;
6625                         }
6626                         child._prev = prevTween;
6627                         if (this._timeline) {
6628                                 this._uncache(true);
6629                         }
6630                         return this;
6631                 };
6632
6633                 p._remove = function(tween, skipDisable) {
6634                         if (tween.timeline === this) {
6635                                 if (!skipDisable) {
6636                                         tween._enabled(false, true);
6637                                 }
6638                                 tween.timeline = null;
6639
6640                                 if (tween._prev) {
6641                                         tween._prev._next = tween._next;
6642                                 } else if (this._first === tween) {
6643                                         this._first = tween._next;
6644                                 }
6645                                 if (tween._next) {
6646                                         tween._next._prev = tween._prev;
6647                                 } else if (this._last === tween) {
6648                                         this._last = tween._prev;
6649                                 }
6650
6651                                 if (this._timeline) {
6652                                         this._uncache(true);
6653                                 }
6654                         }
6655                         return this;
6656                 };
6657
6658                 p.render = function(time, suppressEvents, force) {
6659                         var tween = this._first,
6660                                 next;
6661                         this._totalTime = this._time = this._rawPrevTime = time;
6662                         while (tween) {
6663                                 next = tween._next; //record it here because the value could change after rendering...
6664                                 if (tween._active || (time >= tween._startTime && !tween._paused)) {
6665                                         if (!tween._reversed) {
6666                                                 tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force);
6667                                         } else {
6668                                                 tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force);
6669                                         }
6670                                 }
6671                                 tween = next;
6672                         }
6673                 };
6674
6675                 p.rawTime = function() {
6676                         if (!_tickerActive) {
6677                                 _ticker.wake();
6678                         }
6679                         return this._totalTime;
6680                 };
6681
6682 /*
6683  * ----------------------------------------------------------------
6684  * TweenLite
6685  * ----------------------------------------------------------------
6686  */
6687                 var TweenLite = _class("TweenLite", function(target, duration, vars) {
6688                                 Animation.call(this, duration, vars);
6689                                 this.render = TweenLite.prototype.render; //speed optimization (avoid prototype lookup on this "hot" method)
6690
6691                                 if (target == null) {
6692                                         throw "Cannot tween a null target.";
6693                                 }
6694
6695                                 this.target = target = (typeof(target) !== "string") ? target : TweenLite.selector(target) || target;
6696
6697                                 var isSelector = (target.jquery || (target.length && target !== window && target[0] && (target[0] === window || (target[0].nodeType && target[0].style && !target.nodeType)))),
6698                                         overwrite = this.vars.overwrite,
6699                                         i, targ, targets;
6700
6701                                 this._overwrite = overwrite = (overwrite == null) ? _overwriteLookup[TweenLite.defaultOverwrite] : (typeof(overwrite) === "number") ? overwrite >> 0 : _overwriteLookup[overwrite];
6702
6703                                 if ((isSelector || target instanceof Array || (target.push && _isArray(target))) && typeof(target[0]) !== "number") {
6704                                         this._targets = targets = _slice.call(target, 0);
6705                                         this._propLookup = [];
6706                                         this._siblings = [];
6707                                         for (i = 0; i < targets.length; i++) {
6708                                                 targ = targets[i];
6709                                                 if (!targ) {
6710                                                         targets.splice(i--, 1);
6711                                                         continue;
6712                                                 } else if (typeof(targ) === "string") {
6713                                                         targ = targets[i--] = TweenLite.selector(targ); //in case it's an array of strings
6714                                                         if (typeof(targ) === "string") {
6715                                                                 targets.splice(i+1, 1); //to avoid an endless loop (can't imagine why the selector would return a string, but just in case)
6716                                                         }
6717                                                         continue;
6718                                                 } else if (targ.length && targ !== window && targ[0] && (targ[0] === window || (targ[0].nodeType && targ[0].style && !targ.nodeType))) { //in case the user is passing in an array of selector objects (like jQuery objects), we need to check one more level and pull things out if necessary. Also note that <select> elements pass all the criteria regarding length and the first child having style, so we must also check to ensure the target isn't an HTML node itself.
6719                                                         targets.splice(i--, 1);
6720                                                         this._targets = targets = targets.concat(_slice.call(targ, 0));
6721                                                         continue;
6722                                                 }
6723                                                 this._siblings[i] = _register(targ, this, false);
6724                                                 if (overwrite === 1) if (this._siblings[i].length > 1) {
6725                                                         _applyOverwrite(targ, this, null, 1, this._siblings[i]);
6726                                                 }
6727                                         }
6728
6729                                 } else {
6730                                         this._propLookup = {};
6731                                         this._siblings = _register(target, this, false);
6732                                         if (overwrite === 1) if (this._siblings.length > 1) {
6733                                                 _applyOverwrite(target, this, null, 1, this._siblings);
6734                                         }
6735                                 }
6736                                 if (this.vars.immediateRender || (duration === 0 && this._delay === 0 && this.vars.immediateRender !== false)) {
6737                                         this._time = -_tinyNum; //forces a render without having to set the render() "force" parameter to true because we want to allow lazying by default (using the "force" parameter always forces an immediate full render)
6738                                         this.render(-this._delay);
6739                                 }
6740                         }, true),
6741                         _isSelector = function(v) {
6742                                 return (v.length && v !== window && v[0] && (v[0] === window || (v[0].nodeType && v[0].style && !v.nodeType))); //we cannot check "nodeType" if the target is window from within an iframe, otherwise it will trigger a security error in some browsers like Firefox.
6743                         },
6744                         _autoCSS = function(vars, target) {
6745                                 var css = {},
6746                                         p;
6747                                 for (p in vars) {
6748                                         if (!_reservedProps[p] && (!(p in target) || p === "transform" || p === "x" || p === "y" || p === "width" || p === "height" || p === "className" || p === "border") && (!_plugins[p] || (_plugins[p] && _plugins[p]._autoCSS))) { //note: <img> elements contain read-only "x" and "y" properties. We should also prioritize editing css width/height rather than the element's properties.
6749                                                 css[p] = vars[p];
6750                                                 delete vars[p];
6751                                         }
6752                                 }
6753                                 vars.css = css;
6754                         };
6755
6756                 p = TweenLite.prototype = new Animation();
6757                 p.constructor = TweenLite;
6758                 p.kill()._gc = false;
6759
6760 //----TweenLite defaults, overwrite management, and root updates ----------------------------------------------------
6761
6762                 p.ratio = 0;
6763                 p._firstPT = p._targets = p._overwrittenProps = p._startAt = null;
6764                 p._notifyPluginsOfEnabled = p._lazy = false;
6765
6766                 TweenLite.version = "1.12.1";
6767                 TweenLite.defaultEase = p._ease = new Ease(null, null, 1, 1);
6768                 TweenLite.defaultOverwrite = "auto";
6769                 TweenLite.ticker = _ticker;
6770                 TweenLite.autoSleep = true;
6771                 TweenLite.lagSmoothing = function(threshold, adjustedLag) {
6772                         _ticker.lagSmoothing(threshold, adjustedLag);
6773                 };
6774                 TweenLite.selector = window.$ || window.jQuery || function(e) { if (window.$) { TweenLite.selector = window.$; return window.$(e); } return window.document ? window.document.getElementById((e.charAt(0) === "#") ? e.substr(1) : e) : e; };
6775
6776                 var _lazyTweens = [],
6777                         _lazyLookup = {},
6778                         _internals = TweenLite._internals = {isArray:_isArray, isSelector:_isSelector, lazyTweens:_lazyTweens}, //gives us a way to expose certain private values to other GreenSock classes without contaminating tha main TweenLite object.
6779                         _plugins = TweenLite._plugins = {},
6780                         _tweenLookup = _internals.tweenLookup = {},
6781                         _tweenLookupNum = 0,
6782                         _reservedProps = _internals.reservedProps = {ease:1, delay:1, overwrite:1, onComplete:1, onCompleteParams:1, onCompleteScope:1, useFrames:1, runBackwards:1, startAt:1, onUpdate:1, onUpdateParams:1, onUpdateScope:1, onStart:1, onStartParams:1, onStartScope:1, onReverseComplete:1, onReverseCompleteParams:1, onReverseCompleteScope:1, onRepeat:1, onRepeatParams:1, onRepeatScope:1, easeParams:1, yoyo:1, immediateRender:1, repeat:1, repeatDelay:1, data:1, paused:1, reversed:1, autoCSS:1, lazy:1},
6783                         _overwriteLookup = {none:0, all:1, auto:2, concurrent:3, allOnStart:4, preexisting:5, "true":1, "false":0},
6784                         _rootFramesTimeline = Animation._rootFramesTimeline = new SimpleTimeline(),
6785                         _rootTimeline = Animation._rootTimeline = new SimpleTimeline(),
6786                         _lazyRender = function() {
6787                                 var i = _lazyTweens.length;
6788                                 _lazyLookup = {};
6789                                 while (--i > -1) {
6790                                         a = _lazyTweens[i];
6791                                         if (a && a._lazy !== false) {
6792                                                 a.render(a._lazy, false, true);
6793                                                 a._lazy = false;
6794                                         }
6795                                 }
6796                                 _lazyTweens.length = 0;
6797                         };
6798
6799                 _rootTimeline._startTime = _ticker.time;
6800                 _rootFramesTimeline._startTime = _ticker.frame;
6801                 _rootTimeline._active = _rootFramesTimeline._active = true;
6802                 setTimeout(_lazyRender, 1); //on some mobile devices, there isn't a "tick" before code runs which means any lazy renders wouldn't run before the next official "tick".
6803
6804                 Animation._updateRoot = TweenLite.render = function() {
6805                                 var i, a, p;
6806                                 if (_lazyTweens.length) { //if code is run outside of the requestAnimationFrame loop, there may be tweens queued AFTER the engine refreshed, so we need to ensure any pending renders occur before we refresh again.
6807                                         _lazyRender();
6808                                 }
6809                                 _rootTimeline.render((_ticker.time - _rootTimeline._startTime) * _rootTimeline._timeScale, false, false);
6810                                 _rootFramesTimeline.render((_ticker.frame - _rootFramesTimeline._startTime) * _rootFramesTimeline._timeScale, false, false);
6811                                 if (_lazyTweens.length) {
6812                                         _lazyRender();
6813                                 }
6814                                 if (!(_ticker.frame % 120)) { //dump garbage every 120 frames...
6815                                         for (p in _tweenLookup) {
6816                                                 a = _tweenLookup[p].tweens;
6817                                                 i = a.length;
6818                                                 while (--i > -1) {
6819                                                         if (a[i]._gc) {
6820                                                                 a.splice(i, 1);
6821                                                         }
6822                                                 }
6823                                                 if (a.length === 0) {
6824                                                         delete _tweenLookup[p];
6825                                                 }
6826                                         }
6827                                         //if there are no more tweens in the root timelines, or if they're all paused, make the _timer sleep to reduce load on the CPU slightly
6828                                         p = _rootTimeline._first;
6829                                         if (!p || p._paused) if (TweenLite.autoSleep && !_rootFramesTimeline._first && _ticker._listeners.tick.length === 1) {
6830                                                 while (p && p._paused) {
6831                                                         p = p._next;
6832                                                 }
6833                                                 if (!p) {
6834                                                         _ticker.sleep();
6835                                                 }
6836                                         }
6837                                 }
6838                         };
6839
6840                 _ticker.addEventListener("tick", Animation._updateRoot);
6841
6842                 var _register = function(target, tween, scrub) {
6843                                 var id = target._gsTweenID, a, i;
6844                                 if (!_tweenLookup[id || (target._gsTweenID = id = "t" + (_tweenLookupNum++))]) {
6845                                         _tweenLookup[id] = {target:target, tweens:[]};
6846                                 }
6847                                 if (tween) {
6848                                         a = _tweenLookup[id].tweens;
6849                                         a[(i = a.length)] = tween;
6850                                         if (scrub) {
6851                                                 while (--i > -1) {
6852                                                         if (a[i] === tween) {
6853                                                                 a.splice(i, 1);
6854                                                         }
6855                                                 }
6856                                         }
6857                                 }
6858                                 return _tweenLookup[id].tweens;
6859                         },
6860
6861                         _applyOverwrite = function(target, tween, props, mode, siblings) {
6862                                 var i, changed, curTween, l;
6863                                 if (mode === 1 || mode >= 4) {
6864                                         l = siblings.length;
6865                                         for (i = 0; i < l; i++) {
6866                                                 if ((curTween = siblings[i]) !== tween) {
6867                                                         if (!curTween._gc) if (curTween._enabled(false, false)) {
6868                                                                 changed = true;
6869                                                         }
6870                                                 } else if (mode === 5) {
6871                                                         break;
6872                                                 }
6873                                         }
6874                                         return changed;
6875                                 }
6876                                 //NOTE: Add 0.0000000001 to overcome floating point errors that can cause the startTime to be VERY slightly off (when a tween's time() is set for example)
6877                                 var startTime = tween._startTime + _tinyNum,
6878                                         overlaps = [],
6879                                         oCount = 0,
6880                                         zeroDur = (tween._duration === 0),
6881                                         globalStart;
6882                                 i = siblings.length;
6883                                 while (--i > -1) {
6884                                         if ((curTween = siblings[i]) === tween || curTween._gc || curTween._paused) {
6885                                                 //ignore
6886                                         } else if (curTween._timeline !== tween._timeline) {
6887                                                 globalStart = globalStart || _checkOverlap(tween, 0, zeroDur);
6888                                                 if (_checkOverlap(curTween, globalStart, zeroDur) === 0) {
6889                                                         overlaps[oCount++] = curTween;
6890                                                 }
6891                                         } else if (curTween._startTime <= startTime) if (curTween._startTime + curTween.totalDuration() / curTween._timeScale > startTime) if (!((zeroDur || !curTween._initted) && startTime - curTween._startTime <= 0.0000000002)) {
6892                                                 overlaps[oCount++] = curTween;
6893                                         }
6894                                 }
6895
6896                                 i = oCount;
6897                                 while (--i > -1) {
6898                                         curTween = overlaps[i];
6899                                         if (mode === 2) if (curTween._kill(props, target)) {
6900                                                 changed = true;
6901                                         }
6902                                         if (mode !== 2 || (!curTween._firstPT && curTween._initted)) {
6903                                                 if (curTween._enabled(false, false)) { //if all property tweens have been overwritten, kill the tween.
6904                                                         changed = true;
6905                                                 }
6906                                         }
6907                                 }
6908                                 return changed;
6909                         },
6910
6911                         _checkOverlap = function(tween, reference, zeroDur) {
6912                                 var tl = tween._timeline,
6913                                         ts = tl._timeScale,
6914                                         t = tween._startTime;
6915                                 while (tl._timeline) {
6916                                         t += tl._startTime;
6917                                         ts *= tl._timeScale;
6918                                         if (tl._paused) {
6919                                                 return -100;
6920                                         }
6921                                         tl = tl._timeline;
6922                                 }
6923                                 t /= ts;
6924                                 return (t > reference) ? t - reference : ((zeroDur && t === reference) || (!tween._initted && t - reference < 2 * _tinyNum)) ? _tinyNum : ((t += tween.totalDuration() / tween._timeScale / ts) > reference + _tinyNum) ? 0 : t - reference - _tinyNum;
6925                         };
6926
6927
6928 //---- TweenLite instance methods -----------------------------------------------------------------------------
6929
6930                 p._init = function() {
6931                         var v = this.vars,
6932                                 op = this._overwrittenProps,
6933                                 dur = this._duration,
6934                                 immediate = !!v.immediateRender,
6935                                 ease = v.ease,
6936                                 i, initPlugins, pt, p, startVars;
6937                         if (v.startAt) {
6938                                 if (this._startAt) {
6939                                         this._startAt.render(-1, true); //if we've run a startAt previously (when the tween instantiated), we should revert it so that the values re-instantiate correctly particularly for relative tweens. Without this, a TweenLite.fromTo(obj, 1, {x:"+=100"}, {x:"-=100"}), for example, would actually jump to +=200 because the startAt would run twice, doubling the relative change.
6940                                         this._startAt.kill();
6941                                 }
6942                                 startVars = {};
6943                                 for (p in v.startAt) { //copy the properties/values into a new object to avoid collisions, like var to = {x:0}, from = {x:500}; timeline.fromTo(e, 1, from, to).fromTo(e, 1, to, from);
6944                                         startVars[p] = v.startAt[p];
6945                                 }
6946                                 startVars.overwrite = false;
6947                                 startVars.immediateRender = true;
6948                                 startVars.lazy = (immediate && v.lazy !== false);
6949                                 startVars.startAt = startVars.delay = null; //no nesting of startAt objects allowed (otherwise it could cause an infinite loop).
6950                                 this._startAt = TweenLite.to(this.target, 0, startVars);
6951                                 if (immediate) {
6952                                         if (this._time > 0) {
6953                                                 this._startAt = null; //tweens that render immediately (like most from() and fromTo() tweens) shouldn't revert when their parent timeline's playhead goes backward past the startTime because the initial render could have happened anytime and it shouldn't be directly correlated to this tween's startTime. Imagine setting up a complex animation where the beginning states of various objects are rendered immediately but the tween doesn't happen for quite some time - if we revert to the starting values as soon as the playhead goes backward past the tween's startTime, it will throw things off visually. Reversion should only happen in TimelineLite/Max instances where immediateRender was false (which is the default in the convenience methods like from()).
6954                                         } else if (dur !== 0) {
6955                                                 return; //we skip initialization here so that overwriting doesn't occur until the tween actually begins. Otherwise, if you create several immediateRender:true tweens of the same target/properties to drop into a TimelineLite or TimelineMax, the last one created would overwrite the first ones because they didn't get placed into the timeline yet before the first render occurs and kicks in overwriting.
6956                                         }
6957                                 }
6958                         } else if (v.runBackwards && dur !== 0) {
6959                                 //from() tweens must be handled uniquely: their beginning values must be rendered but we don't want overwriting to occur yet (when time is still 0). Wait until the tween actually begins before doing all the routines like overwriting. At that time, we should render at the END of the tween to ensure that things initialize correctly (remember, from() tweens go backwards)
6960                                 if (this._startAt) {
6961                                         this._startAt.render(-1, true);
6962                                         this._startAt.kill();
6963                                         this._startAt = null;
6964                                 } else {
6965                                         pt = {};
6966                                         for (p in v) { //copy props into a new object and skip any reserved props, otherwise onComplete or onUpdate or onStart could fire. We should, however, permit autoCSS to go through.
6967                                                 if (!_reservedProps[p] || p === "autoCSS") {
6968                                                         pt[p] = v[p];
6969                                                 }
6970                                         }
6971                                         pt.overwrite = 0;
6972                                         pt.data = "isFromStart"; //we tag the tween with as "isFromStart" so that if [inside a plugin] we need to only do something at the very END of a tween, we have a way of identifying this tween as merely the one that's setting the beginning values for a "from()" tween. For example, clearProps in CSSPlugin should only get applied at the very END of a tween and without this tag, from(...{height:100, clearProps:"height", delay:1}) would wipe the height at the beginning of the tween and after 1 second, it'd kick back in.
6973                                         pt.lazy = (immediate && v.lazy !== false);
6974                                         pt.immediateRender = immediate; //zero-duration tweens render immediately by default, but if we're not specifically instructed to render this tween immediately, we should skip this and merely _init() to record the starting values (rendering them immediately would push them to completion which is wasteful in that case - we'd have to render(-1) immediately after)
6975                                         this._startAt = TweenLite.to(this.target, 0, pt);
6976                                         if (!immediate) {
6977                                                 this._startAt._init(); //ensures that the initial values are recorded
6978                                                 this._startAt._enabled(false); //no need to have the tween render on the next cycle. Disable it because we'll always manually control the renders of the _startAt tween.
6979                                         } else if (this._time === 0) {
6980                                                 return;
6981                                         }
6982                                 }
6983                         }
6984                         if (!ease) {
6985                                 this._ease = TweenLite.defaultEase;
6986                         } else if (ease instanceof Ease) {
6987                                 this._ease = (v.easeParams instanceof Array) ? ease.config.apply(ease, v.easeParams) : ease;
6988                         } else {
6989                                 this._ease = (typeof(ease) === "function") ? new Ease(ease, v.easeParams) : _easeMap[ease] || TweenLite.defaultEase;
6990                         }
6991                         this._easeType = this._ease._type;
6992                         this._easePower = this._ease._power;
6993                         this._firstPT = null;
6994
6995                         if (this._targets) {
6996                                 i = this._targets.length;
6997                                 while (--i > -1) {
6998                                         if ( this._initProps( this._targets[i], (this._propLookup[i] = {}), this._siblings[i], (op ? op[i] : null)) ) {
6999                                                 initPlugins = true;
7000                                         }
7001                                 }
7002                         } else {
7003                                 initPlugins = this._initProps(this.target, this._propLookup, this._siblings, op);
7004                         }
7005
7006                         if (initPlugins) {
7007                                 TweenLite._onPluginEvent("_onInitAllProps", this); //reorders the array in order of priority. Uses a static TweenPlugin method in order to minimize file size in TweenLite
7008                         }
7009                         if (op) if (!this._firstPT) if (typeof(this.target) !== "function") { //if all tweening properties have been overwritten, kill the tween. If the target is a function, it's probably a delayedCall so let it live.
7010                                 this._enabled(false, false);
7011                         }
7012                         if (v.runBackwards) {
7013                                 pt = this._firstPT;
7014                                 while (pt) {
7015                                         pt.s += pt.c;
7016                                         pt.c = -pt.c;
7017                                         pt = pt._next;
7018                                 }
7019                         }
7020                         this._onUpdate = v.onUpdate;
7021                         this._initted = true;
7022                 };
7023
7024                 p._initProps = function(target, propLookup, siblings, overwrittenProps) {
7025                         var p, i, initPlugins, plugin, pt, v;
7026                         if (target == null) {
7027                                 return false;
7028                         }
7029
7030                         if (_lazyLookup[target._gsTweenID]) {
7031                                 _lazyRender(); //if other tweens of the same target have recently initted but haven't rendered yet, we've got to force the render so that the starting values are correct (imagine populating a timeline with a bunch of sequential tweens and then jumping to the end)
7032                         }
7033
7034                         if (!this.vars.css) if (target.style) if (target !== window && target.nodeType) if (_plugins.css) if (this.vars.autoCSS !== false) { //it's so common to use TweenLite/Max to animate the css of DOM elements, we assume that if the target is a DOM element, that's what is intended (a convenience so that users don't have to wrap things in css:{}, although we still recommend it for a slight performance boost and better specificity). Note: we cannot check "nodeType" on the window inside an iframe.
7035                                 _autoCSS(this.vars, target);
7036                         }
7037                         for (p in this.vars) {
7038                                 v = this.vars[p];
7039                                 if (_reservedProps[p]) {
7040                                         if (v) if ((v instanceof Array) || (v.push && _isArray(v))) if (v.join("").indexOf("{self}") !== -1) {
7041                                                 this.vars[p] = v = this._swapSelfInParams(v, this);
7042                                         }
7043
7044                                 } else if (_plugins[p] && (plugin = new _plugins[p]())._onInitTween(target, this.vars[p], this)) {
7045
7046                                         //t - target            [object]
7047                                         //p - property          [string]
7048                                         //s - start                     [number]
7049                                         //c - change            [number]
7050                                         //f - isFunction        [boolean]
7051                                         //n - name                      [string]
7052                                         //pg - isPlugin         [boolean]
7053                                         //pr - priority         [number]
7054                                         this._firstPT = pt = {_next:this._firstPT, t:plugin, p:"setRatio", s:0, c:1, f:true, n:p, pg:true, pr:plugin._priority};
7055                                         i = plugin._overwriteProps.length;
7056                                         while (--i > -1) {
7057                                                 propLookup[plugin._overwriteProps[i]] = this._firstPT;
7058                                         }
7059                                         if (plugin._priority || plugin._onInitAllProps) {
7060                                                 initPlugins = true;
7061                                         }
7062                                         if (plugin._onDisable || plugin._onEnable) {
7063                                                 this._notifyPluginsOfEnabled = true;
7064                                         }
7065
7066                                 } else {
7067                                         this._firstPT = propLookup[p] = pt = {_next:this._firstPT, t:target, p:p, f:(typeof(target[p]) === "function"), n:p, pg:false, pr:0};
7068                                         pt.s = (!pt.f) ? parseFloat(target[p]) : target[ ((p.indexOf("set") || typeof(target["get" + p.substr(3)]) !== "function") ? p : "get" + p.substr(3)) ]();
7069                                         pt.c = (typeof(v) === "string" && v.charAt(1) === "=") ? parseInt(v.charAt(0) + "1", 10) * Number(v.substr(2)) : (Number(v) - pt.s) || 0;
7070                                 }
7071                                 if (pt) if (pt._next) {
7072                                         pt._next._prev = pt;
7073                                 }
7074                         }
7075
7076                         if (overwrittenProps) if (this._kill(overwrittenProps, target)) { //another tween may have tried to overwrite properties of this tween before init() was called (like if two tweens start at the same time, the one created second will run first)
7077                                 return this._initProps(target, propLookup, siblings, overwrittenProps);
7078                         }
7079                         if (this._overwrite > 1) if (this._firstPT) if (siblings.length > 1) if (_applyOverwrite(target, this, propLookup, this._overwrite, siblings)) {
7080                                 this._kill(propLookup, target);
7081                                 return this._initProps(target, propLookup, siblings, overwrittenProps);
7082                         }
7083                         if (this._firstPT) if ((this.vars.lazy !== false && this._duration) || (this.vars.lazy && !this._duration)) { //zero duration tweens don't lazy render by default; everything else does.
7084                                 _lazyLookup[target._gsTweenID] = true;
7085                         }
7086                         return initPlugins;
7087                 };
7088
7089                 p.render = function(time, suppressEvents, force) {
7090                         var prevTime = this._time,
7091                                 duration = this._duration,
7092                                 prevRawPrevTime = this._rawPrevTime,
7093                                 isComplete, callback, pt, rawPrevTime;
7094                         if (time >= duration) {
7095                                 this._totalTime = this._time = duration;
7096                                 this.ratio = this._ease._calcEnd ? this._ease.getRatio(1) : 1;
7097                                 if (!this._reversed ) {
7098                                         isComplete = true;
7099                                         callback = "onComplete";
7100                                 }
7101                                 if (duration === 0) if (this._initted || !this.vars.lazy || force) { //zero-duration tweens are tricky because we must discern the momentum/direction of time in order to determine whether the starting values should be rendered or the ending values. If the "playhead" of its timeline goes past the zero-duration tween in the forward direction or lands directly on it, the end values should be rendered, but if the timeline's "playhead" moves past it in the backward direction (from a postitive time to a negative time), the starting values must be rendered.
7102                                         if (this._startTime === this._timeline._duration) { //if a zero-duration tween is at the VERY end of a timeline and that timeline renders at its end, it will typically add a tiny bit of cushion to the render time to prevent rounding errors from getting in the way of tweens rendering their VERY end. If we then reverse() that timeline, the zero-duration tween will trigger its onReverseComplete even though technically the playhead didn't pass over it again. It's a very specific edge case we must accommodate.
7103                                                 time = 0;
7104                                         }
7105                                         if (time === 0 || prevRawPrevTime < 0 || prevRawPrevTime === _tinyNum) if (prevRawPrevTime !== time) {
7106                                                 force = true;
7107                                                 if (prevRawPrevTime > _tinyNum) {
7108                                                         callback = "onReverseComplete";
7109                                                 }
7110                                         }
7111                                         this._rawPrevTime = rawPrevTime = (!suppressEvents || time || prevRawPrevTime === time) ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient.
7112                                 }
7113
7114                         } else if (time < 0.0000001) { //to work around occasional floating point math artifacts, round super small values to 0.
7115                                 this._totalTime = this._time = 0;
7116                                 this.ratio = this._ease._calcEnd ? this._ease.getRatio(0) : 0;
7117                                 if (prevTime !== 0 || (duration === 0 && prevRawPrevTime > 0 && prevRawPrevTime !== _tinyNum)) {
7118                                         callback = "onReverseComplete";
7119                                         isComplete = this._reversed;
7120                                 }
7121                                 if (time < 0) {
7122                                         this._active = false;
7123                                         if (duration === 0) if (this._initted || !this.vars.lazy || force) { //zero-duration tweens are tricky because we must discern the momentum/direction of time in order to determine whether the starting values should be rendered or the ending values. If the "playhead" of its timeline goes past the zero-duration tween in the forward direction or lands directly on it, the end values should be rendered, but if the timeline's "playhead" moves past it in the backward direction (from a postitive time to a negative time), the starting values must be rendered.
7124                                                 if (prevRawPrevTime >= 0) {
7125                                                         force = true;
7126                                                 }
7127                                                 this._rawPrevTime = rawPrevTime = (!suppressEvents || time || prevRawPrevTime === time) ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient.
7128                                         }
7129                                 } else if (!this._initted) { //if we render the very beginning (time == 0) of a fromTo(), we must force the render (normal tweens wouldn't need to render at a time of 0 when the prevTime was also 0). This is also mandatory to make sure overwriting kicks in immediately.
7130                                         force = true;
7131                                 }
7132                         } else {
7133                                 this._totalTime = this._time = time;
7134
7135                                 if (this._easeType) {
7136                                         var r = time / duration, type = this._easeType, pow = this._easePower;
7137                                         if (type === 1 || (type === 3 && r >= 0.5)) {
7138                                                 r = 1 - r;
7139                                         }
7140                                         if (type === 3) {
7141                                                 r *= 2;
7142                                         }
7143                                         if (pow === 1) {
7144                                                 r *= r;
7145                                         } else if (pow === 2) {
7146                                                 r *= r * r;
7147                                         } else if (pow === 3) {
7148                                                 r *= r * r * r;
7149                                         } else if (pow === 4) {
7150                                                 r *= r * r * r * r;
7151                                         }
7152
7153                                         if (type === 1) {
7154                                                 this.ratio = 1 - r;
7155                                         } else if (type === 2) {
7156                                                 this.ratio = r;
7157                                         } else if (time / duration < 0.5) {
7158                                                 this.ratio = r / 2;
7159                                         } else {
7160                                                 this.ratio = 1 - (r / 2);
7161                                         }
7162
7163                                 } else {
7164                                         this.ratio = this._ease.getRatio(time / duration);
7165                                 }
7166                         }
7167
7168                         if (this._time === prevTime && !force) {
7169                                 return;
7170                         } else if (!this._initted) {
7171                                 this._init();
7172                                 if (!this._initted || this._gc) { //immediateRender tweens typically won't initialize until the playhead advances (_time is greater than 0) in order to ensure that overwriting occurs properly. Also, if all of the tweening properties have been overwritten (which would cause _gc to be true, as set in _init()), we shouldn't continue otherwise an onStart callback could be called for example.
7173                                         return;
7174                                 } else if (!force && this._firstPT && ((this.vars.lazy !== false && this._duration) || (this.vars.lazy && !this._duration))) {
7175                                         this._time = this._totalTime = prevTime;
7176                                         this._rawPrevTime = prevRawPrevTime;
7177                                         _lazyTweens.push(this);
7178                                         this._lazy = time;
7179                                         return;
7180                                 }
7181                                 //_ease is initially set to defaultEase, so now that init() has run, _ease is set properly and we need to recalculate the ratio. Overall this is faster than using conditional logic earlier in the method to avoid having to set ratio twice because we only init() once but renderTime() gets called VERY frequently.
7182                                 if (this._time && !isComplete) {
7183                                         this.ratio = this._ease.getRatio(this._time / duration);
7184                                 } else if (isComplete && this._ease._calcEnd) {
7185                                         this.ratio = this._ease.getRatio((this._time === 0) ? 0 : 1);
7186                                 }
7187                         }
7188                         if (this._lazy !== false) { //in case a lazy render is pending, we should flush it because the new render is occuring now (imagine a lazy tween instantiating and then immediately the user calls tween.seek(tween.duration()), skipping to the end - the end render would be forced, and then if we didn't flush the lazy render, it'd fire AFTER the seek(), rendering it at the wrong time.
7189                                 this._lazy = false;
7190                         }
7191                         if (!this._active) if (!this._paused && this._time !== prevTime && time >= 0) {
7192                                 this._active = true;  //so that if the user renders a tween (as opposed to the timeline rendering it), the timeline is forced to re-render and align it with the proper time/frame on the next rendering cycle. Maybe the tween already finished but the user manually re-renders it as halfway done.
7193                         }
7194                         if (prevTime === 0) {
7195                                 if (this._startAt) {
7196                                         if (time >= 0) {
7197                                                 this._startAt.render(time, suppressEvents, force);
7198                                         } else if (!callback) {
7199                                                 callback = "_dummyGS"; //if no callback is defined, use a dummy value just so that the condition at the end evaluates as true because _startAt should render AFTER the normal render loop when the time is negative. We could handle this in a more intuitive way, of course, but the render loop is the MOST important thing to optimize, so this technique allows us to avoid adding extra conditional logic in a high-frequency area.
7200                                         }
7201                                 }
7202                                 if (this.vars.onStart) if (this._time !== 0 || duration === 0) if (!suppressEvents) {
7203                                         this.vars.onStart.apply(this.vars.onStartScope || this, this.vars.onStartParams || _blankArray);
7204                                 }
7205                         }
7206
7207                         pt = this._firstPT;
7208                         while (pt) {
7209                                 if (pt.f) {
7210                                         pt.t[pt.p](pt.c * this.ratio + pt.s);
7211                                 } else {
7212                                         pt.t[pt.p] = pt.c * this.ratio + pt.s;
7213                                 }
7214                                 pt = pt._next;
7215                         }
7216
7217                         if (this._onUpdate) {
7218                                 if (time < 0) if (this._startAt && this._startTime) { //if the tween is positioned at the VERY beginning (_startTime 0) of its parent timeline, it's illegal for the playhead to go back further, so we should not render the recorded startAt values.
7219                                         this._startAt.render(time, suppressEvents, force); //note: for performance reasons, we tuck this conditional logic inside less traveled areas (most tweens don't have an onUpdate). We'd just have it at the end before the onComplete, but the values should be updated before any onUpdate is called, so we ALSO put it here and then if it's not called, we do so later near the onComplete.
7220                                 }
7221                                 if (!suppressEvents) if (this._time !== prevTime || isComplete) {
7222                                         this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray);
7223                                 }
7224                         }
7225
7226                         if (callback) if (!this._gc) { //check _gc because there's a chance that kill() could be called in an onUpdate
7227                                 if (time < 0 && this._startAt && !this._onUpdate && this._startTime) { //if the tween is positioned at the VERY beginning (_startTime 0) of its parent timeline, it's illegal for the playhead to go back further, so we should not render the recorded startAt values.
7228                                         this._startAt.render(time, suppressEvents, force);
7229                                 }
7230                                 if (isComplete) {
7231                                         if (this._timeline.autoRemoveChildren) {
7232                                                 this._enabled(false, false);
7233                                         }
7234                                         this._active = false;
7235                                 }
7236                                 if (!suppressEvents && this.vars[callback]) {
7237                                         this.vars[callback].apply(this.vars[callback + "Scope"] || this, this.vars[callback + "Params"] || _blankArray);
7238                                 }
7239                                 if (duration === 0 && this._rawPrevTime === _tinyNum && rawPrevTime !== _tinyNum) { //the onComplete or onReverseComplete could trigger movement of the playhead and for zero-duration tweens (which must discern direction) that land directly back on their start time, we don't want to fire again on the next render. Think of several addPause()'s in a timeline that forces the playhead to a certain spot, but what if it's already paused and another tween is tweening the "time" of the timeline? Each time it moves [forward] past that spot, it would move back, and since suppressEvents is true, it'd reset _rawPrevTime to _tinyNum so that when it begins again, the callback would fire (so ultimately it could bounce back and forth during that tween). Again, this is a very uncommon scenario, but possible nonetheless.
7240                                         this._rawPrevTime = 0;
7241                                 }
7242                         }
7243
7244                 };
7245
7246                 p._kill = function(vars, target) {
7247                         if (vars === "all") {
7248                                 vars = null;
7249                         }
7250                         if (vars == null) if (target == null || target === this.target) {
7251                                 this._lazy = false;
7252                                 return this._enabled(false, false);
7253                         }
7254                         target = (typeof(target) !== "string") ? (target || this._targets || this.target) : TweenLite.selector(target) || target;
7255                         var i, overwrittenProps, p, pt, propLookup, changed, killProps, record;
7256                         if ((_isArray(target) || _isSelector(target)) && typeof(target[0]) !== "number") {
7257                                 i = target.length;
7258                                 while (--i > -1) {
7259                                         if (this._kill(vars, target[i])) {
7260                                                 changed = true;
7261                                         }
7262                                 }
7263                         } else {
7264                                 if (this._targets) {
7265                                         i = this._targets.length;
7266                                         while (--i > -1) {
7267                                                 if (target === this._targets[i]) {
7268                                                         propLookup = this._propLookup[i] || {};
7269                                                         this._overwrittenProps = this._overwrittenProps || [];
7270                                                         overwrittenProps = this._overwrittenProps[i] = vars ? this._overwrittenProps[i] || {} : "all";
7271                                                         break;
7272                                                 }
7273                                         }
7274                                 } else if (target !== this.target) {
7275                                         return false;
7276                                 } else {
7277                                         propLookup = this._propLookup;
7278                                         overwrittenProps = this._overwrittenProps = vars ? this._overwrittenProps || {} : "all";
7279                                 }
7280
7281                                 if (propLookup) {
7282                                         killProps = vars || propLookup;
7283                                         record = (vars !== overwrittenProps && overwrittenProps !== "all" && vars !== propLookup && (typeof(vars) !== "object" || !vars._tempKill)); //_tempKill is a super-secret way to delete a particular tweening property but NOT have it remembered as an official overwritten property (like in BezierPlugin)
7284                                         for (p in killProps) {
7285                                                 if ((pt = propLookup[p])) {
7286                                                         if (pt.pg && pt.t._kill(killProps)) {
7287                                                                 changed = true; //some plugins need to be notified so they can perform cleanup tasks first
7288                                                         }
7289                                                         if (!pt.pg || pt.t._overwriteProps.length === 0) {
7290                                                                 if (pt._prev) {
7291                                                                         pt._prev._next = pt._next;
7292                                                                 } else if (pt === this._firstPT) {
7293                                                                         this._firstPT = pt._next;
7294                                                                 }
7295                                                                 if (pt._next) {
7296                                                                         pt._next._prev = pt._prev;
7297                                                                 }
7298                                                                 pt._next = pt._prev = null;
7299                                                         }
7300                                                         delete propLookup[p];
7301                                                 }
7302                                                 if (record) {
7303                                                         overwrittenProps[p] = 1;
7304                                                 }
7305                                         }
7306                                         if (!this._firstPT && this._initted) { //if all tweening properties are killed, kill the tween. Without this line, if there's a tween with multiple targets and then you killTweensOf() each target individually, the tween would technically still remain active and fire its onComplete even though there aren't any more properties tweening.
7307                                                 this._enabled(false, false);
7308                                         }
7309                                 }
7310                         }
7311                         return changed;
7312                 };
7313
7314                 p.invalidate = function() {
7315                         if (this._notifyPluginsOfEnabled) {
7316                                 TweenLite._onPluginEvent("_onDisable", this);
7317                         }
7318                         this._firstPT = null;
7319                         this._overwrittenProps = null;
7320                         this._onUpdate = null;
7321                         this._startAt = null;
7322                         this._initted = this._active = this._notifyPluginsOfEnabled = this._lazy = false;
7323                         this._propLookup = (this._targets) ? {} : [];
7324                         return this;
7325                 };
7326
7327                 p._enabled = function(enabled, ignoreTimeline) {
7328                         if (!_tickerActive) {
7329                                 _ticker.wake();
7330                         }
7331                         if (enabled && this._gc) {
7332                                 var targets = this._targets,
7333                                         i;
7334                                 if (targets) {
7335                                         i = targets.length;
7336                                         while (--i > -1) {
7337                                                 this._siblings[i] = _register(targets[i], this, true);
7338                                         }
7339                                 } else {
7340                                         this._siblings = _register(this.target, this, true);
7341                                 }
7342                         }
7343                         Animation.prototype._enabled.call(this, enabled, ignoreTimeline);
7344                         if (this._notifyPluginsOfEnabled) if (this._firstPT) {
7345                                 return TweenLite._onPluginEvent((enabled ? "_onEnable" : "_onDisable"), this);
7346                         }
7347                         return false;
7348                 };
7349
7350
7351 //----TweenLite static methods -----------------------------------------------------
7352
7353                 TweenLite.to = function(target, duration, vars) {
7354                         return new TweenLite(target, duration, vars);
7355                 };
7356
7357                 TweenLite.from = function(target, duration, vars) {
7358                         vars.runBackwards = true;
7359                         vars.immediateRender = (vars.immediateRender != false);
7360                         return new TweenLite(target, duration, vars);
7361                 };
7362
7363                 TweenLite.fromTo = function(target, duration, fromVars, toVars) {
7364                         toVars.startAt = fromVars;
7365                         toVars.immediateRender = (toVars.immediateRender != false && fromVars.immediateRender != false);
7366                         return new TweenLite(target, duration, toVars);
7367                 };
7368
7369                 TweenLite.delayedCall = function(delay, callback, params, scope, useFrames) {
7370                         return new TweenLite(callback, 0, {delay:delay, onComplete:callback, onCompleteParams:params, onCompleteScope:scope, onReverseComplete:callback, onReverseCompleteParams:params, onReverseCompleteScope:scope, immediateRender:false, useFrames:useFrames, overwrite:0});
7371                 };
7372
7373                 TweenLite.set = function(target, vars) {
7374                         return new TweenLite(target, 0, vars);
7375                 };
7376
7377                 TweenLite.getTweensOf = function(target, onlyActive) {
7378                         if (target == null) { return []; }
7379                         target = (typeof(target) !== "string") ? target : TweenLite.selector(target) || target;
7380                         var i, a, j, t;
7381                         if ((_isArray(target) || _isSelector(target)) && typeof(target[0]) !== "number") {
7382                                 i = target.length;
7383                                 a = [];
7384                                 while (--i > -1) {
7385                                         a = a.concat(TweenLite.getTweensOf(target[i], onlyActive));
7386                                 }
7387                                 i = a.length;
7388                                 //now get rid of any duplicates (tweens of arrays of objects could cause duplicates)
7389                                 while (--i > -1) {
7390                                         t = a[i];
7391                                         j = i;
7392                                         while (--j > -1) {
7393                                                 if (t === a[j]) {
7394                                                         a.splice(i, 1);
7395                                                 }
7396                                         }
7397                                 }
7398                         } else {
7399                                 a = _register(target).concat();
7400                                 i = a.length;
7401                                 while (--i > -1) {
7402                                         if (a[i]._gc || (onlyActive && !a[i].isActive())) {
7403                                                 a.splice(i, 1);
7404                                         }
7405                                 }
7406                         }
7407                         return a;
7408                 };
7409
7410                 TweenLite.killTweensOf = TweenLite.killDelayedCallsTo = function(target, onlyActive, vars) {
7411                         if (typeof(onlyActive) === "object") {
7412                                 vars = onlyActive; //for backwards compatibility (before "onlyActive" parameter was inserted)
7413                                 onlyActive = false;
7414                         }
7415                         var a = TweenLite.getTweensOf(target, onlyActive),
7416                                 i = a.length;
7417                         while (--i > -1) {
7418                                 a[i]._kill(vars, target);
7419                         }
7420                 };
7421
7422
7423
7424 /*
7425  * ----------------------------------------------------------------
7426  * TweenPlugin   (could easily be split out as a separate file/class, but included for ease of use (so that people don't need to include another <script> call before loading plugins which is easy to forget)
7427  * ----------------------------------------------------------------
7428  */
7429                 var TweenPlugin = _class("plugins.TweenPlugin", function(props, priority) {
7430                                         this._overwriteProps = (props || "").split(",");
7431                                         this._propName = this._overwriteProps[0];
7432                                         this._priority = priority || 0;
7433                                         this._super = TweenPlugin.prototype;
7434                                 }, true);
7435
7436                 p = TweenPlugin.prototype;
7437                 TweenPlugin.version = "1.10.1";
7438                 TweenPlugin.API = 2;
7439                 p._firstPT = null;
7440
7441                 p._addTween = function(target, prop, start, end, overwriteProp, round) {
7442                         var c, pt;
7443                         if (end != null && (c = (typeof(end) === "number" || end.charAt(1) !== "=") ? Number(end) - start : parseInt(end.charAt(0) + "1", 10) * Number(end.substr(2)))) {
7444                                 this._firstPT = pt = {_next:this._firstPT, t:target, p:prop, s:start, c:c, f:(typeof(target[prop]) === "function"), n:overwriteProp || prop, r:round};
7445                                 if (pt._next) {
7446                                         pt._next._prev = pt;
7447                                 }
7448                                 return pt;
7449                         }
7450                 };
7451
7452                 p.setRatio = function(v) {
7453                         var pt = this._firstPT,
7454                                 min = 0.000001,
7455                                 val;
7456                         while (pt) {
7457                                 val = pt.c * v + pt.s;
7458                                 if (pt.r) {
7459                                         val = Math.round(val);
7460                                 } else if (val < min) if (val > -min) { //prevents issues with converting very small numbers to strings in the browser
7461                                         val = 0;
7462                                 }
7463                                 if (pt.f) {
7464                                         pt.t[pt.p](val);
7465                                 } else {
7466                                         pt.t[pt.p] = val;
7467                                 }
7468                                 pt = pt._next;
7469                         }
7470                 };
7471
7472                 p._kill = function(lookup) {
7473                         var a = this._overwriteProps,
7474                                 pt = this._firstPT,
7475                                 i;
7476                         if (lookup[this._propName] != null) {
7477                                 this._overwriteProps = [];
7478                         } else {
7479                                 i = a.length;
7480                                 while (--i > -1) {
7481                                         if (lookup[a[i]] != null) {
7482                                                 a.splice(i, 1);
7483                                         }
7484                                 }
7485                         }
7486                         while (pt) {
7487                                 if (lookup[pt.n] != null) {
7488                                         if (pt._next) {
7489                                                 pt._next._prev = pt._prev;
7490                                         }
7491                                         if (pt._prev) {
7492                                                 pt._prev._next = pt._next;
7493                                                 pt._prev = null;
7494                                         } else if (this._firstPT === pt) {
7495                                                 this._firstPT = pt._next;
7496                                         }
7497                                 }
7498                                 pt = pt._next;
7499                         }
7500                         return false;
7501                 };
7502
7503                 p._roundProps = function(lookup, value) {
7504                         var pt = this._firstPT;
7505                         while (pt) {
7506                                 if (lookup[this._propName] || (pt.n != null && lookup[ pt.n.split(this._propName + "_").join("") ])) { //some properties that are very plugin-specific add a prefix named after the _propName plus an underscore, so we need to ignore that extra stuff here.
7507                                         pt.r = value;
7508                                 }
7509                                 pt = pt._next;
7510                         }
7511                 };
7512
7513                 TweenLite._onPluginEvent = function(type, tween) {
7514                         var pt = tween._firstPT,
7515                                 changed, pt2, first, last, next;
7516                         if (type === "_onInitAllProps") {
7517                                 //sorts the PropTween linked list in order of priority because some plugins need to render earlier/later than others, like MotionBlurPlugin applies its effects after all x/y/alpha tweens have rendered on each frame.
7518                                 while (pt) {
7519                                         next = pt._next;
7520                                         pt2 = first;
7521                                         while (pt2 && pt2.pr > pt.pr) {
7522                                                 pt2 = pt2._next;
7523                                         }
7524                                         if ((pt._prev = pt2 ? pt2._prev : last)) {
7525                                                 pt._prev._next = pt;
7526                                         } else {
7527                                                 first = pt;
7528                                         }
7529                                         if ((pt._next = pt2)) {
7530                                                 pt2._prev = pt;
7531                                         } else {
7532                                                 last = pt;
7533                                         }
7534                                         pt = next;
7535                                 }
7536                                 pt = tween._firstPT = first;
7537                         }
7538                         while (pt) {
7539                                 if (pt.pg) if (typeof(pt.t[type]) === "function") if (pt.t[type]()) {
7540                                         changed = true;
7541                                 }
7542                                 pt = pt._next;
7543                         }
7544                         return changed;
7545                 };
7546
7547                 TweenPlugin.activate = function(plugins) {
7548                         var i = plugins.length;
7549                         while (--i > -1) {
7550                                 if (plugins[i].API === TweenPlugin.API) {
7551                                         _plugins[(new plugins[i]())._propName] = plugins[i];
7552                                 }
7553                         }
7554                         return true;
7555                 };
7556
7557                 //provides a more concise way to define plugins that have no dependencies besides TweenPlugin and TweenLite, wrapping common boilerplate stuff into one function (added in 1.9.0). You don't NEED to use this to define a plugin - the old way still works and can be useful in certain (rare) situations.
7558                 _gsDefine.plugin = function(config) {
7559                         if (!config || !config.propName || !config.init || !config.API) { throw "illegal plugin definition."; }
7560                         var propName = config.propName,
7561                                 priority = config.priority || 0,
7562                                 overwriteProps = config.overwriteProps,
7563                                 map = {init:"_onInitTween", set:"setRatio", kill:"_kill", round:"_roundProps", initAll:"_onInitAllProps"},
7564                                 Plugin = _class("plugins." + propName.charAt(0).toUpperCase() + propName.substr(1) + "Plugin",
7565                                         function() {
7566                                                 TweenPlugin.call(this, propName, priority);
7567                                                 this._overwriteProps = overwriteProps || [];
7568                                         }, (config.global === true)),
7569                                 p = Plugin.prototype = new TweenPlugin(propName),
7570                                 prop;
7571                         p.constructor = Plugin;
7572                         Plugin.API = config.API;
7573                         for (prop in map) {
7574                                 if (typeof(config[prop]) === "function") {
7575                                         p[map[prop]] = config[prop];
7576                                 }
7577                         }
7578                         Plugin.version = config.version;
7579                         TweenPlugin.activate([Plugin]);
7580                         return Plugin;
7581                 };
7582
7583
7584                 //now run through all the dependencies discovered and if any are missing, log that to the console as a warning. This is why it's best to have TweenLite load last - it can check all the dependencies for you.
7585                 a = window._gsQueue;
7586                 if (a) {
7587                         for (i = 0; i < a.length; i++) {
7588                                 a[i]();
7589                         }
7590                         for (p in _defLookup) {
7591                                 if (!_defLookup[p].func) {
7592                                         //window.console.log("GSAP encountered missing dependency: com.greensock." + p);
7593                                 }
7594                         }
7595                 }
7596
7597                 _tickerActive = false; //ensures that the first official animation forces a ticker.tick() to update the time when it is instantiated
7598
7599 })(window);
7600
7601 angular.module('att.abs.transition', [])
7602
7603 .factory('$transition', ['$q', '$timeout', '$rootScope', function($q, $timeout, $rootScope) {
7604
7605   var $transition = function(element, trigger, options) {
7606     options = options || {};
7607     var deferred = $q.defer();
7608     var endEventName = $transition[options.animation ? "animationEndEventName" : "transitionEndEventName"];
7609
7610     var transitionEndHandler = function() {
7611       $rootScope.$apply(function() {
7612         element.unbind(endEventName, transitionEndHandler);
7613         deferred.resolve(element);
7614       });
7615     };
7616
7617     if (endEventName) {
7618       element.bind(endEventName, transitionEndHandler);
7619     }
7620
7621     // Wrap in a timeout to allow the browser time to update the DOM before the transition is to occur
7622     $timeout(function() {
7623       if ( angular.isString(trigger) ) {
7624         element.addClass(trigger);
7625       } else if ( angular.isFunction(trigger) ) {
7626         trigger(element);
7627       } else if ( angular.isObject(trigger) ) {
7628         element.css(trigger);
7629       }
7630       //If browser does not support transitions, instantly resolve
7631       if ( !endEventName ) {
7632         deferred.resolve(element);
7633       }
7634     }, 100);
7635
7636     // Add our custom cancel function to the promise that is returned
7637     // We can call this if we are about to run a new transition, which we know will prevent this transition from ending,
7638     // i.e. it will therefore never raise a transitionEnd event for that transition
7639     deferred.promise.cancel = function() {
7640       if ( endEventName ) {
7641         element.unbind(endEventName, transitionEndHandler);
7642       }
7643       deferred.reject('Transition cancelled');
7644     };
7645
7646     return deferred.promise;
7647   };
7648
7649   // Work out the name of the transitionEnd event
7650   var transElement = document.createElement('trans');
7651   var transitionEndEventNames = {
7652     'WebkitTransition': 'webkitTransitionEnd',
7653     'MozTransition': 'transitionend',
7654     'OTransition': 'oTransitionEnd',
7655     'transition': 'transitionend'
7656   };
7657   var animationEndEventNames = {
7658     'WebkitTransition': 'webkitAnimationEnd',
7659     'MozTransition': 'animationend',
7660     'OTransition': 'oAnimationEnd',
7661     'transition': 'animationend'
7662   };
7663   function findEndEventName(endEventNames) {
7664     for (var name in endEventNames){
7665       if (transElement.style[name] !== undefined) {
7666         return endEventNames[name];
7667       }
7668     }
7669   }
7670   $transition.transitionEndEventName = findEndEventName(transitionEndEventNames);
7671   $transition.animationEndEventName = findEndEventName(animationEndEventNames);
7672   return $transition;
7673 }])
7674
7675 .factory('$scrollTo', ['$window', function($window) {
7676     var $scrollTo = function(offsetLeft, offsetTop, duration) {
7677         TweenMax.to($window, duration || 1, {scrollTo: {y: offsetTop, x: offsetLeft}, ease: Power4.easeOut});
7678     };
7679     return $scrollTo;
7680 }])
7681 .factory('animation', function(){
7682     return TweenMax;
7683 })
7684 .factory('$progressBar', function(){
7685
7686    //Provides a function to pass in code for closure purposes
7687    var loadingAnimationCreator = function(onUpdateCallback){
7688
7689       //Use closure to setup some resuable code
7690       var loadingAnimation = function(callback, duration){
7691           TweenMax.to({}, duration, {
7692               onUpdateParams: ["{self}"],
7693               onUpdate: onUpdateCallback,
7694               onComplete: callback
7695           });
7696       };
7697       //Returns a function that takes a callback function and a duration for the animation
7698       return (function(){
7699         return loadingAnimation;
7700       })();
7701     };
7702
7703   return loadingAnimationCreator;
7704 })
7705 .factory('$height', function(){
7706   var heightAnimation = function(element,duration,height,alpha){
7707     TweenMax.to(element,
7708       duration,
7709       {height:height, autoAlpha:alpha},
7710       0);
7711   };
7712   return heightAnimation;
7713 });
7714 angular.module('att.abs.accordion', ['att.abs.utilities', 'att.abs.position', 'att.abs.transition'])
7715 .constant('accordionConfig', {
7716     closeOthers: false
7717 }).controller('AccordionController', ['$scope', '$attrs', 'accordionConfig', '$log',
7718 function ($scope, $attrs, accordionConfig, $log) {
7719 // This array keeps track of the accordion groups
7720 this.groups = [];
7721 this.index = -1;
7722 // Keep reference to user's scope to properly assign `is-open`
7723 this.scope = $scope;
7724 $scope.forceExpand = false;
7725 // Ensure that all the groups in this accordion are closed, unless close-others explicitly says not to
7726 this.closeOthers = function (openGroup) {
7727     var closeOthers = angular.isDefined($attrs.closeOthers) ? $scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers;
7728     if (closeOthers && !$scope.forceExpand) {
7729         angular.forEach(this.groups, function (group) {
7730             if (group !== openGroup) {
7731                 group.isOpen = false;
7732             }
7733         });
7734     }
7735     if (this.groups.indexOf(openGroup) === (this.groups.length - 1) && $scope.forceExpand) {
7736         $scope.forceExpand = false;
7737     }
7738 };
7739 this.expandAll = function () {
7740     $scope.forceExpand = true;
7741     angular.forEach(this.groups, function (group) {
7742         group.isOpen = true;
7743     });
7744 };
7745 this.collapseAll = function () {
7746     angular.forEach(this.groups, function (group) {
7747         group.isOpen = false;
7748     });
7749 };
7750 /**function focus @param focusGroup */
7751 this.focus = function (focusGroup) {
7752     var self = this;
7753     angular.forEach(this.groups, function (group, index) {
7754         if (group !== focusGroup) {
7755             group.focused = false;
7756         } else {
7757             self.index = index;
7758             group.focused = true;
7759         }
7760     });
7761 };
7762 /** @param blurGroup*/
7763 this.blur = function (blurGroup) {
7764     blurGroup.focused = false;
7765     this.index = -1;
7766     $log.log("accordion.blur()", blurGroup);
7767 };
7768 /** @param group - the group in current focus @param down - cycling down */
7769 this.cycle = function (group, down, noRecycle) {
7770     if (!down) {
7771         if (this.index <= 0 && !noRecycle) {
7772             this.index = this.groups.length - 1;
7773         } else {
7774             this.index--;
7775         }
7776     } else {
7777         if (this.index === (this.groups.length - 1))
7778         {
7779             if (noRecycle) {
7780                 this.index = 0;
7781                 group.focused = false;
7782                 $scope.$apply();
7783                 return;
7784             }
7785             else
7786             {
7787                 this.index = 0;
7788             }
7789         } else {
7790             this.index++;
7791         }
7792     }
7793
7794     group.focused = false;
7795     this.groups[this.index].setFocus = true;
7796     this.groups[this.index].focused = true;
7797     $scope.$apply();
7798 };
7799 // This is called from the accordion-group directive to add itself to the accordion
7800 this.addGroup = function (groupScope) {
7801     var that = this;
7802     groupScope.index = this.groups.length;
7803     groupScope.focused = false;
7804     this.groups.push(groupScope);
7805
7806     if(this.groups.length > 0){
7807         this.index = 0;
7808     }
7809
7810     groupScope.$on('$destroy', function () {
7811         that.removeGroup(groupScope);
7812     });
7813 };
7814 // This is called from the accordion-group directive when to remove itself
7815 this.removeGroup = function (group) {
7816     var index = this.groups.indexOf(group);
7817     if (index !== -1) {
7818         this.groups.splice(this.groups.indexOf(group), 1);
7819     }
7820 };
7821 }])
7822 //The accordion directive simply sets up the directive controller and adds an accordion CSS class to itself element.
7823 .directive('accordion', function () {
7824     return {
7825         restrict: 'EA',
7826         controller: 'AccordionController',
7827         transclude: true,
7828         replace: false,
7829         scope: {
7830             cClass: '@css',
7831             expandAll: "=?",
7832             collapseAll: "=?"
7833         },
7834         template: '<div class="{{cClass}}" ng-transclude></div>',
7835         link: function (scope, elem, attribute, ctrl) {
7836             scope.$watch("expandAll", function (value) {
7837                 if (value) {
7838                     ctrl.expandAll();
7839                     scope.expandAll = false;
7840                 }
7841             });
7842             scope.$watch("collapseAll", function (value) {
7843                 if (value) {
7844                     ctrl.collapseAll();
7845                     scope.collapseAll = false;
7846                 }
7847             });
7848         }
7849     };
7850 })
7851 //The accordion-group directive indicates a block of html that will expand and collapse in an accordion
7852 .directive('accordionGroup', [ function () {
7853         return {
7854             // We need this directive to be inside an accordion
7855             require: ['^accordion', 'accordionGroup'],
7856             restrict: 'EA',
7857             // It transcludes the contents of the directive into the template
7858             transclude: true,
7859             // The element containing the directive will be replaced with the template
7860             replace: true,
7861             templateUrl: 'app/scripts/ng_js_att_tpls/accordion/accordion.html',
7862             scope: {
7863                 // Create an isolated scope and interpolate the heading attribute onto this scope
7864                 heading: '@',
7865                 isOpen: '=?'
7866             },
7867             controller: ['$scope', function ($scope)
7868                 {
7869                     $scope.showicon = true;
7870                     this.setHeading = function (element)
7871                     {
7872                         this.heading = element;
7873                         $scope.showicon = false;
7874                     };
7875                     this.isIsOpen = function ()
7876                     {
7877                         return $scope.isOpen;
7878                     };
7879                 }],
7880             link: function (scope, element, attrs, ctrl) {
7881                 var accordionCtrl = ctrl[0];
7882                 var accordionGroupCtrl = ctrl[1];
7883                 var keys = {tab: 9, enter: 13, esc: 27, space: 32, pageup: 33, pagedown: 34, end: 35, home: 36, left: 37, up: 38, right: 39, down: 40};
7884                 //not a fix
7885                 var tab = element.children().eq(0);
7886                 var parentHyperLink=attrs.parentLink;
7887                 scope.setFocus = false;
7888                 scope.childLength = attrs.childLength;
7889                 scope.headingIconClass = attrs.imageSource;
7890
7891                 var handleKeydown = function (ev) {
7892                     var boolFlag = true;
7893                     switch (ev.keyCode)
7894                     {
7895                         case keys.enter:
7896                             ev.preventDefault();
7897                             scope.toggle();
7898                             scope.$apply();
7899                             break;
7900                         case keys.up:
7901                         case keys.left:
7902                             ev.preventDefault();
7903                             accordionCtrl.cycle(scope, false);
7904                             break;
7905                         case keys.down:
7906                         case keys.right:
7907                             ev.preventDefault();
7908                             accordionCtrl.cycle(scope, true);
7909                             break;
7910                         default:
7911                             boolFlag = false;
7912                             break;
7913                     }
7914                     ev.stopPropagation();
7915                     return boolFlag;
7916                 };
7917
7918                 if (angular.isUndefined(scope.isOpen)) {
7919                     scope.isOpen = false;
7920                 }
7921
7922                 tab.bind("keydown", handleKeydown);
7923
7924                 accordionCtrl.addGroup(scope);
7925
7926                 if (scope.index === 0) {
7927                     scope.focused = true;
7928                 }
7929
7930                 accordionGroupCtrl.toggle = scope.toggle = function () {
7931                         /* if the menu item has children, toggle/expand child menu of this item */
7932                         if (scope.childLength>0) {
7933                         scope.isOpen = !scope.isOpen;
7934                         accordionCtrl.focus(scope);
7935                         return scope.isOpen;
7936                         }
7937                         /* if the menu item does not have children, redirect to parent action URL*/
7938                         else {
7939                                 window.location.href = parentHyperLink;
7940                         }
7941                         
7942                 };
7943
7944                 scope.$watch('isOpen', function (value) {
7945                     if (value) {
7946                         accordionCtrl.closeOthers(scope);
7947                     }
7948                 });
7949
7950                 scope.$watch("focused", function (value) {
7951                     if (!!value) {
7952                         tab.attr("tabindex", "0");
7953                         if(scope.setFocus){
7954                             tab[0].focus();
7955                         }
7956                     }
7957                     else{
7958                         scope.setFocus = false;
7959                         tab.attr("tabindex", "-1");
7960                     }
7961                 });
7962             }
7963         };
7964     }])
7965 //Use accordion-heading below an accordion-group to provide a heading containing HTML
7966 //<accordion-group>
7967 //<accordion-heading>Heading containing HTML - <img src="..."></accordion-heading>
7968 //</accordion-group>
7969 .directive('accordionToggle', function () {
7970     return{
7971         restrict: 'EA',
7972         require: '^accordionGroup',
7973         scope: {
7974             expandIcon: '@',
7975             collapseIcon: '@'
7976         },
7977         link: function (scope, element, attr, accordionCtrl)
7978         {
7979             var setIcon = function (isOpen) {
7980                 if (scope.expandIcon && scope.collapseIcon)
7981                 {
7982                     if (isOpen) {
7983                         element.removeClass(scope.expandIcon);
7984                         element.addClass(scope.collapseIcon);
7985                     }
7986                     else {
7987                         element.removeClass(scope.collapseIcon);
7988                         element.addClass(scope.expandIcon);
7989                     }
7990                 }
7991             };
7992             element.bind('click', function ()
7993             {
7994                 accordionCtrl.toggle();
7995                 scope.$apply();
7996             });
7997             scope.$watch(function () {
7998                 return accordionCtrl.isIsOpen();
7999             }, function (value) {
8000                 setIcon(value);
8001             });
8002         }
8003     };
8004 }).directive('accordionHeading', function () {
8005 return {
8006 restrict: 'EA',
8007 transclude: true,
8008 template: '',
8009 require: '^accordionGroup',
8010 compile: function (element, attr, transclude) {
8011     var link = function (scope, element, attr, accordionGroupCtrl) {
8012         // Pass the heading to the accordion-group controller
8013         // so that it can be transcluded into the right place in the template
8014         // [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat]
8015         transclude(scope, function (clone) {
8016             element.append(clone);
8017             accordionGroupCtrl.setHeading(element);
8018         });
8019     };
8020     return link;
8021 }
8022 };
8023 })
8024 // Use in the accordion-group template to indicate where you want the heading to be transcluded
8025 // You must provide the property on the accordion-group controller that will hold the transcluded element
8026         .directive('accordionTransclude', function () {
8027             return {
8028                 require: '^accordionGroup',
8029                 link: function (scope, element, attr, controller) {
8030                     scope.$watch(function () {
8031                         return controller[attr.accordionTransclude];
8032                     }, function (heading) {
8033                         if (heading) {
8034                             element.find("span").eq(0).prepend(heading);
8035                         }
8036                     });
8037                 }
8038             };
8039         })
8040         .directive('attGoTop', ['$scrollTo', function ($scrollTo) {
8041                 return {
8042                     restrict: 'A',
8043                     transclude: false,
8044                     link: function (scope, elem, attrs)
8045                     {
8046                         elem.bind('click', function ()
8047                         {
8048                             $scrollTo(0, attrs["attGoTop"]);
8049                         });
8050                     }
8051                 };
8052             }])
8053         .directive('attGoTo', ['$anchorScroll', '$location', function ($anchorScroll, $location) {
8054                 return {
8055                     restrict: 'A',
8056                     transclude: false,
8057                     link: function (scope, elem, attrs)
8058                     {
8059                         elem.bind('click', function ()
8060                         {
8061                             var newHash = attrs["attGoTo"];
8062                             if ($location.hash() !== newHash)
8063                             {
8064                                 $location.hash(attrs["attGoTo"]);
8065                             }
8066                             else
8067                             {
8068                                 $anchorScroll();
8069                             }
8070                         });
8071                     }
8072                 };
8073             }])
8074         .directive('freeStanding', function () {
8075             return {
8076                 restrict: 'EA',
8077                 transclude: true,
8078                 replace: true,
8079                 scope: true,
8080                 template: "<div><span class='att-accordion__freestanding' ng-show='showAccordion'></span>\n" +
8081                         "<div class='section-toggle'>\n" +
8082                         "<button class='section-toggle__button' ng-click='fsToggle()'>\n" +
8083                         "    {{btnText}}<i style='font-size:0.875rem' ng-class='{\"ion-ios-arrow-up\": showAccordion,\"ion-ios-arrow-down\": !showAccordion, }'></i> \n" +
8084                         "</button>\n" +
8085                         "</div></div>",
8086                 compile: function (element, attr, transclude)
8087                 {
8088                     var link = function (scope, elem, attrs) {
8089                         scope.content = "";
8090                         transclude(scope, function (clone)
8091                         {
8092                             elem.find("span").append(clone);
8093                         });
8094                         scope.showAccordion = false;
8095                         scope.btnText = scope.showAccordion ? attrs.hideMsg : attrs.showMsg;
8096                         scope.fsToggle = function ()
8097                         {
8098                             scope.showAccordion = !scope.showAccordion;
8099                             scope.btnText = scope.showAccordion ? attrs.hideMsg : attrs.showMsg;
8100                         };
8101                     };
8102                     return link;
8103                 }
8104             };
8105         }).directive('expanders', function () {
8106     return{
8107         restrict: 'EA',
8108         replace: true,
8109         transclude: true,
8110         template: "<div ng-transclude></div>",
8111         controller: ['$scope', function ($scope){
8112                 var bodyScope = null;
8113                 this.setScope = function (scope) {
8114                     bodyScope = scope;
8115                 };
8116                 this.toggle = function () {
8117                     $scope.isOpen = bodyScope.isOpen = !bodyScope.isOpen;
8118                     return bodyScope.isOpen;
8119                 };
8120             }],
8121         link: function (scope)
8122         {
8123             scope.isOpen = false;
8124         }
8125     };
8126 }).directive('expanderHeading', function () {
8127     return{
8128         require: "^expanders",
8129         restrict: 'EA',
8130         replace: true,
8131         transclude: true,
8132         scope: true,
8133         template: "<div style='padding:10px !important' ng-transclude></div>"
8134     };
8135 }).directive('expanderBody', function () {
8136     return{
8137         restrict: 'EA',
8138         require: "^expanders",
8139         replace: true,
8140         transclude: true,
8141         scope: {},
8142         template: "<div collapse='!isOpen'><div ng-transclude></div></div>",
8143         link: function (scope, elem, attr, myCtrl) {
8144             scope.isOpen = false;
8145             myCtrl.setScope(scope);
8146         }
8147     };
8148 }).directive('expanderToggle', function () {
8149     return{
8150         restrict: 'EA',
8151         require: "^expanders",
8152         scope: {
8153             expandIcon: '@',
8154             collapseIcon: '@'
8155         },
8156         link: function (scope, element, attr, myCtrl)
8157         {
8158             var isOpen = false;
8159             var setIcon = function () {
8160                 if (scope.expandIcon && scope.collapseIcon)
8161                 {
8162                     if (isOpen) {
8163                         element.removeClass(scope.expandIcon);
8164                         element.addClass(scope.collapseIcon);
8165                     }
8166                     else {
8167                         element.removeClass(scope.collapseIcon);
8168                         element.addClass(scope.expandIcon);
8169                     }
8170                 }
8171             };
8172             element.bind("keydown", function (e) {
8173                 if (e.keyCode === 13)
8174                 {
8175                     scope.toggleit();
8176                 }
8177             });
8178             element.bind('click', function ()
8179             {
8180                 scope.toggleit();
8181             });
8182             scope.toggleit = function ()
8183             {
8184                 isOpen = myCtrl.toggle();
8185                 setIcon();
8186                 scope.$apply();
8187             };
8188             setIcon();
8189         }
8190     };
8191 }).directive('collapse', ['$transition', function ($transition) {
8192         // CSS transitions don't work with height: auto, so we have to manually change the height to a
8193         // specific value and then once the animation completes, we can reset the height to auto.
8194         // Unfortunately if you do this while the CSS transitions are specified (i.e. in the CSS class
8195         // "collapse") then you trigger a change to height 0 in between.
8196         // The fix is to remove the "collapse" CSS class while changing the height back to auto - phew!
8197         var props = {
8198             open: {
8199                 marginTop: null,
8200                 marginBottom: null,
8201                 paddingTop: null,
8202                 paddingBottom: null,
8203                 display: 'block'
8204             },
8205             closed: {
8206                 marginTop: 0,
8207                 marginBottom: 0,
8208                 paddingTop: 0,
8209                 paddingBottom: 0,
8210                 display: 'none'
8211             }
8212         };
8213         var fixUpHeight = function (scope, element, height) {
8214             // We remove the collapse CSS class to prevent a transition when we change to height: auto
8215             element.removeClass('collapse');
8216             element.css({height: height});
8217             //adjusting for any margin or padding
8218             if (height === 0) {
8219                 element.css(props.closed);
8220             } else {
8221                 element.css(props.open);
8222             }
8223             // It appears that  reading offsetWidth makes the browser realise that we have changed the
8224             // height already :-/
8225             element.addClass('collapse');
8226         };
8227         return {
8228             link: function (scope, element, attrs) {
8229                 var isCollapsed;
8230                 var initialAnimSkip = true;
8231                 scope.$watch(function () {
8232                     return element[0].scrollHeight;
8233                 }, function () {
8234                     //The listener is called when scrollHeight changes
8235                     //It actually does on 2 scenarios:
8236                     // 1. Parent is set to display none
8237                     // 2. angular bindings inside are resolved
8238                     //When we have a change of scrollHeight we are setting again the correct height if the group is opened
8239                     if (element[0].scrollHeight !== 0 && !isCollapsed) {
8240                         if (initialAnimSkip) {
8241                             fixUpHeight(scope, element, element[0].scrollHeight + 'px');
8242                         } else {
8243                             fixUpHeight(scope, element, 'auto');
8244                         }
8245                     }
8246                 });
8247                 var currentTransition;
8248                 var doTransition = function (change) {
8249                     if (currentTransition) {
8250                         currentTransition.cancel();
8251                     }
8252                     currentTransition = $transition(element, change);
8253                     currentTransition.then(
8254                             function () {
8255                                 currentTransition = undefined;
8256                             },
8257                             function () {
8258                                 currentTransition = undefined;
8259                             }
8260                     );
8261                     return currentTransition;
8262                 };
8263                 var expand = function () {
8264                     scope.postTransition = true;
8265                     if (initialAnimSkip) {
8266                         initialAnimSkip = false;
8267                         if (!isCollapsed) {
8268                             fixUpHeight(scope, element, 'auto');
8269                         }
8270                     } else {
8271                         doTransition(angular.extend({height: element[0].scrollHeight + 'px'}, props.open))
8272                                 .then(function () {
8273                                     // This check ensures that we don't accidentally update the height if the user has closed
8274                                     // the group while the animation was still running
8275                                     if (!isCollapsed)
8276                                     {
8277                                         fixUpHeight(scope, element, 'auto');
8278                                     }
8279                                 });
8280                     }
8281                     isCollapsed = false;
8282                 };
8283                 var collapse = function () {
8284                     isCollapsed = true;
8285                     if (initialAnimSkip) {
8286                         initialAnimSkip = false;
8287                         fixUpHeight(scope, element, 0);
8288                     } else {
8289                         fixUpHeight(scope, element, element[0].scrollHeight + 'px');
8290                         doTransition(angular.extend({height: 0}, props.closed)).then(function () {
8291                             scope.postTransition = false;
8292                         });
8293                     }
8294                 };
8295                 scope.$watch(attrs.collapse, function (value) {
8296                     if (value) {
8297                         collapse();
8298                     } else {
8299                         expand();
8300                     }
8301                 });
8302             }
8303         };
8304     }])
8305         .directive('attAccord', function () {
8306             return {
8307                 restrict: 'EA',
8308                 transclude: true,
8309                 replace: true,
8310                 scope: {},
8311                 controller: 'AttAccordCtrl',
8312                 templateUrl: 'app/scripts/ng_js_att_tpls/accordion/attAccordHeader.html'
8313             };
8314         })
8315         .controller('AttAccordCtrl', [function () {
8316                 this.type = 'attAccord';
8317                 this.headerCtrl;
8318                 this.bodyCtrl;
8319                 var isOpen = true;
8320                 this.toggleBody = function () {
8321                     if (isOpen) {
8322                         this.expandBody();
8323                     }
8324                     else {
8325                         this.collapseBody();
8326                     }
8327                     isOpen = !isOpen;
8328                 };
8329                 this.expandBody = function () {
8330                     this.bodyCtrl.expand();
8331                 };
8332                 this.collapseBody = function () {
8333                     this.bodyCtrl.collapse();
8334                 };
8335             }])
8336         .controller('AttAccordHeaderCtrl', [function () {
8337                 this.type = 'header';
8338             }])
8339         .directive('attAccordHeader', ['keymap', 'events', function (keymap, events) {
8340             return {
8341                 restrict: 'EA',
8342                 transclude: true,
8343                 replace: true,
8344                 require: ['^attAccord', 'attAccordHeader'],
8345                 controller: 'AttAccordHeaderCtrl',
8346                 templateUrl: 'app/scripts/ng_js_att_tpls/accordion/attAccordHeader.html',
8347                 link: function (scope, element, attr, ctrls) {
8348                     var attAccordCtrl = ctrls[0];
8349                     var attAccordHeaderCtrl = ctrls[1];
8350                     attAccordCtrl.headerCtrl = attAccordHeaderCtrl;
8351                     var tab = element.children().eq(0);
8352                         
8353                     scope.clickFunc = function () {
8354                         attAccordCtrl.toggleBody();
8355                     };
8356
8357                     var handleKeydown = function (ev) {
8358                         var boolFlag = true;
8359                         switch (ev.keyCode)
8360                         {
8361                             case keymap.KEY.ENTER:
8362                                 ev.preventDefault();
8363                                 scope.clickFunc();
8364                                 scope.$apply();
8365                                 break;
8366                             default:
8367                                 boolFlag = false;
8368                                 break;
8369                         }
8370                         ev.stopPropagation();
8371                         return boolFlag;
8372                     };
8373                         
8374                     if (angular.isUndefined(scope.isOpen)) {
8375                         scope.isOpen = false;
8376                     }
8377
8378                     tab.bind("keydown", handleKeydown);
8379                 }
8380             };
8381         }])
8382         .controller('AttAccordBodyCtrl', ['$scope', function ($scope) {
8383                 this.type = 'body';
8384                 this.expand = function () {
8385                     $scope.expand();
8386                 };
8387                 this.collapse = function () {
8388                     $scope.collapse();
8389                 };
8390             }])
8391         .directive('attAccordBody', ['$timeout', '$height', function ($timeout, $height) {
8392                 return {
8393                     restrict: 'EA',
8394                     transclude: true,
8395                     replace: true,
8396                     require: ['^attAccord', 'attAccordBody'],
8397                     controller: 'AttAccordBodyCtrl',
8398                     templateUrl: 'app/scripts/ng_js_att_tpls/accordion/attAccordBody.html',
8399                     link: function (scope, element, attr, ctrls) {
8400                         var attAccordCtrl = ctrls[0];
8401                         var attAccordBodyCtrl = ctrls[1];
8402                         attAccordCtrl.bodyCtrl = attAccordBodyCtrl;
8403                         var originalHeight;
8404                         $timeout(function () {
8405                             originalHeight = element[0].offsetHeight;
8406                             $height(element, 0, 0, 0);
8407                         });
8408                         scope.expand = function () {
8409                             $height(element, 0.05, originalHeight, 1);
8410                         };
8411                         scope.collapse = function () {
8412                             $height(element, 0.25, 0, 0);
8413                         };
8414                     }
8415                 };
8416             }]);
8417 angular.module('att.abs.alert', [])
8418 .directive('attAlert', [function()
8419 {
8420     return {
8421         restrict:'EA',
8422         replace : true,
8423         transclude : true,
8424         scope: {
8425             alertType : "@type",
8426             showTop : "@topPos",
8427             showAlert : "="
8428         },
8429        templateUrl : 'app/scripts/ng_js_att_tpls/alert/alert.html',
8430        link: function(scope)
8431         {
8432             if(scope.showTop === 'true'){
8433                 scope.cssStyle = {'top':'50px'};
8434             }
8435             else{
8436                scope.cssStyle = {'top':'0px'};
8437             }
8438            scope.close = function(){
8439                scope.showAlert = false;
8440             };
8441         }
8442     };
8443 }]);
8444
8445 angular.module('att.abs.boardStrip', ['att.abs.utilities'])
8446 .constant('BoardStripConfig', {
8447     'maxVisibleBoards': 4,
8448     'boardsToScroll': 1,
8449     /* These parameters are non-configurable and remain unaltered, until there is a change in corresponding SCSS */
8450     'boardLength': 140,
8451     'boardMargin': 15
8452 })
8453 .directive('attBoard', [function() {
8454     return {
8455         restrict: 'AE',
8456         replace: true,
8457         transclude: true,
8458         require: '^attBoardStrip',
8459         scope : {
8460             boardIndex : '=',
8461             boardLabel : '='
8462         },
8463         templateUrl: 'app/scripts/ng_js_att_tpls/boardStrip/attBoard.html',
8464         link: function(scope, element, attrs, ctrls) {
8465
8466             var parentCtrl = ctrls;
8467
8468             scope.getCurrentIndex = function() {
8469                 return parentCtrl.getCurrentIndex();
8470             };
8471             scope.selectBoard = function(boardIndex) {
8472                 if (!isNaN(boardIndex)) {
8473                     parentCtrl.setCurrentIndex(boardIndex);
8474                 }
8475             };
8476             scope.isInView = function(boardIndex) {
8477                 return parentCtrl.isInView(boardIndex);
8478             };
8479         }
8480     };
8481 }])
8482 .directive('attBoardStrip', ['BoardStripConfig', '$timeout', '$ieVersion', function(BoardStripConfig, $timeout, $ieVersion) {
8483     return {
8484         restrict: 'AE',
8485         replace: true,
8486         transclude: true,
8487         scope: {
8488             currentIndex: '=selectedIndex',
8489             boardsMasterArray : '=',
8490             onAddBoard : '&?'
8491         },
8492         templateUrl: 'app/scripts/ng_js_att_tpls/boardStrip/attBoardStrip.html',
8493         controller: function($scope) {
8494             if(!angular.isDefined($scope.boardsMasterArray)){
8495                 $scope.boardsMasterArray = [];
8496             }
8497
8498             this.rectifyMaxVisibleBoards = function() {
8499                 if (this.maxVisibleIndex >= $scope.boardsMasterArray.length) {
8500                     this.maxVisibleIndex = $scope.boardsMasterArray.length - 1;
8501                 }
8502
8503                 if (this.maxVisibleIndex < 0) {
8504                     this.maxVisibleIndex = 0;
8505                 }
8506             };
8507
8508             this.resetBoardStrip = function(){
8509                 $scope.currentIndex = 0;
8510
8511                 this.maxVisibleIndex = BoardStripConfig.maxVisibleBoards-1;
8512                 this.minVisibleIndex = 0;
8513
8514                 this.rectifyMaxVisibleBoards();
8515             };
8516
8517
8518             if ($scope.currentIndex > 0) {
8519                 var index = $scope.currentIndex;
8520                 this.resetBoardStrip();
8521                 if (index > $scope.boardsMasterArray.length) {
8522                     $scope.currentIndex = $scope.boardsMasterArray.length-1;
8523                 } else {
8524                     $scope.currentIndex = index;
8525                 }
8526             } else {
8527                 this.resetBoardStrip();
8528             }
8529             
8530
8531             this.getCurrentIndex = function() {
8532                 return $scope.currentIndex;
8533             };
8534             this.setCurrentIndex = function(indx) {
8535                 $scope.currentIndex = indx;
8536             };
8537
8538             this.isInView = function(index) {
8539                 return (index <= this.maxVisibleIndex && index >= this.minVisibleIndex);
8540             };
8541
8542             this.getBoardsMasterArrayLength = function() {
8543                 return $scope.boardsMasterArray.length;
8544             };
8545         },
8546         link: function(scope, element, attrs, ctrl) {
8547                         var ieVersion = $ieVersion();
8548
8549                         var oldTimeout;
8550                         var animationTimeout = 1000;
8551                         
8552                         if(ieVersion && ieVersion < 10) {
8553                                 animationTimeout = 0;
8554                         }
8555
8556                         var getBoardViewportWidth = function (numberOfVisibleBoards) {
8557                                 return numberOfVisibleBoards * (BoardStripConfig.boardLength + BoardStripConfig.boardMargin);
8558                         };
8559                         if(element[0].querySelector(".board-viewport")) {
8560                                 angular.element(element[0].querySelector(".board-viewport")).css({"width": getBoardViewportWidth(BoardStripConfig.maxVisibleBoards) + "px"});
8561                         }
8562
8563                         var getBoardstripContainerWidth = function (totalNumberOfBoards) {
8564                                 return totalNumberOfBoards * (BoardStripConfig.boardLength + BoardStripConfig.boardMargin);
8565                         };
8566                         if(element[0].querySelector(".boardstrip-container")) {
8567                                 angular.element(element[0].querySelector(".boardstrip-container")).css({"width": getBoardstripContainerWidth(ctrl.getBoardsMasterArrayLength()) + "px"});
8568                                 angular.element(element[0].querySelector(".boardstrip-container")).css({"left": "0px"});
8569                         }
8570
8571                         var calculateAndGetBoardstripContainerAdjustment = function () {
8572
8573                                 var calculatedAdjustmentValue;
8574
8575                                 if(ctrl.getBoardsMasterArrayLength() <= BoardStripConfig.maxVisibleBoards) {
8576                                         calculatedAdjustmentValue = 0;
8577                                 }
8578                                 else{
8579                                         calculatedAdjustmentValue = (ctrl.minVisibleIndex * (BoardStripConfig.boardLength + BoardStripConfig.boardMargin))* -1;
8580                                 }
8581                                 
8582                                 return calculatedAdjustmentValue;
8583                         };
8584
8585             var updateBoardsTabIndex = function(boardArray, minViewIndex, maxViewIndex) {
8586                 for (var i = 0; i < boardArray.length; i++) {
8587                     angular.element(boardArray[i]).attr('tabindex', '-1');
8588                 }
8589                 for (var i = minViewIndex; i <= maxViewIndex; i++) {
8590                     angular.element(boardArray[i]).attr('tabindex', '0');
8591                 }
8592             };
8593                         
8594             scope.$watchCollection('boardsMasterArray', function(newVal, oldVal){
8595                 if(newVal !== oldVal){
8596                                         /* When a board is removed */
8597                                         if(newVal.length < oldVal.length){
8598                                                 ctrl.resetBoardStrip();
8599                                                 $timeout(function(){
8600                                                         
8601                                                         var currentBoardArray = element[0].querySelectorAll('[att-board]');
8602                                                         if(currentBoardArray.length !== 0) {
8603
8604                                                                 var oldContainerAdjustment = angular.element(element[0].querySelector(".boardstrip-container"))[0].style.left;
8605                                                                 var containerAdjustment = calculateAndGetBoardstripContainerAdjustment();
8606                                                                 if(oldContainerAdjustment !== containerAdjustment+'px') {
8607                                                                         angular.element(element[0].querySelector(".boardstrip-container")).css({"left": containerAdjustment + "px"});
8608
8609                                                                         $timeout.cancel(oldTimeout);
8610                                                                         oldTimeout = $timeout(function(){
8611                                                                                 currentBoardArray[0].focus();
8612                                                                         }, animationTimeout);
8613                                                                 }
8614                                                                 else{
8615                                                                         currentBoardArray[0].focus();
8616                                                                 }
8617                                                         }
8618                                                         else{
8619                                                                 element[0].querySelector('div.boardstrip-item--add').focus();
8620                                                         }
8621                                                         
8622                                                         angular.element(element[0].querySelector(".boardstrip-container")).css({"width": getBoardstripContainerWidth(ctrl.getBoardsMasterArrayLength()) + "px"});
8623                                                 });
8624                                         }
8625                                         /* When a board is added */
8626                                         else {
8627                                                 ctrl.maxVisibleIndex = ctrl.getBoardsMasterArrayLength()-1;
8628                                                 ctrl.minVisibleIndex = Math.max(ctrl.maxVisibleIndex - BoardStripConfig.maxVisibleBoards + 1, 0);
8629
8630                                                 ctrl.setCurrentIndex(ctrl.maxVisibleIndex);
8631
8632                                                 $timeout(function(){
8633                                                         angular.element(element[0].querySelector(".boardstrip-container")).css({"width": getBoardstripContainerWidth(ctrl.getBoardsMasterArrayLength()) + "px"});
8634                                                         
8635                                                         var oldContainerAdjustment = angular.element(element[0].querySelector(".boardstrip-container"))[0].style.left;
8636                                                         var containerAdjustment = calculateAndGetBoardstripContainerAdjustment();
8637                                                         var currentBoardArray = element[0].querySelectorAll('[att-board]');
8638                                                         if(oldContainerAdjustment !== containerAdjustment+'px') {
8639                                                                 angular.element(element[0].querySelector(".boardstrip-container")).css({"left": containerAdjustment + "px"});
8640                                                                 
8641                                                                 $timeout.cancel(oldTimeout);
8642                                                                 oldTimeout = $timeout(function(){
8643                                                                         currentBoardArray[currentBoardArray.length-1].focus();
8644                                                                 }, animationTimeout);
8645                                                         }
8646                                                         else{
8647                                                                 currentBoardArray[currentBoardArray.length-1].focus();
8648                                                         }
8649                             /* Update tabindecies to ensure keyboard navigation behaves correctly */
8650                             updateBoardsTabIndex(currentBoardArray, ctrl.minVisibleIndex, ctrl.maxVisibleIndex);
8651                                                 });
8652                                         }
8653                 }
8654             });
8655
8656             scope.nextBoard = function() {
8657                 ctrl.maxVisibleIndex += BoardStripConfig.boardsToScroll;
8658                 ctrl.rectifyMaxVisibleBoards();
8659                 ctrl.minVisibleIndex = ctrl.maxVisibleIndex - (BoardStripConfig.maxVisibleBoards-1);
8660
8661                                 $timeout.cancel(oldTimeout);
8662                                 angular.element(element[0].querySelector(".boardstrip-container")).css({"left": calculateAndGetBoardstripContainerAdjustment() + "px"});
8663
8664                 $timeout(function(){
8665                     var currentBoardArray = element[0].querySelectorAll('[att-board]');
8666
8667                     /* Remove tabindex from non-visible boards */
8668                     updateBoardsTabIndex(currentBoardArray, ctrl.minVisibleIndex, ctrl.maxVisibleIndex);
8669
8670                     if (!(scope.isNextBoard())) {
8671                         try {
8672                             currentBoardArray[currentBoardArray.length-1].focus();
8673                         } catch(e) {}
8674                     }
8675                 }, animationTimeout);
8676             };
8677             scope.prevBoard = function() {
8678
8679                 ctrl.minVisibleIndex -= BoardStripConfig.boardsToScroll;
8680                 if (ctrl.minVisibleIndex < 0) {
8681                     ctrl.minVisibleIndex = 0;
8682                 }
8683
8684                 ctrl.maxVisibleIndex = ctrl.minVisibleIndex + BoardStripConfig.maxVisibleBoards-1;
8685                 ctrl.rectifyMaxVisibleBoards();
8686
8687                                 $timeout.cancel(oldTimeout);
8688                                 angular.element(element[0].querySelector(".boardstrip-container")).css({"left": calculateAndGetBoardstripContainerAdjustment() + "px"});
8689
8690                 $timeout(function(){
8691                     var currentBoardArray = element[0].querySelectorAll('[att-board]');
8692
8693                     /* Remove tabindex from non-visible boards */
8694                     updateBoardsTabIndex(currentBoardArray, ctrl.minVisibleIndex, ctrl.maxVisibleIndex);
8695
8696                     if (ctrl.minVisibleIndex === 0) {
8697                         try {
8698                             element[0].querySelector('div.boardstrip-item--add').focus();
8699                         } catch (e) {} /* IE8 may throw exception */
8700                     }
8701                 });
8702             };
8703
8704             scope.isPrevBoard = function() {
8705                 return (ctrl.minVisibleIndex > 0);
8706             };
8707             scope.isNextBoard = function() {
8708                 return (ctrl.getBoardsMasterArrayLength()-1 > ctrl.maxVisibleIndex);
8709             };
8710         }
8711     };
8712 }])
8713 .directive('attAddBoard', ['BoardStripConfig', '$parse', '$timeout', function(BoardStripConfig, $parse, $timeout) {
8714     return {
8715         restrict: 'AE',
8716         replace: true,
8717         require: '^attBoardStrip',
8718         scope : {
8719             onAddBoard : '&?'
8720         },
8721         templateUrl: 'app/scripts/ng_js_att_tpls/boardStrip/attAddBoard.html',
8722         link: function(scope, element, attrs, ctrls) {
8723             var parentCtrl = ctrls;
8724             scope.addBoard = function() {
8725                 if (attrs['onAddBoard'] ) {
8726                     scope.onAddBoard = $parse(scope.onAddBoard);
8727                     scope.onAddBoard();
8728                 }
8729             };
8730         }
8731     };
8732 }])
8733 .directive('attBoardNavigation', ['keymap', 'events', function(keymap, events) {
8734     return {
8735         restrict: 'AE',
8736         link: function(scope, elem) {
8737
8738             var prevElem = keymap.KEY.LEFT;
8739             var nextElem = keymap.KEY.RIGHT;
8740
8741             elem.bind('keydown', function (ev) {
8742
8743                 if (!(ev.keyCode)) {
8744                     ev.keyCode = ev.which;
8745                 }
8746
8747                 switch (ev.keyCode) {
8748                 case nextElem:
8749                     events.preventDefault(ev);
8750                     events.stopPropagation(ev);
8751
8752                     if (elem[0].nextElementSibling && parseInt(angular.element(elem[0].nextElementSibling).attr('tabindex')) >= 0) {
8753                         angular.element(elem[0])[0].nextElementSibling.focus();
8754                     } else {
8755                         /* IE8 fix */
8756                         var el = angular.element(elem[0])[0];
8757                         do {
8758                             if (el.nextSibling){
8759                                 el = el.nextSibling;
8760                             }
8761                             else{
8762                                 break;
8763                             }
8764                         } while (el && el.tagName !== 'LI');
8765
8766                         if (el.tagName && el.tagName === 'LI' && parseInt(angular.element(el).attr('tabindex')) >= 0){
8767                             el.focus();
8768                         }
8769                     }
8770
8771                     break;
8772                 case prevElem:
8773                     events.preventDefault(ev);
8774                     events.stopPropagation(ev);
8775
8776                     if (elem[0].previousElementSibling && parseInt(angular.element(elem[0].previousElementSibling).attr('tabindex')) >= 0) {
8777                         angular.element(elem[0])[0].previousElementSibling.focus();
8778                     } else {
8779                         /* IE8 fix */
8780                         var el1 = angular.element(elem[0])[0];
8781                         do {
8782                             if (el1.previousSibling){
8783                                 el1 = el1.previousSibling;
8784                             }
8785                             else{
8786                                 break;
8787                             }
8788                         } while (el1 && el1.tagName !== 'LI');
8789
8790                         if (el1.tagName && el1.tagName === 'LI' && parseInt(angular.element(el).attr('tabindex')) >= 0){
8791                             el1.focus();
8792                         }
8793                     }
8794                     break;
8795                 default:
8796                     break;
8797                 }
8798             });
8799         }
8800     };
8801 }]);
8802
8803 angular.module('att.abs.breadCrumbs', [])
8804     .constant("classConstant",{
8805             "defaultClass" : "breadcrumbs__link",
8806             "activeClass": "breadcrumbs__link--active"
8807         })
8808     .directive('attCrumb', ['classConstant', function(classConstant) {
8809         return {
8810             restrict: 'A',
8811             link: function(scope, elem, attr) {
8812                 elem.addClass(classConstant.defaultClass);
8813                 if(attr.attCrumb === 'active'){
8814                      elem.addClass(classConstant.activeClass);
8815                 }
8816                if(!elem.hasClass('last')){
8817                    elem.after('<i class="breadcrumbs__item"></i>');
8818                }
8819             }
8820         };
8821     }
8822 ]);
8823 angular.module('att.abs.buttons', ['att.abs.position', 'att.abs.utilities'])
8824         .constant('btnConfig', {
8825             btnClass: 'button',
8826             btnPrimaryClass: 'button--primary',
8827             btnSecondaryClass: 'button--secondary',
8828             btnDisabledClass: 'button--inactive',
8829             btnSmallClass: 'button--small'
8830         })
8831         .directive('attButton', ['btnConfig', function (btnConfig) {
8832                 return {
8833                     restrict: 'A',
8834                     link: function (scope, element, attrs) {
8835                         element.addClass(btnConfig.btnClass);
8836                         if (attrs.size === 'small') {
8837                             element.addClass(btnConfig.btnSmallClass);
8838                         }
8839                         attrs.$observe('btnType', function (value) {
8840                             if (value === 'primary') {
8841                                 element.addClass(btnConfig.btnPrimaryClass);
8842                                 element.removeClass(btnConfig.btnSecondaryClass);
8843                                 element.removeClass(btnConfig.btnDisabledClass);
8844                                 element.removeAttr('disabled');
8845                             } else if (value === 'secondary') {
8846                                 element.addClass(btnConfig.btnSecondaryClass);
8847                                 element.removeClass(btnConfig.btnPrimaryClass);
8848                                 element.removeClass(btnConfig.btnDisabledClass);
8849                                 element.removeAttr('disabled');
8850                             } else if (value === 'disabled') {
8851                                 element.addClass(btnConfig.btnDisabledClass);
8852                                 element.removeClass(btnConfig.btnPrimaryClass);
8853                                 element.removeClass(btnConfig.btnSecondaryClass);
8854                                 element.attr('disabled', 'disabled');
8855                             }
8856                         });
8857                     }
8858                 };
8859             }])
8860         .directive('attButtonLoader', [function () {
8861                 return {
8862                     restrict: 'A',
8863                     replace: false,
8864                     scope: {
8865                         size: '@'
8866                     },
8867                     template: '<div ng-class="{\'button--loading\': size === \'large\',\'button--loading__small\': size === \'small\'}"><i></i><i class="second__loader"></i><i></i></div>',
8868                     link: function (scope, element) {
8869                         element.addClass('button button--inactive');
8870                     }
8871                 };
8872             }])
8873         .directive('attButtonHero', [function () {
8874                 return {
8875                     restrict: 'A',
8876                     replace: false,
8877                     transclude: true,
8878                     scope: {
8879                         icon: '@'
8880                     },
8881                     template: '<div class="button--hero__inner"><span ng-transclude></span> <i ng-class="{\'icon-arrow-right\': icon === \'arrow-right\',\'icon-cart\': icon === \'cart\'}"></i></div>',
8882                     link: function (scope, element) {
8883                         element.addClass('button button--hero');
8884                         element.attr("tabindex", "0");
8885                     }
8886                 };
8887             }])
8888         .directive('attBtnDropdown', ['$document', '$timeout', '$isElement', '$documentBind', 'keymap', 'events', function ($document, $timeout, $isElement, $documentBind, keymap, events) {
8889                 return {
8890                     restrict: 'EA',
8891                     scope: {
8892                         type: "@dropdowntype"
8893                     },
8894                     replace: true,
8895                     transclude: true,
8896                     templateUrl: 'app/scripts/ng_js_att_tpls/buttons/buttonDropdown.html',
8897                     link: function (scope, element) {
8898                         scope.isOpen = false;
8899                         var currentIndex = -1;
8900                         // Capture all the li elements after compilation
8901                         var list = [], button = undefined;
8902                         $timeout(function() {
8903                             list = element.find('li');
8904                             button = element.find('button')[0];
8905                         }, 10);
8906                         var toggle = scope.toggle = function (show) {
8907                             if (angular.isUndefined(show) || show === '') {
8908                                 scope.isOpen = !scope.isOpen;
8909                             }
8910                             else {
8911                                 scope.isOpen = show;
8912                             }
8913                         };
8914                         var selectNext = function() {
8915                             if (currentIndex+1 < list.length) {
8916                                 currentIndex++;
8917                                 list[currentIndex].focus();
8918                             }
8919                         };
8920                         var selectPrev = function() {
8921                             if (currentIndex-1 >= 0) {
8922                                 currentIndex--;
8923                                 list[currentIndex].focus();
8924                             }
8925                         };
8926                         element.bind("keydown", function($event) {
8927                             var keyCode = $event.keyCode;
8928                             if (keymap.isAllowedKey(keyCode) || keymap.isControl($event) || keymap.isFunctionKey($event)) {
8929                                 switch (keyCode) {
8930                                     case keymap.KEY.ENTER:
8931                                         if (currentIndex > 0) {
8932                                             button.focus();
8933                                             scope.$apply();
8934                                         }
8935                                         break;
8936                                     case keymap.KEY.ESC:
8937                                         toggle(false);
8938                                         currentIndex = -1;
8939                                         button.focus();
8940                                         scope.$apply();
8941                                         break;
8942                                     case keymap.KEY.DOWN:
8943                                         selectNext();
8944                                         scope.$apply();
8945                                         events.preventDefault($event);
8946                                         events.stopPropagation($event);
8947                                         break;
8948                                     case keymap.KEY.UP:
8949                                         selectPrev();
8950                                         scope.$apply();
8951                                         events.preventDefault($event);
8952                                         events.stopPropagation($event);
8953                                         break;
8954                                     default:
8955                                         break;
8956                                 }
8957                             } else if (keyCode === keymap.KEY.TAB) {
8958                                 toggle(false);
8959                                 currentIndex = -1;
8960                                 scope.$apply();
8961                             }
8962                         });
8963                         var outsideClick = function (e) {
8964                             var isElement = $isElement(angular.element(e.target), element, $document);
8965                             if (!isElement) {
8966                                 toggle(false);
8967                                 currentIndex = -1;
8968                                 for (var i = 0; i < list.length; i++) {
8969                                     angular.element(list[i]).removeClass('selected');
8970                                 }
8971                                 button.focus();
8972                                 scope.$apply();
8973                             }
8974                         };
8975                         $documentBind.click('isOpen', outsideClick, scope);
8976                     }
8977                 };
8978             }]);
8979 angular.module('att.abs.checkbox', [])
8980 .constant("attCheckboxConfig", {
8981     activeClass : "att-checkbox--on",
8982     disabledClass : "att-checkbox--disabled"
8983 })
8984 .directive('checkboxLimit', function () {
8985 return {
8986     scope: {
8987         checkboxLimit:'=',
8988         selectLimit:'@?',
8989         maxSelected:'&?'
8990     },
8991     restrict: 'A',
8992     require:'checkboxLimit',
8993     controller: ['$scope',function($scope)
8994     {
8995         $scope.limit=true;
8996         this.getMaxLimits=function(){
8997             return $scope.limit;
8998         };
8999         this.setMaxLimits=function(value){
9000             $scope.limit=value;
9001         };
9002         this.maxCheckboxSelected=function(){
9003             $scope.maxSelected();
9004         };
9005     }],
9006     link: function (scope, element, attribute, ctrl) {
9007         scope.$watch('checkboxLimit', function()
9008         {
9009             var countTrue = 0;
9010             for (var keys in scope.checkboxLimit) {
9011                 if (scope.checkboxLimit.hasOwnProperty(keys) && scope.checkboxLimit[keys]) {
9012                         countTrue = countTrue + 1;
9013                 }
9014             };
9015             if(countTrue>=parseInt(scope.selectLimit)){
9016                 ctrl.setMaxLimits(false);
9017             }
9018             else{
9019                 ctrl.setMaxLimits(true);
9020             }
9021             }, true);
9022     }
9023 };
9024 })
9025 .directive('attCheckbox', ['$compile', "attCheckboxConfig", function ($compile, attCheckboxConfig) {
9026     return {
9027         scope: {},
9028         restrict: 'A',
9029         require: ['ngModel','^?checkboxLimit'],
9030         link: function (scope, element, attribute, ctrl) {
9031             var ngCtrl = ctrl[0];
9032             var checkboxLimitCtrl = ctrl[1];
9033             var parentDiv = $compile('<div tabindex="0" role="checkbox" att-accessibility-click="13,32" aria-label="Checkbox" ng-click="updateModel($event)" class="att-checkbox"></div>')(scope);
9034             element.css({display:'none'});
9035             element.wrap(parentDiv);
9036             element.parent().append('<div class="att-checkbox__indicator"></div>');
9037             element.parent().attr("title", attribute.title);
9038             element.parent().attr("aria-label", attribute.title);
9039             element.parent().attr("id", attribute.id);
9040             element.removeAttr("id");
9041             //element.removeAttr("title");
9042             //model -> UI
9043             ngCtrl.$render = function () {
9044                 var selected = ngCtrl.$modelValue ? true : false;
9045                 element.parent().toggleClass(attCheckboxConfig.activeClass, selected);
9046                 element.parent().attr("aria-checked", selected);
9047             };
9048
9049             //ui->model
9050             scope.updateModel = function (evt) {
9051                 if (!scope.disabled) {
9052                     ngCtrl.$setViewValue(element.parent().hasClass(attCheckboxConfig.activeClass) ? false : true);
9053                     if(checkboxLimitCtrl && !(checkboxLimitCtrl.getMaxLimits())){
9054                         if(!ngCtrl.$modelValue){
9055                             ngCtrl.$render();
9056                         }
9057                         else{
9058                             checkboxLimitCtrl.maxCheckboxSelected();
9059                             ngCtrl.$setViewValue(element.parent().hasClass(attCheckboxConfig.activeClass) ? true : false);
9060                         }
9061                     }
9062                     else{
9063                         ngCtrl.$render();
9064                     }
9065                 }
9066                 evt.preventDefault();
9067             };
9068
9069             attribute.$observe('disabled', function(val) {
9070                 scope.disabled = (val || val === "disabled" || val === "true");
9071                 element.parent().toggleClass(attCheckboxConfig.disabledClass, scope.disabled);
9072                 element.parent().attr("tabindex", scope.disabled ? "-1" : "0");
9073             });
9074         }
9075     };
9076 }])
9077 .directive('checkboxGroup', ['$compile',function($compile) {
9078     return {
9079         scope:{
9080             checkboxGroup: "=",
9081             checkboxGroupValue: "=?"
9082         },
9083         restrict: 'A',
9084         link: function(scope, element, attribute){
9085                 scope.checkboxState = 'none';
9086                 if (scope.checkboxGroupValue === undefined) {
9087                     scope.checkboxGroupValue = "indeterminate";
9088                 }
9089                 element.css({display:'none'});
9090                 element.wrap($compile('<div tabindex="0" role="checkbox" att-accessibility-click="13,32" ng-click="updateModel($event)" class="att-checkbox"></div>')(scope));
9091                 element.parent().append('<div class="att-checkbox__indicator"></div>');
9092                 element.parent().attr("title", attribute.title);
9093                 element.parent().attr("aria-label", attribute.title);
9094                 scope.$watch('checkboxState', function(val) {
9095                     if (val === 'all') {
9096                         element.parent().addClass('att-checkbox--on');
9097                         element.parent().removeClass('att-checkbox--indeterminate');
9098                         element.parent().attr("aria-checked", true);
9099                     }
9100                     else if (val === 'none') {
9101                         element.parent().removeClass('att-checkbox--on');
9102                         element.parent().removeClass('att-checkbox--indeterminate');
9103                         element.parent().attr("aria-checked", false);
9104                     }
9105                     else if (val === 'indeterminate') {
9106                         element.parent().removeClass('att-checkbox--on');
9107                         element.parent().addClass('att-checkbox--indeterminate');
9108                         element.parent().attr("aria-checked", true);
9109                     }
9110                 });
9111                 scope.updateModel = function(evt){
9112                     if (element.parent().hasClass('att-checkbox--on')) {
9113                             element.parent().removeClass('att-checkbox--on');
9114                             for (var keys in scope.checkboxGroup) {
9115                                 if (scope.checkboxGroup.hasOwnProperty(keys)) {
9116                                     scope.checkboxGroup[keys] = false;
9117                                 }
9118                             };
9119                             }
9120                     else {
9121                         element.parent().addClass('att-checkbox--on');
9122                         for (var key in scope.checkboxGroup) {
9123                             if (scope.checkboxGroup.hasOwnProperty(key)) {
9124                                 scope.checkboxGroup[key] = true;
9125                             }
9126                         };
9127                     }
9128                     evt.preventDefault();
9129                 };
9130                 scope.$watch('checkboxGroupValue', function (value) {
9131                     if (value===false) {
9132                             element.parent().removeClass('att-checkbox--on');
9133                             for (var keys in scope.checkboxGroup) {
9134                                 if (scope.checkboxGroup.hasOwnProperty(keys)) {
9135                                         scope.checkboxGroup[keys] = false;
9136                                 }
9137                             };
9138                             }
9139                     else if (value === true){
9140                         element.parent().addClass('att-checkbox--on');
9141                         for (var key in scope.checkboxGroup) {
9142                             if (scope.checkboxGroup.hasOwnProperty(key)) {
9143                                     scope.checkboxGroup[key] = true;
9144                             }
9145                         };
9146                     }
9147                 });
9148             scope.$watch('checkboxGroup', function(){
9149                 var countTrue = 0;
9150                 var countFalse = 0;
9151                 var count = 0;
9152                 for (var keys in scope.checkboxGroup) {
9153                     if (scope.checkboxGroup.hasOwnProperty(keys)) {
9154                         count = count + 1;
9155                         if (scope.checkboxGroup[keys]) {
9156                             countTrue = countTrue + 1;
9157                         }
9158                         else if (!scope.checkboxGroup[keys]) {
9159                             countFalse = countFalse + 1;
9160                         }
9161                     }
9162                 };
9163                 if (count === countTrue) {
9164                     scope.checkboxState = "all";
9165                      scope.checkboxGroupValue=true;
9166                 }
9167                 else if (count === countFalse) {
9168                     scope.checkboxState = "none";
9169                     scope.checkboxGroupValue=false;
9170                 }
9171                 else {
9172                     scope.checkboxState = "indeterminate";
9173                     scope.checkboxGroupValue="indeterminate";
9174                 }
9175                 }, true);
9176         }
9177     };
9178 }]);
9179
9180 angular.module('att.abs.colorselector', [])
9181     .directive('colorSelectorWrapper', [function() {
9182         return {
9183             scope: {
9184                 selected: '=',
9185                 iconColor: '@'
9186                 
9187             },
9188             restrict: 'AE',
9189             transclude: true,
9190             templateUrl: 'app/scripts/ng_js_att_tpls/colorselector/colorselector.html',
9191             link: function(scope) {
9192                 scope.applycolor = {'background-color': scope.iconColor};
9193                 scope.selectedcolor = function(iconColor) {
9194                     scope.selected = iconColor;
9195                 };
9196             }
9197         };
9198      }])
9199     .directive('colorSelector', ['$compile', function($compile) {
9200         return{
9201             restrict: 'A',
9202             scope: {
9203                 colorSelector: '@',                
9204                 ngModel: '='
9205             },
9206             link: function(scope, element, attr) {
9207                 element.removeAttr('color-selector');
9208                 var colorTitle = attr.title;
9209                 var wrapcont = angular.element('<color-selector-wrapper selected="ngModel" title="' + colorTitle + '" icon-color="{{colorSelector}}">' + element.prop('outerHTML') + '</color-selector-wrapper>');
9210                 var newWrapcont = $compile(wrapcont)(scope);
9211                 element.replaceWith(newWrapcont);
9212             }
9213         };
9214     }]);
9215 angular.module('att.abs.datepicker', ['att.abs.position', 'att.abs.utilities'])
9216
9217 .constant('datepickerConfig', {
9218     dateFormat: 'MM/dd/yyyy',
9219     dayFormat: 'd',
9220     monthFormat: 'MMMM',
9221     yearFormat: 'yyyy',
9222     dayHeaderFormat: 'EEEE',
9223     dayTitleFormat: 'MMMM yyyy',
9224     disableWeekend: false,
9225     disableSunday: false,
9226     startingDay: 0,
9227     minDate: null,
9228     maxDate: null,
9229     mode: 0,
9230     dateFilter: {
9231         defaultText: 'Select from list'
9232     },
9233     datepickerEvalAttributes: ['dateFormat', 'dayFormat', 'monthFormat', 'yearFormat', 'dayHeaderFormat', 'dayTitleFormat', 'disableWeekend', 'disableSunday', 'startingDay', 'mode'],
9234     datepickerWatchAttributes: ['min', 'max']
9235 })
9236
9237 .factory('datepickerService', ['datepickerConfig', 'dateFilter', function (datepickerConfig, dateFilter) {
9238     var setAttributes = function (attr, elem) {
9239         if (angular.isDefined(attr) && attr !== null && angular.isDefined(elem) && elem !== null) {
9240             var attributes = datepickerConfig.datepickerEvalAttributes.concat(datepickerConfig.datepickerWatchAttributes);
9241             for (var key in attr) {
9242                 var val = attr[key];
9243                 if (attributes.indexOf(key) !== -1 && angular.isDefined(val)) {
9244                     elem.attr(key.toSnakeCase(), key);
9245                 }
9246             }
9247         }
9248     };
9249
9250     var bindScope = function (attr, scope) {
9251         if (angular.isDefined(attr) && attr !== null && angular.isDefined(scope) && scope !== null) {
9252             var evalFunction = function (key, val) {
9253                 scope[key] = scope.$parent.$eval(val);
9254             };
9255
9256             var watchFunction = function (key, val) {
9257                 scope.$parent.$watch(val, function (value) {
9258                     scope[key] = value;
9259                 });
9260                 scope.$watch(key, function (value) {
9261                     scope.$parent[val] = value;
9262                 });
9263             };
9264
9265             var evalAttributes = datepickerConfig.datepickerEvalAttributes;
9266             var watchAttributes = datepickerConfig.datepickerWatchAttributes;
9267             for (var key in attr) {
9268                 var val = attr[key];
9269                 if (evalAttributes.indexOf(key) !== -1 && angular.isDefined(val)) {
9270                     evalFunction(key, val);
9271                 } else if (watchAttributes.indexOf(key) !== -1 && angular.isDefined(val)) {
9272                     watchFunction(key, val);
9273                 }
9274             }
9275         }
9276     };
9277
9278     var validateDateString = function (dateString, dateFormat) {
9279         if (dateString && dateFormat) {
9280             var delimiter;
9281             if (dateFormat.indexOf('/') !== -1) {
9282                 delimiter = '/';
9283             } else if (dateFormat.indexOf('-') !== -1) {
9284                 delimiter = '-';
9285             } else if (dateFormat.indexOf('.') !== -1) {
9286                 delimiter = '.';
9287             }
9288
9289             var dateStringArray = dateString.split(delimiter);
9290             var dateFormatArray = dateFormat.split(delimiter);
9291             if (dateStringArray.length !== dateFormatArray.length) {
9292                 return false;
9293             }
9294
9295             for (var i = 0; i < dateStringArray.length; i++) {
9296                 dateStringArray[i] = dateStringArray[i].lPad(dateFormatArray[i].length, '0');
9297             }
9298             var intermediateDateString = dateStringArray.join(delimiter);
9299
9300             var actualDateString = dateFilter(new Date(intermediateDateString), dateFormat);
9301             return intermediateDateString === actualDateString;
9302         }
9303     };
9304
9305     return {
9306         setAttributes: setAttributes,
9307         bindScope: bindScope,
9308         validateDateString: validateDateString
9309     };
9310 }])
9311
9312 .controller('DatepickerController', ['$scope', '$attrs', 'dateFilter', 'datepickerConfig', function($scope, $attrs, dateFilter, dtConfig) {
9313     var format = {
9314         date: getValue($attrs.dateFormat, dtConfig.dateFormat),
9315         day: getValue($attrs.dayFormat, dtConfig.dayFormat),
9316         month: getValue($attrs.monthFormat, dtConfig.monthFormat),
9317         year: getValue($attrs.yearFormat, dtConfig.yearFormat),
9318         dayHeader: getValue($attrs.dayHeaderFormat, dtConfig.dayHeaderFormat),
9319         dayTitle: getValue($attrs.dayTitleFormat, dtConfig.dayTitleFormat),
9320         disableWeekend: getValue($attrs.disableWeekend, dtConfig.disableWeekend),
9321         disableSunday: getValue($attrs.disableSunday, dtConfig.disableSunday)
9322     },
9323     startingDay = getValue($attrs.startingDay, dtConfig.startingDay);
9324     $scope.mode = getValue($attrs.mode, dtConfig.mode);
9325
9326     $scope.minDate = dtConfig.minDate ? $scope.resetTime(dtConfig.minDate) : null;
9327     $scope.maxDate = dtConfig.maxDate ? $scope.resetTime(dtConfig.maxDate) : null;
9328
9329     function getValue(value, defaultValue) {
9330         return angular.isDefined(value) ? $scope.$parent.$eval(value) : defaultValue;
9331     }
9332
9333     function getDaysInMonth(year, month) {
9334         return new Date(year, month, 0).getDate();
9335     }
9336
9337     function getDates(startDate, n) {
9338         var dates = [];
9339         var current = startDate, i = 0;
9340         while (i < n) {
9341             dates[i++] = new Date(current);
9342             current.setDate(current.getDate() + 1);
9343         }
9344         return dates;
9345     }
9346
9347     var compare = this.compare = function(date1, date2) {
9348         return (new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate()));
9349     };
9350
9351     function isSelected(dt) {
9352         if (dt && angular.isDate($scope.currentDate) && compare(dt, $scope.currentDate) === 0) {
9353             return true;
9354         }
9355         return false;
9356     }
9357
9358     function isFromDate(dt) {
9359         if (dt && angular.isDate($scope.fromDate) && compare(dt, $scope.fromDate) === 0) {
9360             return true;
9361         }
9362         return false;
9363     }
9364
9365     function isToDate(dt) {
9366         if (dt && angular.isDate($scope.fromDate) && angular.isDate($scope.currentDate) && compare(dt, $scope.currentDate) === 0) {
9367             return true;
9368         }
9369         return false;
9370     }
9371
9372     function isDateRange(dt) {
9373         if (dt && angular.isDate($scope.fromDate) && angular.isDate($scope.currentDate) && (compare(dt, $scope.fromDate) >= 0) && (compare(dt, $scope.currentDate) <= 0)) {
9374             return true;
9375         }
9376         return false;
9377     }
9378
9379     function isWeekend(date) {
9380         if (dateFilter(date, format.dayHeader) === "Saturday" || dateFilter(date, format.dayHeader) === "Sunday") {
9381             return true;
9382         }
9383         return false;
9384     }
9385
9386     function isToday(date) {
9387         if (compare(date, $scope.resetTime(new Date())) === 0) {
9388             return true;
9389         }
9390         return false;
9391     }
9392     function isFocused(date) {
9393         if (date && angular.isDate($scope.focusedDate) && compare(date, $scope.focusedDate) === 0) {
9394             return true;
9395         }
9396         return false;
9397     }
9398
9399     var isDisabled = this.isDisabled = function(date) {
9400         if (format.disableWeekend === true && (dateFilter(date, format.dayHeader) === "Saturday" || dateFilter(date, format.dayHeader) === "Sunday")) {
9401             return true;
9402         }
9403         if (format.disableSunday === true && (dateFilter(date, format.dayHeader) === "Sunday")) {
9404             return true;
9405         }
9406         return (($scope.minDate && compare(date, $scope.minDate) < 0) || ($scope.maxDate && compare(date, $scope.maxDate) > 0));
9407     };
9408
9409
9410     function isMinDateAvailable(startDate, endDate) {
9411        return ($scope.minDate && $scope.minDate.getTime() >= startDate.getTime()) && ($scope.minDate.getTime() <= endDate.getTime());
9412     }
9413
9414     function isMaxDateAvailable(startDate, endDate) {
9415         return ($scope.maxDate && $scope.maxDate.getTime() >= startDate.getTime()) && ($scope.maxDate.getTime() <= endDate.getTime());
9416     }
9417
9418     function getLabel(label) {
9419         if (label)
9420         {
9421             var labelObj = {
9422                 pre: label.substr(0, 3),
9423                 post: label
9424             };
9425             return labelObj;
9426         }
9427         return;
9428     }
9429     function makeDate(dateobj) {
9430         return {date: dateobj.date, label: dateFilter(dateobj.date, dateobj.formatDay), header: dateFilter(dateobj.date, dateobj.formatHeader), focused: !!dateobj.isFocused, selected: !!dateobj.isSelected, from: !!dateobj.isFromDate, to: !!dateobj.isToDate, dateRange: !!dateobj.isDateRange, oldMonth: !!dateobj.oldMonth, nextMonth: !!dateobj.newMonth, disabled: !!dateobj.isDisabled, today: !!dateobj.isToday, weekend: !!dateobj.isWeakend};
9431     }
9432
9433     this.modes = [
9434         {
9435             name: 'day',
9436             getVisibleDates: function(date, calendar) {
9437                 var year = date.getFullYear(), month = date.getMonth(), firstDayOfMonth = new Date(year, month, 1), lastDayOfMonth = new Date(year, month+1, 0);
9438                 var difference = startingDay - firstDayOfMonth.getDay(),
9439                         numDisplayedFromPreviousMonth = (difference > 0) ? 7 - difference : -difference,
9440                         firstDate = new Date(firstDayOfMonth), numDates = 0;
9441
9442                 if (numDisplayedFromPreviousMonth > 0) {
9443                     firstDate.setDate(-numDisplayedFromPreviousMonth + 1);
9444                     numDates += numDisplayedFromPreviousMonth; // Previous
9445                 }
9446                 numDates += getDaysInMonth(year, month + 1); // Current
9447                 numDates += (7 - numDates % 7) % 7; // Next
9448
9449                 var days = getDates(firstDate, numDates), labels = [];
9450                 for (var i = 0; i < numDates; i++) {
9451                     var dt = new Date(days[i]);
9452                     days[i] = makeDate({date:dt,
9453                                 formatDay:format.day,
9454                                 formatHeader:format.dayHeader,
9455                                 isFocused:isFocused(dt),
9456                                 isSelected:isSelected(dt),
9457                                 isFromDate:isFromDate(dt),
9458                                 isToDate:isToDate(dt),
9459                                 isDateRange:isDateRange(dt),
9460                                 oldMonth:(new Date(dt.getFullYear(), dt.getMonth(), 1, 0, 0, 0).getTime() < new Date(year, month, 1, 0, 0, 0).getTime()),
9461                                 newMonth:(new Date(dt.getFullYear(), dt.getMonth(), 1, 0, 0, 0).getTime() > new Date(year, month, 1, 0, 0, 0).getTime()),
9462                                 isDisabled:isDisabled(dt),
9463                                 isToday:isToday(dt),
9464                                 isWeakend:isWeekend(dt)});
9465                 }
9466                 for (var j = 0; j < 7; j++) {
9467                     labels[j] = getLabel(dateFilter(days[j].date, format.dayHeader));
9468                 }
9469                 if (calendar === 'top') {
9470                     $scope.disablePrevTop = isMinDateAvailable(firstDayOfMonth, lastDayOfMonth);
9471                     $scope.disableNextTop = isMaxDateAvailable(firstDayOfMonth, lastDayOfMonth);
9472                 } else if (calendar === 'bottom') {
9473                     $scope.disablePrevBottom = isMinDateAvailable(firstDayOfMonth, lastDayOfMonth);
9474                     $scope.disableNextBottom = isMaxDateAvailable(firstDayOfMonth, lastDayOfMonth);
9475                 } else {
9476                     $scope.disablePrevTop = $scope.disablePrevBottom = isMinDateAvailable(firstDayOfMonth, lastDayOfMonth);
9477                     $scope.disableNextTop = $scope.disableNextBottom = isMaxDateAvailable(firstDayOfMonth, lastDayOfMonth);
9478                 }
9479                 $scope.disablePrev = $scope.disablePrevTop || $scope.disablePrevBottom;
9480                 $scope.disableNext = $scope.disableNextTop || $scope.disableNextBottom;
9481                 return {objects: days, title: dateFilter(date, format.dayTitle), labels: labels};
9482             },
9483             split: 7,
9484             step: {months: 1}
9485         },
9486         {
9487             name: 'month',
9488             getVisibleDates: function(date) {
9489                 var months = [], labels = [], year = date.getFullYear();
9490                 for (var i = 0; i < 12; i++) {
9491                    var dt = new Date(year,i,1);
9492                     months[i] = makeDate({date:dt,
9493                                 formatDay:format.month,
9494                                 formatHeader:format.month,
9495                                 isFocused:isFocused(dt),
9496                                 isSelected:isSelected(dt),
9497                                 isFromDate:isFromDate(dt),
9498                                 isToDate:isToDate(dt),
9499                                 isDateRange:isDateRange(dt),
9500                                 oldMonth:false,
9501                                 newMonth:false,
9502                                 isDisabled:isDisabled(dt),
9503                                 isToday:isToday(dt),
9504                                 isWeakend:false});
9505                 }
9506                 return {objects: months, title: dateFilter(date, format.year), labels: labels};
9507             },
9508             split:3,
9509             step: {years: 1}
9510         }
9511     ];
9512
9513 }])
9514
9515 .directive('datepicker', ['$timeout', function ($timeout) {
9516     return {
9517         restrict: 'EA',
9518         replace: true,
9519         transclude: true,
9520         templateUrl: 'app/scripts/ng_js_att_tpls/datepicker/datepicker.html',
9521         scope: {
9522             currentDate: "=?current",
9523             fromDate: "=?from"
9524         },
9525         require: 'datepicker',
9526         controller: 'DatepickerController',
9527         link: function(scope, element, attrs, ctrl) {
9528             var datepickerCtrl = ctrl;
9529             var selected, calendarSelected = false;
9530             scope.focusedDate;
9531
9532             scope.resetTime = function(date) {
9533                 var dt;
9534                 if (!isNaN(new Date(date))) {
9535                     dt = new Date(date);
9536                     if(scope.mode === 1){
9537                         dt = new Date(dt.getFullYear(), dt.getMonth());
9538                     }else{
9539                         dt = new Date(dt.getFullYear(), dt.getMonth(), dt.getDate());
9540                     }
9541                 } else {
9542                     return null;
9543                 }
9544                 return dt;
9545             };
9546
9547             if (attrs.min) {
9548                 scope.$parent.$watch(attrs.min, function(value) {
9549                     scope.minDate = value ? scope.resetTime(value) : null;
9550                     refill();
9551                 });
9552             }
9553             if (attrs.max) {
9554                 scope.$parent.$watch(attrs.max, function(value) {
9555                     scope.maxDate = value ? scope.resetTime(value) : null;
9556                     refill();
9557                 });
9558             }
9559
9560             // Split array into smaller arrays
9561             function split(arr, size) {
9562                 var arrays = [];
9563                 while (arr.length > 0) {
9564                     arrays.push(arr.splice(0, size));
9565                 }
9566                 return arrays;
9567             }
9568             var moveMonth = function(selectedDate, direction) {
9569                 var step = datepickerCtrl.modes[scope.mode].step;
9570                 selectedDate.setDate(1);
9571                 selectedDate.setMonth(selectedDate.getMonth() + direction * (step.months || 0));
9572                 selectedDate.setFullYear(selectedDate.getFullYear() + direction * (step.years || 0));
9573
9574                 return selectedDate;
9575             };
9576
9577             function refill(date) {
9578                 if (angular.isDate(date) && !isNaN(date)) {
9579                     selected = new Date(date);
9580                 } else {
9581                     if (!selected) {
9582                         selected = new Date();
9583                     }
9584                 }
9585
9586                 if (selected) {
9587                     var selectedCalendar;
9588                     if(scope.mode === 1){
9589                         selected = new Date();
9590                         selectedCalendar = moveMonth(angular.copy(selected), -1);
9591                     } else {
9592                         selectedCalendar = angular.copy(selected);
9593                     }
9594
9595                     var currentMode = datepickerCtrl.modes[scope.mode];
9596                     var currentData = currentMode.getVisibleDates(selectedCalendar, 'top');
9597                     scope.currentRows = split(currentData.objects, currentMode.split);
9598                     scope.currentTitle = currentData.title;
9599                     scope.labels = currentData.labels || [];
9600
9601                     var nextData = currentMode.getVisibleDates(moveMonth(angular.copy(selectedCalendar), 1), 'bottom');
9602                     scope.nextRows = split(nextData.objects, currentMode.split);
9603                     scope.nextTitle = nextData.title;
9604                 }
9605             }
9606
9607             var selectCurrentDate = function(date) {
9608                 var dt = new Date(date.getFullYear(), date.getMonth(), date.getDate());
9609                 scope.currentDate = dt;
9610             };
9611
9612             var selectFromDate = function(date) {
9613                 var dt = new Date(date.getFullYear(), date.getMonth(), date.getDate());
9614                 scope.fromDate = dt;
9615             };
9616
9617             scope.select = function(date) {
9618                 calendarSelected = true;
9619                 if(attrs.from) {
9620                     if(!(angular.isDate(scope.fromDate) && angular.isDate(scope.currentDate))) {
9621                         if(angular.isDate(scope.fromDate)) {
9622                             selectCurrentDate(date);
9623                         } else if(!angular.isDate(scope.fromDate)) {
9624                             selectFromDate(date);
9625                         }
9626                     }
9627                 } else {
9628                     selectCurrentDate(date);
9629                 }
9630                 scope.focusedDate = date;
9631             };
9632
9633             var swapDate = function(fromDate, currentDate) {
9634                 selectFromDate(currentDate);
9635                 $timeout(function () {
9636                     calendarSelected = true;
9637                     scope.focusedDate = currentDate;
9638                     selectCurrentDate(fromDate);
9639                 });
9640             };
9641
9642             scope.move = function(direction) {
9643                 selected = moveMonth(angular.copy(selected), direction);
9644                 refill();
9645             };
9646
9647             scope.$watch('currentDate', function (value) {
9648                 if(angular.isDate(value) && !isNaN(value) && datepickerCtrl.isDisabled(value)) {
9649                     scope.currentDate = null;
9650                     return;
9651                 }
9652
9653                 if (attrs.from && !isNaN(value) && !isNaN(scope.fromDate) && datepickerCtrl.compare(value, scope.fromDate) < 0) {
9654                         swapDate(scope.fromDate, value);
9655                         return;
9656                 }
9657
9658                 if (calendarSelected) {
9659                     refill();
9660                     calendarSelected = false;
9661                 } else {
9662                     if (angular.isDefined(value) && value !== null) {
9663                         refill(value);
9664                     } else {
9665                         refill();
9666                     }
9667                 }
9668                 scope.focusedDate = undefined;
9669             });
9670
9671             scope.$watch('fromDate', function (value) {
9672                 if(angular.isDate(value) && !isNaN(value) && datepickerCtrl.isDisabled(value)) {
9673                     scope.fromDate = null;
9674                     return;
9675                 }
9676                 if (attrs.from) {
9677                     if (!isNaN(scope.currentDate) && !isNaN(value) && datepickerCtrl.compare(scope.currentDate, value) < 0) {
9678                         swapDate(value, scope.currentDate);
9679                         return;
9680                     }
9681                     if (calendarSelected) {
9682                         refill();
9683                         calendarSelected = false;
9684                     } else {
9685                         if (angular.isDefined(value) && value !== null) {
9686                             refill(value);
9687                         } else {
9688                             refill();
9689                         }
9690                     }
9691                 }
9692                 scope.focusedDate = undefined;
9693             });
9694         }
9695     };
9696 }])
9697 .directive('datepickerPopup', ['$document', 'datepickerService', '$isElement', '$documentBind', function($document, datepickerService, $isElement, $documentBind) {
9698     var link = function (scope, elem, attr) {
9699         datepickerService.bindScope(attr, scope);
9700
9701         scope.isOpen = false;
9702
9703         var toggle = scope.toggle = function (show) {
9704             if(show === true || show === false) {
9705                 scope.isOpen = show;
9706             } else {
9707                 scope.isOpen = !scope.isOpen;
9708             }
9709         };
9710
9711         scope.$watch('current', function () {
9712             toggle(false);
9713         });
9714
9715         var outsideClick = function (e) {
9716             var isElement = $isElement(angular.element(e.target), elem, $document);
9717             if(!isElement) {
9718                 toggle(false);
9719                 scope.$apply();
9720             }
9721         };
9722
9723         $documentBind.click('isOpen', outsideClick, scope);
9724     };
9725
9726     return {
9727         restrict: 'EA',
9728         replace: true,
9729         transclude: true,
9730         templateUrl: 'app/scripts/ng_js_att_tpls/datepicker/datepickerPopup.html',
9731         scope: {
9732             current: "=current"
9733         },
9734         compile: function (elem, attr) {
9735             var wrapperElement = elem.find('span').eq(1);
9736             wrapperElement.attr('current', 'current');
9737             datepickerService.setAttributes(attr, wrapperElement);
9738
9739             return link;
9740         }
9741     };
9742 }])
9743
9744 .directive('attDatepicker', ['$log', function($log) {
9745     return {
9746         restrict: 'A',
9747         require: 'ngModel',
9748         scope: {},
9749         controller: ['$scope', '$element', '$attrs', '$compile', 'datepickerConfig', 'datepickerService', function($scope, $element, $attrs, $compile, datepickerConfig, datepickerService) {
9750             var dateFormatString = angular.isDefined($attrs.dateFormat) ? $scope.$parent.$eval($attrs.dateFormat) : datepickerConfig.dateFormat;
9751             var selectedDateMessage = '<div class="sr-focus hidden-spoken" tabindex="-1">the date you selected is {{$parent.current | date : \'' + dateFormatString + '\'}}</div>';
9752
9753             $element.removeAttr('att-datepicker');
9754             $element.removeAttr('ng-model');
9755             $element.attr('ng-model', '$parent.current');
9756             $element.attr('aria-describedby', 'datepicker');
9757             $element.attr('format-date', dateFormatString);
9758             $element.attr('att-input-deny', '[^0-9\/-]');
9759             $element.attr('maxlength', 10);
9760                         $element.attr('readonly', 'readonly'); //Trinity for CATO
9761             var wrapperElement = angular.element('<div></div>');
9762             wrapperElement.attr('datepicker-popup', '');
9763             wrapperElement.attr('current', 'current');
9764
9765             datepickerService.setAttributes($attrs, wrapperElement);
9766             datepickerService.bindScope($attrs, $scope);
9767
9768             wrapperElement.html('');
9769             wrapperElement.append($element.prop('outerHTML'));
9770             if (navigator.userAgent.match(/MSIE 8/) === null) {
9771                 wrapperElement.append(selectedDateMessage);
9772             }
9773             var elm = wrapperElement.prop('outerHTML');
9774             elm = $compile(elm)($scope);
9775             $element.replaceWith(elm);
9776         }],
9777         link: function(scope, elem, attr, ctrl) {
9778             if (!ctrl) {
9779                 // do nothing if no ng-model
9780                 $log.error("ng-model is required.");
9781                 return;
9782             }
9783
9784             scope.$watch('current', function(value) {
9785                 ctrl.$setViewValue(value);
9786             });
9787             ctrl.$render = function() {
9788                 scope.current = ctrl.$viewValue;
9789             };
9790         }
9791     };
9792 }])
9793
9794 .directive('formatDate', ['dateFilter', 'datepickerService', function(dateFilter, datepickerService) {
9795     return {
9796         restrict: 'A',
9797         require: 'ngModel',
9798         link: function(scope, elem, attr, ctrl) {
9799             var formatDate = "";
9800             attr.$observe('formatDate', function (value) {
9801                 formatDate = value;
9802             });
9803             var dateToString = function(value) {
9804                 if (value) {
9805                     ctrl.$setValidity('invalidDate', true);
9806                     return dateFilter(value, formatDate);
9807                 } else {
9808                     ctrl.$setValidity('invalidDate', false);
9809                     return elem.val();
9810                 }
9811             };
9812             var stringToDate = function(value) {
9813                 if(datepickerService.validateDateString(value, formatDate)) {
9814                     ctrl.$setValidity('invalidDate', true);
9815                     return new Date(value);
9816                 } else {
9817                     ctrl.$setValidity('invalidDate', false);
9818                     return null;
9819                 }
9820             };
9821             ctrl.$formatters.unshift(dateToString);
9822             ctrl.$parsers.unshift(stringToDate);
9823         }
9824     };
9825 }])
9826
9827 .directive('attDateFilter', ['$document', 'dateFilter', 'datepickerConfig', 'datepickerService', '$isElement', '$documentBind', function($document, dateFilter, datepickerConfig, datepickerService, $isElement, $documentBind) {
9828
9829     var link = function (scope, elem, attr, ctrl) {
9830         datepickerService.bindScope(attr, scope);
9831
9832         scope.selectedOption = datepickerConfig.dateFilter.defaultText;
9833         scope.showDropdownList = false;
9834         scope.showCalendar = false;
9835         scope.applyButtonType = "disabled";
9836
9837         scope.currentSelection = "";
9838         var dateFormatString = angular.isDefined(attr.dateFormat) ? scope.$parent.$eval(attr.dateFormat) : datepickerConfig.dateFormat;
9839         var inputChange = false;
9840
9841         var setDropdownText = function(value) {
9842             if(inputChange) {
9843                 return;
9844             }
9845
9846             var fromDateText = dateFormatString.toUpperCase();
9847             var currentDateText = dateFormatString.toUpperCase();
9848
9849             if(!isNaN(new Date(scope.fromDate))) {
9850                 fromDateText = dateFilter(scope.fromDate, dateFormatString);
9851             }
9852             if(!isNaN(new Date(scope.currentDate))) {
9853                 currentDateText = dateFilter(scope.currentDate, dateFormatString);
9854             }
9855
9856             if(value === 'Custom Single Date') {
9857                 ctrl.$setValidity('invalidDate', true);
9858                 scope.maxLength = 10;
9859                 scope.selectedOption = currentDateText;
9860             } else if(value === 'Custom Range') {
9861                 ctrl.$setValidity('invalidDate', true);
9862                 ctrl.$setValidity('invalidDateRange', true);
9863                 scope.maxLength = 21;
9864                 scope.selectedOption = fromDateText + '-' + currentDateText;
9865             }
9866         };
9867
9868         var clear = scope.clear = function(partial) {
9869             scope.fromDate = undefined;
9870             scope.currentDate = undefined;
9871             scope.applyButtonType = "disabled";
9872             if(!partial) {
9873                 ctrl.$setValidity('invalidDate', true);
9874                 ctrl.$setValidity('invalidDateRange', true);
9875                 setDropdownText(scope.currentSelection);
9876             }
9877         };
9878
9879         var showCalendar = function() {
9880             scope.showCalendar = true;
9881         };
9882
9883         var hideCalendar = function() {
9884             scope.showCalendar = false;
9885             if(scope.currentSelection !== 'Custom Single Date' && scope.currentSelection !== 'Custom Range') {
9886                 clear(true);
9887             }
9888         };
9889
9890         var showDropdown = scope.showDropdown = function (show) {
9891             if(show === true || show === false) {
9892                 scope.showDropdownList = show;
9893             } else {
9894                 scope.showDropdownList = !scope.showDropdownList;
9895             }
9896
9897             if (!scope.showDropdownList) {
9898                 scope.focusInputButton = true;
9899                 hideCalendar();
9900             } else {
9901                 if (scope.currentSelection === 'Custom Single Date' || scope.currentSelection === 'Custom Range') {
9902                     showCalendar();
9903                 }
9904             }
9905         };
9906
9907         scope.resetTime = function(date) {
9908             var dt;
9909             if (!isNaN(new Date(date))) {
9910                 dt = new Date(date);
9911             } else {
9912                 return null;
9913             }
9914             return new Date(dt.getFullYear(), dt.getMonth(), dt.getDate());
9915         };
9916
9917         scope.getDropdownText = function () {
9918             inputChange = true;
9919             var dropdownText = scope.selectedOption;
9920
9921             if (scope.currentSelection === 'Custom Single Date') {
9922                 if (!isNaN(new Date(dropdownText)) && datepickerService.validateDateString(dropdownText, dateFormatString)) {
9923                     ctrl.$setValidity('invalidDate', true);
9924                     scope.fromDate = undefined;
9925                     scope.currentDate = new Date(dropdownText);
9926                 } else {
9927                     ctrl.$setValidity('invalidDate', false);
9928                     clear(true);
9929                 }
9930             } else if (scope.currentSelection === 'Custom Range') {
9931                 if (dropdownText.indexOf('-') !== -1 && (dropdownText.split('-').length === 2 || dropdownText.split('-').length === 6)) {
9932                     ctrl.$setValidity('invalidDateRange', true);
9933                     var resultDropdownText = dropdownText.split('-');
9934                     if (resultDropdownText.length === 2) {
9935                         resultDropdownText[0] = resultDropdownText[0].trim();
9936                         resultDropdownText[1] = resultDropdownText[1].trim();
9937                     } else if (resultDropdownText.length === 6) {
9938                         var firstDateString = resultDropdownText[0].trim() + '-' + resultDropdownText[1].trim() + '-' + resultDropdownText[2].trim();
9939                         var secondDateString = resultDropdownText[3].trim() + '-' + resultDropdownText[4].trim() + '-' + resultDropdownText[5].trim();
9940                         resultDropdownText[0] = firstDateString;
9941                         resultDropdownText[1] = secondDateString;
9942                     }
9943
9944                     if (!isNaN(new Date(resultDropdownText[0])) && !isNaN(new Date(resultDropdownText[1])) && datepickerService.validateDateString(resultDropdownText[0], dateFormatString) && datepickerService.validateDateString(resultDropdownText[1], dateFormatString)) {
9945                         ctrl.$setValidity('invalidDate', true);
9946                         var fromDate = new Date(resultDropdownText[0]);
9947                         var currentDate = new Date(resultDropdownText[1]);
9948                         if(fromDate.getTime() < currentDate.getTime()) {
9949                             ctrl.$setValidity('invalidDateRange', true);
9950                             scope.fromDate = fromDate;
9951                             scope.currentDate = currentDate;
9952                         } else {
9953                             ctrl.$setValidity('invalidDateRange', false);
9954                             clear(true);
9955                         }
9956                     } else {
9957                         ctrl.$setValidity('invalidDate', false);
9958                         clear(true);
9959                     }
9960                 } else {
9961                     ctrl.$setValidity('invalidDateRange', false);
9962                     clear(true);
9963                 }
9964             }
9965         };
9966
9967         scope.untrackInputChange = function() {
9968             inputChange = false;
9969         };
9970
9971         scope.selectAdvancedOption = function (value, notClearFlag) {
9972             scope.currentSelection = value;
9973             if(!notClearFlag){
9974                 clear();
9975                 showCalendar();
9976             }
9977             scope.$watch('currentDate', function(val) {
9978                 if(!isNaN(new Date(val))) {
9979                     scope.applyButtonType = "primary";
9980                     setDropdownText(value);
9981                     if (!inputChange) {
9982                         scope.focusApplyButton = true;
9983                     }
9984                 }
9985             });
9986             scope.$watch('fromDate', function(val) {
9987                 if(!isNaN(new Date(val))) {
9988                     setDropdownText(value);
9989                 }
9990             });
9991             if (value === 'Custom Single Date') {
9992                 scope.focusSingleDateCalendar = true;
9993             } else if (value === 'Custom Range') {
9994                 scope.focusRangeCalendar = true;
9995             }
9996         };
9997
9998         scope.resetFocus = function () {
9999             scope.focusSingleDateCalendar = false;
10000             scope.focusRangeCalendar = false;
10001             scope.focusApplyButton = false;
10002         };
10003
10004         scope.apply = function() {
10005             scope.dateRange.selection = scope.selectedOption;
10006             if(!isNaN(new Date(scope.fromDate))) {
10007                 scope.from = scope.fromDate;
10008                 scope.dateRange.from = scope.fromDate;
10009             } else {
10010                 scope.from = undefined;
10011                 scope.dateRange.from = undefined;
10012             }
10013             if(!isNaN(new Date(scope.currentDate))) {
10014                 scope.current = scope.currentDate;
10015                 scope.dateRange.current = scope.currentDate;
10016             } else {
10017                 scope.current = undefined;
10018                 scope.dateRange.current = undefined;
10019             }
10020
10021             showDropdown();
10022         };
10023
10024         scope.$watchCollection(function() {
10025             return scope.dateRange;
10026         }, function(value) {
10027             if(ctrl) {
10028                 var finalDateRange = angular.copy(value);
10029                 ctrl.$setViewValue(finalDateRange);
10030             }
10031         });
10032
10033         ctrl.$render = function () {
10034             if (ctrl.$viewValue) {
10035                 var inputRange = ctrl.$viewValue;
10036                 scope.selectedOption = inputRange.selection;
10037                 scope.fromDate = inputRange.from;
10038                 scope.currentDate = inputRange.current;
10039                 if (scope.fromDate !== undefined && scope.currentDate !== undefined) {
10040                     scope.selectAdvancedOption('Custom Range', true);
10041                     scope.dateRange.from = scope.fromDate;
10042                     scope.dateRange.current = scope.currentDate;
10043                 } else if (scope.currentDate !== undefined) {
10044                     scope.selectAdvancedOption('Custom Single Date', true);
10045                     scope.dateRange.from = undefined;
10046                     scope.dateRange.current = scope.currentDate;
10047                 }
10048             }
10049         };
10050         
10051         scope.cancel = function() {
10052             scope.currentSelection = "";
10053             scope.selectedOption = datepickerConfig.dateFilter.defaultText;
10054             showDropdown();
10055         };
10056
10057         var outsideClick = function (e) {
10058             var isElement = $isElement(angular.element(e.target), elem, $document);
10059             if(!isElement) {
10060                 scope.cancel();
10061                 scope.$apply();
10062             }
10063         };
10064         $documentBind.click('showDropdownList', outsideClick, scope);
10065     };
10066
10067     return {
10068         restrict: 'EA',
10069         scope: {
10070             from: '=?from',
10071             current: "=?current"
10072         },
10073         replace: true,
10074         require: '?ngModel',
10075         transclude:true,
10076         templateUrl: 'app/scripts/ng_js_att_tpls/datepicker/dateFilter.html',
10077         controller:['$scope', '$element', '$attrs',function($scope){
10078             $scope.dateRange = {
10079                 selection: undefined,
10080                 from: undefined,
10081                 current: undefined
10082             };
10083             this.selectOption = function (fromDate,toDate,caption) {
10084                 $scope.selectedOption = caption;
10085                 $scope.currentSelection =caption;
10086                 $scope.dateRange.selection = caption;
10087                 $scope.dateRange.current = $scope.resetTime(toDate);
10088                 $scope.dateRange.from = $scope.resetTime(fromDate);
10089                 $scope.showDropdown();
10090         };
10091          $scope.checkCurrentSelection=this.checkCurrentSelection = function(value) {
10092             if(value === $scope.currentSelection) {
10093                 return true;
10094             }
10095             return false;
10096         };
10097         }],
10098         compile: function(elem, attr) {
10099             var singleDateCalendar = elem.find('span').eq(4);
10100             var rangeCalendar = elem.find('span').eq(5);
10101             rangeCalendar.attr('from', 'fromDate');
10102             singleDateCalendar.attr('current', 'currentDate');
10103             rangeCalendar.attr('current', 'currentDate');
10104             datepickerService.setAttributes(attr, singleDateCalendar);
10105             datepickerService.setAttributes(attr, rangeCalendar);
10106
10107             return link;
10108         }
10109     };
10110 }])
10111 .directive('attDateFilterList',function(){
10112     return{
10113         restrict:'EA',
10114         scope:{
10115             fromDate:'=fromDate',
10116             toDate:'=toDate',
10117             caption:'=caption',
10118             disabled:'=disabled'
10119         },
10120         require:'^attDateFilter',
10121         transclude:true,
10122         replace:true,
10123         templateUrl:'app/scripts/ng_js_att_tpls/datepicker/dateFilterList.html',
10124         link:function(scope,elem,attr,ctrl){
10125             scope.selectOption=function(fromDate,toDate,caption){
10126                 ctrl.selectOption(fromDate,toDate,caption);
10127             };
10128             scope.checkCurrentSelection=ctrl.checkCurrentSelection;
10129         }
10130     };
10131 });
10132 angular.module('att.abs.devNotes', [])
10133
10134   .directive('attDevNotes', function() {
10135     return {
10136       restrict: 'EA',
10137       transclude: true,
10138       scope: {},
10139       controller: function($scope){
10140         var panes = $scope.panes = [];
10141         $scope.select = function(pane)
10142         {
10143             angular.forEach(panes, function(pane)
10144             {
10145                 pane.selected = false;
10146             });
10147             pane.selected = true;
10148         };
10149         this.addPane = function(pane) {
10150             if (panes.length === 0) {
10151                 $scope.select(pane);
10152             }
10153           panes.push(pane);
10154         };
10155       },
10156       template:'<div>'+
10157         '<ul class="tabs">' +
10158             '<li ng-repeat="pane in panes" ng-class="{active:pane.selected}">'+
10159               '<a href="javascript:void(0)" ng-click="select(pane)">{{pane.title}}</a>' +
10160             '</li>' +
10161           '</ul>' +
10162           '<div ng-transclude></div>'+
10163           '</div>',
10164           replace: true
10165     };
10166   })
10167
10168   .directive('pane', function() {
10169     return {
10170       require: '^attDevNotes',
10171       restrict: 'EA',
10172       transclude: true,
10173       scope: {
10174           title: '@'
10175       },
10176       link: function(scope, element, attrs, tabsCtrl) {
10177         tabsCtrl.addPane(scope);
10178       },
10179       template:
10180         '<div class="tab-pane" ng-class="{active: selected}">' +
10181         '<pre ng-class="{\'language-markup\':title==\'HTML\',\'language-javascript\':title==\'JavaScript\',\'language-json\':title==\'JSON\'}"  class=" line-numbers">' +
10182          '<code ng-transclude></code>' +
10183          '</pre>' +
10184         '</div>',
10185       replace: true
10186     };
10187   });
10188
10189 angular.module('att.abs.dividerLines', [])
10190         .directive('attDividerLines', [function()
10191             {
10192                 return {
10193                     scope: {
10194                         attDividerLines: '@'
10195                     },
10196                     restrict: 'A',
10197                     replace: true,
10198                     templateUrl: 'app/scripts/ng_js_att_tpls/dividerLines/dividerLines.html',
10199                     link: function(scope, element, attribute)
10200                     {
10201                         scope.lightContainer = attribute.attDividerLines;
10202                     }
10203                 };
10204             }]);
10205
10206 angular.module('att.abs.dragdrop', [])
10207         .directive('attFileDrop', ['$parse', function($parse) {
10208                 return {
10209                     restrict: 'A',
10210                     scope: {
10211                         fileModel : '=',
10212                         onDrop : '&',
10213                         attFileDrop : '&'
10214                     },
10215                     controller: ['$scope', '$attrs', function($scope, $attrs){
10216                         if($attrs.attFileDrop!==""){
10217                             $scope.onDrop=$scope.attFileDrop;
10218                         }
10219                         this.onDrop = $scope.onDrop;
10220                     }],
10221                     link: function(scope, element) {
10222                         element.addClass('dragdrop');
10223                         element.bind(
10224                             'dragover',
10225                             function(e) {
10226                                 if(e.originalEvent){
10227                                     e.dataTransfer = e.originalEvent.dataTransfer;
10228                                 }
10229                                 e.dataTransfer.dropEffect = 'move';
10230                                 // allows us to drop
10231                                 if (e.preventDefault) {
10232                                     e.preventDefault();
10233                                 }
10234                                 element.addClass('dragdrop-over');
10235                                 return false;
10236                             }
10237                         );
10238                         element.bind(
10239                             'dragenter',
10240                             function(e) {
10241                                 // allows us to drop
10242                                 if (e.preventDefault) {
10243                                     e.preventDefault();
10244                                 }
10245                                 element.addClass('dragdrop-over');
10246                                 return false;
10247                             }
10248                         );
10249                         element.bind(
10250                             'dragleave',
10251                             function() {
10252                                 element.removeClass('dragdrop-over');
10253                                 return false;
10254                             }
10255                         );
10256                         element.bind(
10257                             'drop',
10258                             function(e) {
10259                                 // Stops some browsers from redirecting.
10260                                 if(e.preventDefault) {
10261                                     e.preventDefault();
10262                                 }
10263                                 if (e.stopPropagation) {
10264                                     e.stopPropagation();
10265                                 }
10266                                 if(e.originalEvent){
10267                                     e.dataTransfer = e.originalEvent.dataTransfer;
10268                                 }
10269                                 element.removeClass('dragdrop-over');
10270                                 if(e.dataTransfer.files && e.dataTransfer.files.length > 0){
10271                                     scope.fileModel = e.dataTransfer.files[0];
10272                                     scope.$apply();
10273                                     if(typeof scope.onDrop === "function"){
10274                                         scope.onDrop = $parse(scope.onDrop);
10275                                         scope.onDrop();
10276                                     }
10277                                 }
10278                                 return false;
10279                             }
10280                         );
10281                     }
10282                 };
10283             }])
10284         .directive('attFileLink', [ function() {
10285                 return {
10286                     restrict: 'EA',
10287                     require: '^?attFileDrop',
10288                     replace: true,
10289                     transclude: true,
10290                     templateUrl: 'app/scripts/ng_js_att_tpls/dragdrop/fileUpload.html',
10291                     scope: {
10292                         fileModel : '=?',
10293                         onFileSelect : '&',
10294                         attFileLink : '&'
10295                     },
10296                     controller: ['$scope', '$parse', function($scope, $parse){
10297                         this.setFileModel= function(fileModel){
10298                             if($scope.takeFileModelFromParent){
10299                                 $scope.$parent.fileModel = fileModel;
10300                                 $scope.$parent.$apply();
10301                             }
10302                             else{
10303                                 $scope.fileModel = fileModel;
10304                                 $scope.$apply();
10305                             }
10306                         };
10307                         this.callbackFunction= function(){
10308                             if(typeof $scope.onFileSelect === "function"){
10309                                 $scope.onFileSelect = $parse($scope.onFileSelect);
10310                                 $scope.onFileSelect();
10311                             }
10312                         };
10313                       
10314                     }],
10315                     link: function(scope, element, attr, attFileDropCtrl) {
10316                         scope.takeFileModelFromParent = false;
10317                         if(!(attr.fileModel) && attFileDropCtrl){
10318                             scope.takeFileModelFromParent = true;
10319                         }
10320                         if(attr.attFileLink!==""){
10321                             scope.onFileSelect=scope.attFileLink;
10322                         }
10323                         else if(!(attr.onFileSelect) && attFileDropCtrl){
10324                             scope.onFileSelect = attFileDropCtrl.onDrop;
10325                         }
10326                     }
10327                 };
10328             }])
10329         .directive('attFileChange', ['$log','$rootScope',function($log,$rootScope) {
10330                 return {
10331                     restrict: 'A',
10332                     require: '^attFileLink',
10333                     link: function(scope, element, attr, attFileLinkCtrl) {
10334                         element.bind('change',changeFileModel);
10335                         function changeFileModel(e) {
10336                             if (e.target.files && e.target.files.length > 0) {
10337                                 attFileLinkCtrl.setFileModel(e.target.files[0]);
10338                                 attFileLinkCtrl.callbackFunction();
10339                             }
10340                             else {
10341                                 var strFileName = e.target.value;
10342                                 try {
10343                                     var objFSO = new ActiveXObject("Scripting.FileSystemObject");
10344                                     attFileLinkCtrl.setFileModel(objFSO.getFile(strFileName));
10345                                     attFileLinkCtrl.callbackFunction();
10346                                 }
10347                                 catch (e) {
10348                                     var errMsg = "Error: Please follow the guidelines of Drag and Drop component on Sandbox demo page.";
10349                                     $log.error(errMsg);
10350                                     $rootScope.$broadcast('att-file-link-failure', errMsg);
10351                                 }
10352                             }
10353                         }
10354                     }
10355                 };
10356             }]);
10357 angular.module("att.abs.drawer", ['att.abs.utilities'])
10358 .directive('attDrawer', ['$document', '$timeout', 'DOMHelper', function ($document, $timeout, DOMHelper) {
10359         return {
10360             restrict: 'EA',
10361             replace: true,
10362             transclude: true,
10363             scope: {
10364                 drawerOpen: "=?",
10365                 drawerAutoClose: "&?"
10366             },
10367             template: '<div><div class="att-drawer" ng-transclude></div><div ng-class="{\'drawer-backdrop\':drawerOpen}"></div></div>',
10368             link: function ($scope, element, attrs) {
10369                 var param = {};
10370                 // First Element in Drawer component
10371                 var firstElement = undefined;
10372                 // Element drawer is toggled from
10373                 var drawerLaunchingElement = undefined;
10374                 // Override default parameters
10375                 param.side = attrs.drawerSlide || 'top';
10376                 param.speed = attrs.drawerSpeed || '0.25';
10377                 param.size = attrs.drawerSize || '300px';
10378                 param.zindex = attrs.drawerZindex || 1000;
10379                 param.className = attrs.drawerClass || 'att-drawer';
10380                 var slider = element.eq(0).children()[0];
10381                 var content = angular.element(slider).children()[0];
10382                 slider.className = param.className;
10383                 /* Style setup */
10384                 slider.style.transitionDuration = param.speed + 's';
10385                 slider.style.webkitTransitionDuration = param.speed + 's';
10386                 slider.style.zIndex = param.zindex;
10387                 slider.style.position = 'fixed';
10388                 slider.style.width = 0;
10389                 slider.style.height = 0;
10390                 slider.style.transitionProperty = 'width, height';
10391                 if(param.side==='right'){
10392                     slider.style.height = attrs.drawerCustomHeight || '100%';
10393                     slider.style.top = attrs.drawerCustomTop ||  '0px';
10394                     slider.style.bottom = attrs.drawerCustomBottom ||  '0px';
10395                     slider.style.right = attrs.drawerCustomRight ||  '0px';
10396                 }else if(param.side==='left'){      /*Added this part for ECOM*/
10397                         slider.style.height = attrs.drawerCustomHeight || '100%';
10398                         slider.style.top = attrs.drawerCustomTop ||  '0px';
10399                         slider.style.bottom = attrs.drawerCustomBottom ||  '0px';
10400                         slider.style.left = attrs.drawerCustomRight ||  '0px';
10401                 }
10402                 else if(param.side==='top' || param.side==='bottom'){
10403                     slider.style.width = attrs.drawerCustomWidth || '100%';
10404                     slider.style.left = attrs.drawerCustomLeft || '0px';
10405                     slider.style.top = attrs.drawerCustomTop || '0px';
10406                     slider.style.right = attrs.drawerCustomRight || '0px';
10407                 }
10408                 $timeout(function() {
10409                     firstElement = DOMHelper.firstTabableElement(element[0]);
10410                 }, 10, false);
10411                 /* Closed */
10412                 function drawerClose(slider, param) {
10413                     if (slider && slider.style.width !== 0 && slider.style.height !== 0){
10414                         content.style.display = 'none';
10415                         if(param.side==='right' || param.side==='left'){
10416                             slider.style.width = '0px';
10417                         }
10418                         else if(param.side==='top' || param.side==='bottom'){
10419                             slider.style.height = '0px';
10420                         }
10421                     }
10422                     $scope.drawerOpen = false;
10423                     // Shift focus
10424                     if (angular.isDefined(drawerLaunchingElement) && drawerLaunchingElement != null) {
10425                         drawerLaunchingElement.focus();
10426                     }
10427                 }
10428                 /* Open */
10429                 function drawerOpen(slider, param) {
10430                     // Before opening drawer, find the focused element
10431                     drawerLaunchingElement = document.activeElement;
10432                     if (slider.style.width !== 0 && slider.style.height !== 0){
10433                         if(param.side==='right' || param.side==='left'){
10434                             slider.style.width = param.size;
10435                         }
10436                         else if(param.side==='top' || param.side==='bottom'){
10437                             slider.style.height = param.size;
10438                         }
10439                         $timeout(function() {
10440                             content.style.display = 'block';
10441                             // Shift focus
10442                             if (angular.isDefined(firstElement) && firstElement != null) {
10443                                 firstElement.focus();
10444                             }
10445                         },(param.speed * 1000));
10446                     }
10447                 }
10448                 function isFunction(functionToCheck) {
10449                     var getType = {};
10450                     return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
10451                 }
10452                 /*
10453                 * Watchers
10454                 * */
10455                 if(attrs.drawerSize) {
10456                     $scope.$watch(function() {
10457                         return attrs.drawerSize;
10458                     }, function(newVal) {
10459                         param.size = newVal;
10460                         if($scope.drawerOpen) {
10461                             drawerOpen(slider,param);
10462                         }
10463                     });
10464                 }
10465                 $scope.$watch("drawerOpen", function (value){
10466                     if (!!value) {
10467                         // Open
10468                         drawerOpen(slider,param);
10469                     } else {
10470                         // Close
10471                         drawerClose(slider,param);
10472                     }
10473                 });
10474                 // close panel on location change
10475                 if($scope.drawerAutoClose()) {
10476                     $scope.$on("$locationChangeStart", function(){
10477                         drawerClose(slider, param);
10478                         if(isFunction($scope.drawerAutoClose())) {
10479                             $scope.drawerAutoClose();
10480                         }
10481                     });
10482                     $scope.$on("$stateChangeStart", function(){
10483                         drawerClose(slider, param);
10484                         if(isFunction($scope.drawerAutoClose)) {
10485                             $scope.drawerAutoClose();
10486                         }
10487                     });
10488                 }
10489             }
10490         };
10491     }
10492 ]);
10493 angular.module('att.abs.message', [])
10494
10495 .directive('attMessages', [function() {
10496     return {
10497         restrict: 'EA',
10498         scope: {
10499             messageType: '=?'
10500         },
10501         controller: ['$scope', '$element', '$attrs', function($scope, $element, $attrs) {
10502             $scope.messageScope = [];
10503             this.registerScope = function(messageScope) {
10504                 $scope.messageScope.push(messageScope);
10505             };
10506             $scope.$parent.$watchCollection($attrs['for'], function(errors) {
10507                 for (var key in errors) {
10508                     if (errors[key]) {
10509                         $scope.error = key;
10510                         break;
10511                     } else {
10512                         $scope.error = null;
10513                     }
10514                 }
10515                 for (var i = 0; i < $scope.messageScope.length; i++) {
10516                     if($scope.messageScope[i].when === $scope.error) {
10517                         $scope.messageScope[i].show();
10518                         $scope.setMessageType($scope.messageScope[i].type);
10519                     } else {
10520                         $scope.messageScope[i].hide();
10521                     }
10522                 }
10523                 if($scope.error === null) {
10524                     $scope.setMessageType(null);
10525                 }
10526             });
10527             $scope.setMessageType = this.setMessageType = function(messageType) {
10528                 if($attrs.messageType) {
10529                     $scope.messageType = messageType;
10530                 }
10531             };
10532         }]
10533     };
10534 }])
10535
10536 .directive('attMessage', [function() {
10537     return {
10538         restrict: 'EA',
10539         scope: {},
10540         require: '^attMessages',
10541         link: function(scope, elem, attr, ctrl) {
10542             ctrl.registerScope(scope);
10543             elem.attr('role', 'alert'); //Trinity CATO
10544             scope.when = attr.when || attr.attMessage;
10545             scope.type = attr.type;
10546             scope.show = function() {
10547                 elem.css({display: 'block'});
10548             };
10549             scope.hide = function() {
10550                 elem.css({display: 'none'});
10551             };
10552             scope.hide();
10553         }
10554     };
10555 }]);
10556
10557 angular.module('att.abs.formField', ['att.abs.message', 'att.abs.utilities'])
10558 .directive('attFormField', [function() {
10559     return {
10560         priority: 101,
10561         restrict: 'A',
10562         controller:function() {
10563         },
10564         link: function(scope, elem, attr) {
10565             elem.wrap('<div class="form-field"></div>');
10566             elem.parent().append('<label class="form-field__label">' + attr.placeholder || attr.attFormField + '</label>');
10567             elem.wrap('<div class="form-field-input-container"></div>');
10568
10569             elem.bind('keyup', function() {
10570                 if (this.value !== '') {
10571                     elem.parent().parent().find('label').addClass('form-field__label--show').removeClass('form-field__label--hide');
10572                 } else {
10573                     elem.parent().parent().find('label').addClass('form-field__label--hide').removeClass('form-field__label--show');
10574                 }
10575             });
10576
10577             elem.bind('blur', function() {
10578                 if (this.value === '') {
10579                     elem.parent().parent().find('label').removeClass('form-field__label--hide');
10580                 }
10581             });
10582         }
10583     };
10584 }])
10585 .directive('attFormFieldValidation', ['$compile', '$log', function($compile, $log) {
10586     return {
10587         priority: 102,
10588         scope: {},
10589         restrict: 'A',
10590         require: ['?ngModel', '?attFormField'],
10591         link: function(scope, elem, attr, ctrl) {
10592             var ngCtrl = ctrl[0];
10593             var attFormFieldCtrl = ctrl[1];
10594             scope.valid = "";
10595             if (!ngCtrl) {
10596                 $log.error("att-form-field-validation :: ng-model directive is required.");
10597                 return;
10598             }
10599             if (!attFormFieldCtrl) {
10600                 $log.error("att-form-field-validation :: att-form-field directive is required.");
10601                 return;
10602             }
10603
10604             elem.parent().append($compile(angular.element('<i class="icon-info-alert error" ng-show="valid===false">&nbsp;</i>'))(scope));
10605             elem.parent().append($compile(angular.element('<i class="icon-info-success success" ng-show="valid===true">&nbsp;</i>'))(scope));
10606
10607             scope.$watch('valid', function(value) {
10608                 if (value) {
10609                     elem.parent().parent().addClass('success');
10610                 } else if (value === false) {
10611                     elem.parent().parent().addClass('error');
10612                 } else {
10613                     elem.parent().parent().removeClass('success').removeClass('error');
10614                 }
10615             });
10616
10617             elem.bind('keyup', function() {
10618                 if (ngCtrl.$valid) {
10619                     scope.valid = true;
10620                 } else if (ngCtrl.$invalid) {
10621                     scope.valid = false;
10622                 } else {
10623                     scope.valid = "";
10624                 }
10625                 scope.$apply();
10626             });
10627         }
10628     };
10629 }])
10630 .directive('attFormFieldValidationAlert', ['$timeout', function($timeout) {
10631         return {
10632         scope: {
10633             messageType: '=?'
10634         },
10635         restrict: 'EA',
10636         replace: true,
10637         transclude: true,
10638         templateUrl: 'app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlert.html',
10639         link: function(scope, elem, attr, ctrl) {
10640             scope.showLabel = false;
10641             scope.hideLabel = false;
10642             scope.errorMessage = false;
10643             scope.warningMessage = false;
10644             var checkMessageType = function() {
10645                 var messageType = scope.messageType;
10646                 if (messageType === 'error') {
10647                     scope.errorMessage = true;
10648                     scope.warningMessage = false;
10649                 } else if (messageType === 'warning') {
10650                     scope.errorMessage = false;
10651                     scope.warningMessage = true;
10652                 } else {
10653                     scope.errorMessage = false;
10654                     scope.warningMessage = false;
10655                 }
10656             };
10657             var oldIE = navigator.userAgent.toLowerCase().indexOf('msie 8.0') !== -1;
10658             elem.find('label').text(elem.find('input').attr('placeholder'));
10659             elem.find('input').bind('keyup', function() {
10660                 if (this.value !== '') {
10661                     scope.showLabel = true;
10662                     scope.hideLabel = false;
10663                     if (oldIE) {
10664                         elem.find('label').css({top: '-20px'});
10665                     }
10666                 } else {
10667                     scope.showLabel = false;
10668                     scope.hideLabel = true;
10669                     if (oldIE) {
10670                         elem.find('label').css({top: '0px'});
10671                     }
10672                 }
10673                 checkMessageType();
10674                 scope.$apply();
10675             });
10676
10677             elem.find('input').bind('blur', function() {
10678                 if (this.value === '') {
10679                     scope.showLabel = false;
10680                     scope.hideLabel = false;
10681                 }
10682                 scope.$apply();
10683             });
10684             $timeout(function() {
10685                 checkMessageType();
10686             }, 100);
10687         }
10688     };
10689 }])
10690 .constant("CoreFormsUiConfig", {
10691             phoneMask: '(___) ___-____'
10692         })
10693 .directive('attPhoneMask', ['$parse', 'CoreFormsUiConfig', function($parse, CoreFormsUiConfig) {
10694                 return {
10695                     require: 'ngModel',
10696                     scope: {
10697                         ngModel: '='
10698                     },
10699                     link: function(scope, iElement, iAttrs, ctrl) {
10700                         var B = navigator.userAgent.toLowerCase(), C = B.indexOf("android") > -1,
10701                                 oldIE = B.indexOf('msie 8.0') !== -1;;
10702                         var A = '';
10703                         var validPhoneNumber = false;
10704                         if (C) {
10705                             A = "__________";
10706                         }
10707                         else {
10708                             A = CoreFormsUiConfig.phoneMask;
10709                         }
10710                         iElement.attr("maxlength", A.length);
10711                         var checkValidity = function(unmaskedValue) {
10712                         var valid = false;
10713                         if (unmaskedValue){
10714                         valid = (unmaskedValue.length === 10);}
10715                         ctrl.$setValidity('invalidPhoneNumber', validPhoneNumber);
10716                         ctrl.$setValidity('mask', valid);
10717                         return valid;
10718                         };
10719                         
10720                         var handleKeyup = function() {
10721                             var E,D = ctrl.$modelValue;
10722                             if (!D.length) {
10723                                 return;
10724                             }
10725                             var L, K, G, J, I;
10726                             J = [];
10727                             G = A.split("");
10728                             I = G.length;
10729                             L = D.substring(0, A.length);
10730                             K = D.replace(/[^0-9]/g, "").split("");
10731                             for (E = 0; E < I; E++) {
10732                                 J.push(G[E] === "_" ? K.shift() : G[E]);
10733                                 if (K.length === 0) {
10734                                     break;
10735                                 }
10736                             }
10737                             D = J.join("");
10738                             if (D === '('){
10739                                 D = '';}
10740                             ctrl.$setViewValue(D);
10741                             ctrl.$render();
10742                             return D;
10743                         };
10744
10745
10746                         // since we are only allowing 0-9, why even let the keypress go forward?
10747                         // also added in delete... in case they want to delete :)
10748                         var handlePress = function(e) {
10749                             if (e.which) {
10750                                 if ((e.which < 48 || e.which > 57) && (e.which < 96 || e.which > 105)) {
10751                                          if (e.which !== 8 && e.which !== 9 && e.which !== 46 && e.which !== 13 && e.which !== 37 && e.which !== 39 &&
10752                                             // Allow: Ctrl+V/v
10753                                             (e.ctrlKey !== true && (e.which !== '118' || e.which !== '86'))&&
10754                                              // Allow: Ctrl+C/c
10755                                             (e.ctrlKey !== true && (e.which !== '99' || e.which !== '67'))&&
10756                                             // Allow: Ctrl+X/x
10757                                             (e.ctrlKey !== true && (e.which !== '120' || e.which !== '88')))
10758                                             {
10759                                                 e.preventDefault ? e.preventDefault() : e.returnValue = false;
10760                                                 iElement.attr("aria-label","Only numbers are allowed");
10761                                                 validPhoneNumber = false;
10762                                             }}
10763                                 else{
10764                                         iElement.removeAttr("aria-label");
10765                                         validPhoneNumber = true;
10766                                     }
10767                                    }
10768                             scope.$apply();
10769                         };
10770                         // i moved this out because i thought i might need focus as well..
10771                         // to handle setting the model as the view changes
10772                         var parser = function(fromViewValue) {
10773                             var letters = /^[A-Za-z]+$/;
10774                             var numbers = /^[0-9]+$/;
10775                             if(fromViewValue.match(letters))
10776                                 {validPhoneNumber = false;}
10777                             if(fromViewValue.match(numbers))
10778                                 {validPhoneNumber = true;}
10779                             var clean = "";
10780                             if (fromViewValue && fromViewValue.length > 0) {
10781                                 clean = fromViewValue.replace(/[^0-9]/g, '');
10782                             }
10783                             checkValidity(clean);
10784                             return clean;
10785                         };
10786
10787                         //to handle reading the model and formatting it
10788                         var formatter = function(fromModelView) {
10789                             var input = '';
10790                             checkValidity(fromModelView);
10791                             if (fromModelView){
10792                                 input = handleKeyup();}
10793                             return input;
10794                         };
10795                         ctrl.$parsers.push(parser);
10796                         ctrl.$formatters.push(formatter);
10797                         iElement.bind('keyup', handleKeyup);
10798                         iElement.bind('keydown', handlePress);
10799                         iElement.bind('input', function(e){
10800                             handleKeyup(e);
10801                             handlePress(e);
10802                         });
10803                     }
10804                 };
10805 }])
10806 .constant('validationTypeInt', {
10807             validationNum: {'number':'1','text':'2','email':'3'}
10808         })        
10809 .directive('attFormFieldPrv', [ 'keyMapAc', 'validationTypeInt', function( keyMapAc, validationTypeInt ) {
10810     return {
10811         priority: 101,
10812         restrict: 'AE',
10813                 controller:['$scope', function($scope) {
10814                         this.showHideErrorMessage = function ( booleanValue ){
10815                                 if(  $scope.$$prevSibling != null && angular.isDefined( $scope.$$prevSibling )
10816                                         && angular.isDefined( $scope.$$prevSibling.hideErrorMsg ) ){
10817                                         $scope.$$prevSibling.hideErrorMsg = booleanValue;
10818                                         $scope.$apply();
10819                                 }
10820                         };
10821                         this.findAllowedCharactor = function( keyCode ){
10822                                 var keyMapSc = keyMapAc.keys;
10823                                 if( angular.isDefined( $scope.allowedSpecialCharacters )
10824                                                 && angular.isDefined( $scope.allowedSpecialCharacters.length )
10825                                                 && $scope.allowedSpecialCharacters.length > 0 ){
10826                                         var allowedCharList = $scope.allowedSpecialCharacters;
10827                                         var charFound = false;
10828                                         for( var i=0 ; i < allowedCharList.length ; i++){
10829                                                 if( allowedCharList[i] === keyMapSc[keyCode] ){
10830                                                         charFound = true;
10831                                                         break;
10832                                                 }
10833                                         }
10834                                         return charFound;
10835                                 }else{
10836                                         return false;
10837                                 }
10838                         };
10839                         this.validateText = function( validationType, allowedChars, validationInput, outputSpecialChars ){
10840                                 if( angular.isDefined( allowedChars ) &&  allowedChars.length === 0 ){
10841                                         var expAlphanumeric = /^[a-zA-Z0-9]*$/i;
10842                                         return expAlphanumeric.test( validationInput );
10843                                 }else{
10844                                         var expAlphanumericSpecialChar = '^[a-zA-Z0-9' + outputSpecialChars + ']*$';
10845                                         var regularExp = new RegExp( expAlphanumericSpecialChar, 'i' );
10846                                         return regularExp.test( validationInput );
10847                                 }
10848                         };
10849                         this.validateNumber = function( validationType, allowedChars, validationInput, outputSpecialChars ){
10850                                 if( angular.isDefined( allowedChars ) &&  allowedChars.length === 0 ){
10851                                         var expNumber = /^[0-9\.]+$/;
10852                                         return expNumber.test( validationInput );
10853                                 }else{
10854                                         var expNumberSpecial = '^[0-9\.' + outputSpecialChars + ']*$';
10855                                         var regularExp = new RegExp( expNumberSpecial, 'i' );
10856                                         return regularExp.test( validationInput );
10857                                 }
10858                         };
10859                         this.validateEmail = function( validationType, allowedChars, validationInput, outputSpecialChars ){
10860                                 if( angular.isDefined( allowedChars ) &&  allowedChars.length === 0 ){
10861                                         var expEmail = /(([a-zA-Z0-9\-?\.?]+)@(([a-zA-Z0-9\-_]+\.)+)([a-z]{2,3}))+$/;
10862                                         return expEmail.test( validationInput );
10863                                 }else{
10864                                         var expEmailSpecial = '(([a-z' + outputSpecialChars + 'A-Z0-9\-?\.?]+)@(([a-z'
10865                                                 + outputSpecialChars + 'A-Z0-9\-_]+\.)+)([' + outputSpecialChars + 'a-z]{2,3}))+$';
10866                                         var regularExp = new RegExp( expEmailSpecial, 'i' );
10867                                         return regularExp.test( validationInput );
10868                                 }
10869                         };
10870                         this.validateInput = function( validationType, allowedChars, validationInput ){
10871                                 var outputSpecialChars = '';
10872                                 var result = false;
10873                                 if( angular.isDefined( allowedChars ) && angular.isDefined( allowedChars.length )
10874                                         && allowedChars.length > 0 ){
10875                                         for( var i = 0; i < allowedChars.length; i++){
10876                                                 outputSpecialChars += '\\'+allowedChars[i];
10877                                         }
10878                                 }
10879                                 switch ( validationTypeInt.validationNum[ validationType ] ) {
10880                                         case validationTypeInt.validationNum["text"]:
10881                                                 result = this.validateText( validationType, allowedChars, validationInput, outputSpecialChars  );
10882                                                 break;
10883                                         case validationTypeInt.validationNum["number"]:
10884                                                 result = this.validateNumber( validationType, allowedChars, validationInput, outputSpecialChars  );
10885                                                 break;
10886                                         case validationTypeInt.validationNum["email"]:
10887                                                 result = this.validateEmail( validationType, allowedChars, validationInput, outputSpecialChars  );
10888                                                 break;
10889                                         default:
10890                                                 break;
10891                                 }
10892                                 return result;
10893                         };
10894         }],
10895         link: function(scope, elem, attr ) {
10896             elem.parent().prepend('<label class="form-field__label">' + attr.placeholder + '</label>');
10897             elem.wrap('<div class="form-field-input-container"></div>');
10898                         elem.parent().parent().find('label').addClass('form-field__label--show');
10899         }
10900     };
10901 }])
10902 .directive('attFormFieldValidationPrv', [ 'keyMapAc','validationTypeInt' , function( keyMapAc, validationTypeInt ) {
10903     return {
10904         priority: 202,
10905         scope: {
10906             validationType: '=',
10907             allowedChars: '='
10908                 },
10909         restrict: 'A',
10910         require: ['?ngModel', '^attFormFieldPrv'],
10911         link: function(scope, elem, attr, ctrl) {
10912             var attFormFieldCtrl = ctrl[1];
10913             elem.bind('keyup', function() {
10914                                 /* email validation has tobe done on keyup */
10915                                 if( attFormFieldCtrl.validateInput( scope.validationType, scope.allowedChars, elem[0].value ) ){
10916                                         attFormFieldCtrl.showHideErrorMessage(false);
10917                                 }
10918                                 else{
10919                                         attFormFieldCtrl.showHideErrorMessage(true);
10920                                 }
10921             });
10922                         var keyMapSc = keyMapAc.keyRange;
10923                         var allowedKeys = keyMapAc.allowedKeys;
10924                         var validateTextCode = function( charFound,event ){
10925                                 var resultOne = (event.which < keyMapSc['startNum'] || event.which > keyMapSc['endNum'] );
10926                                 var resultTwo = (event.which < keyMapSc['startCapitalLetters'] || event.which > keyMapSc['endCapitalLetters'] );
10927                                 var resultThree = (event.which < keyMapSc['startSmallLetters'] || event.which > keyMapSc['endSmallLetters'] );
10928                                 var result = ( resultOne && resultTwo &&  resultThree );
10929                                 return ( result && ( !charFound )  );
10930                         };
10931                         var validateNumberCode = function( charFound,event ){
10932                                 return ( ( event.which < keyMapSc['startNum'] || event.which > keyMapSc['endNum'] ) &&   ( !charFound ) );
10933                         };
10934                         var validateEmailCode = function( charFound,event ){
10935                                 var condOne = String.fromCharCode( event.which ) !== '-' && String.fromCharCode( event.which ) !== '_';
10936                                 var condTwo = String.fromCharCode( event.which ) !== '@' && String.fromCharCode( event.which ) !== '.';
10937                                 var ifAllowedChars = condOne && condTwo;
10938                                 var ifCharRange = validateTextCode( charFound,event );
10939                                 return (  ( !charFound ) && ifAllowedChars && ifCharRange );
10940                         };
10941                         var validateSwitch = function( validationTypeSwitch, charFound, event ){
10942                                 switch ( validationTypeSwitch ) {
10943                                                 case validationTypeInt.validationNum["text"]:
10944                                                         /* 97-122 65-90 48-57 if keyCode is outside range of alphanumeric chars and not found in list then prevent */
10945                                                         if( validateTextCode( charFound, event ) ){
10946                                                                 return true;
10947                                                         }
10948                                                         break;
10949                                                 case validationTypeInt.validationNum["number"]:
10950                                                         /* if key code is outside number range and notfound then prevent */
10951                                                         if( validateNumberCode( charFound, event ) ){
10952                                                                 return true;
10953                                                         }
10954                                                         break;
10955                                                 case validationTypeInt.validationNum["email"]:
10956                                                         /* if keyCode is outside charactor/number range and not _-@. then prevent */
10957                                                         if( validateEmailCode( charFound, event ) ){
10958                                                                 return true;
10959                                                         }
10960                                                         break;
10961                                                 default:
10962                                                         break;
10963                                 }
10964                                 return false;
10965                         };
10966                         /* key stroke prevention has to be happen on numeric and alphanumeric fields */
10967                         elem.bind('keypress', function( event ){
10968                                 if(!(event.which)){
10969                                     if(event.keyCode){
10970                                         event.which = event.keyCode;
10971                                     }
10972                                     else if(event.charCode){
10973                                         event.which = event.charCode;
10974                                     }
10975                                 }
10976                                 var charFound = attFormFieldCtrl.findAllowedCharactor( event.which );
10977                                 var insideCondOne = ( angular.isDefined( scope.validationType ) && scope.validationType !== '');
10978                                 var insideCondTwo = ( event.which !== allowedKeys['TAB']
10979                                         && event.which !== allowedKeys['BACKSPACE'] && event.which!== allowedKeys['DELETE'] );
10980                                 var goInside = insideCondOne && insideCondTwo;
10981                                 if( goInside && validateSwitch( validationTypeInt.validationNum[ scope.validationType ], charFound, event ) ){
10982                                         event.preventDefault();
10983                                 }
10984                         });
10985         }
10986     };
10987 }])
10988 .directive('attFormFieldValidationAlertPrv', [ function() {
10989         return {
10990                         restrict: 'A',
10991                         scope : { errorMessage : '=' },
10992                         transclude: true,
10993                         templateUrl: 'app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlertPrv.html',
10994                         link: function( scope ) {
10995                                 scope.errorMessage = scope.errorMessage;
10996                                 if( angular.isDefined( scope.$parent.hideErrorMsg ) ){
10997                                         scope.hideErrorMsg = scope.$parent.hideErrorMsg;
10998                                 }
10999                                 else{
11000                                         scope.hideErrorMsg = true;
11001                                 }
11002                         }
11003                 };
11004 }])
11005 //Credit card validation directives starts here
11006 .factory('Cards', [function() {
11007         var defaultFormat = /(\d{1,4})/g;
11008         var defaultInputFormat = /(?:^|\s)(\d{4})$/;
11009         var cards = [
11010             {
11011                 type: 'discover',
11012                 pattern: /^(6011|65|64[4-9]|622)/,
11013                 format: defaultFormat,
11014                 inputFormat: defaultInputFormat,
11015                 length: [16],
11016                 cvcLength: [3],
11017                 cvcSecurityImg: 'visaI',
11018                 zipLength: [5],
11019                 luhn: true
11020             },
11021             {
11022                 type: 'mc',
11023                 pattern: /^5[1-5]/,
11024                 format: defaultFormat,
11025                 inputFormat: defaultInputFormat,
11026                 length: [16],
11027                 cvcLength: [3],
11028                 cvcSecurityImg: 'visaI',
11029                 zipLength: [5],
11030                 luhn: true
11031             },
11032             {
11033                 type: 'amex',
11034                 pattern: /^3[47]/,
11035                 format: /(\d{1,4})(\d{1,6})?(\d{1,5})?/,
11036                 inputFormat: /^(\d{4}|\d{4}\s\d{6})$/,
11037                 length: [15],
11038                 cvcLength: [4],
11039                 cvcSecurityImg: 'amexI',
11040                 zipLength: [5],
11041                 luhn: true
11042             },
11043             {
11044                 type: 'visa',
11045                 pattern: /^4/,
11046                 format: defaultFormat,
11047                 inputFormat: defaultInputFormat,
11048                 length: [16],
11049                 cvcLength: [3],
11050                 cvcSecurityImg: 'visaI',
11051                 zipLength: [5],
11052                 luhn: true
11053             }
11054         ];
11055
11056         var _fromNumber = function(num) {
11057             var card, i, len;
11058
11059             num = (num + '').replace(/\D/g, '');
11060
11061             for (i = 0, len = cards.length; i < len; i++) {
11062
11063                 card = cards[i];
11064
11065                 if (card.pattern.test(num)) {
11066                     return card;
11067                 }
11068
11069             }
11070         };
11071
11072         var _fromType = function(type) {
11073             var card, i, len;
11074
11075             for (i = 0, len = cards.length; i < len; i++) {
11076
11077                 card = cards[i];
11078
11079                 if (card.type === type) {
11080                     return card;
11081                 }
11082
11083             }
11084         };
11085
11086         return {
11087             fromNumber: function(val) {
11088                 return _fromNumber(val);
11089             },
11090             fromType: function(val) {
11091                 return _fromType(val);
11092             },
11093             defaultFormat: function() {
11094                 return defaultFormat;
11095             },
11096             defaultInputFormat: function() {
11097                 return defaultInputFormat;
11098             }
11099         };
11100
11101     }])
11102 .factory('_Validate', ['Cards', '$parse', function(Cards, $parse) {
11103         var __indexOf = [].indexOf || function(item)
11104         {
11105             for (var i = 0, l = this.length; i < l; i++)
11106             {
11107                 if (i in this && this[i] === item)
11108                 {
11109                     return i;
11110                 }
11111             }
11112             return -1;
11113         };
11114
11115         var _luhnCheck = function(num) {
11116             var digit, digits, odd, sum, i, len;
11117
11118             odd = true;
11119             sum = 0;
11120             digits = (num + '').split('').reverse();
11121
11122             for (i = 0, len = digits.length; i < len; i++) {
11123
11124                 digit = digits[i];
11125                 digit = parseInt(digit, 10);
11126
11127                 if ((odd = !odd)) {
11128                     digit *= 2;
11129                 }
11130
11131                 if (digit > 9) {
11132                     digit -= 9;
11133                 }
11134
11135                 sum += digit;
11136
11137             }
11138
11139             return sum % 10 === 0;
11140         };
11141
11142         var _validators = {};
11143
11144         _validators['cvc'] = function(cvc, ctrl, scope, attr) {
11145             var ref, ref1;
11146
11147             // valid if empty - let ng-required handle empty
11148             if ((angular.isUndefined(cvc)) || (cvc === null) || (cvc.length === 0))
11149             {
11150                 return true;
11151             }
11152
11153             if (!/^\d+$/.test(cvc)) {
11154                 return false;
11155             }
11156
11157             var type;
11158             if (attr.paymentsTypeModel) {
11159                 var typeModel = $parse(attr.paymentsTypeModel);
11160                 type = typeModel(scope);
11161             }
11162
11163             if (type)
11164             {
11165                 ref1 = Cards.fromType(type);
11166                 return (ref = cvc.length, __indexOf.call((ref1 !== null) ? ref1.cvcLength : void 0, ref)) >= 0;
11167             }
11168             else
11169             {
11170                 return cvc.length >= 3 && cvc.length <= 4;
11171             }
11172         };
11173         _validators['zip'] = function(zip, ctrl, scope, attr) {
11174             var ref, ref1;
11175
11176             // valid if empty - let ng-required handle empty
11177             if ((angular.isUndefined(zip)) || (zip === null) || (zip.length === 0))
11178             {
11179                 return true;
11180             }
11181
11182             if (!/^\d+$/.test(zip)) {
11183                 return false;
11184             }
11185
11186             var type;
11187             if (attr.paymentsTypeModel) {
11188                 var typeModel = $parse(attr.paymentsTypeModel);
11189                 type = typeModel(scope);
11190             }
11191             if (type)
11192             {
11193                 ref1 = Cards.fromType(type);
11194                 return (ref = zip.length, __indexOf.call(ref1 !== null ? ref1.zipLength : void 0, ref)) >= 0;
11195             }
11196             else
11197             {
11198                 return zip.length < 6;
11199             }
11200         };
11201         _validators['card'] = function(num, ctrl, scope, attr) {
11202             var card, ref, typeModel;
11203
11204             if (attr.paymentsTypeModel) {
11205                 typeModel = $parse(attr.paymentsTypeModel);
11206             }
11207
11208             var clearCard = function() {
11209                 if (typeModel) {
11210                     typeModel.assign(scope, null);
11211                 }
11212                 ctrl.$card = null;
11213             };
11214
11215             // valid if empty - let ng-required handle empty
11216             if ((angular.isUndefined(num)) || (num === null) || (num.length === 0)) {
11217                 clearCard();
11218                 return true;
11219             }
11220
11221             num = (num + '').replace(/\s+|-/g, '');
11222
11223             if (!/^\d+$/.test(num)) {
11224                 clearCard();
11225                 return false;
11226             }
11227
11228             card = Cards.fromNumber(num);
11229             if (!card) {
11230                 clearCard();
11231                 return false;
11232             }
11233             ctrl.$card = angular.copy(card);
11234
11235             if (typeModel) {
11236                 typeModel.assign(scope, card.type);
11237             }
11238
11239             ret = (ref = num.length, __indexOf.call(card.length, ref) >= 0) && (card.luhn === false || _luhnCheck(num));
11240             return ret;
11241         };
11242         return function(type, val, ctrl, scope, attr) {
11243             if (!_validators[type]) {
11244
11245                 types = Object.keys(_validators);
11246
11247                 errstr = 'Unknown type for validation: "' + type + '". ';
11248                 errstr += 'Should be one of: "' + types.join('", "') + '"';
11249
11250                 throw errstr;
11251             }
11252             return _validators[type](val, ctrl, scope, attr);
11253         };
11254     }])
11255 .factory('_ValidateWatch', ['_Validate', function(_Validate) {
11256
11257         var _validatorWatches = {};
11258
11259         _validatorWatches['cvc'] = function(type, ctrl, scope, attr) {
11260             if (attr.paymentsTypeModel) {
11261                 scope.$watch(attr.paymentsTypeModel, function(newVal, oldVal) {
11262                     if (newVal !== oldVal) {
11263                         var valid = _Validate(type, ctrl.$modelValue, ctrl, scope, attr);
11264                         ctrl.$setValidity(type, valid);
11265                     }
11266                 });
11267             }
11268         };
11269         _validatorWatches['zip'] = function(type, ctrl, scope, attr) {
11270             if (attr.paymentsTypeModel) {
11271                 scope.$watch(attr.paymentsTypeModel, function(newVal, oldVal) {
11272                     if (newVal !== oldVal) {
11273                         var valid = _Validate(type, ctrl.$modelValue, ctrl, scope, attr);
11274                         ctrl.$setValidity(type, valid);
11275                     }
11276                 });
11277             }
11278         };
11279         return function(type, ctrl, scope, attr) {
11280             if (_validatorWatches[type]) {
11281                 return _validatorWatches[type](type, ctrl, scope, attr);
11282             }
11283         };
11284     }])
11285 .directive('validateCard', ['$window', '_Validate', '_ValidateWatch', function($window, _Validate, _ValidateWatch) {
11286         return {
11287             restrict: 'A',
11288             require: 'ngModel',
11289             link: function(scope, elem, attr, ctrl) {
11290
11291                 var type = attr.validateCard;
11292                 _ValidateWatch(type, ctrl, scope, attr);
11293                 var validateFn = function(val) {
11294                     var valid = _Validate(type, val, ctrl, scope, attr);
11295                     ctrl.$setValidity(type, valid);
11296                     if (type === 'card')
11297                     {
11298                         if (ctrl.$card === null)
11299                         {
11300                             if ((val == null) || (val === "") || (val === ''))
11301                             {
11302                                 scope.invalidCardError = '';
11303                                 scope.invalidCard = "";
11304                             }
11305                             else if (val.length >= 1)
11306                             {
11307                                 scope.invalidCardError = 'error';
11308                                 scope.invalidCard = "The number entered is not a recognized credit card number.";
11309                             }
11310                         }
11311                         else
11312                         {
11313                             if (!valid)
11314                             {
11315                                 if (ctrl.$card.length.indexOf(val.length) >= 0)
11316                                 {
11317                                     scope.invalidCardError = 'error';
11318                                     scope.invalidCard = "The number entered is not a recognized credit card number.";
11319                                 }
11320                                 else
11321                                 {
11322                                     scope.invalidCardError = '';
11323                                     scope.invalidCard = "";
11324                                 }
11325                             }
11326                             else
11327                             {
11328                                 scope.invalidCardError = '';
11329                                 scope.invalidCard = "";
11330                             }
11331                         }
11332                         elem.bind("blur", function()
11333                         {
11334                             if ((!valid) || (ctrl.$card === null))
11335                             {
11336                                 scope.invalidCardError = 'error';
11337                                 scope.invalidCard = "The number entered is not a recognized credit card number.";
11338                             }
11339                             else
11340                             {
11341                                 scope.invalidCardError = '';
11342                                 scope.invalidCard = "";
11343                             }
11344                         });
11345                     }
11346                     return valid ? val : undefined;
11347                 };
11348                 ctrl.$formatters.push(validateFn);
11349                 ctrl.$parsers.push(validateFn);
11350             }
11351         };
11352     }])
11353 .directive('creditCardImage', function() {
11354     return{
11355         templateUrl: 'app/scripts/ng_js_att_tpls/formField/creditCardImage.html',
11356         replace: false,
11357         transclude: false,
11358         link: function(scope, element, attr)
11359         {
11360             scope.$watch(attr.creditCardImage, function(newVal, oldVal)
11361             {
11362                 if (newVal !== oldVal)
11363                 {
11364                     scope.cvc = '';
11365                     if (!angular.isUndefined(newVal) && newVal !== null)
11366                     {
11367                         scope.newValCCI = 'show-' + newVal;
11368                     }
11369                     if (newVal === null)
11370                     {
11371                         scope.newValCCI = '';
11372                     }
11373                 }
11374             });
11375         }
11376     };
11377 })
11378 .directive('securityCodeImage', ['$document', function($document) {
11379         return{
11380             templateUrl: 'app/scripts/ng_js_att_tpls/formField/cvcSecurityImg.html',
11381             replace: false,
11382             transclude: false,
11383             link: function(scope, element, attr)
11384             {
11385                 scope.$watch(attr.securityCodeImage, function(newVal, oldVal)
11386                 {
11387                     if (newVal !== oldVal)
11388                     {
11389                         if (!angular.isUndefined(newVal) && newVal !== null)
11390                         {
11391                             if (newVal === 'amexI')
11392                             {
11393                                 scope.newValI = 'ccv2-security-amex';
11394                                 scope.newValIAlt = "The 4 digit CVC security code is on the front of the card.";
11395                                 scope.cvcPlaceholder = "4 digits";
11396                                 scope.cvcMaxlength = 4;
11397                             }
11398                             else if (newVal === 'visaI')
11399                             {
11400                                 scope.newValI = 'ccv2-security';
11401                                 scope.newValIAlt = "The CVC security code is on the back of your card right after the credit card number.";
11402                                 scope.cvcPlaceholder = "3 digits";
11403                                 scope.cvcMaxlength = 3;
11404                             }
11405                         }
11406                         if (newVal === null)
11407                         {
11408                             scope.newValI = 'ccv2-security';
11409                             scope.cvcPlaceholder = "3 digits";
11410                             scope.cvcMaxlength = 3;
11411                             scope.newValIAlt = "The CVC security code is on the back of your card right after the credit card number.";
11412                         }
11413
11414                     }
11415                 });
11416                 element.bind("click", function(ev) {
11417                     ev.preventDefault();
11418                     if (element.find("button").hasClass("active")) {
11419                         element.find("button").removeClass("active");
11420                     }
11421                     else {
11422                         element.find("button").addClass("active");
11423                     }
11424                 });
11425
11426                 var window = angular.element($document);
11427                 window.bind("click", function(ev) {
11428                     var targetClassname = ev.target.className;
11429                     if ((targetClassname !== "btn btn-alt btn-tooltip active")) {
11430                         if (element.find("button").hasClass("active")) {
11431                             element.find("button").removeClass("active");
11432                         }
11433                     }
11434
11435                 });
11436             }
11437         };
11438     }]);
11439
11440 angular.module('att.abs.hourpicker', ['att.abs.utilities'])
11441     .constant('hourpickerConfig', {
11442         days: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
11443         customOption: 'Custom'
11444     })
11445
11446 .controller('hourPickerController', ['$scope', function ($scope) {
11447
11448     $scope.options = [];
11449     this.setOptions = function (value, fromtime, totime, preselect, uncheckedFromTime, uncheckedToTime) {
11450         $scope.options.push(value);
11451
11452         if (preselect !== undefined) {
11453             $scope.preselect = preselect;
11454         }
11455
11456         var daycount;
11457
11458         if (fromtime !== undefined) {
11459             $scope.fromtime = fromtime;
11460             for (daycount in $scope.days) {
11461                 if ($scope.days.hasOwnProperty(daycount)) {
11462                     $scope.FrtimeList[$scope.days[daycount]] = {};
11463                     if (uncheckedFromTime !== undefined) {
11464                         $scope.FrtimeList[$scope.days[daycount]].value = uncheckedFromTime;
11465                         $scope.selectedFromOption[$scope.days[daycount]] = uncheckedFromTime;
11466                     } else {
11467                         $scope.FrtimeList[$scope.days[daycount]].value = fromtime[0].value;
11468                         $scope.selectedFromOption[$scope.days[daycount]] = fromtime[0].value;
11469                     }
11470                 }
11471             }
11472         }
11473         if (totime !== undefined) {
11474             $scope.totime = totime;
11475             for (daycount in $scope.days) {
11476                 if ($scope.days.hasOwnProperty(daycount)) {
11477                     $scope.TotimeList[$scope.days[daycount]] = {};
11478                     if (uncheckedToTime !== undefined) {
11479                         $scope.TotimeList[$scope.days[daycount]].value = uncheckedToTime;
11480                         $scope.selectedToOption[$scope.days[daycount]] = uncheckedToTime;
11481                     } else {
11482                         $scope.TotimeList[$scope.days[daycount]].value = totime[0].value;
11483                         $scope.selectedToOption[$scope.days[daycount]] = totime[0].value;
11484                     }
11485                     $scope.showToTimeErrorDay[$scope.days[daycount]] = false;
11486                 }
11487             }
11488         }
11489
11490         if (uncheckedFromTime !== undefined) {
11491             $scope.uncheckedFromTime = uncheckedFromTime;
11492         }
11493         if (uncheckedToTime !== undefined) {
11494             $scope.uncheckedToTime = uncheckedToTime;
11495         }
11496     };
11497
11498     this.getSelectedOption = function () {
11499         return $scope.selectedOption;
11500     };
11501
11502     this.setToTimeErrorDay = function (day, flag) {
11503         $scope.showToTimeErrorDay[day] = flag;
11504     };
11505 }])
11506
11507 .directive('attHourpickerOption', [function () {
11508     return {
11509         restrict: 'EA',
11510         require: '^attHourpicker',
11511         scope: {
11512             option: "=option",
11513             fromtime: "=fromtime",
11514             totime: "=totime",
11515             preselect: "=preselect",
11516             uncheckedFromTime: "=",
11517             uncheckedToTime: "="
11518         },
11519         link: function (scope, element, attr, ctrl) {
11520             ctrl.setOptions(scope.option,
11521                 scope.fromtime,
11522                 scope.totime,
11523                 scope.preselect,
11524                 scope.uncheckedFromTime,
11525                 scope.uncheckedToTime);
11526         }
11527     };
11528 }])
11529
11530 .directive('attHourpicker', ["hourpickerConfig", "$document", "$log", "$documentBind", "$timeout", function (hourpickerConfig, $document, $log, $documentBind, $timeout) {
11531     return {
11532         require: 'ngModel',
11533         restrict: 'EA',
11534         controller: 'hourPickerController',
11535         transclude: true,
11536         scope: {
11537             model: "=ngModel",
11538             resetFlag: "=?"
11539         },
11540         templateUrl: 'app/scripts/ng_js_att_tpls/hourpicker/hourpicker.html',
11541         link: function (scope, element, attr, ctrl) {
11542             var flag = false;
11543             scope.isFromDropDownOpen = false;
11544             scope.isToDropDownOpen = false;
11545             var dropDownOpenValue = "";
11546             var custTime = {};
11547             scope.days = hourpickerConfig.days;
11548             scope.daysList = {};
11549             scope.FrtimeList = {};
11550             scope.FrtimeListDay = {};
11551             scope.TotimeListDay = {};
11552             scope.selectedFromOption = {};
11553             scope.selectedToOption = {};
11554             scope.TotimeList = {};
11555             scope.selectedIndex = 0;
11556             scope.selectedOption = "Select from list";
11557             scope.customTime = [];
11558
11559             scope.resetFlag = false;
11560             scope.showToTimeErrorDay = {};
11561             scope.validatedCustomPreselect = [];
11562
11563             scope.$watch('resetFlag', function (newVal, oldVal) {
11564                 if (newVal !== oldVal) {
11565                     if (newVal && scope.selectedOption === hourpickerConfig.customOption) {
11566                         //disable and reset all days checkbox
11567                         for (day in scope.daysList) {
11568                             if (scope.daysList.hasOwnProperty(day)) {
11569                                 scope.daysList[day] = false;
11570                                 scope.addSelectedValue(day);
11571                             }
11572                         }
11573                         scope.preselectUpdateFxn(scope.preselect);
11574                     }
11575                     scope.resetFlag = false;
11576                 }
11577             });
11578
11579             scope.$watch('selCategory', function (value) {
11580                 if (value) {
11581                     ctrl.$setViewValue(value);
11582                 }
11583             }, true);
11584
11585             scope.updateData = function (value) {
11586                 if (value.constructor === Array) {
11587                     scope.showDaysSelector = true;
11588                     scope.selectedOption = hourpickerConfig.customOption;
11589                     for (var arry in value) {
11590                         if (value.hasOwnProperty(arry)) {
11591                             var day = value[arry].day;
11592                             
11593                             if (typeof value[arry].preEnabled === 'boolean' && value[arry].preEnabled) {
11594                                 scope.daysList[day] = true;
11595                             } else {
11596                                 scope.daysList[day] = false;
11597                             }
11598                             
11599                             for (var fromcount in scope.fromtime) {
11600                                 if (scope.fromtime[fromcount].value === value[arry].FromTime && !scope.uncheckedFromTime) {
11601                                     scope.FrtimeList[day].value = scope.fromtime[fromcount].value;
11602                                     scope.selectedFromOption[day] = scope.FrtimeList[day].value;
11603                                 }
11604                             }
11605                             for (var tocount in scope.totime) {
11606                                 if (scope.totime[tocount].value === value[arry].ToTime && !scope.uncheckedToTime) {
11607                                     scope.TotimeList[day].value = scope.totime[tocount].value;
11608                                     scope.selectedToOption[day] = scope.TotimeList[day].value;
11609                                 }
11610                             }
11611                             
11612                             scope.addSelectedValue(day, value[arry].FromTime, value[arry].ToTime);
11613
11614                             //for IE8 Fix
11615                             if (parseInt(arry) + 1 === value.length) {
11616                                 break;
11617                             }
11618                         }
11619                     }
11620                 } else {
11621                     scope.selectOption(value.day);
11622                 }
11623             };
11624
11625             scope.$watch('preselect', function (value) {
11626                 scope.preselectUpdateFxn(value);
11627             });
11628
11629             scope.preselectUpdateFxn = function (value) {
11630                 if (value !== undefined) {
11631                     if (scope.options) {
11632                         value = scope.validatePreselectData(value);
11633                     }
11634                     if (value === "") {
11635                         return;
11636                     }
11637                     scope.updateData(value);
11638                 }
11639             };
11640
11641             scope.validatePreselectData = function (value) {
11642                 if (value.constructor === Array) {
11643                     for (var arry in value) {
11644                         if (value.hasOwnProperty(arry)) {
11645                             var day = value[arry].day;
11646                             var isDayFound = false;
11647                             var isFrmFound = false;
11648                             var isToFound = false;
11649                             for (var daycount in scope.days) {
11650                                 if (scope.days[daycount] === day) {
11651                                     isDayFound = true;
11652                                     break;
11653                                 }
11654                             }
11655                             if (!isDayFound) {
11656                                 value.splice(arry, 1);
11657                                 continue;
11658                             }
11659                             for (var fromcount in scope.fromtime) {
11660                                 if (scope.fromtime[fromcount].value === value[arry].FromTime) {
11661                                     isFrmFound = true;
11662                                     break;
11663                                 }
11664                             }
11665                             if (!isFrmFound) {
11666                                 value[arry].FromTime = scope.fromtime[0].value;
11667                             }
11668                             for (var tocount in scope.totime) {
11669                                 if (scope.totime[tocount].value === value[arry].ToTime) {
11670                                     isToFound = true;
11671                                     break;
11672                                 }
11673                             }
11674                             if (!isToFound) {
11675                                 value[arry].ToTime = scope.totime[0].value;
11676                             }
11677
11678                             if (typeof value[arry].preEnabled === 'boolean' && value[arry].preEnabled) {
11679                                 value[arry].preEnabled = true;
11680                             } else {
11681                                 value[arry].preEnabled = false;
11682                             }
11683                             
11684                             scope.validatedCustomPreselect[day] = {};
11685                             scope.validatedCustomPreselect[day].FromTime = value[arry].FromTime;
11686                             scope.validatedCustomPreselect[day].ToTime = value[arry].ToTime;
11687
11688                             //for IE8 Fix
11689                             if (parseInt(arry) + 1 === value.length) {
11690                                 break;
11691                             }
11692                         }
11693                     }
11694                 } else {
11695                     var isOptionFound = false;
11696                     for (var optcount in scope.options) {
11697                         if (scope.options[optcount] === value.day) {
11698                             isOptionFound = true;
11699                             break;
11700                         }
11701                     }
11702                     if (!isOptionFound) {
11703                         value = "";
11704                     }
11705                 }
11706                 return value;
11707             };
11708
11709             scope.selectPrevNextValue = function ($event, arrayValues, currValue) {
11710
11711                 var value;
11712                 var index = 0;
11713                 if ($event.keyCode === 38) {
11714                     value = -1;
11715                 } else if ($event.keyCode === 40) {
11716                     value = 1;
11717                 } else {
11718                     return currValue;
11719                 }
11720
11721                 if (arrayValues.indexOf(currValue) !== -1) {
11722                     index = arrayValues.indexOf(currValue) + value;
11723                 } else {
11724                     for (var count in arrayValues) {
11725                         if (arrayValues[count].value === currValue) {
11726                             index = parseInt(count) + value;
11727                             break;
11728                         }
11729                     }
11730                 }
11731
11732                 if (index === arrayValues.length) {
11733                     index = index - 1;
11734                 } else if (index === -1) {
11735                     index = index + 1;
11736                 }
11737
11738                 $event.preventDefault();
11739                 if (arrayValues[index].value) {
11740                     return arrayValues[index].value;
11741                 } else {
11742                     return arrayValues[index];
11743                 }
11744             };
11745
11746             scope.showDropdown = function () {
11747                 scope.showlist = !scope.showlist;
11748                 flag = !flag;
11749             };
11750
11751             scope.showfromDayDropdown = function (value) {
11752                 //close dropdown if any other From drop down is opened
11753                 for (count in scope.FrtimeListDay) {
11754                     if (count !== value && scope.FrtimeListDay[count]) {
11755                         scope.FrtimeListDay[count] = false;
11756                     }
11757                 }
11758                 for (count in scope.TotimeListDay) {
11759                     if (scope.TotimeListDay[count]) {
11760                         scope.TotimeListDay[count] = false;
11761                     }
11762                 }
11763                 scope.FrtimeListDay[value] = !scope.FrtimeListDay[value];
11764                 flag = !flag;
11765                 scope.showlist = false;
11766
11767                 //save model value so we can close current dropdown on click of other part of the document
11768                 if (scope.FrtimeListDay[value]) {
11769                     scope.isFromDropDownOpen = true;
11770                     dropDownOpenValue = value;
11771                 } else {
11772                     scope.isFromDropDownOpen = false;
11773                 }
11774
11775                 $timeout(function () {
11776                     if (scope.FrtimeListDay[value]) {
11777                         var daysContainerDIV = angular.element(element)[0].querySelector(".customdays-width");
11778                         var containerUL = angular.element(daysContainerDIV.querySelector('.select2-container-active')).parent()[0].querySelector("ul");
11779                         var selectedElemTopPos = angular.element(containerUL.querySelector('.selectedItemInDropDown'))[0].offsetTop;
11780                         angular.element(containerUL)[0].scrollTop = selectedElemTopPos;
11781                     }
11782                 });
11783             };
11784
11785             scope.showtoDayDropdown = function (value) {
11786                 //close dropdown if any other To drop down is opened
11787                 for (count in scope.TotimeListDay) {
11788                     if (count !== value && scope.TotimeListDay[count]) {
11789                         scope.TotimeListDay[count] = false;
11790                     }
11791                 }
11792                 for (count in scope.FrtimeListDay) {
11793                     if (scope.FrtimeListDay[count]) {
11794                         scope.FrtimeListDay[count] = false;
11795                     }
11796                 }
11797                 scope.TotimeListDay[value] = !scope.TotimeListDay[value];
11798                 flag = !flag;
11799                 scope.showlist = false;
11800
11801                 //save model value so we can close current dropdown on click of other part of the document
11802                 if (scope.TotimeListDay[value]) {
11803                     scope.isToDropDownOpen = true;
11804                     dropDownOpenValue = value;
11805
11806                 } else {
11807                     scope.isToDropDownOpen = false;
11808                 }
11809
11810                 $timeout(function () {
11811                     if (scope.TotimeListDay[value]) {
11812                         var daysContainerDIV = angular.element(element)[0].querySelector(".customdays-width");
11813                         var containerUL = angular.element(daysContainerDIV.querySelector('.select2-container-active')).parent()[0].querySelector("ul");
11814                         var selectedElemTopPos = angular.element(containerUL.querySelector('.selectedItemInDropDown'))[0].offsetTop;
11815                         angular.element(containerUL)[0].scrollTop = selectedElemTopPos;
11816                     }
11817                 });
11818             };
11819
11820             scope.selectFromDayOption = function (day, value) {
11821                 scope.selectedFromOption[day] = value;
11822                 scope.FrtimeList[day].value = value;
11823                 scope.FrtimeListDay[day] = false;
11824                 scope.isFromDropDownOpen = false;
11825             };
11826
11827             scope.selectToDayOption = function (day, value) {
11828                 scope.selectedToOption[day] = value;
11829                 scope.TotimeList[day].value = value;
11830                 scope.TotimeListDay[day] = false;
11831                 scope.isToDropDownOpen = false;
11832             };
11833
11834             scope.addSelectedValue = function (value, fromtime, totime) {
11835                 var count, len;
11836                 if (scope.daysList[value] !== undefined && !scope.daysList[value]) {
11837                     for (count = 0, len = scope.customTime.length; count < len; count++) {
11838                         if (scope.customTime[count].day === value) {
11839                             if (scope.uncheckedFromTime) {
11840                                 scope.selectedFromOption[scope.customTime[count].day] = scope.uncheckedFromTime;
11841                             } else {
11842                                 scope.selectedFromOption[scope.customTime[count].day] = scope.FrtimeList[scope.customTime[count].day].value;
11843                             }
11844
11845                             if (scope.uncheckedToTime) {
11846                                 scope.selectedToOption[scope.customTime[count].day] = scope.uncheckedToTime;
11847                             } else {
11848                                 scope.selectedToOption[scope.customTime[count].day] = scope.TotimeList[scope.customTime[count].day].value;
11849                             }
11850
11851                             scope.customTime.splice(count, 1);
11852                             break;
11853                         }
11854                     }
11855                 } else {
11856                     if (scope.selectedFromOption[value] === scope.uncheckedFromTime) {
11857
11858                         if (angular.isDefined(scope.validatedCustomPreselect[value])) {
11859                             scope.selectedFromOption[value] = scope.validatedCustomPreselect[value].FromTime;
11860                             fromtime = scope.validatedCustomPreselect[value].FromTime;
11861                             scope.FrtimeList[value].value = scope.validatedCustomPreselect[value].FromTime;
11862                         } else {
11863                             scope.selectedFromOption[value] = scope.fromtime[0].value;
11864                             fromtime = scope.fromtime[0].value;
11865                             scope.FrtimeList[value].value = scope.fromtime[0].value;
11866                         }
11867
11868                     }
11869
11870                     if (scope.selectedToOption[value] === scope.uncheckedToTime) {
11871
11872                         if (angular.isDefined(scope.validatedCustomPreselect[value])) {
11873                             scope.selectedToOption[value] = scope.validatedCustomPreselect[value].ToTime;
11874                             totime = scope.validatedCustomPreselect[value].ToTime;
11875                             scope.TotimeList[value].value = scope.validatedCustomPreselect[value].ToTime;
11876                         } else {
11877                             scope.selectedToOption[value] = scope.totime[0].value;
11878                             totime = scope.totime[0].value;
11879                             scope.TotimeList[value].value = scope.totime[0].value;
11880                         }
11881                     }
11882
11883                     custTime["day"] = value;
11884                     custTime["FromTime"] = scope.FrtimeList[value].value;
11885                     custTime["ToTime"] = scope.TotimeList[value].value;
11886
11887                     for (count = 0, len = scope.customTime.length; count < len; count++) {
11888                         if (scope.customTime[count].day === value) {
11889                             scope.customTime[count].FromTime = custTime["FromTime"];
11890                             scope.customTime[count].ToTime = custTime["ToTime"];
11891                             break;
11892                         }
11893                     }
11894                     if (count === len) {
11895                         var x = angular.copy(custTime);
11896                         scope.customTime.push(x);
11897                     }
11898                 }
11899                 scope.selCategory = scope.customTime;
11900             };
11901
11902
11903             var outsideClick = function () {
11904                 if (scope.showlist) {
11905                     scope.$apply(function () {
11906                         scope.showlist = false;
11907                     });
11908                 }
11909             };
11910
11911             $documentBind.click('showlist', outsideClick, scope);
11912
11913             var outsideClickFromDropdown = function () {
11914                 scope.$apply(function () {
11915                     if (scope.isFromDropDownOpen) {
11916                         scope.FrtimeListDay[dropDownOpenValue] = false;
11917                         scope.isFromDropDownOpen = false;
11918                     }
11919                 });
11920             };
11921
11922             $documentBind.click('isFromDropDownOpen', outsideClickFromDropdown, scope);
11923
11924             var outsideClickToDropdown = function () {
11925                 scope.$apply(function () {
11926                     if (scope.isToDropDownOpen) {
11927                         scope.TotimeListDay[dropDownOpenValue] = false;
11928                         scope.isToDropDownOpen = false;
11929                     }
11930                 });
11931             };
11932
11933             $documentBind.click('isToDropDownOpen', outsideClickToDropdown, scope);
11934
11935             scope.selectOption = function (sItem) {
11936
11937                 if (sItem === hourpickerConfig.customOption) {
11938                     scope.showDaysSelector = true;
11939                     scope.selCategory = scope.customTime;
11940                 } else {
11941                     scope.showDaysSelector = false;
11942                     var fromTime = /[0-9]\s?am/i.exec(sItem);
11943                     var toTime = /[0-9]\s?pm/i.exec(sItem);
11944                     scope.selCategory = {
11945                         day: sItem,
11946                         FromTime: fromTime === null ? 'NA' : fromTime[0],
11947                         ToTime: toTime === null ? 'NA' : toTime[0]
11948                     };
11949                 }
11950
11951                 scope.showlist = false;
11952                 flag = false;
11953                 scope.selectedOption = sItem;
11954             };
11955         }
11956     };
11957 }])
11958
11959 .directive('attHourpickerValidator', ['hourpickerConfig', function (hourpickerConfig) {
11960     return {
11961         restrict: 'A',
11962         require: ['attHourpicker', 'ngModel'],
11963         link: function (scope, element, attr, ctrl) {
11964
11965             var attHourpickerCtrl = ctrl[0];
11966             var ngModelCtrl = ctrl[1];
11967
11968             //required format [h:MM tt] like '1:10 PM'
11969             var convertTimeStrngToMilitaryFormat = function (time) {
11970                 var hours = Number(time.match(/^(\d+)/)[1]);
11971                 var minutes = Number(time.match(/:(\d+)/)[1]);
11972                 var AMPM = (time.match(/\s(.*)$/)[1]).toUpperCase();
11973                 if (AMPM === 'PM' && hours < 12) {
11974                     hours = hours + 12;
11975                 }
11976                 if (AMPM === 'AM' && hours === 12) {
11977                     hours = hours - 12;
11978                 }
11979                 var sHours = hours.toString();
11980                 var sMinutes = minutes.toString();
11981                 if (hours < 10) {
11982                     sHours = '0' + sHours;
11983                 }
11984                 if (minutes < 10) {
11985                     sMinutes = '0' + sMinutes;
11986                 }
11987                 return parseInt(sHours + sMinutes, 10);
11988             };
11989
11990             var compareTimeStrings = function (fromTimeString, toTimeString) {
11991                 var fromMilitaryTime = convertTimeStrngToMilitaryFormat(fromTimeString);
11992                 var toMilitaryTime = convertTimeStrngToMilitaryFormat(toTimeString);
11993                 return (toMilitaryTime - fromMilitaryTime);
11994             };
11995
11996             var validateCustomData = function (finalDataModal) {
11997
11998                 if (attHourpickerCtrl.getSelectedOption() === hourpickerConfig.customOption) {
11999
12000                     var errorDaysCount = 0;
12001
12002                     for (var item in finalDataModal) {
12003                         if (finalDataModal.hasOwnProperty(item)) {
12004                             if (compareTimeStrings(finalDataModal[item].FromTime, finalDataModal[item].ToTime) <= 0) {
12005                                 attHourpickerCtrl.setToTimeErrorDay(finalDataModal[item].day, true);
12006                                 errorDaysCount++;
12007                             } else {
12008                                 attHourpickerCtrl.setToTimeErrorDay(finalDataModal[item].day, false);
12009                             }
12010                         }
12011                     }
12012
12013                     if (errorDaysCount > 0) {
12014                         //validation error
12015                         ngModelCtrl.$setValidity('validationStatus', false);
12016                         return [];
12017                     } else {
12018                         //validation successful
12019                         ngModelCtrl.$setValidity('validationStatus', true);
12020                         return finalDataModal;
12021                     }
12022                 } else {
12023                     //default case no validation
12024                     ngModelCtrl.$setValidity('validationStatus', true);
12025                     return finalDataModal;
12026                 }
12027
12028             };
12029
12030             ngModelCtrl.$parsers.unshift(validateCustomData);
12031         }
12032     };
12033 }]);
12034 angular.module('att.abs.iconButtons', [])
12035         .constant('buttonConfig', {
12036             activeClass: 'active--button',
12037             toggleEvent: 'click'
12038         })
12039         .directive('attIconBtnRadio', ['buttonConfig', function(buttonConfig) {
12040                 var activeClass = buttonConfig.activeClass || 'active--button';
12041                 var toggleEvent = buttonConfig.toggleEvent || 'click';
12042                 return {
12043                     require: 'ngModel',
12044                     link: function(scope, element, attrs, ngModelCtrl) {
12045                         element.attr("tabindex","0");
12046                         element.append("<span class='hidden-spoken'>"+attrs.attIconBtnRadio+"</span>");
12047                         //model -> UI
12048                         ngModelCtrl.$render = function() {
12049                             element.parent().toggleClass(activeClass, angular.equals(ngModelCtrl.$modelValue, attrs.attIconBtnRadio));
12050                         };
12051                         //ui->model
12052                         element.parent().bind(toggleEvent, function() {
12053                             if (!element.parent().hasClass(activeClass)) {
12054                                 scope.$apply(function() {
12055                                     ngModelCtrl.$setViewValue(attrs.attIconBtnRadio);
12056                                     ngModelCtrl.$render();
12057                                 });
12058                             }
12059                         });
12060                     }
12061                 };
12062             }])
12063         .directive('attIconBtnCheckbox', ['buttonConfig', function(buttonConfig) {
12064                 var activeClass = buttonConfig.activeClass || 'active--button';
12065                 var toggleEvent = buttonConfig.toggleEvent || 'click';
12066                 return {
12067                     require: 'ngModel',
12068                     link: function(scope, element, attrs, ngModelCtrl) {
12069                         element.attr("tabindex","0");
12070                         element.append("<span class='hidden-spoken'>"+attrs.attIconBtnCheckbox+"</span>");
12071                         function getTrueValue() {
12072                             var trueValue = scope.$eval(attrs.btnCheckboxTrue);
12073                             return angular.isDefined(trueValue) ? trueValue : true;
12074                         }
12075                         function getFalseValue() {
12076                             var falseValue = scope.$eval(attrs.btnCheckboxFalse);
12077                             return angular.isDefined(falseValue) ? falseValue : false;
12078                         }
12079                         //model -> UI
12080                         ngModelCtrl.$render = function() {
12081                             element.parent().toggleClass(activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue()));
12082                         };
12083                         //ui->model
12084                         element.parent().bind(toggleEvent, function() {
12085                             scope.$apply(function() {
12086                                 ngModelCtrl.$setViewValue(element.parent().hasClass(activeClass) ? getFalseValue() : getTrueValue());
12087                                 ngModelCtrl.$render();
12088                             });
12089                         });
12090                     }
12091                 };
12092             }]);
12093
12094 angular.module('att.abs.links', ['ngSanitize'])
12095         .directive('attLink', [function() {
12096                 return {
12097                     restrict: 'A',
12098                     link: function(scope, elem) {
12099                         elem.addClass('link');
12100                         if(!(elem.attr('href'))){
12101                             elem.attr("tabindex", "0");
12102                         }
12103                     }
12104                 };
12105             }])
12106         .directive('attLinkVisited', [function() {
12107                 return {
12108                     restrict: 'A',
12109                     link: function(scope, elem) {
12110                         elem.addClass('link--visited');
12111                         if(!(elem.attr('href'))){
12112                             elem.attr("tabindex", "0");
12113                         }
12114                     }
12115                 };
12116             }])
12117         .directive('attReadmore', ['$timeout',function($timeout) {
12118                 return {
12119                     restrict: 'A',
12120                     scope: {
12121                         lines:"@noOfLines",
12122                         textModel: "=",
12123                         //attribute to use readmore inside accordion
12124                         isOpen: "="
12125                     },
12126                     templateUrl: 'app/scripts/ng_js_att_tpls/links/readMore.html',
12127                     link: function(scope, elem) {
12128                         var height = 1;
12129                         scope.$watch('textModel', function(val){
12130                             if(!val){
12131                                 scope.textToDisplay = '';
12132                                 scope.readMoreLink = false;
12133                                 scope.readLessLink = false;
12134                                 scope.readFlag = false;
12135                             }
12136                             else{
12137                                 if (typeof String.prototype.trim !== 'function') {
12138                                     String.prototype.trim = function() {
12139                                        return this.replace(/^\s+|\s+$/g, '');
12140                                     };
12141                                 }
12142                                 scope.textToDisplay = val.trim();
12143                                 scope.readFlag = true;
12144                                 $timeout(function() {
12145                                     var readElem = elem[0].children[0].children[0];
12146                                     if(height===1){
12147                                         if(window.getComputedStyle){
12148                                             height = parseInt(scope.lines) * parseFloat(window.getComputedStyle(readElem,null).getPropertyValue("height"));
12149                                         }
12150                                         else {
12151                                             height = parseInt(scope.lines) * parseFloat(readElem.currentStyle.height);
12152                                         }
12153                                         scope.elemHeight = height;
12154                                         scope.readLinkStyle = {'height': scope.elemHeight + 'px'};
12155                                     }
12156                                 });
12157                                 scope.readMoreLink = true;
12158                                 scope.readLessLink = false;
12159                             }
12160                         });
12161                         // Code to use readmore inside accordion
12162                         var parentElem = elem.parent();
12163                         if (parentElem.hasClass('att-accordion__body')) {
12164                             scope.$watch('isOpen', function(val) {
12165                                 if (!val) {
12166                                     scope.readMoreLink = true;
12167                                     scope.readLessLink = false;
12168                                     scope.readLinkStyle = {'height': scope.elemHeight + 'px'};
12169                                     scope.readFlag = true;
12170                                 }
12171                             });
12172                         }
12173                         scope.readMore = function() {
12174                             scope.readMoreLink = false;
12175                             scope.readLessLink = true;
12176                             scope.readLinkStyle = {'height': 'auto'};
12177                             scope.readFlag = false;
12178                             var moreLink = angular.element(elem).children().eq(1).find('a')[0];
12179                             $timeout(function()
12180                              {
12181                                 moreLink.focus();
12182                              });
12183                         };
12184                         scope.readLess = function() {
12185                             scope.readMoreLink = true;
12186                             scope.readLessLink = false;
12187                             scope.readLinkStyle = {'height': scope.elemHeight + 'px'};
12188                             scope.readFlag = true;
12189                             var readLessLink = angular.element(elem).children().eq(0).find('a')[0];
12190                             $timeout(function()
12191                              {
12192                                 readLessLink.focus();
12193                              });
12194                         };
12195                     }
12196                 };
12197             }])
12198         .directive('attLinksList', [function() {
12199                 return {
12200                     restrict: 'A',
12201                     controller: function() {
12202                     },
12203                     link: function(scope, elem) {
12204                         elem.addClass('links-list');
12205                     }
12206                 };
12207             }])
12208         .directive('attLinksListItem', [function() {
12209                 return {
12210                     restrict: 'A',
12211                     require: '^attLinksList',
12212                     link: function(scope, elem) {
12213                         elem.addClass('links-list__item');
12214                         if(!(elem.attr('href'))){
12215                             elem.attr("tabindex", "0");
12216                         }
12217                     }
12218                 };
12219             }]);
12220 angular.module('att.abs.loading', [])
12221         .directive('attLoading', ['$window',function($window) {
12222                 return {
12223                     restrict: 'A',
12224                     replace: true,
12225                     scope: {
12226                         icon: '@attLoading',
12227                         progressStatus: '=?',
12228                         colorClass: '=?'
12229                     },
12230                     templateUrl: 'app/scripts/ng_js_att_tpls/loading/loading.html',
12231                     link: function(scope, element) {
12232                         var progressvalue = scope.progressStatus;
12233                         scope.progressStatus = Math.min(100, Math.max(0, progressvalue));
12234                         if($window.navigator.userAgent.indexOf("MSIE 8.")!==-1){
12235                             var shiftX = 0, shiftY = scope.progressStatus * 36;
12236                             element.css({
12237                                 'background-position-x' : shiftX,
12238                                 'background-position-y' : -shiftY
12239                             });
12240                         }
12241                     }
12242             };
12243         }]);
12244 angular.module('att.abs.modal', ['att.abs.utilities'])
12245 /**
12246  * A helper, internal data structure that acts as a map but also allows getting / removing
12247  * elements in the LIFO order
12248  */
12249   .factory('$$stackedMap', function () {
12250     return {
12251       createNew: function () {
12252         var stack = [];
12253
12254         return {
12255           add: function (key, value) {
12256             stack.push({
12257               key: key,
12258               value: value
12259             });
12260           },
12261           get: function (key) {
12262             for (var i = 0; i < stack.length; i++) {
12263               if (key === stack[i].key) {
12264                 return stack[i];
12265               }
12266             }
12267           },
12268           keys: function() {
12269             var keys = [];
12270             for (var i = 0; i < stack.length; i++) {
12271               keys.push(stack[i].key);
12272             }
12273             return keys;
12274           },
12275           top: function () {
12276             return stack[stack.length - 1];
12277           },
12278           remove: function (key) {
12279             var idx = -1;
12280             for (var i = 0; i < stack.length; i++) {
12281               if (key === stack[i].key) {
12282                 idx = i;
12283                 break;
12284               }
12285             }
12286             return stack.splice(idx, 1)[0];
12287           },
12288           removeTop: function () {
12289             return stack.splice(stack.length - 1, 1)[0];
12290           },
12291           length: function () {
12292             return stack.length;
12293           }
12294         };
12295       }
12296     };
12297   })
12298
12299 /**
12300  * A helper directive for the $modal service. It creates a backdrop element.
12301  */
12302   .directive('modalBackdrop', ['$timeout', function ($timeout) {
12303     return {
12304       restrict: 'EA',
12305       replace: true,
12306       templateUrl: 'app/scripts/ng_js_att_tpls/modal/backdrop.html',
12307       link: function (scope) {
12308         scope.animate = false;
12309         //trigger CSS transitions
12310         $timeout(function () {
12311           scope.animate = true;
12312         });
12313     }
12314     };
12315   }])
12316
12317   .directive('modalWindow', ['$modalStack','$timeout','$document', function ($modalStack,$timeout,$document) {
12318     return {
12319       restrict: 'EA',
12320       scope: {
12321         index: '@',
12322                 modalTitle: '@?'
12323       },
12324       replace: true,
12325       transclude: true,
12326       templateUrl: 'app/scripts/ng_js_att_tpls/modal/window.html',
12327       link: function (scope, element, attrs) {
12328         scope.windowClass = attrs.windowClass || '';
12329                 if (attrs['modalTitle'] && attrs['modalTitle']!=="") {
12330                         element[0].setAttribute('aria-label', attrs['modalTitle']);
12331                         element[0].removeAttribute('modal-title');
12332                 }
12333         $timeout(function () {
12334             // trigger CSS transitions
12335             scope.focusModalFlag = true;
12336             scope.animate = true;
12337         });
12338                 $document.on('focus keydown', function(e){
12339                     if (e.which ===9) {
12340                         String.prototype.contains = function(it) {
12341                             return this.indexOf(it) !== -1;
12342                         };
12343                         if (element[0] !== e.target && !element[0].contains( e.target )) {
12344                                 element[0].focus();
12345                         }
12346                         }
12347                 });
12348         scope.close = function (evt) {
12349             var modal = $modalStack.getTop();
12350             if (modal && modal.value.backdrop && modal.value.backdrop != 'static'  && (evt.target === evt.currentTarget)) {
12351             // Check if preventDefault exists due to lack of support for IE8
12352             if (evt.preventDefault) {
12353               evt.preventDefault();
12354               evt.stopPropagation();
12355           } else {
12356               evt.returnValue = false;
12357             }
12358             $modalStack.dismiss(modal.key, 'backdrop click');
12359           }
12360         };
12361       }
12362     };
12363   }])
12364
12365   .factory('$modalStack', ['$document', '$compile', '$rootScope', '$$stackedMap', 'events', 'keymap',
12366     function ($document, $compile, $rootScope, $$stackedMap, events, keymap) {
12367       var OPENED_MODAL_CLASS = 'modal-open';
12368       var backdropjqLiteEl, backdropDomEl;
12369       var backdropScope = $rootScope.$new(true);
12370       var openedWindows = $$stackedMap.createNew();
12371       var $modalStack = {};
12372       var modalLaunchingElement = undefined;
12373       function backdropIndex() {
12374         var topBackdropIndex = -1;
12375         var opened = openedWindows.keys();
12376         for (var i = 0; i < opened.length; i++) {
12377           if (openedWindows.get(opened[i]).value.backdrop) {
12378             topBackdropIndex = i;
12379           }
12380         }
12381         return topBackdropIndex;
12382       }
12383
12384       $rootScope.$watch(backdropIndex, function(newBackdropIndex){
12385         backdropScope.index = newBackdropIndex;
12386       });
12387
12388       function removeModalWindow(modalInstance) {
12389
12390         var body = $document.find('body').eq(0);
12391         var html = $document.find('html').eq(0);
12392         var modalWindow = openedWindows.get(modalInstance).value;
12393         //clean up the stack
12394         openedWindows.remove(modalInstance);
12395         ////remove window DOM element
12396         modalWindow.modalDomEl.remove();
12397         body.toggleClass(OPENED_MODAL_CLASS, openedWindows.length() > 0);
12398         html.css({overflow: 'scroll'});
12399
12400         //remove backdrop if no longer needed
12401         if (backdropDomEl && backdropIndex() == -1) {
12402           backdropDomEl.remove();
12403           backdropDomEl = undefined;
12404         }
12405         //destroy scope
12406         modalWindow.modalScope.$destroy();
12407           
12408         // Shift focus
12409         if (angular.isDefined(modalLaunchingElement) && modalLaunchingElement != null) {
12410             modalLaunchingElement.focus();
12411         }
12412       }
12413       $document.bind('keydown', function (evt) {
12414         var modal;
12415         if (evt.which === 27) {
12416           modal = openedWindows.top();
12417           if (modal && modal.value.keyboard) {
12418             $rootScope.$apply(function () {
12419               $modalStack.dismiss(modal.key);
12420             });
12421           }
12422         } else if (evt.keyCode === keymap.KEY.BACKSPACE) {
12423           var doPrevent = false;
12424           var d = evt.srcElement || evt.target;
12425           var type;
12426           if (d.type === undefined) { 
12427                 doPrevent = true;
12428           } else if (d.tagName.toUpperCase() === 'INPUT' && 
12429             ( (type = d.type.toUpperCase()) === 'TEXT' || 
12430               type === 'PASSWORD' || 
12431               type === 'FILE' ||
12432               type === 'SEARCH' ||
12433               type === 'EMAIL' ||
12434               type === 'NUMBER' ||
12435               type === 'DATE' ||
12436               type === 'TEL' ||
12437               type === 'URL' ||
12438               type === 'TIME')
12439             || d.tagName.toUpperCase() === 'TEXTAREA') {
12440                 doPrevent = d.readOnly || d.disabled;
12441           } else {
12442             doPrevent = true;
12443           }
12444           if (doPrevent) {
12445               events.preventDefault(evt);
12446           }
12447         }
12448       });
12449
12450       $modalStack.open = function (modalInstance, modal) {
12451           openedWindows.add(modalInstance, {
12452           deferred: modal.deferred,
12453           modalScope: modal.scope,
12454           backdrop: modal.backdrop,
12455           keyboard: modal.keyboard
12456         });
12457         
12458         //Before opening modal, find the focused element
12459         modalLaunchingElement = document.activeElement;
12460         
12461         var body = $document.find('body').eq(0);
12462         var html = $document.find('html').eq(0);
12463
12464         if (backdropIndex() >= 0 && !backdropDomEl) {
12465             backdropjqLiteEl = angular.element('<div modal-backdrop></div>');
12466             backdropDomEl = $compile(backdropjqLiteEl)(backdropScope);
12467             body.append(backdropDomEl);
12468         }
12469         var angularDomEl = angular.element('<div modal-window></div>');
12470         angularDomEl.attr('window-class', modal.windowClass);
12471         angularDomEl.attr('index', openedWindows.length() - 1);
12472                 angularDomEl.attr('modal-title', modal.modalTitle);
12473         angularDomEl.html(modal.content);
12474
12475         var modalDomEl = $compile(angularDomEl)(modal.scope);
12476         openedWindows.top().value.modalDomEl = modalDomEl;
12477         body.append(modalDomEl);
12478         body.addClass(OPENED_MODAL_CLASS);
12479         html.css({overflow: 'hidden'});
12480       };
12481
12482       $modalStack.close = function (modalInstance, result) {
12483         var modal = openedWindows.get(modalInstance);
12484         if (modal) {
12485           modal.value.deferred.resolve(result);
12486           removeModalWindow(modalInstance);
12487         }
12488       };
12489
12490       $modalStack.dismiss = function (modalInstance, reason) {
12491         var modalWindow = openedWindows.get(modalInstance).value;
12492         if (modalWindow) {
12493           modalWindow.deferred.reject(reason);
12494           removeModalWindow(modalInstance);
12495         }
12496       };
12497
12498       $modalStack.getTop = function () {
12499         return openedWindows.top();
12500       };
12501
12502       return $modalStack;
12503     }])
12504
12505   .provider('$modal', function () {
12506
12507     var $modalProvider = {
12508       options: {
12509         //can be also false or 'static'
12510         backdrop: true,
12511         keyboard: true
12512       },
12513       $get: ['$injector', '$rootScope', '$q', '$http', '$templateCache', '$controller', '$modalStack',
12514         function ($injector, $rootScope, $q, $http, $templateCache, $controller, $modalStack) {
12515             var $modal = {};
12516             function getTemplatePromise(options) {
12517             return options.template ? $q.when(options.template) :
12518               $http.get(options.templateUrl, {cache: $templateCache}).then(function (result) {
12519                 return result.data;
12520               });
12521           }
12522
12523           function getResolvePromises(resolves) {
12524             var promisesArr = [];
12525             angular.forEach(resolves, function (value) {
12526               if (angular.isFunction(value) || angular.isArray(value)) {
12527                 promisesArr.push($q.when($injector.invoke(value)));
12528               }
12529             });
12530             return promisesArr;
12531           }
12532           $modal.open = function (modalOptions) {
12533             var modalResultDeferred = $q.defer();
12534             var modalOpenedDeferred = $q.defer();
12535
12536             //prepare an instance of a modal to be injected into controllers and returned to a caller
12537             var modalInstance = {
12538               result: modalResultDeferred.promise,
12539               opened: modalOpenedDeferred.promise,
12540               close: function (result) {
12541                 $modalStack.close(modalInstance, result);
12542               },
12543               dismiss: function (reason) {
12544                 $modalStack.dismiss(modalInstance, reason);
12545               }
12546             };
12547             //merge and clean up options
12548             modalOptions = angular.extend({}, $modalProvider.options, modalOptions);
12549             modalOptions.resolve = modalOptions.resolve || {};
12550
12551             //verify options
12552             if (!modalOptions.template && !modalOptions.templateUrl) {
12553               throw new Error('One of template or templateUrl options is required.');
12554             }
12555
12556             var templateAndResolvePromise =
12557               $q.all([getTemplatePromise(modalOptions)].concat(getResolvePromises(modalOptions.resolve)));
12558               templateAndResolvePromise.then(function(tplAndVars) {
12559               var modalScope = (modalOptions.scope || $rootScope).$new();
12560               modalScope.$close = modalInstance.close;
12561               modalScope.$dismiss = modalInstance.dismiss;
12562
12563               var ctrlInstance, ctrlLocals = {};
12564               var resolveIter = 1;
12565
12566               //controllers
12567               if (modalOptions.controller) {
12568                 ctrlLocals.$scope = modalScope;
12569                 ctrlLocals.$modalInstance = modalInstance;
12570                 angular.forEach(modalOptions.resolve, function (value, key) {
12571                   ctrlLocals[key] = tplAndVars[resolveIter++];
12572                 });
12573
12574                 ctrlInstance = $controller(modalOptions.controller, ctrlLocals);
12575               }
12576
12577               $modalStack.open(modalInstance, {
12578                 scope: modalScope,
12579                 deferred: modalResultDeferred,
12580                 content: tplAndVars[0],
12581                 backdrop: modalOptions.backdrop,
12582                 keyboard: modalOptions.keyboard,
12583                 windowClass: modalOptions.windowClass,
12584                                 modalTitle: modalOptions.modalTitle
12585               });
12586
12587             }, function(reason) {
12588               modalResultDeferred.reject(reason);
12589             });
12590
12591             templateAndResolvePromise.then(function () {
12592               modalOpenedDeferred.resolve(true);
12593             }, function () {
12594               modalOpenedDeferred.reject(false);
12595             });
12596
12597             return modalInstance;
12598           };
12599
12600           return $modal;
12601         }]
12602     };
12603
12604     return $modalProvider;
12605   })
12606
12607 .directive("simpleModal", ["$modal", function($modal) {
12608         return {
12609             restrict: 'EA',
12610             scope: {
12611                 simpleModal: '@',
12612                 backdrop:'@',
12613                 keyboard:'@',
12614                 modalOk:'&',
12615                 modalCancel:'&',
12616                 windowClass:'@',
12617                 controller:'@',
12618                                 modalTitle: '@?'
12619             },
12620             link: function(scope, elm) {
12621                 elm.bind('click', function(ev) {
12622                     ev.preventDefault();
12623                     if (angular.isDefined(elm.attr("href")) && elm.attr("href") !== "") {
12624                         scope.simpleModal = elm.attr("href");
12625                     }
12626
12627                     scope.backdrop === "false" ? scope.backdropclick = 'static' : scope.backdropclick = true;
12628                     scope.keyboard === "false" ? scope.keyboardev = false : scope.keyboardev = true;
12629
12630                     $modal.open({
12631                         templateUrl: scope.simpleModal,
12632                         backdrop:scope.backdropclick,
12633                         keyboard:scope.keyboardev,
12634                         windowClass:scope.windowClass,
12635                         controller: scope.controller,
12636                                                 modalTitle: scope.modalTitle
12637                     }).result.then(scope.modalOk, scope.modalCancel);
12638                 });
12639             }
12640         };
12641     }])
12642
12643 .directive('tabbedItem', ['$modal', '$log',function ($modal, $log){
12644     return {
12645         restrict: 'AE',
12646         replace: true,
12647         scope: {
12648             items: "=items",
12649             controller: "@",
12650             templateId:"@",
12651                         modalTitle: '@?'
12652         },
12653         templateUrl: 'app/scripts/ng_js_att_tpls/modal/tabbedItem.html',
12654         controller: ['$scope', '$rootScope', '$attrs', function ($scope) {
12655                 $scope.clickTab = function (index) {
12656                     for (var i = 0; i < $scope.items.length; i++) {
12657                         if (i === index) {
12658                             $scope.items[i].isTabOpen = true;
12659                             $scope.items[i].showData = true;
12660                         }
12661                         else {
12662                             $scope.items[i].isTabOpen = false;
12663                             $scope.items[i].showData = false;
12664                         }
12665                     }
12666                     var modalInstance = $modal.open({
12667                         templateUrl: $scope.templateId,
12668                         controller: $scope.controller,
12669                         windowClass: 'tabbedOverlay_modal',
12670                                                 modalTitle: $scope.modalTitle,
12671                         resolve: {
12672                             items: function () {
12673                                 return $scope.items;
12674                             }
12675                         }
12676                     });
12677                     modalInstance.result.then(function (selectedItem) {
12678                         $scope.selected = selectedItem;
12679                     }, function () {
12680                         $log.info('Modal dismissed at: ' + new Date());
12681                     });
12682                 };
12683                 $scope.isActiveTab = function (index) {
12684                     return $scope.items && $scope.items[index] && $scope.items[index].isTabOpen;
12685                 };
12686             }]
12687                 };
12688 }])
12689
12690 .directive('tabbedOverlay', [function () {
12691     return {
12692         restrict: 'AE',
12693         replace: true,
12694         scope: {
12695             items: "="
12696         },
12697         transclude: true,
12698         templateUrl: 'app/scripts/ng_js_att_tpls/modal/tabbedOverlayItem.html',
12699         controller: ['$scope', function ($scope) {
12700                 $scope.clickTab = function (index) {
12701                     for (var i = 0; i < $scope.items.length; i++) {
12702                         if (i === index) {
12703                             $scope.items[i].isTabOpen = true;
12704                             $scope.items[i].showData = true;
12705                         }
12706                         else {
12707                             $scope.items[i].isTabOpen = false;
12708                             $scope.items[i].showData = false;
12709                         }
12710                     }
12711                 };
12712                 $scope.isActiveTab = function (index) {
12713                     return $scope.items && $scope.items[index] && $scope.items[index].isTabOpen;
12714                 };
12715             }]
12716     };
12717 }]);
12718 angular.module('att.abs.pagination', ['att.abs.utilities'])
12719 .directive('attPagination', [ function() {
12720      return {
12721         restrict: 'EA',
12722         scope: {
12723             totalPages: '=',
12724             currentPage: '=',
12725             showInput: '=',
12726             clickHandler: '=?'
12727         },
12728         replace: true,
12729         templateUrl: 'app/scripts/ng_js_att_tpls/pagination/pagination.html',
12730         link: function(scope) {
12731             scope.focusedPage;
12732             scope.$watch('totalPages', function(value) {
12733                 if(angular.isDefined(value) && value !== null){
12734                     scope.pages = [];
12735                     if (value < 1) {
12736                         scope.totalPages = 1;
12737                         return;
12738                     }
12739                     if (value <= 7) {
12740                         for (var i = 1; i <= value; i++) {
12741                             scope.pages.push(i);
12742                         }
12743                     } else if (value > 7) {
12744                         var midVal = Math.ceil(value / 2);
12745                         scope.pages = [midVal - 1, midVal, midVal + 1];
12746                     }
12747                     currentPageChanged(1);
12748                 }
12749             });
12750             scope.$watch('currentPage', function(value) {
12751                 currentPageChanged(value);
12752             });
12753             var callbackHandler = function(num) {
12754                 if (angular.isFunction(scope.clickHandler)){
12755                     scope.clickHandler(num);
12756                 }
12757             };
12758             function currentPageChanged(value) {
12759                 if (angular.isDefined(value) && value !== null) {
12760                     if (!value || value < 1) {
12761                         value = 1;
12762                     }
12763                     if (value > scope.totalPages) {
12764                         value = scope.totalPages;
12765                     }
12766                     if(scope.currentPage !== value) {
12767                         scope.currentPage = value;
12768                         callbackHandler(scope.currentPage);
12769                     }
12770                     if (scope.totalPages > 7) {
12771                         if (value < scope.pages[0] && value > 3) {
12772                             scope.pages = [value, value + 1, value + 2];
12773                         } else if (value > scope.pages[2] && value < scope.totalPages - 2) {
12774                            scope.pages = [value - 2, value - 1, value];
12775                         } else if (value <= 3) {
12776                              scope.pages = [1, 2, 3];
12777                         } else if (value >= scope.totalPages - 2) {
12778                              scope.pages = [scope.totalPages - 2, scope.totalPages - 1, scope.totalPages];
12779                         }
12780                     }
12781                 }
12782             }
12783             scope.next = function(event) {
12784                 event.preventDefault();
12785                 if (scope.currentPage < scope.totalPages) {
12786                     scope.currentPage += 1;
12787                     callbackHandler(scope.currentPage);
12788                 }
12789             };
12790             scope.prev = function(event) {
12791                 event.preventDefault();
12792                 if (scope.currentPage > 1) {
12793                     scope.currentPage -= 1;
12794                     callbackHandler(scope.currentPage);
12795                 }
12796             };
12797             scope.selectPage = function(value, event) {
12798                 event.preventDefault();
12799                 scope.currentPage = value;
12800                 scope.focusedPage = value;
12801                 callbackHandler(scope.currentPage);
12802             };
12803             scope.checkSelectedPage = function(value) {
12804                 if(scope.currentPage === value) {
12805                     return true;
12806                 }
12807                 return false;
12808             };
12809             scope.isFocused = function(page) {
12810                  return scope.focusedPage === page;
12811             };
12812         }
12813     };
12814 }]);
12815
12816 angular.module('att.abs.paneSelector',['att.abs.utilities'])
12817 .constant('paneGroupConstants',{
12818     SIDE_WIDTH_DEFAULT: '33%',
12819     INNER_PANE_DEFAULT: '67%',
12820     SIDE_PANE_ID: 'sidePane',
12821     NO_DRILL_DOWN: 'none'
12822 })
12823 .factory('animation', function(){
12824     return TweenLite;
12825 }).directive('attPaneAccessibility',['keymap','$window',function(keymap,$window) {
12826         return{
12827             restrict: 'A',
12828             require: ['^?sidePane','^?innerPane'],
12829             link: function (scope, elem,attr,ctrl) {
12830                 var sidepaneCtrl = ctrl[0],innerPaneCtrl = ctrl[1],ieFlag=false;
12831                 scope.ie = (function () {
12832                     var undef,v = 3,div = document.createElement('div'),
12833                             all = div.getElementsByTagName('i');
12834                     while (
12835                             div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i>< ![endif]-->',
12836                             all[0]
12837                             );
12838                     return v > 4 ? v : undef;
12839                 }());
12840                  if(scope.ie === 8){
12841                         ieFlag = true;
12842                     }
12843                     else{
12844                         ieFlag = false;
12845                     }
12846                 elem.bind('keydown',function(ev){
12847                     if (keymap.isAllowedKey(ev.keyCode) || keymap.isControl(ev) || keymap.isFunctionKey(ev)) {
12848                         ev.preventDefault();
12849                         ev.stopPropagation();
12850                         var el;
12851                     switch (ev.keyCode) {
12852                         case keymap.KEY.DOWN:
12853                             el = angular.element(elem[0])[0];
12854                             if(el && el.nextElementSibling){
12855                                 el.nextElementSibling.focus();
12856                             }
12857                             /*IE8 fix*/
12858                             if(ieFlag){
12859                                 do {
12860                                     if (el && el.nextSibling){
12861                                         el = el.nextSibling;
12862                                     }
12863                                     else{
12864                                         break;
12865                                     }
12866                                 } while (el && el.tagName !== 'DIV');
12867                                 el.focus();
12868                             }
12869                             break;
12870                         case keymap.KEY.UP:
12871                             el = angular.element(elem[0])[0];
12872                             if(el && el.previousElementSibling){
12873                                 el.previousElementSibling.focus();
12874                             }
12875                              /*IE8 fix*/
12876                              if(ieFlag){
12877                                 do {
12878                                     if (el && el.previousSibling){
12879                                         el = el.previousSibling;
12880                                     }
12881                                     else{
12882                                         break;
12883                                     }
12884                                 } while (el && el.tagName !== 'DIV');
12885                                 el.focus();
12886                             }
12887                             break;
12888                         case keymap.KEY.RIGHT:
12889                             if(angular.isDefined(sidepaneCtrl)){
12890                                 el = sidepaneCtrl.getElement()[0];
12891                             }
12892                             if(angular.isDefined(innerPaneCtrl)){
12893                                 el = innerPaneCtrl.getElement()[0];
12894                             }
12895                             do {
12896                                 if (el && el.nextElementSibling){
12897                                     el = el.nextElementSibling;
12898                                 }
12899                                 else{
12900                                     break;
12901                                 }
12902                             }while(window.getComputedStyle(el, null).getPropertyValue("display") === 'none');
12903                             /*IE8 fix*/
12904                             if(ieFlag){
12905                                 do {
12906                                     if (el && el.nextSibling){
12907                                         el = el.nextSibling;
12908                                     }
12909                                     else{
12910                                         break;
12911                                     }
12912                                 }while ((el && el.tagName == 'DIV') && el.currentStyle['display'] == 'none');
12913                             }
12914                            if (el){
12915                             el.querySelector("[att-pane-accessibility]").focus();
12916                         }
12917                         break;
12918                         case keymap.KEY.LEFT:
12919                             if(angular.isDefined(sidepaneCtrl)){
12920                                 el = sidepaneCtrl.getElement()[0];
12921                             }
12922                             if(angular.isDefined(innerPaneCtrl)){
12923                                 el = innerPaneCtrl.getElement()[0];
12924                             }
12925                             do {
12926                                 if (el && el.previousElementSibling){
12927                                     el = el.previousElementSibling;
12928                                 }
12929                                 else{
12930                                     break;
12931                                 }
12932                                 }while (window.getComputedStyle(el, null).getPropertyValue("display") == 'none');
12933                            
12934                             /*IE8 fix*/
12935                             if(ieFlag){
12936                                 do {
12937                                     if (el && el.previousSibling){
12938                                         el = el.previousSibling;
12939                                     }
12940                                     else{
12941                                         break;
12942                                     }
12943                                 }while((el && el.tagName == 'DIV') && el.currentStyle['display'] == 'none');   
12944                             }
12945                             if (el){
12946                             el.querySelector("[att-pane-accessibility]").focus();
12947                         }
12948                         break;
12949                         default:
12950                             break;
12951                         }
12952                     }
12953                 });
12954             }
12955         };
12956 }])
12957 .directive('sideRow', [function(){
12958     return {
12959         restrict: 'A',
12960         replace:true,
12961         require: ['^sidePane','^paneGroup'],
12962         link: function(scope,element,attr,ctrls){
12963             var sidePaneCtrl = ctrls[0];
12964             var paneGroupCtrl = ctrls[1];
12965             if(scope.$first){
12966                 /*
12967                 Reset the sidePaneId array if a new
12968                 set of ngRepeat data appeared
12969                 */
12970                 sidePaneCtrl.sidePaneIds = [];
12971             }
12972             var paneId =attr['paneId'];
12973             var drillDownTo = attr['drillDownTo'];
12974             sidePaneCtrl.sidePaneRows.push({'paneId':paneId, 'drillDownTo':drillDownTo});
12975             element.on('click', function(){
12976                 sidePaneCtrl.currentSelectedRowPaneId = paneId;
12977                 paneGroupCtrl.slideOutPane(paneId,true);
12978             });
12979         }
12980     };
12981 }])
12982 .controller('SidePaneCtrl',['$scope', '$element','animation', 'paneGroupConstants',
12983  function($scope,$element,animation, paneGroupConstants){
12984         this.getElement = function(){
12985             return $element;
12986         };
12987         this.sidePaneTracker = {};
12988         this.currentWidth = paneGroupConstants.SIDE_WIDTH_DEFAULT;
12989         this.paneId = paneGroupConstants.SIDE_PANE_ID;
12990         this.currentSelectedRowPaneId;
12991         this.drillDownToMapper = {};
12992         this.sidePaneRows = [];
12993         this.init = function(){
12994             var sidePaneRows = this.sidePaneRows;
12995             if(sidePaneRows){
12996                 for(var index in sidePaneRows){
12997                     if (sidePaneRows.hasOwnProperty(index)) {
12998                         var paneId = sidePaneRows[index].paneId;
12999                         var drillDownTo = sidePaneRows[index].drillDownTo;
13000                         this.drillDownToMapper[paneId] = drillDownTo;
13001                         if(index == 0){
13002                             this.currentSelectedRowPaneId = paneId;
13003                             this.sidePaneTracker[paneId] = [];
13004                         }
13005                     }
13006                 }
13007             }
13008         };
13009         this.getSidePanesList = function(){
13010             return this.sidePaneTracker[this.currentSelectedRowPaneId];
13011         };
13012         this.addToSidePanesList = function(newPaneId){
13013             if(this.sidePaneTracker[this.currentSelectedRowPaneId] === undefined){
13014                 this.sidePaneTracker[this.currentSelectedRowPaneId] = [];
13015             }
13016             else if(newPaneId){
13017                 this.sidePaneTracker[this.currentSelectedRowPaneId].push(newPaneId);
13018             }
13019         };
13020         this.setWidth = function(val){
13021             if(val){
13022                 this.currentWidth = val;
13023             }
13024             animation.set($element,{width:this.currentWidth});
13025         };
13026         this.resizeWidth = function(val){
13027             if(val){
13028                 this.currentWidth = val;
13029             }
13030             animation.to($element,.5,{width:val});
13031         };
13032
13033 }])
13034 .directive('sidePane', ['paneGroupConstants', function(paneGroupConstants){
13035     return {
13036         restrict: 'EA',
13037         transclude: true,
13038         replace: true,
13039         templateUrl: 'app/scripts/ng_js_att_tpls/paneSelector/sidePane.html',
13040         require: ['^paneGroup', 'sidePane'],
13041         controller: 'SidePaneCtrl',
13042         scope:{},
13043         link: function(scope,element,attr, ctrls){
13044             var paneGroupCtrl = ctrls[0];
13045             var sidePaneCtrl = ctrls[1];
13046             paneGroupCtrl.addPaneCtrl(paneGroupConstants.SIDE_PANE_ID, sidePaneCtrl);
13047         }
13048     };
13049 }])
13050 .directive('drillDownRow', ['$parse', 'paneGroupConstants',function($parse,paneGroupConstants){
13051     return {
13052         restrict: 'A',
13053         replace:true,
13054         require: ['^innerPane','^paneGroup'],
13055         link: function(scope,element,attr,ctrls){
13056             var innerPaneCtrl = ctrls[0];
13057             var paneGroupCtrl = ctrls[1];
13058             element.on('click', function(){
13059                     var drillDownTo = innerPaneCtrl.drillDownTo;
13060                     if(innerPaneCtrl.drillDownTo !== paneGroupConstants.NO_DRILL_DOWN){
13061                         paneGroupCtrl.slideOutPane(drillDownTo);
13062                     }
13063                     element[0].focus();
13064             });
13065         }
13066     };
13067 }])
13068 .controller('InnerPaneCtrl', ['$scope', '$element','animation', 'paneGroupConstants',
13069         function($scope,$element,animation,paneGroupConstants){
13070         this.getElement = function(){
13071             return $element;
13072         };
13073         this.paneId = $scope.paneId;
13074         this.drillDownTo;
13075         this.currentWidth = paneGroupConstants.INNER_PANE_DEFAULT;
13076         this.setWidth = function(val){
13077             if(val){
13078                 this.currentWidth = val;
13079             }
13080             animation.set($element,{width:this.currentWidth});
13081         };
13082         this.resizeWidth = function(val,callback){
13083             animation.to($element,.25,{width:val,onComplete: callback});
13084         };
13085         this.displayNone = function(){
13086             animation.set($element, {display:'none'});
13087         };
13088         this.displayBlock = function(){
13089             animation.set($element,{display:'block'});
13090             if(this){
13091                 this.hideRightBorder();
13092             }
13093         };
13094         this.floatLeft = function(){
13095             animation.set($element,{float:'left'});
13096         };
13097         this.hideLeftBorder = function(){
13098             animation.set($element, {borderLeftWidth: '0px'});
13099         };
13100         this.showLeftBorder = function(){
13101             animation.set($element,{borderLeftWidth: '1px'});
13102         };
13103         this.hideRightBorder = function(){
13104             animation.set($element,{borderRightWidth: '0px'});
13105         };
13106         this.showRightBorder = function(){
13107             animation.set($element, {borderRightWidth: '1px'});
13108         };
13109         this.slideFromRight = function(){
13110             animation.set($element, {float:'right'});
13111             animation.set($element, {width: this.currentWidth});
13112         };
13113         this.startOpen = function(){
13114             return $scope.startOpen;
13115         };
13116 }])
13117 .directive('innerPane', function(){
13118     return {
13119         restrict: 'EA',
13120         replace: true,
13121         transclude: true,
13122         templateUrl: 'app/scripts/ng_js_att_tpls/paneSelector/innerPane.html',
13123         require: ['^paneGroup', 'innerPane'],
13124         controller: 'InnerPaneCtrl',
13125         scope:{
13126                 paneId:'@'
13127         },
13128         link: function(scope,element,attr,ctrls){
13129             if(attr.startOpen === ""){
13130                 scope.startOpen  = true;
13131             }
13132             var paneGroupCtrl = ctrls[0];
13133             var innerPaneCtrl = ctrls[1];
13134             paneGroupCtrl.addPaneCtrl(scope.paneId,innerPaneCtrl);
13135         }
13136     };
13137 })
13138 .controller('PaneGroupCtrl', ['$scope', '$element', 'paneGroupConstants',function($scope,$element,paneGroupConstants){
13139         this.panes = {};
13140         this.accountLevelPaneModel = [];
13141         this.title = $scope.title;
13142         this.init = function(){
13143                 var sidePane = this.panes[paneGroupConstants.SIDE_PANE_ID];
13144                 if(sidePane){
13145                     sidePane.init();
13146
13147                     //Show the other panes that may be set to startOpen
13148                     //numOpen starts at 1 because of the side pane
13149                     var numOpen = 1;
13150                     var key;
13151                     for(key in this.panes){
13152                         if(this.panes[key].startOpen && this.panes[key].startOpen()){
13153                                 numOpen++;
13154                         }
13155                     }
13156                     var width;
13157                     if(numOpen >= 3){
13158                         width = ((100/numOpen)) + '%';
13159                     }
13160                     if(this.panes[sidePane.currentSelectedRowPaneId])
13161                     {
13162                         if(width){
13163                             sidePane.setWidth(width);
13164                             this.panes[sidePane.currentSelectedRowPaneId].setWidth(width);
13165                         }
13166                         else{
13167                             sidePane.setWidth();
13168                             this.panes[sidePane.currentSelectedRowPaneId].setWidth();
13169                         }
13170                         this.panes[sidePane.currentSelectedRowPaneId].displayBlock();
13171                         for(key in this.panes){
13172                             if(key !== paneGroupConstants.SIDE_PANE_ID && key !== sidePane.currentSelectedRowPaneId){
13173                                 this.panes[key].displayNone();
13174                             }
13175                                 this.panes[key].drillDownTo = sidePane.drillDownToMapper[key];
13176                         }
13177                     }
13178                     openOtherPanesOnStart(sidePane, this.panes);
13179                 }
13180
13181                 function openOtherPanesOnStart(sidePane, panes){
13182                     //Build an array of the panes that need to be out
13183                     var otherPanesStartOpened = [];
13184                     var index;
13185                     for(index in sidePane.sidePaneRows){
13186                         if (sidePane.sidePaneRows.hasOwnProperty(index)) {
13187                             var pane = sidePane.sidePaneRows[index];
13188
13189                             //Skip the first pane row since we handled it in the begining
13190                             if(index > 0 && panes[pane.paneId].startOpen && panes[pane.paneId].startOpen()){
13191                                     otherPanesStartOpened.push(pane);
13192                                     //Remember the panes that are opened for the first pane row Index
13193                                     sidePane.addToSidePanesList(pane.paneId);
13194                             }
13195                         }
13196                     }
13197
13198                     if(width){
13199                         for(index in otherPanesStartOpened){
13200                             if (otherPanesStartOpened.hasOwnProperty(index)) {
13201                                 var paneId = otherPanesStartOpened[index].paneId;
13202                                 var paneCtrl = panes[paneId];
13203                                 if(paneCtrl && paneCtrl.setWidth && paneCtrl.displayBlock){
13204                                     paneCtrl.setWidth(width);
13205                                     paneCtrl.displayBlock();
13206                                 }
13207                             }
13208                         }
13209                     }
13210
13211                 }
13212         };
13213
13214         /*
13215           Resets all the panels to their original positions at the end of a sidebar click
13216           By setting the sideBar to its default width
13217           Setting all panes to float left and displaynone
13218           Setting the pane that was clicked to default width and slide right
13219         */
13220
13221         this.resetPanes = function(){
13222             for(var key in this.panes){
13223                 if(this.panes.hasOwnProperty(key)){
13224                     var pane = this.panes[key];
13225                     if(pane && (pane.paneId !== paneGroupConstants.SIDE_PANE_ID)){
13226                             pane.floatLeft();
13227                             pane.displayNone();
13228                     }
13229                 }
13230             }
13231
13232             if(this.panes[paneGroupConstants.SIDE_PANE_ID]){
13233                 this.panes[paneGroupConstants.SIDE_PANE_ID].setWidth(paneGroupConstants.SIDE_WIDTH_DEFAULT);
13234             }
13235         };
13236
13237         this.addPaneCtrl = function(paneId,paneCtrl){
13238             this.panes[paneId] = paneCtrl;
13239         };
13240
13241         this._slideOutPane = function(paneId,isFromSidePane){
13242                 this.resetPanes();
13243                 //Check current side pane stack to see how many panes are already open for that side pane choice
13244                 //then add the new pane that needs to be there
13245                 var panesList;
13246                 if(isFromSidePane){
13247
13248                     //Check if the side pane id has already been clicked
13249                     if(this.panes[paneGroupConstants.SIDE_PANE_ID]){
13250                         panesList = this.panes[paneGroupConstants.SIDE_PANE_ID].getSidePanesList();
13251                     }
13252                     if(!panesList){
13253                         if(this.panes && this.panes[paneGroupConstants.SIDE_PANE_ID] && this.panes[paneId]){
13254                             this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId = paneId;
13255                             this.panes[paneGroupConstants.SIDE_PANE_ID].addToSidePanesList();
13256
13257                             this.panes[paneId].slideFromRight();
13258                             this.panes[paneId].displayBlock();
13259
13260                             this.panes[paneId].setWidth(paneGroupConstants.INNER_PANE_DEFAULT);
13261                         }
13262                     }
13263                     else if(this.panes && this.panes[paneGroupConstants.SIDE_PANE_ID]){
13264                                 //Restore the panes based on the panelist
13265                         if(panesList.length === 0 && this.panes[paneId]){
13266                             //Only one pane is out
13267                             this.panes[paneGroupConstants.SIDE_PANE_ID].setWidth(paneGroupConstants.SIDE_WIDTH_DEFAULT);
13268                             this.panes[paneId].displayBlock();
13269                             this.panes[paneId].setWidth(paneGroupConstants.INNER_PANE_DEFAULT);
13270                         }
13271                         else{
13272                             //Multiple panes out
13273                             var numPanes = panesList.length + 2;
13274                             var width = ((100/numPanes)) + '%';
13275                             this.panes[paneGroupConstants.SIDE_PANE_ID].setWidth(width);
13276
13277                             //Set the sidePanes pane
13278                             //set the panes children list
13279                             if(this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId]){
13280                                 this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId].displayBlock();
13281                                 this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId].setWidth(width);
13282                             }
13283                             for(var i in panesList){
13284                                 if(this.panes[panesList[i]]){
13285                                         this.panes[panesList[i]].displayBlock();
13286                                         this.panes[panesList[i]].setWidth(width);
13287                                 }
13288                             }
13289                         }
13290                     }
13291                 }
13292                 else{
13293
13294                     //Have to check the paneId that was given and where it is drilling down to
13295                     var isPaneInStack = false;
13296                     var stackPaneList;
13297                     if(this.panes[paneGroupConstants.SIDE_PANE_ID]){
13298                         stackPaneList = this.panes[paneGroupConstants.SIDE_PANE_ID].getSidePanesList();
13299                     }
13300                     for(var j in stackPaneList){
13301                         if(stackPaneList.hasOwnProperty(j)){
13302                             var pId = stackPaneList[j];
13303                             if(pId === paneId){
13304                                 isPaneInStack = true;
13305                                 break;
13306                             }
13307                         }
13308                     }
13309                     if(!isPaneInStack && this.panes[paneGroupConstants.SIDE_PANE_ID]){
13310                         this.panes[paneGroupConstants.SIDE_PANE_ID].addToSidePanesList(paneId);
13311                     }
13312                     var sidePanesListLength;
13313                     if(this.panes[paneGroupConstants.SIDE_PANE_ID]){
13314                         sidePanesListLength = this.panes[paneGroupConstants.SIDE_PANE_ID].getSidePanesList().length;
13315                     }
13316                     var numberPanes = sidePanesListLength + 2;
13317                     var widthToSet = ((100/numberPanes)) + '%';
13318                     if(this.panes[paneGroupConstants.SIDE_PANE_ID]){
13319                         this.panes[paneGroupConstants.SIDE_PANE_ID].setWidth(widthToSet);
13320                     }
13321                     var slideInPaneId;
13322
13323                     if(this.panes[paneGroupConstants.SIDE_PANE_ID]){
13324                             slideInPaneId = this.panes[paneGroupConstants.SIDE_PANE_ID].getSidePanesList()[sidePanesListLength - 1];
13325                     }
13326
13327                     var that = this;
13328
13329                     if(that.panes[paneGroupConstants.SIDE_PANE_ID]){
13330                             panesList = that.panes[paneGroupConstants.SIDE_PANE_ID].getSidePanesList();
13331                     }
13332
13333                     for(var p in panesList){
13334                         if(panesList.hasOwnProperty(p)){
13335                             var paneListPaneId = panesList[p];
13336                             var pane = this.panes[paneListPaneId];
13337                             if(paneListPaneId !== slideInPaneId && pane){
13338                                     pane.setWidth(widthToSet);
13339                                     pane.displayBlock();
13340                                     pane.floatLeft();
13341                             }
13342                         }
13343                     }
13344
13345                     if(this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId]){
13346                             this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId].displayBlock();
13347                             this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId].showRightBorder();
13348
13349                             this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId].resizeWidth(widthToSet,function(){
13350
13351                                     if(that.panes[slideInPaneId] && that.panes[that.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId]){
13352                                             that.panes[that.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId].hideRightBorder();
13353                                             that.panes[slideInPaneId].setWidth(widthToSet);
13354                                             that.panes[slideInPaneId].slideFromRight();
13355                                             that.panes[slideInPaneId].displayBlock();
13356                                             that.panes[slideInPaneId].floatLeft();
13357                                     }
13358
13359                             });
13360                     }
13361                 }
13362         };
13363
13364         this.slideOutPane = function(paneId,isFromSidePane){
13365             this._slideOutPane(paneId,isFromSidePane);
13366         };
13367 }])
13368 .directive('paneGroup', ['$timeout',function($timeout){
13369         return {
13370                 restrict: 'EA',
13371                 transclude: true,
13372                 replace: true,
13373                 templateUrl: 'app/scripts/ng_js_att_tpls/paneSelector/paneGroup.html',
13374                 scope:{
13375                 },
13376                 controller: 'PaneGroupCtrl',
13377                 link: function(scope,element,attr,ctrl){
13378                         $timeout(initialize,100);
13379                         function initialize(){
13380                                 ctrl.init();
13381                         }
13382                 }
13383         };
13384 }]);
13385 angular.module('att.abs.tooltip', ['att.abs.position', 'att.abs.utilities', 'ngSanitize'])
13386         // The default options tooltip and popover.
13387         .constant('tooltipDefaultOptions', {
13388             placement: 'above',
13389             animation: false,
13390             popupDelay: 0,
13391             stylett: 'dark',
13392             appendToBody: true
13393         })
13394
13395         /**
13396          * The $tooltip service creates tooltip- and popover-like directives as well as
13397          * houses global options for them.
13398          */
13399         .provider('$tooltip', ['tooltipDefaultOptions', function(tooltipDefaultOptions) {
13400
13401             // Default hide triggers for each show trigger
13402             var triggerMap = {
13403                 'mouseenter': 'mouseleave',
13404                 'click': 'click',
13405                 'focus': 'blur',
13406                 'mouseover':'mouseout'
13407             };
13408
13409             // The options specified to the provider globally.
13410             var globalOptions = {};
13411
13412             this.options = function(value) {
13413                 angular.extend(globalOptions, value);
13414             };
13415
13416             /**
13417              * This allows you to extend the set of trigger mappings available. E.g.:
13418              *
13419              *   $tooltipProvider.setTriggers( 'openTrigger': 'closeTrigger' );
13420              */
13421             this.setTriggers = function(triggers) {
13422                 angular.extend(triggerMap, triggers);
13423             };
13424
13425             /**
13426              * This is a helper function for translating camel-case to snake-case.
13427              */
13428             function snakeCase(name) {
13429                 var regexp = /[A-Z]/g;
13430                 var separator = '-';
13431                 return name.replace(regexp, function(letter, pos) {
13432                     return (pos ? separator : '') + letter.toLowerCase();
13433                 });
13434             }
13435
13436             /**
13437              * Returns the actual instance of the $tooltip service.
13438              */
13439             this.$get = ['$window', '$compile', '$timeout', '$parse', '$document', '$position', '$interpolate', '$attElementDetach', function($window, $compile, $timeout, $parse, $document, $position, $interpolate, $attElementDetach) {
13440                     return function (type, prefix, defaultTriggerShow) {
13441                         var options = angular.extend({}, tooltipDefaultOptions, globalOptions);
13442                         /**
13443                          * Returns an object of show and hide triggers.
13444                          *
13445                          * If a trigger is supplied,
13446                          * it is used to show the tooltip; otherwise, it will use the `trigger`
13447                          * option passed to the `$tooltipProvider.options` method; else it will
13448                          * default to the trigger supplied to this directive factory.
13449                          *
13450                          * The hide trigger is based on the show trigger. If the `trigger` option
13451                          * was passed to the `$tooltipProvider.options` method, it will use the
13452                          * mapped trigger from `triggerMap` or the passed trigger if the map is
13453                          * undefined; otherwise, it uses the `triggerMap` value of the show
13454                          * trigger; else it will just use the show trigger.
13455                          */
13456                         function getTriggers(trigger) {
13457                             var show = trigger || options.trigger || defaultTriggerShow;
13458                             var hide = triggerMap[show] || show;
13459                             return {
13460                                 show: show,
13461                                 hide: hide
13462                             };
13463                         }
13464
13465                         var directiveName = snakeCase(type);
13466
13467                         var startSym = $interpolate.startSymbol();
13468                         var endSym = $interpolate.endSymbol();
13469
13470                         return {
13471                             restrict: 'EA',
13472                             scope: true,
13473                             link: function (scope, element, attrs) {
13474                                 /* Allows a developer to force element to be non-tabable */
13475                                 if (!element.attr('tabindex')) {
13476                                     element.attr('tabindex', '0');
13477                                 } 
13478
13479                                 var isElementHovered = false;
13480                                 element.bind('mouseenter', function(){
13481                                     isElementHovered = true;
13482                                     element.removeAttr('title');
13483                                 });
13484                                 element.bind('mouseleave', function(){
13485                                     isElementHovered = false;
13486                                  //   setTooltipAriaLabel();
13487                                 });
13488
13489                                 /* We store our attributes on our scope so any user of $tooltip service can access attributes */
13490                                 scope.parentAttrs = attrs;
13491                                 var template =
13492                                         '<div ' + directiveName + '-popup ' +
13493                                         'title="' + startSym + 'tt_title' + endSym + '" ' +
13494                                         'content="' + startSym + 'tt_content' + endSym + '" ' +
13495                                         'placement="' + startSym + 'tt_placement' + endSym + '" ' +
13496                                         'animation="tt_animation()" ' +
13497                                         'is-open="tt_isOpen" ' +
13498                                         'stylett="' + startSym + 'tt_style' + endSym + '" ' +
13499                                         '>' +
13500                                         '</div>';
13501
13502                                 var tooltip = $compile(template)(scope);
13503                                 var transitionTimeout;
13504                                 var popupTimeout;
13505                                 var $body;
13506                                 var appendToBody = angular.isDefined(options.appendToBody) ? options.appendToBody : false;
13507                                 var triggers = getTriggers(undefined);
13508                                 var hasRegisteredTriggers = false;
13509                                 var hasEnableExp = angular.isDefined(attrs[prefix + 'Enable']);
13510                                 var tooltipOffset = 0;
13511                                 var tooltipAriaLabelDefined = false;
13512
13513                                 // By default, the tooltip is not open.
13514                                 // add ability to start tooltip opened
13515                                 scope.tt_isOpen = false;
13516
13517                                 //Adding a scope watch, to remove the created popup from DOM, incase it is updated outside the provider code.
13518                                 scope.$watch('tt_isOpen', function(newVal, oldVal){
13519                                     if(newVal !== oldVal && !newVal){
13520                                         $attElementDetach(tooltip[0]);
13521                                     }
13522                                 });
13523
13524                                 function toggleTooltipBind() {
13525                                     if (!scope.tt_isOpen) {
13526                                         showTooltipBind();
13527                                     } else {
13528                                         hideTooltipBind();
13529                                     }
13530                                 }
13531
13532                                 // Show the tooltip with delay if specified, otherwise show it immediately
13533                                 function showTooltipBind() {
13534                                     if (hasEnableExp && !scope.$eval(attrs[prefix + 'Enable'])) {
13535                                         return;
13536                                     }
13537                                     if (scope.tt_popupDelay) {
13538                                         popupTimeout = $timeout(show, scope.tt_popupDelay);
13539                                     } else {
13540                                         scope.$apply(show);
13541                                     }
13542                                 }
13543
13544                                 function hideTooltipBind() {
13545                                     scope.$apply(function() {
13546                                         hide();
13547                                     });
13548                                 }
13549
13550                                 // Show the tooltip popup element.
13551                                 function show() {
13552                                     var position,
13553                                             ttWidth,
13554                                             ttHeight,
13555                                             ttPosition;
13556
13557                                     // Don't show empty tooltips.
13558                                     if (!scope.tt_content) {
13559                                         return;
13560                                     }
13561
13562                                     // If there is a pending remove transition, we must cancel it, lest the
13563                                     // tooltip be mysteriously removed.
13564                                     if (transitionTimeout) {
13565                                         $timeout.cancel(transitionTimeout);
13566                                     }
13567
13568                                     // Set the initial positioning.
13569                                     tooltip.css({top: 0, left: 0, display: 'block', 'z-index': 9999});
13570
13571                                     // Now we add it to the DOM because need some info about it. But it's not
13572                                     // visible yet anyway.
13573                                     if (appendToBody) {
13574                                         $body = $body || $document.find('body');
13575                                         $body.append(tooltip);
13576                                     } else {
13577                                         element.after(tooltip);
13578                                     }
13579
13580                                     // Get the position of the directive element.
13581                                     position = appendToBody ? $position.offset(element) : $position.position(element);
13582
13583                                     // Get the height and width of the tooltip so we can center it.
13584                                     ttWidth = tooltip.prop('offsetWidth');
13585                                     ttHeight = tooltip.prop('offsetHeight');
13586
13587                                     // Calculate the tooltip's top and left coordinates to center it with
13588                                     // this directive.
13589                                     var ttArrowOffset = 10;
13590                                     switch (scope.tt_placement) {
13591                                         case 'right':
13592                                             if(appendToBody){
13593                                                 ttPosition = {
13594                                                     top: position.top + position.height / 2 - ttHeight / 2,
13595                                                     left: (position.left + position.width) + tooltipOffset
13596                                                 };
13597                                             }else{
13598                                                 ttPosition = {
13599                                                     top: position.top + position.height / 2 - ttHeight / 2,
13600                                                     left: (position.left + position.width + ttArrowOffset) + tooltipOffset
13601                                                 };
13602                                             }
13603                                             break;
13604                                         case 'below':
13605                                             if(appendToBody){
13606                                                 ttPosition = {
13607                                                     top: (position.top + position.height) + tooltipOffset,
13608                                                     left: position.left + position.width / 2 - ttWidth / 2
13609                                                 };
13610                                             }else{
13611                                                 ttPosition = {
13612                                                     top: (position.top + position.height + ttArrowOffset) + tooltipOffset,
13613                                                     left: position.left + position.width / 2 - ttWidth / 2
13614                                                 };
13615                                             }
13616                                             break;
13617                                         case 'left':
13618                                             if(appendToBody){
13619                                                 ttPosition = {
13620                                                     top: position.top + position.height / 2 - ttHeight / 2,
13621                                                     left: (position.left - ttWidth) - tooltipOffset
13622                                                 };
13623                                             }else{
13624                                                 ttPosition = {
13625                                                     top: position.top + position.height / 2 - ttHeight / 2,
13626                                                     left: (position.left - ttWidth - ttArrowOffset) - tooltipOffset
13627                                                 };
13628                                             }
13629                                             break;
13630                                         default:
13631                                             if(appendToBody){
13632                                                 ttPosition = {
13633                                                     top: (position.top - ttHeight) - tooltipOffset,
13634                                                     left: position.left + position.width / 2 - ttWidth / 2
13635                                                 };
13636                                             }else{
13637                                                 ttPosition = {
13638                                                     top: (position.top - ttHeight - ttArrowOffset) - tooltipOffset,
13639                                                     left: position.left + position.width / 2 - ttWidth / 2
13640                                                 };
13641                                             }
13642                                             break;
13643                                     }
13644
13645                                     ttPosition.top += 'px';
13646                                     ttPosition.left += 'px';
13647
13648                                     // Now set the calculated positioning.
13649                                     tooltip.css(ttPosition);
13650
13651                                     // And show the tooltip.
13652                                     scope.tt_isOpen = true;
13653                                 }
13654
13655                                 // Hide the tooltip popup element.
13656                                 function hide() {
13657                                     // First things first: we don't show it anymore.
13658                                     scope.tt_isOpen = false;
13659
13660                                     //if tooltip is going to be shown after delay, we must cancel this
13661                                     $timeout.cancel(popupTimeout);
13662
13663                                     // And now we remove it from the DOM. However, if we have animation, we
13664                                     // need to wait for it to expire beforehand.
13665                                     // This is a placeholder for a port of the transitions library.
13666                                     if (angular.isDefined(scope.tt_animation) && scope.tt_animation()) {
13667                                         transitionTimeout = $timeout(function() {
13668                                             $attElementDetach(tooltip[0]);
13669                                         }, 500);
13670                                     } else {
13671                                         $attElementDetach(tooltip[0]);
13672                                     }
13673                                 }
13674
13675                                 function setTooltipAriaLabel() {
13676                                     element.removeAttr('title');
13677                                     if(!isElementHovered){
13678                                         if (tooltipAriaLabelDefined) {
13679                                             element.attr('title', scope.tooltipAriaLabel);
13680                                         } else {
13681                                             element.attr('title', scope.tt_content);
13682                                         }
13683                                     }
13684                                 }
13685
13686                                 /**
13687                                  * Observe the relevant attributes.
13688                                  */
13689                                 attrs.$observe(type, function(val) {
13690                                     if (val) {
13691                                         scope.tt_content = val;
13692                                        // setTooltipAriaLabel();
13693                                     } else {
13694                                         if (scope.tt_isOpen) {
13695                                             hide();
13696                                         }
13697                                     }
13698                                 });
13699
13700                                 attrs.$observe(prefix + 'Title', function(val) {
13701                                     scope.tt_title = val;
13702                                 });
13703
13704                                 attrs.$observe(prefix + 'Placement', function(val) {
13705                                     scope.tt_placement = angular.isDefined(val) ? val : options.placement;
13706                                 });
13707
13708                                 attrs.$observe(prefix + 'Style', function(val) {
13709                                     scope.tt_style = angular.isDefined(val) ? val : options.stylett;
13710                                 });
13711
13712                                 attrs.$observe(prefix + 'Animation', function(val) {
13713                                     scope.tt_animation = angular.isDefined(val) ? $parse(val) : function() {
13714                                         return options.animation;
13715                                     };
13716                                 });
13717
13718                                 attrs.$observe(prefix + 'PopupDelay', function(val) {
13719                                     var delay = parseInt(val, 10);
13720                                     scope.tt_popupDelay = !isNaN(delay) ? delay : options.popupDelay;
13721                                 });
13722
13723                                 attrs.$observe(prefix + 'Trigger', function(val) {
13724
13725                                     if (hasRegisteredTriggers) {
13726                                         element.unbind(triggers.show, showTooltipBind);
13727                                         element.unbind(triggers.hide, hideTooltipBind);
13728                                     }
13729
13730                                     triggers = getTriggers(val);
13731
13732                                     /* This fixes issue in which a click on input field with trigger as focus 
13733                                         causes focus to fire following click thus making tooltip flash. */
13734                                     if (triggers.show === 'focus') {
13735                                         element.bind('focus', showTooltipBind);
13736                                         element.bind('blur', hideTooltipBind);
13737                                         element.bind('click', function(e) {
13738                                             e.stopPropagation();
13739                                         });
13740                                     } else if (triggers.show === triggers.hide) {
13741                                         element.bind(triggers.show, toggleTooltipBind);
13742                                     } else {
13743                                         element.bind(triggers.show, showTooltipBind);
13744                                         element.bind(triggers.hide, hideTooltipBind);
13745                                     }
13746
13747                                     hasRegisteredTriggers = true;
13748                                 });
13749
13750                                 attrs.$observe(prefix + 'AppendToBody', function (val) {
13751                                     appendToBody = angular.isDefined(val) ? $parse(val)(scope) : appendToBody;
13752                                 });
13753
13754                                 attrs.$observe(prefix + 'Offset', function (val) {
13755                                     tooltipOffset = angular.isDefined(val) ? parseInt(val, 10) : 0;
13756                                 });
13757
13758                                 attrs.$observe(prefix + 'AriaLabel', function (val) {
13759                                     if (angular.isDefined(val)) {
13760                                         scope.tooltipAriaLabel = val;
13761                                         tooltipAriaLabelDefined = true;
13762                                     } else {
13763                                         tooltipAriaLabelDefined = false;
13764                                     }
13765                                     setTooltipAriaLabel();
13766                                 });
13767
13768                                 // if a tooltip is attached to <body> we need to remove it on
13769                                 // location change as its parent scope will probably not be destroyed
13770                                 // by the change.
13771                                 if (appendToBody) {
13772                                     scope.$on('$locationChangeSuccess', function() {
13773                                         if (scope.tt_isOpen) {
13774                                             hide();
13775                                         }
13776                                     });
13777                                 }
13778
13779                                 // Make sure tooltip is destroyed and removed.
13780                                 scope.$on('$destroy', function() {
13781                                     if (scope.tt_isOpen) {
13782                                         hide();
13783                                     } else {
13784                                         tooltip.remove();
13785                                     }
13786                                 });
13787                             }
13788                         };
13789                     };
13790                 }];
13791         }])
13792
13793         .directive('tooltipPopup', ['$document', '$documentBind', function($document, $documentBind) {
13794             return {
13795                 restrict: 'EA',
13796                 replace: true,
13797                 transclude: true,
13798                 scope: {content: '@', placement: '@', animation: '&', isOpen: '=', stylett: '@'},
13799                 templateUrl: 'app/scripts/ng_js_att_tpls/tooltip/tooltip-popup.html',
13800                 link: function(scope, elem) {
13801                     scope.$watch("isOpen", function() {
13802                         scope.isOpen;
13803                     });
13804                     elem.bind('click', function (e) {
13805                         e.stopPropagation();
13806                     });
13807                     var outsideClick = function() {
13808                         scope.$apply(function() {
13809                             scope.isOpen = false;
13810                         });
13811                     };
13812
13813                     $documentBind.event('click', 'isOpen', outsideClick, scope, true, 10);
13814                 }
13815             };
13816         }])
13817
13818         .directive('tooltip', ['$tooltip', function($tooltip) {
13819             return $tooltip('tooltip', 'tooltip', 'mouseenter');
13820         }])
13821
13822         .directive('tooltipCondition', [ '$timeout',function($timeout) {
13823                 return  {
13824                     restrict: 'EA',
13825                     replace: true,
13826                     scope:{
13827                         tooltipCondition:"@?"
13828                     },
13829                     template:'<p><span tooltip=\"{{tooltipCondition}}\" ng-if=\"showpop\">{{tooltipCondition}}</span><span id=\"innerElement\" ng-hide=\"showpop\">{{tooltipCondition}}</span></p>',
13830                     link: function(scope, elem, attr){
13831                         scope.showpop=false;
13832                         if(attr.height==='true'){
13833                             $timeout(function () {
13834                                var maxHeight=(elem[0].offsetHeight);
13835                                var elemHeight=elem.children(0)[0].offsetHeight;
13836                                if(elemHeight > maxHeight){
13837                                    scope.showpop=true;
13838                                }
13839                             });
13840                         }
13841                         else if(scope.tooltipCondition.length>=25){
13842                         scope.showpop=true;
13843                         }
13844                     }
13845                 };
13846         }]);
13847 angular.module('att.abs.popOvers', ['att.abs.tooltip', 'att.abs.utilities', 'ngSanitize'])
13848         .directive('popover', ['$tooltip', function($tooltip) {
13849                 return $tooltip('popover', 'popover', 'click');
13850             }])
13851         .directive('popoverPopup', ['$document', '$documentBind', '$timeout', 'events', 'DOMHelper', function($document, $documentBind, $timeout, events, DOMHelper) {
13852                 return {
13853                     restrict: 'EA',
13854                     replace: true,
13855                     transclude: true,
13856                     templateUrl: 'app/scripts/ng_js_att_tpls/popOvers/popOvers.html',
13857                     scope: {content: '@', placement: '@', animation: '&', isOpen: '=', stylett: '@'},
13858                     link: function(scope, elem, attr, ctrl) {
13859
13860                         scope.closeable = false;
13861                         try {
13862                             scope.closeable = scope.$parent.parentAttrs['closeable'] === '' ? true : false;
13863                         } catch (e) {}
13864
13865                         /* Before opening modal, find the focused element */
13866                         var launchingElement = undefined, 
13867                             firstTabableElement = undefined;
13868
13869                         var outsideClick = function(evt) {
13870                             scope.$apply(function() {
13871                                 scope.isOpen = false;
13872                             });
13873                         };
13874                         var escKeydown = function(evt) {
13875                             if (evt.which === 27 || evt.keyCode === 27) {
13876                                     console.log('ESC was pressed!');
13877                                     scope.$apply(function() {
13878                                         scope.isOpen = false;
13879                                 });
13880                             }
13881                         };
13882
13883                         $timeout(function() {
13884                             firstTabableElement = DOMHelper.firstTabableElement(elem);
13885                         }, 10, false);
13886                         
13887                         scope.$watch('isOpen', function(value) {
13888                             if (scope.isOpen) {
13889                                 launchingElement = document.activeElement;
13890                                 /* Focus on first tabbable element */
13891                                 if (angular.isDefined(firstTabableElement)) {
13892                                     try {
13893                                         firstTabableElement.focus();
13894                                     } catch(e) {}
13895                                 }
13896                             } else {
13897                                 if (angular.isDefined(launchingElement)) {
13898                                     try {
13899                                         launchingElement.focus();
13900                                     } catch (e) {} /* IE8 will throw exception */
13901                                 }
13902                             }
13903                         });
13904                         
13905                         scope.$watch("stylett", function(value) {
13906                             scope.popOverStyle = value;
13907                         });
13908
13909                         scope.$watch("placement", function(value) {
13910                             scope.popOverPlacement = value;
13911                         });
13912                         
13913                         scope.closeMe = function(){
13914                            scope.isOpen = false;
13915                         };
13916                         
13917                         elem.bind('click', function (e) {
13918                             events.stopPropagation(e);
13919                         });
13920                         
13921                         $documentBind.event('click', 'isOpen', outsideClick, scope, true, 10);
13922                         $documentBind.event('keydown', 'isOpen', escKeydown, scope, true, 10);
13923                     }
13924                 };
13925             }]);
13926
13927 angular.module('att.abs.profileCard', [])
13928             .constant('profileStatus',{
13929                 status:{
13930                     ACTIVE:{status:"Active",color:"green"},
13931                     DEACTIVATED:{status:"Deactivated",color:"red"},
13932                     LOCKED:{status:"Locked",color:"red"},
13933                     IDLE:{status:"Idle",color:"yellow"},
13934                     PENDING:{status:"Pending",color:"blue"}
13935                     },
13936                 role:"COMPANY ADMINISTRATOR"
13937                 })
13938             .directive('profileCard',['$http','$q','profileStatus', function($http,$q,profileStatus) {
13939                return {
13940                     restrict: 'EA',
13941                     replace:'true',
13942                     templateUrl:function(element, attrs){
13943                         if(!attrs.addUser){
13944                             return 'app/scripts/ng_js_att_tpls/profileCard/profileCard.html';
13945                         }
13946                         else{
13947                             return 'app/scripts/ng_js_att_tpls/profileCard/addUser.html';
13948                         }
13949                     },
13950                     scope:{
13951                         profile:'='
13952                     },
13953                     link: function(scope, elem, attr){
13954                         scope.image=true;
13955                         function isImage(src) {
13956                             var deferred = $q.defer();
13957                             var image = new Image();
13958                             image.onerror = function() {
13959                                 deferred.reject(false);
13960                             };
13961                             image.onload = function() {
13962                                 deferred.resolve(true);
13963                             };
13964                             if(src!==undefined && src.length>0 ){
13965                                 image.src = src;
13966                             }else{
13967                                  deferred.reject(false);
13968                             }
13969                             return deferred.promise;
13970                         }
13971                         if(!attr.addUser){
13972                         scope.image=false;
13973                         isImage(scope.profile.img).then(function(img) {
13974                             scope.image=img;
13975                         });
13976                         var splitName=(scope.profile.name).split(' ');
13977                         scope.initials='';
13978                         for(var i=0;i<splitName.length;i++){
13979                             scope.initials += splitName[i][0];
13980                         }
13981                         if(scope.profile.role.toUpperCase()===profileStatus.role){
13982                             scope.badge=true;
13983                         }
13984                         var profileState=profileStatus.status[scope.profile.state.toUpperCase()];
13985                         if(profileState) {
13986                             scope.profile.state=profileStatus.status[scope.profile.state.toUpperCase()].status;
13987                             scope.colorIcon=profileStatus.status[scope.profile.state.toUpperCase()].color;
13988                             if(scope.profile.state.toUpperCase()===profileStatus.status.PENDING.status.toUpperCase()||scope.profile.state.toUpperCase()===profileStatus.status.LOCKED.status.toUpperCase()){
13989                                     scope.profile.lastLogin=scope.profile.state;
13990                             }
13991                         }
13992                         var today=new Date().getTime();
13993                         var lastlogin=new Date(scope.profile.lastLogin).getTime();
13994                         var diff=(today-lastlogin)/(1000*60*60*24);
13995                         if(diff<=1){
13996                             scope.profile.lastLogin="Today";
13997                         }
13998                         else if(diff<=2){
13999                             scope.profile.lastLogin="Yesterday";
14000                         }
14001                     }
14002                 }
14003             };
14004         }]);
14005 angular.module('att.abs.progressBars', [])
14006
14007 .directive('attProgressBar', [function(){
14008     return {
14009         restrict: 'A',
14010         replace: true,
14011         templateUrl : 'app/scripts/ng_js_att_tpls/progressBars/progressBars.html'
14012     };
14013 }]);
14014 angular.module('att.abs.radio', [])
14015     .constant('attRadioConfig', {
14016         activeClass : "att-radio--on",
14017         disabledClass : "att-radio--disabled"
14018     })
14019 .directive('attRadio', ['$compile','attRadioConfig', function ($compile, attRadioConfig) {
14020     return {
14021         scope: {},
14022         restrict: 'A',
14023         require: 'ngModel',
14024         link: function (scope, element, attr, ctrl) {
14025             var ngCtrl = ctrl;
14026             scope.radioVal='';
14027             var parentDiv = angular.element('<div att-accessibility-click="13,32" ng-click="updateModel($event)" class="att-radio"></div>');
14028             element.attr("value",attr.attRadio);
14029             element.removeAttr("att-radio");
14030             element.removeAttr("title");
14031             element.attr("ng-model","radioVal");
14032             parentDiv.append(element.prop('outerHTML'));
14033             parentDiv.append('<div class="att-radio__indicator"></div>');
14034             parentDiv.attr("title", attr.title);
14035
14036             var elm = parentDiv.prop('outerHTML');
14037             elm = $compile(elm)(scope);
14038             element = element.replaceWith(elm);
14039             var radioElm = elm.find("input");
14040
14041             radioElm.on('focus', function() {                
14042                 elm.css("outline","2px solid #5E9ED6");
14043                // elm.css("outline","-mos-focus-ring-color auto 5px");
14044                 elm.css("outline","-webkit-focus-ring-color auto 5px");
14045                
14046             });
14047             radioElm.on('blur', function() {
14048                elm.css("outline","none");
14049             });
14050
14051             ngCtrl.$render = function () {
14052                 scope.radioVal = ngCtrl.$modelValue;
14053                 var selected = angular.equals(ngCtrl.$modelValue, attr.attRadio);                
14054                 elm.toggleClass(attRadioConfig.activeClass, selected);
14055             };
14056
14057             scope.updateModel = function () {
14058                radioElm[0].focus();
14059                 var isActive = elm.hasClass(attRadioConfig.activeClass);
14060
14061                 if (!isActive && !scope.disabled) {
14062                     ngCtrl.$setViewValue(isActive ? null : attr.attRadio);      
14063                     ngCtrl.$render();
14064                 }
14065             };
14066
14067             attr.$observe('disabled', function (val) {
14068                 scope.disabled = (val || val === "disabled" || val === "true");
14069                 if (scope.disabled){
14070                     elm.addClass(attRadioConfig.disabledClass);
14071                     elm.attr("tabindex", "-1");
14072                 }else { 
14073                     elm.removeClass(attRadioConfig.disabledClass); 
14074                     elm.attr("tabindex", "0"); 
14075                 }
14076             });
14077         }
14078     };
14079 }]);
14080 angular.module('att.abs.scrollbar', ['att.abs.position'])
14081
14082 .constant('attScrollbarConstant', {
14083     defaults: {
14084         // Vertical or horizontal scrollbar? ( x || y ).
14085         axis: 'y',
14086         // Whether navigation pane is required of not.
14087         navigation: false,
14088         // Enable or disable the mousewheel.
14089         wheel: true,
14090         // How many pixels must the mouswheel scroll at a time.
14091         wheelSpeed: 40,
14092         // Lock default scrolling window when there is no more content.
14093         wheelLock: true,
14094         //// Enable invert style scrolling
14095         scrollInvert: false,
14096         // Set the size of the scrollbar to auto or a fixed number.
14097         trackSize: false,
14098         // Set the size of the thumb to auto or a fixed number.
14099         thumbSize: false,
14100         // Set to false to hide the scrollbar if not being used
14101         alwaysVisible: true
14102     }
14103 })
14104
14105 .directive('attScrollbar', ['$window', '$timeout', '$parse', '$animate', 'attScrollbarConstant', '$position', function ($window, $timeout, $parse, $animate, attScrollbarConstant, $position) {
14106     return {
14107         restrict: 'A',
14108         scope: true,
14109         transclude: true,
14110         templateUrl: 'app/scripts/ng_js_att_tpls/scrollbar/scrollbar.html',
14111         controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
14112             var defaults = {
14113                 axis: $attrs.attScrollbar || attScrollbarConstant.defaults.axis,
14114                 navigation: $attrs.navigation || attScrollbarConstant.defaults.navigation,
14115                 wheel: attScrollbarConstant.defaults.wheel,
14116                 wheelSpeed: attScrollbarConstant.defaults.wheelSpeed,
14117                 wheelLock: attScrollbarConstant.defaults.wheelLock,
14118                 scrollInvert: attScrollbarConstant.defaults.scrollInvert,
14119                 trackSize: attScrollbarConstant.defaults.trackSize,
14120                 thumbSize: attScrollbarConstant.defaults.thumbSize,
14121                 alwaysVisible: attScrollbarConstant.defaults.alwaysVisible
14122             };
14123             var options = $attrs.scrollbar;
14124             if (options) {
14125                 options = $parse(options)($scope);
14126             } else {
14127                 options = {};
14128             }
14129             this.options = angular.extend({}, defaults, options);
14130             this._defaults = defaults;
14131
14132             var self = this,
14133                 $body = angular.element(document.querySelectorAll('body')[0]),
14134                 $document = angular.element(document),
14135                 $viewport = angular.element($element[0].querySelectorAll('.scroll-viewport')[0]),
14136                 $overview = angular.element($element[0].querySelectorAll('.scroll-overview')[0]),
14137                 $scrollbar = angular.element($element[0].querySelectorAll('.scroll-bar')[0]),
14138                 $thumb = angular.element($element[0].querySelectorAll('.scroll-thumb')[0]),
14139                 mousePosition = 0,
14140                 isHorizontal = this.options.axis === 'x',
14141                 hasTouchEvents = false,
14142                 // Modern browsers support "wheel"
14143                 wheelEvent = ("onwheel" in document ? "wheel" :
14144                     // Webkit and IE support at least "mousewheel"
14145                     document.onmousewheel !== undefined ? "mousewheel" :
14146                     // let's assume that remaining browsers are older Firefox
14147                     "DOMMouseScroll"),
14148                 sizeLabel = isHorizontal ? 'width' : 'height',
14149                 sizeLabelCap = sizeLabel.charAt(0).toUpperCase() + sizeLabel.slice(1).toLowerCase(),
14150                 posiLabel = isHorizontal ? 'left' : 'top',
14151                 // moveEvent = document.createEvent('HTMLEvents'),
14152                 restoreVisibilityAfterWheel,
14153                 thumbscrolltouch = false,
14154                 documnetscrolltouch = false;
14155             if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
14156                 hasTouchEvents = true;
14157             }
14158
14159             //moveEvent.initEvent('move', true, true);
14160             this.contentPosition = 0;
14161             this.viewportSize = 0;
14162             this.contentSize = 0;
14163             this.contentRatio = 0;
14164             this.trackSize = 0;
14165             this.trackRatio = 0;
14166             this.thumbSize = 0;
14167             this.thumbPosition = 0;
14168
14169             this.initialize = function () {
14170                 if (!this.options.alwaysVisible) {
14171                     $scrollbar.css('opacity', 0);
14172                 }
14173                 self.update();
14174                 setEvents();
14175                 return self;
14176             };
14177
14178             this.setSizeData = function () {
14179                 this.viewportSize = $viewport.prop('offset' + sizeLabelCap) || 1;
14180                 this.contentSize = $overview.prop('scroll' + sizeLabelCap) || 1;
14181                 this.contentRatio = this.viewportSize / this.contentSize;
14182                 this.trackSize = this.options.trackSize || this.viewportSize;
14183                 this.thumbSize = Math.min(this.trackSize, Math.max(0, (this.options.thumbSize || (this.trackSize * this.contentRatio))));
14184                 this.trackRatio = this.options.thumbSize ? (this.contentSize - this.viewportSize) / (this.trackSize - this.thumbSize) : (this.contentSize / this.trackSize);
14185             };
14186
14187             this.update = function (scrollTo) {
14188                 self.setSizeData();
14189                 mousePosition = $scrollbar.prop('offsetTop');
14190
14191                 $scrollbar.toggleClass('disable', this.contentRatio >= 1 || isNaN(this.contentRatio));
14192
14193                 if (!this.options.alwaysVisible && this.contentRatio < 1 && this.viewportSize > 0) {
14194                     //flash the scrollbar when update happens
14195                     $animate.addClass($scrollbar, 'visible').then(function () {
14196                         $animate.removeClass($scrollbar, 'visible');
14197                         $scope.$digest();
14198                     });
14199                 }
14200
14201                 if (scrollTo !== null) {
14202                     if (scrollTo === 'bottom') {
14203                         this.contentPosition = this.contentSize - this.viewportSize;
14204                     } else {
14205                         this.contentPosition = parseInt(scrollTo, 10) || 0;
14206                     }
14207                 }
14208
14209                 ensureContentPosition();
14210                 $thumb.css(posiLabel, self.contentPosition / self.trackRatio + 'px');
14211                 $scrollbar.css(sizeLabel, self.trackSize + 'px');
14212                 $thumb.css(sizeLabel, self.thumbSize + 'px');
14213                 $overview.css(posiLabel, -self.contentPosition + 'px');
14214
14215                 return this;
14216             };
14217
14218             fireEvent = function (obj, evt) {
14219                 var fireOnThis = obj;
14220                 var evtObj;
14221                 if (document.createEvent) {
14222                     // alert("FF");
14223                     evtObj = document.createEvent('HTMLEvents');
14224                     evtObj.initEvent(evt, true, false);
14225                     fireOnThis.dispatchEvent(evtObj);
14226                 } else if (document.createEventObject) {
14227                     // alert("IE8");
14228                     evtObj = document.createEventObject();
14229                     fireOnThis.fireEvent('on' + evt, evtObj);
14230                 }
14231             };
14232
14233             function ensureContentPosition() {
14234                 // if scrollbar is on, ensure the bottom of the content does not go above the bottom of the viewport
14235                 if (self.contentRatio <= 1 && self.contentPosition > self.contentSize - self.viewportSize) {
14236                     self.contentPosition = self.contentSize - self.viewportSize;
14237                 }
14238                 // if scrollbar is off, ensure the top of the content does not go below the top of the viewport
14239                 else if (self.contentRatio > 1 && self.contentPosition > 0) {
14240                     self.contentPosition = 0;
14241                 }
14242
14243                 if (self.contentPosition <= 0) {
14244                     $scope.prevAvailable = false;
14245                 } else {
14246                     $scope.prevAvailable = true;
14247                 }
14248
14249                 if (self.contentPosition >= (self.contentSize - self.viewportSize)) {
14250                     $scope.nextAvailable = false;
14251                 } else {
14252                     $scope.nextAvailable = true;
14253                 }
14254             }
14255
14256             function setEvents() {
14257                 if (hasTouchEvents) {
14258                     $viewport.on('touchstart', touchstart);
14259                     $thumb.on('touchstart', touchstart);
14260                 } else {
14261                     $thumb.on('mousedown', start);
14262                     $scrollbar.on('mousedown', drag);
14263                 }
14264
14265                 angular.element($window).on('resize', resize);
14266
14267                 if (self.options.wheel) {
14268                     $element.on(wheelEvent, wheel);
14269                 }
14270             }
14271
14272             function resize() {
14273                 self.update();
14274             }
14275
14276             function touchstart(event) {
14277                 if (1 === event.touches.length) {
14278                     event.stopPropagation();
14279                     start(event.touches[0]);
14280                 }
14281             }
14282
14283             function start(event) {
14284                 $body.addClass('scroll-no-select');
14285                 $element.addClass('scroll-no-select');
14286
14287                 if (!self.options.alwaysVisible) {
14288                     $scrollbar.addClass('visible');
14289                 }
14290                 mousePosition = isHorizontal ? event.clientX : event.clientY;
14291                 self.thumbPosition = parseInt($thumb.css(posiLabel), 10) || 0;
14292
14293                 if (hasTouchEvents) {
14294                     documnetscrolltouch = false;
14295                     thumbscrolltouch = false;
14296                     $viewport.on('touchmove', touchdrag);
14297                     $viewport.on('touchend', end);
14298                     $thumb.on('touchmove', touchdragthumb);
14299                     $thumb.on('touchend', end);
14300                 } else {
14301                     $document.on('mousemove', drag);
14302                     $document.on('mouseup', end);
14303                     $thumb.on('mouseup', end);
14304                 }
14305             }
14306
14307             function wheel(event) {
14308                 if (self.contentRatio >= 1) {
14309                     return;
14310                 }
14311
14312                 if (!self.options.alwaysVisible) {
14313                     //cancel removing visibility if wheel event is triggered before the timeout
14314                     if (restoreVisibilityAfterWheel) {
14315                         $timeout.cancel(restoreVisibilityAfterWheel);
14316                     }
14317                     $scrollbar.addClass('visible');
14318
14319                     restoreVisibilityAfterWheel = $timeout(function () {
14320                         $scrollbar.removeClass('visible');
14321                     }, 100);
14322                 }
14323
14324                 var evntObj = (event && event.originalEvent) || event || $window.event,
14325                     deltaDir = self.options.axis.toUpperCase(),
14326                     delta = {
14327                         X: evntObj.deltaX || 0,
14328                         Y: evntObj.deltaY || 0
14329                     },
14330                     wheelSpeed = evntObj.deltaMode === 0 ? self.options.wheelSpeed : 1;
14331
14332                 if (self.options.scrollInvert) {
14333                     wheelSpeed *= -1;
14334                 }
14335
14336                 if (wheelEvent === 'mousewheel') {
14337                     delta.Y = -1 * evntObj.wheelDelta / 40;
14338                     if (evntObj.wheelDeltaX) {
14339                         delta.X = -1 * evntObj.wheelDeltaX / 40;
14340                     }
14341                 }
14342                 delta.X *= -1 / wheelSpeed;
14343                 delta.Y *= -1 / wheelSpeed;
14344
14345                 var wheelSpeedDelta = delta[deltaDir];
14346
14347                 self.contentPosition -= wheelSpeedDelta * self.options.wheelSpeed;
14348                 self.contentPosition = Math.min((self.contentSize - self.viewportSize), Math.max(0, self.contentPosition));
14349
14350                 fireEvent($element[0], 'move');
14351
14352                 ensureContentPosition();
14353                 $thumb.css(posiLabel, self.contentPosition / self.trackRatio + 'px');
14354                 $overview.css(posiLabel, -self.contentPosition + 'px');
14355
14356                 if (self.options.wheelLock || (self.contentPosition !== (self.contentSize - self.viewportSize) && self.contentPosition !== 0)) {
14357                     evntObj.preventDefault();
14358                 }
14359
14360                 $scope.$apply();
14361             }
14362
14363             function touchdrag(event) {
14364                 event.preventDefault();
14365                 documnetscrolltouch = true;
14366                 drag(event.touches[0]);
14367             }
14368
14369             function touchdragthumb(event) {
14370                 event.preventDefault();
14371                 thumbscrolltouch = true;
14372                 drag(event.touches[0]);
14373             }
14374
14375             function drag(event) {
14376                 if (self.contentRatio >= 1) {
14377                     return;
14378                 }
14379
14380                 var mousePositionNew = isHorizontal ? event.clientX : event.clientY,
14381                     thumbPositionDelta = mousePositionNew - mousePosition;
14382
14383                 if ((self.options.scrollInvert && !hasTouchEvents) ||
14384                     (hasTouchEvents && !self.options.scrollInvert)) {
14385                     thumbPositionDelta = mousePosition - mousePositionNew;
14386                 }
14387                 if (documnetscrolltouch && hasTouchEvents) {
14388                     thumbPositionDelta = mousePosition - mousePositionNew;
14389                 }
14390                 if (thumbscrolltouch && hasTouchEvents) {
14391                     thumbPositionDelta = mousePositionNew - mousePosition;
14392                 }
14393                 var thumbPositionNew = Math.min((self.trackSize - self.thumbSize), Math.max(0, self.thumbPosition + thumbPositionDelta));
14394                 self.contentPosition = thumbPositionNew * self.trackRatio;
14395
14396                 fireEvent($element[0], 'move');
14397
14398                 ensureContentPosition();
14399                 $thumb.css(posiLabel, thumbPositionNew + 'px');
14400                 $overview.css(posiLabel, -self.contentPosition + 'px');
14401
14402                 $scope.$apply();
14403             }
14404
14405             $scope.customScroll = function (direction) {
14406                 if (self.contentRatio >= 1) {
14407                     return;
14408                 }
14409
14410                 var customScrollDelta;
14411                 var viewportDimension = $position.position($viewport);
14412
14413                 if (isHorizontal) {
14414                     customScrollDelta = viewportDimension.width;
14415                 } else {
14416                     customScrollDelta = viewportDimension.height;
14417                 }
14418
14419                 if (direction) {
14420                     self.contentPosition += customScrollDelta;
14421                 } else {
14422                     self.contentPosition -= customScrollDelta;
14423                 }
14424                 self.contentPosition = Math.min((self.contentSize - self.viewportSize), Math.max(0, self.contentPosition));
14425
14426                 fireEvent($element[0], 'move');
14427
14428                 ensureContentPosition();
14429                 $thumb.css(posiLabel, self.contentPosition / self.trackRatio + 'px');
14430                 $overview.css(posiLabel, -self.contentPosition + 'px');
14431             };
14432
14433             function end() {
14434                 $body.removeClass('scroll-no-select');
14435                 $element.removeClass('scroll-no-select');
14436                 if (!self.options.alwaysVisible) {
14437                     $scrollbar.removeClass('visible');
14438                 }
14439                 $document.off('mousemove', drag);
14440                 $document.off('mouseup', end);
14441                 $thumb.off('mouseup', end);
14442                 $document.off('touchmove', touchdrag);
14443                 $document.off('ontouchend', end);
14444                 $thumb.off('touchmove', touchdragthumb);
14445                 $thumb.off('touchend', end);
14446             }
14447
14448             this.cleanup = function () {
14449                 $viewport.off('touchstart', touchstart);
14450                 $thumb.off('mousedown', start);
14451                 $scrollbar.off('mousedown', drag);
14452                 $thumb.off('touchmove', touchdragthumb);
14453                 $thumb.off('touchend', end);
14454                 angular.element($window).off('resize', resize);
14455                 $element.off(wheelEvent, wheel);
14456                 //ensure scrollbar isn't activated
14457                 self.options.alwaysVisible = true;
14458                 end();
14459             };
14460         }],
14461         link: function (scope, iElement, iAttrs, controller) {
14462             scope.navigation = controller.options.navigation;
14463             scope.viewportHeight = iAttrs.viewportHeight;
14464             scope.viewportWidth = iAttrs.viewportWidth;
14465             scope.scrollbarAxis = controller.options.axis;
14466             if (scope.scrollbarAxis === 'x') {
14467                 iElement.addClass('horizontal');
14468             } else if (scope.scrollbarAxis === 'y') {
14469                 iElement.addClass('vertical');
14470             }
14471
14472             var position = iElement.css('position');
14473             if (position !== 'relative' && position !== 'absolute') {
14474                 iElement.css('position', 'relative');
14475             }
14476
14477             scope.$watch(function () {
14478                 $timeout(refreshScrollbar, 100, false);
14479             });
14480
14481             var refreshScrollbar = function () {
14482                 var $overview = angular.element(iElement[0].querySelectorAll('.scroll-overview')[0]);
14483                 var newValue = $overview.prop('scrollHeight');
14484                 var oldValue = scope.oldValue;
14485                 if (newValue !== oldValue) {
14486                     scope.oldValue = newValue;
14487                     controller.update();
14488                 }
14489             };
14490
14491             controller.initialize();
14492             iElement.on('$destroy', function () {
14493                 controller.cleanup();
14494             });
14495         }
14496     };
14497 }]);
14498
14499 angular.module('att.abs.search', ['att.abs.utilities', 'att.abs.position', 'att.abs.utilities'])
14500 .directive('attSearch', ['$document', '$filter', '$isElement', '$documentBind', '$timeout', '$log', 'keymap', function($document, $filter, $isElement, $documentBind, $timeout, $log, keymap){
14501     return{
14502         restrict: 'A',
14503         scope:{cName: '=attSearch'},
14504         transclude: false,
14505         replace: false,
14506         require:'ngModel',
14507         templateUrl: 'app/scripts/ng_js_att_tpls/search/search.html',
14508         link: function(scope, element, attr, ctrl) {
14509             scope.selectedIndex = -1;
14510             scope.selectedOption = attr.placeholder;
14511             scope.isDisabled = false;
14512             scope.className = "select2-match";
14513             scope.showSearch = false;
14514             scope.showlist = false;
14515
14516             // This is used to jump to elements in list
14517             var search = '';
14518             // This is used to ensure searches only persist so many ms.
14519             var prevSearchDate = new Date();
14520             // This is used to shift focus back after closing dropdown
14521             var dropdownElement = undefined;
14522             // Used to ensure focus on dropdown elements
14523             var list = [];
14524             $timeout(function() {
14525                 list = element.find('li');
14526             }, 10);
14527
14528             $log.warn('attSearch is deprecated, please use attSelect instead. This component will be removed by version 2.7.')
14529                         //scope.noFilter = true;
14530             if (attr.noFilter || attr.noFilter === 'true') {
14531                 scope.noFilter = true;
14532             } else {
14533                 scope.noFilter = false;
14534             }
14535             if (attr.placeholderAsOption === 'false') {
14536                 //scope.selectMsg = '';
14537                 scope.selectedOption = attr.placeholder;
14538             } else {
14539                 scope.selectMsg = attr.placeholder;
14540             }
14541             if (attr.startsWithFilter || attr.startsWithFilter === 'true') {
14542                 scope.startsWithFilter = true;
14543             }
14544             if (attr.showInputFilter === 'true') {
14545                 scope.showSearch = false;
14546                 $log.warn('showInputFilter functionality has been removed from the library.');
14547                 // This is deprecated
14548             }
14549             if (attr.disabled) {
14550                 scope.isDisabled = true;
14551             }
14552             dropdownElement = angular.element(element).children().eq(0).find('a')[0];
14553             var prevIndex = 0;
14554             var selectOptionFromSearch = function() {
14555                 if (!scope.noFilter) {
14556                     return;
14557                 }
14558
14559                 // Find next element that matches search criteria. 
14560                 // If no element is found, loop to beginning and search.
14561                 var criteria = search;
14562                 var i = 0;
14563                 for (i = prevIndex; i < scope.cName.length; i++) {
14564                     // Need to ensure we keep searching until all startsWith have passed before looping
14565                     if (scope.cName[i].title.startsWith(criteria) && i !== scope.selectedIndex) {
14566                         scope.selectOption(scope.cName[i], i, scope.showlist);
14567                         prevIndex = i;
14568                         search = '';
14569                         break;
14570                     }
14571                 }
14572                 if ((i >= scope.cName.length || !scope.cName[i+1].title.startsWith(criteria)) && prevIndex > 0) {
14573                     prevIndex = 0;
14574                 }
14575             };
14576             scope.showDropdown = function() {
14577                 if (!(attr.disabled)) {
14578                     scope.showlist = !scope.showlist;
14579                     scope.setSelectTop();
14580                 }
14581             };
14582             element.bind('keydown', function(e) {
14583                 if (keymap.isAllowedKey(e.keyCode) || keymap.isControl(e) || keymap.isFunctionKey(e)) {
14584                     e.preventDefault();
14585                     e.stopPropagation();
14586
14587                     switch (e.keyCode) {
14588                         case keymap.KEY.DOWN:
14589                             scope.selectNext();
14590                             break;
14591                         case keymap.KEY.UP:
14592                             scope.selectPrev();
14593                             search = '';
14594                             break;
14595                         case keymap.KEY.ENTER:
14596                             scope.selectCurrent();
14597                             search = '';
14598                             break;
14599                         case keymap.KEY.BACKSPACE:
14600                             scope.title = '';
14601                             search = '';
14602                             scope.$apply();
14603                             break;
14604                         case keymap.KEY.SPACE:
14605                             if (!scope.noFilter) {
14606                                 scope.title += ' ';
14607                             }
14608                             scope.$apply();
14609                             break;
14610                         case keymap.KEY.ESC:
14611                             if (scope.title === '' || scope.title === undefined) {
14612                                 scope.showlist = false;
14613                                 dropdownElement.focus();
14614                                 scope.$apply();
14615                             } else {
14616                                 scope.title = '';
14617                                 scope.$apply();
14618                             }
14619                             if (scope.noFilter) {
14620                                 search = '';
14621                                 dropdownElement.focus();
14622                                 scope.showlist = false;
14623                             }
14624                             break;
14625                         default:
14626                             break;
14627                     }
14628                 } else {
14629                     if (e.keyCode !== 9)
14630                     {
14631                         if (!scope.noFilter) {
14632                             scope.showlist = true;
14633                             scope.title = scope.title ? scope.title + String.fromCharCode(e.keyCode) : String.fromCharCode(e.keyCode);
14634                         } else {
14635                             var date = new Date();
14636                             var delta = Math.abs(prevSearchDate.getMilliseconds() - date.getMilliseconds());
14637                             prevSearchDate = date;
14638                             if (delta > 100) {
14639                                 search = '';
14640                             }
14641                             search = search ? search + String.fromCharCode(e.keyCode) : String.fromCharCode(e.keyCode);
14642                             if (search.length > 2) {
14643                                 search = search.substring(0, 2);
14644                             }
14645                             selectOptionFromSearch();
14646                         }
14647                         scope.$apply();
14648                     } else if (e.keyCode === 9) {
14649                         scope.showlist = false;
14650                         scope.title = '';
14651                         scope.$apply();
14652                     }
14653                 }
14654             });
14655             scope.selectOption = function(sTitle, sIndex, keepOpen) {
14656                 if (sIndex === -1 || sIndex === '-1') {
14657                     scope.selCategory = '';
14658                     scope.selectedIndex = -1;
14659                     ctrl.$setViewValue('');
14660                     if(attr.placeholderAsOption !== 'false')
14661                     {
14662                         scope.selectedOption = scope.selectMsg;
14663                     }
14664                 } else {
14665                     scope.selCategory = scope.cName[sIndex];
14666                     scope.selectedIndex = sIndex;
14667                     ctrl.$setViewValue(scope.selCategory);
14668                     scope.selectedOption = scope.selCategory.title;
14669                     if (angular.isDefined(list[sIndex])) {
14670                         list[sIndex].focus();
14671                     }
14672                 }
14673                 scope.title = '';
14674                 if (!keepOpen) {
14675                     scope.showlist = false;
14676                     dropdownElement.focus();
14677                 }
14678                 scope.$apply();
14679             };
14680             scope.selectCurrent = function() {
14681                 if (scope.showlist) {
14682                     scope.selectOption(scope.selectMsg, scope.selectedIndex, false);
14683                     scope.$apply();
14684                 } else {
14685                     scope.showlist = true;
14686                     scope.setSelectTop();
14687                     scope.$apply();
14688                 }
14689             };
14690             scope.hoverIn = function(cItem) {
14691                 scope.selectedIndex = cItem;
14692                 scope.focusme();
14693             };
14694             scope.setSelectTop = function() {
14695                 $timeout(function() {
14696                     if (scope.showlist && !scope.noFilter)
14697                     {
14698                         var containerUL = angular.element(element)[0].querySelector(".select2-results");
14699                         if(angular.element(containerUL.querySelector('.select2-result-current'))[0])
14700                         {
14701                             var selectedElemTopPos = angular.element(containerUL.querySelector('.select2-result-current'))[0].offsetTop;
14702                         }
14703                         angular.element(containerUL)[0].scrollTop = selectedElemTopPos;
14704                     }
14705                 });
14706             };
14707             scope.setCurrentTop = function() {
14708                 $timeout(function() {
14709                     if (scope.showlist) {
14710                         var containerUL = angular.element(element)[0].querySelector(".select2-results");
14711                         if(angular.element(containerUL.querySelector('.hovstyle'))[0])
14712                         {
14713                             var selectedElemTopPos = angular.element(containerUL.querySelector('.hovstyle'))[0].offsetTop;
14714                         }
14715                         if (selectedElemTopPos < (angular.element(containerUL)[0].scrollTop)) {
14716                             angular.element(containerUL)[0].scrollTop -= 30;
14717                         } else if ((selectedElemTopPos + 30) > (angular.element(containerUL)[0].clientHeight)) {
14718                             angular.element(containerUL)[0].scrollTop += 30;
14719                         }
14720
14721                     }
14722                 });
14723             };
14724             scope.selectNext = function() {
14725                 if ((scope.selectedIndex + 1) <= (scope.cName.length - 1)) {
14726                     scope.selectedIndex += 1;
14727                     if (!scope.showlist) {
14728                         scope.selectOption(scope.selectMsg, scope.selectedIndex, false);
14729                     }
14730                     scope.focusme();
14731                     scope.$apply();
14732                 }
14733                 scope.setCurrentTop();
14734             };
14735             scope.selectPrev = function() {
14736                 if ((scope.selectedIndex - 1) >= 0) {
14737                     scope.selectedIndex -= 1;
14738                     if (!scope.showlist) {
14739                         scope.selectOption(scope.selectMsg, scope.selectedIndex, false);
14740                     }
14741                     scope.focusme();
14742                     scope.$apply();
14743                 } else if (scope.selectedIndex - 1 < 0) {
14744                     // If placeholderAsOption is true or undefined (default), ensure we can select it on up key.
14745                     if (attr.placeholderAsOption === undefined || attr.placeholderAsOption === 'true') {
14746                         scope.selectedIndex = -1;
14747                     } else {
14748                         scope.selectedIndex = 0;
14749                     }
14750                     if (!scope.showlist) {
14751                         scope.selectOption(scope.selectMsg, scope.selectedIndex, false);
14752                     }
14753                     scope.focusme();
14754                     scope.$apply();
14755                 }
14756                 scope.setCurrentTop();
14757             };
14758             scope.updateSelection = function(sItem) {
14759                 scope.selectedOption = sItem.title;
14760                 scope.title = "";
14761             };
14762             scope.focusme = function() {
14763                 $timeout(function() {
14764                     var list = angular.element(element).find('ul').find('li');
14765                     var index = scope.selectedIndex + 2;
14766                     if (scope.noFilter) {
14767                         index = scope.selectedIndex;
14768                     }
14769                     if (angular.isDefined(list[index])) {
14770                         list[index].focus();
14771                     }
14772                 });
14773             };
14774             scope.$watch('selCategory', function(value) {
14775                 if (value) {
14776                     scope.updateSelection(value);
14777                 };
14778             });
14779             ctrl.$viewChangeListeners.push(function() {
14780                 scope.$eval(attr.ngChange);
14781             });
14782             ctrl.$render = function() {
14783                 scope.selCategory = ctrl.$viewValue;
14784             };
14785             var outsideClick = function(e) {
14786                 var isElement = $isElement(angular.element(e.target), element, $document);
14787                 if (!isElement) {
14788                     scope.showlist = false;
14789                     dropdownElement.focus();
14790                     scope.$apply();
14791                 }
14792             };
14793             $documentBind.click('showlist', outsideClick, scope);
14794         }
14795     };
14796 }]);
14797 angular.module('att.abs.select', ['att.abs.utilities', 'att.abs.position', 'att.abs.utilities'])
14798 .directive('attSelect', ["$document", "$filter", "$isElement", '$documentBind', '$timeout', 'keymap', '$log', function($document, $filter, $isElement, $documentBind, $timeout, keymap, $log) {
14799     return {
14800         restrict: 'A',
14801         scope: {
14802             cName: '=attSelect'
14803         },
14804         transclude: false,
14805         replace: false,
14806         require: 'ngModel',
14807         templateUrl: 'app/scripts/ng_js_att_tpls/select/select.html',
14808         link: function(scope, element, attr, ctrl) {
14809             scope.selectedIndex = -1;
14810             scope.selectedOption = attr.placeholder;
14811             scope.isDisabled = false;
14812             scope.className = "select2-match";
14813             scope.showSearch = false;
14814             scope.showlist = false;
14815                         scope.titleName = attr.titlename;
14816             scope.$watch('ngModel', function() {
14817                // console.log('sv:', ctrl.$modelValue);
14818             });
14819
14820             // This is used to jump to elements in list
14821             var search = '';
14822             // This is used to ensure searches only persist so many ms.
14823             var prevSearchDate = new Date();
14824             // This is used to shift focus back after closing dropdown
14825             var dropdownElement = undefined;
14826             // Used to ensure focus on dropdown elements
14827             var list = [];
14828             $timeout(function() {
14829                 list = element.find('li');
14830             }, 10);
14831                         //scope.noFilter = true;
14832             if (attr.noFilter || attr.noFilter === 'true') {
14833                 scope.noFilter = true;
14834             } else {
14835                 scope.noFilter = false;
14836             }
14837             if (attr.placeholderAsOption === 'false') {
14838                 scope.selectedOption = attr.placeholder;
14839             } else {
14840                 scope.selectMsg = attr.placeholder;
14841             }
14842             if (attr.startsWithFilter || attr.startsWithFilter === 'true') {
14843                 scope.startsWithFilter = true;
14844             }
14845             if (attr.showInputFilter === 'true') {
14846                 scope.showSearch = false;
14847                 /* This is deprecated */
14848                 $log.warn('showInputFilter functionality has been removed from the library.');   
14849             }
14850             if (attr.disabled) {
14851                 scope.isDisabled = true;
14852             }
14853             var getFilterType = function() {
14854                 if (scope.startsWithFilter) {
14855                     return 'startsWith';
14856                 } else {
14857                     return 'filter';
14858                 }
14859             };
14860             dropdownElement = angular.element(element).children().eq(0).find('span')[0];
14861             var prevIndex = 0;
14862             var selectOptionFromSearch = function() {
14863                 if (!scope.noFilter) {
14864                     return;
14865                 }
14866
14867                 // Find next element that matches search criteria.
14868                 // If no element is found, loop to beginning and search.
14869                 var criteria = search;
14870                 var i = 0;
14871                 for (i = prevIndex; i < scope.cName.length; i++) {
14872                     // Need to ensure we keep searching until all startsWith have passed before looping
14873                     if (scope.cName[i].title.startsWith(criteria) && i !== scope.selectedIndex) {
14874                         scope.selectOption(scope.cName[i], i, scope.showlist);
14875                         prevIndex = i;
14876                         search = '';
14877                         break;
14878                     }
14879                 }
14880                 if ((i >= scope.cName.length || !scope.cName[i+1].title.startsWith(criteria)) && prevIndex > 0) {
14881                     prevIndex = 0;
14882                 }
14883             };
14884             scope.showDropdown = function() {
14885                 if (!(attr.disabled)) {
14886                     scope.showlist = !scope.showlist;
14887                     scope.setSelectTop();
14888                     /* Ensure selected element is focused upon opening dropdown */
14889                     scope.focusme();
14890                 }
14891             };
14892             element.bind('keydown', function(e) {
14893                 if (keymap.isAllowedKey(e.keyCode) || keymap.isControl(e) || keymap.isFunctionKey(e)) {
14894                     e.preventDefault();
14895                     e.stopPropagation();
14896
14897                     switch (e.keyCode) {
14898                         case keymap.KEY.DOWN:
14899                             scope.selectNext();
14900                             break;
14901                         case keymap.KEY.UP:
14902                             scope.selectPrev();
14903                             search = '';
14904                             break;
14905                         case keymap.KEY.ENTER:
14906                             scope.selectCurrent();
14907                             search = '';
14908                             break;
14909                         case keymap.KEY.BACKSPACE:
14910                             scope.title = '';
14911                             search = '';
14912                             scope.$apply();
14913                             break;
14914                         case keymap.KEY.SPACE:
14915                             if (!scope.noFilter) {
14916                                 scope.title += ' ';
14917                             }
14918                             scope.$apply();
14919                             break;
14920                         case keymap.KEY.ESC:
14921                             if (scope.title === '' || scope.title === undefined) {
14922                                 scope.showlist = false;
14923                                 dropdownElement.focus();
14924                                 scope.$apply();
14925                             } else {
14926                                 scope.title = '';
14927                                 scope.$apply();
14928                             }
14929                             if (scope.noFilter) {
14930                                 search = '';
14931                                 dropdownElement.focus();
14932                                 scope.showlist = false;
14933                             }
14934                             break;
14935                         default:
14936                             break;
14937                     }
14938                 } else {
14939                     if (e.keyCode !== keymap.KEY.TAB)
14940                     {
14941                         if (!scope.noFilter) {
14942                             scope.showlist = true;
14943                             scope.title = scope.title ? scope.title + String.fromCharCode(e.keyCode) : String.fromCharCode(e.keyCode);
14944
14945                             /* Perform index correction */
14946                             if (scope.title != '') {
14947                                 var filteredArray = $filter(getFilterType())(scope.cName, scope.title);
14948
14949                                 for (var i = 0; i < filteredArray.length; i++) {
14950                                     for (var j = 0; j < scope.cName.length; j++) {
14951                                         if (!angular.isDefined(scope.cName[scope.selectedIndex])) {
14952                                             break;
14953                                         }
14954                                         if (filteredArray[i]['title'] === scope.cName[scope.selectedIndex]['title']) {
14955                                             scope.selectedIndex = i;
14956                                             scope.focusme();
14957                                             break;
14958                                         }
14959                                     }
14960                                 }
14961                             }
14962                         } else {
14963                             var date = new Date();
14964                             var delta = Math.abs(prevSearchDate.getMilliseconds() - date.getMilliseconds());
14965                             prevSearchDate = date;
14966                             if (delta > 100) {
14967                                 search = '';
14968                             }
14969                             search = search ? search + String.fromCharCode(e.keyCode) : String.fromCharCode(e.keyCode);
14970                             if (search.length > 2) {
14971                                 search = search.substring(0, 2);
14972                             }
14973                             selectOptionFromSearch();
14974                         }
14975                         scope.$apply();
14976                     } else if (e.keyCode === keymap.KEY.TAB) {
14977                         scope.showlist = false;
14978                         scope.title = '';
14979                         scope.$apply();
14980                     }
14981                 }
14982             });
14983             scope.selectOption = function(sTitle, sIndex, keepOpen) {
14984
14985                 if (sIndex === -1 || sIndex === '-1') {
14986                     scope.selCategory = '';
14987                     scope.selectedIndex = -1;
14988                     ctrl.$setViewValue('');
14989                     if(attr.placeholderAsOption !== 'false')
14990                     {
14991                         scope.selectedOption = scope.selectMsg;
14992                     }
14993                 }
14994                 else {
14995                     /* Apply filter here to remap the selected index and shift focus*/
14996                     if (scope.title != '') {
14997                         var filteredArray = $filter(getFilterType())(scope.cName, scope.title);
14998
14999                         if (angular.isDefined(filteredArray) && angular.isDefined(filteredArray[sIndex]))
15000                         {
15001                             for (var i = 0; i < scope.cName.length; i++) {
15002                                 if (filteredArray[sIndex]['title'] === scope.cName[i]['title']) {
15003                                     sIndex = i;
15004                                     break;
15005                                 }
15006                             }
15007                         }
15008                     }
15009                     scope.selCategory = scope.cName[sIndex];
15010                     scope.selectedIndex = sIndex;
15011                     ctrl.$setViewValue(scope.selCategory);
15012                     scope.selectedOption = scope.selCategory.title;
15013                     ctrl.$render();
15014
15015                     $timeout(function(){
15016                         if (angular.isDefined(list[sIndex])) {
15017                             try{
15018                                 list[index].focus();
15019                             } catch (e) {} /* IE8 will throw exception if display:none or not in DOM */
15020                         }
15021                     });
15022                 }
15023                 scope.title = '';
15024                 if (!keepOpen) {
15025                     scope.showlist = false;
15026                     dropdownElement.focus();
15027                 }
15028             };
15029             scope.selectCurrent = function() {
15030                 if (scope.showlist) {
15031                     scope.selectOption(scope.selectMsg,scope.selectedIndex,false);
15032                 } else {
15033                     scope.showlist = true;
15034                     scope.setSelectTop();
15035                 }
15036                 scope.$apply();
15037             };
15038             scope.hoverIn = function(cItem) {
15039                 scope.selectedIndex = cItem;
15040                 scope.focusme();
15041             };
15042             scope.setSelectTop = function() {
15043                 $timeout(function() {
15044                     if (scope.showlist && !scope.noFilter)
15045                     {
15046                         var containerUL = angular.element(element)[0].querySelector(".select2-results");
15047                         if(angular.element(containerUL.querySelector('.select2-result-current'))[0])
15048                         {
15049                             var selectedElemTopPos = angular.element(containerUL.querySelector('.select2-result-current'))[0].offsetTop;
15050                         }
15051                         angular.element(containerUL)[0].scrollTop = selectedElemTopPos;
15052                     }
15053                 });
15054             };
15055             scope.setCurrentTop = function() {
15056                 $timeout(function() {
15057                     if (scope.showlist) {
15058                         var containerUL = angular.element(element)[0].querySelector(".select2-results");
15059                         if(angular.element(containerUL.querySelector('.hovstyle'))[0])
15060                         {
15061                             var selectedElemTopPos = angular.element(containerUL.querySelector('.hovstyle'))[0].offsetTop;
15062                         }
15063                         if (selectedElemTopPos < (angular.element(containerUL)[0].scrollTop)) {
15064                             angular.element(containerUL)[0].scrollTop -= 30;
15065                         } else if ((selectedElemTopPos + 30) > (angular.element(containerUL)[0].clientHeight)) {
15066                             angular.element(containerUL)[0].scrollTop += 30;
15067                         }
15068
15069                     }
15070                 });
15071             };
15072             scope.selectNext = function() {
15073                 var length = scope.cName.length;
15074                 
15075                 if ((scope.selectedIndex + 1) <= (scope.cName.length - 1)) {
15076                     scope.selectedIndex += 1;
15077                     var nextDisabled = scope.cName[scope.selectedIndex].disabled;
15078                     if (nextDisabled) {
15079                         scope.selectedIndex += 1;
15080                     }
15081                     if (!scope.showlist) {
15082                         scope.selectOption(scope.selectMsg, scope.selectedIndex,false);
15083                     }
15084                     scope.focusme();
15085                     scope.$apply();
15086                 }
15087                 scope.setCurrentTop();
15088             };
15089             scope.selectPrev = function() {
15090                 if ((scope.selectedIndex - 1) >= 0) {
15091                     scope.selectedIndex -= 1;
15092                     var prevDisabled = scope.cName[scope.selectedIndex].disabled;
15093                     if (prevDisabled) {
15094                         scope.selectedIndex -= 1;
15095                     }
15096                     if (!scope.showlist) {
15097                         scope.selectOption(scope.selectMsg, scope.selectedIndex,false);
15098                     }
15099                     scope.focusme();
15100                     scope.$apply();
15101                 } else if (scope.selectedIndex - 1 < 0) {
15102                     // If placeholderAsOption is true or undefined (default), ensure we can select it on up key.
15103                     if (attr.placeholderAsOption === undefined || attr.placeholderAsOption === 'true') {
15104                         if(attr.placeholder === undefined ){
15105                             scope.selectedIndex = 0;
15106                         }
15107                         else{
15108                             scope.selectedIndex = -1;
15109                         }
15110                     } else {
15111                         scope.selectedIndex = 0;
15112                     }
15113                     if (!scope.showlist) {
15114                         scope.selectOption(scope.selectMsg, scope.selectedIndex,false);
15115                     }
15116                     scope.focusme();
15117                     scope.$apply();
15118                 }
15119                 scope.setCurrentTop();
15120             };
15121             scope.updateSelection = function(sItem) {
15122                 scope.selectedOption = sItem.title;
15123                 scope.title = '';
15124
15125                 if (sItem.index < 0) {
15126                     scope.selectOption(scope.selectMsg, sItem.index, scope.showlist);
15127                 }
15128             };
15129             scope.focusme = function() {
15130                 $timeout(function() {
15131                     var list = angular.element(element).find('ul').find('li');
15132                     var index = scope.selectedIndex + 2;
15133                     if (scope.noFilter) {
15134                         index = scope.selectedIndex;
15135                     }
15136                     if (angular.isDefined(list[index])) {
15137                         try {
15138                             list[index].focus();
15139                         } catch (e) {} /* IE8 will throw exception if display:none or not in DOM */  
15140                     }
15141                 });
15142             };
15143             scope.$watch('selCategory', function(value) {
15144                 if (value) {
15145                     scope.updateSelection(value);
15146                 };
15147             });
15148             ctrl.$viewChangeListeners.push(function() {
15149                 scope.$eval(attr.ngChange);
15150             });
15151             ctrl.$render = function() {
15152                 scope.selCategory = ctrl.$viewValue;
15153             };
15154             var outsideClick = function(e) {
15155                 var isElement = $isElement(angular.element(e.target), element, $document);
15156                 if (!isElement) {
15157                     scope.showlist = false;
15158                     dropdownElement.focus();
15159                     scope.$apply();
15160                 }
15161             };
15162             $documentBind.click('showlist', outsideClick, scope);
15163         }
15164     };
15165 }])
15166 .directive('textDropdown', ['$document', '$isElement', '$documentBind', "keymap", function($document, $isElement, $documentBind, keymap) {
15167     return {
15168         restrict: 'EA',
15169         replace: true,
15170         scope: {
15171             actions: '=actions',
15172             defaultAction: '=defaultAction',
15173             onActionClicked: '=?'
15174         },
15175         templateUrl: 'app/scripts/ng_js_att_tpls/select/textDropdown.html',
15176         link: function(scope, element, attr) {
15177             scope.selectedIndex = 0;
15178             scope.selectedOption = attr.placeholder;
15179             scope.isDisabled = false;
15180             scope.isActionsShown = false;
15181             var dropdownElement = undefined;
15182             if (attr.disabled) {
15183                 scope.isDisabled = true;
15184             }
15185
15186             dropdownElement = element.find('div')[0];
15187
15188             // Set default Action
15189             if (!angular.isDefined(scope.defaultAction)) {
15190                 scope.currentAction = scope.actions[0];
15191                 scope.selectedIndex = 0;
15192             } else if (angular.isDefined(scope.defaultAction) || scope.defaultAction !== '') {
15193                 for (var act in scope.actions) {
15194                     if (scope.actions[act] === scope.defaultAction) {
15195                         scope.currentAction = scope.actions[act];
15196                         scope.selectedIndex = scope.actions.indexOf(act);
15197                         scope.isActionsShown = false;
15198                         break;
15199                     }
15200                 }
15201             } else {
15202                 scope.currentAction = scope.actions[0];
15203             }
15204             scope.toggle = function() {
15205                 scope.isActionsShown = !scope.isActionsShown;
15206             };
15207             scope.chooseAction = function($event, action, $index) {
15208                 if ($event != null) {
15209                     scope.currentAction = action;
15210                     scope.selectedIndex = $index;
15211                 } else {
15212                     scope.currentAction = scope.actions[scope.selectedIndex];
15213                 }
15214                 if (angular.isFunction(scope.onActionClicked)) {
15215                     scope.onActionClicked(scope.currentAction);
15216                 }
15217                 scope.toggle();
15218             };
15219             scope.isCurrentAction = function(action) {
15220                 return (action === scope.currentAction);
15221             };
15222             element.bind("keydown", function(e) {
15223                 if (keymap.isAllowedKey(e.keyCode) || keymap.isControl(e) || keymap.isFunctionKey(e)) {
15224                     e.preventDefault();
15225                     e.stopPropagation();
15226                     switch (e.keyCode) {
15227                         case keymap.KEY.DOWN:
15228                             scope.selectNext();
15229                             break;
15230                         case keymap.KEY.UP:
15231                             scope.selectPrev();
15232                             break;
15233                         case keymap.KEY.ENTER:
15234                             scope.selectCurrent();
15235                             break;
15236                         case keymap.KEY.ESC:
15237                             scope.isActionsShown = false;
15238                             dropdownElement.focus();
15239                             scope.$apply();
15240                             break;
15241                         default:
15242                             break;
15243                     }
15244                     scope.$apply();
15245                     return;
15246                 } else if (e.keyCode === keymap.KEY.TAB) {
15247                     scope.isActionsShown = false;
15248                     scope.$apply();
15249                 }
15250             });
15251             scope.selectCurrent = function() {
15252                 if (scope.selectedIndex < 0) {
15253                     scope.selectedIndex = 0;
15254                 }
15255                 if (!scope.isActionsShown) {
15256                     scope.toggle();
15257                 } else {
15258                     scope.chooseAction(null, scope.currentAction);
15259                 }
15260             };
15261             scope.selectNext = function() {
15262                 if (scope.isActionsShown) {
15263                     if ((scope.selectedIndex + 1) < scope.actions.length) {
15264                         scope.selectedIndex += 1;
15265                     } else {
15266                         scope.selectedIndex = (scope.actions.length - 1);
15267                     }
15268                     scope.$apply();
15269                 }
15270             };
15271             scope.selectPrev = function() {
15272                 if (scope.isActionsShown) {
15273                     if ((scope.selectedIndex - 1) >= 0) {
15274                         scope.selectedIndex -= 1;
15275                     } else if (scope.selectedIndex - 1 < 0) {
15276                         scope.selectedIndex = 0;
15277                     }
15278                     scope.$apply();
15279                 }
15280             };
15281             scope.hoverIn = function(cItem) {
15282                 scope.selectedIndex = cItem;
15283             };
15284             //end cato
15285             var outsideClick = function(e) {
15286                 var isElement = $isElement(angular.element(e.target), element, $document);
15287                 if (!isElement) {
15288                     scope.toggle();
15289                     scope.$apply();
15290                 }
15291             };
15292             $documentBind.click('isActionsShown', outsideClick, scope);
15293         }
15294     };
15295 }]);
15296 angular.module('att.abs.slider', ['att.abs.position'])
15297         .constant('sliderDefaultOptions', {
15298             width: 300,
15299             step: 1,
15300             precision: 0,
15301             disabledWidth: 116
15302         })
15303         .directive('attSlider', ['sliderDefaultOptions','$position','$document', function(sliderDefaultOptions,$position,$document)
15304             {
15305                 return {
15306                     restrict: 'EA',
15307                     replace: true,
15308                     transclude: true,
15309                     scope: {
15310                         floor: "=",
15311                         ceiling: "=",
15312                         step: "@",
15313                         precision: "@",
15314                         width: "@",
15315                         textDisplay: "=",
15316                         value: "=",
15317                         ngModelSingle: '=?',
15318                         ngModelLow: '=?',
15319                         ngModelHigh: '=?',
15320                         ngModelDisabled: '=?'
15321                     },
15322                     templateUrl: 'app/scripts/ng_js_att_tpls/slider/slider.html',
15323                     link: function(scope, elem, attr)
15324                     {
15325                         var minOffset, maxOffset, newOffset, newOffset1, newOffset2, offsetRange, valueRange, start_x = 0, disabledRange, disabled, evFlag = false, minValue, maxValue, range, refLow, refHigh, maxPtr, minPtr, singlePtr, getHandles;
15326                         scope.minPtrOffset = 0;
15327                         scope.maxPtrOffset = 0;
15328                         var disableWidth = sliderDefaultOptions.disabledWidth;
15329                         //Get handles
15330                         var obj = elem.children();
15331                         disabledRange = obj[0].children;
15332                         disabledRange = angular.element(disabledRange[0]);
15333                         getHandles = obj[1].children;
15334                         singlePtr = angular.element(getHandles[0]);
15335                         minPtr = angular.element(getHandles[1]);
15336                         maxPtr = angular.element(getHandles[2]);
15337                         disabled = ((attr.ngModelSingle == null) && (attr.ngModelLow == null) && (attr.ngModelHigh == null)) && (attr.ngModelDisabled != null);
15338                         range = (attr.ngModelSingle == null) && ((attr.ngModelLow != null) && (attr.ngModelHigh != null));
15339                         refLow = 'ngModelLow';
15340                         refHigh = 'ngModelHigh';
15341                         if (!range) {
15342                             minPtr.remove();
15343                             maxPtr.remove();
15344                         }
15345                         else {
15346                             singlePtr.remove();
15347                         }
15348                         if (!disabled) {
15349                             disabledRange.remove();
15350                         }
15351                         else {
15352                             scope.disabledStyle = {width: disableWidth + 'px', zIndex: 1};
15353                             scope.handleStyle = {left: disableWidth + 'px'};
15354                         }
15355                         minValue = parseFloat(scope.floor);
15356                         maxValue = parseFloat(scope.ceiling);
15357                         valueRange = maxValue - minValue;
15358                         minOffset = 0;
15359                         if (attr.width !== undefined) {
15360                             maxOffset = attr.width;
15361                         }
15362                         else {
15363                             if (elem[0].clientWidth !== 0) {
15364                                 maxOffset = elem[0].clientWidth;
15365                             }
15366                             else {
15367                                 maxOffset = sliderDefaultOptions.width;
15368                             }
15369                         }
15370                         offsetRange = maxOffset - minOffset;
15371                         //Key Down Event
15372                          scope.keyDown = function(ev){
15373                                if(ev.keyCode === 39){
15374                                 var elemLeft = $position.position(elem).left;
15375                                 if (newOffset){
15376                                     if(scope.ref === "ngModelLow"){
15377                                         newOffset1 = sliderDefaultOptions.step + newOffset1;
15378                                         newOffset = newOffset1;
15379                                     }
15380                                     else if(scope.ref === "ngModelHigh"){
15381                                         newOffset2 = sliderDefaultOptions.step + newOffset2;
15382                                         newOffset = newOffset2;
15383                                     }
15384                                     else{newOffset = sliderDefaultOptions.step + newOffset;}
15385                                 }
15386                                 else {
15387                                     if(range &&scope.ref === "ngModelLow"){
15388                                         return;
15389                                     }
15390                                     else {
15391                                         newOffset = sliderDefaultOptions.step + elemLeft;
15392                                         newOffset1 = newOffset2 = newOffset;
15393                                     }
15394                                 }
15395                                 }
15396                             else if(ev.keyCode === 37){
15397                                 var ptrLeft = $position.position(singlePtr).left;
15398                                 if(newOffset){
15399                                 if (!(newOffset<=0)){
15400                                     if(scope.ref === "ngModelLow"){
15401                                         newOffset1 = newOffset1 - sliderDefaultOptions.step;
15402                                         newOffset = newOffset1;
15403                                     }
15404                                     else if(scope.ref === "ngModelHigh"){
15405                                         newOffset2 = newOffset2 - sliderDefaultOptions.step;
15406                                         newOffset = newOffset2;
15407                                     }
15408                                     else {
15409                                         newOffset = newOffset - sliderDefaultOptions.step;
15410                                         newOffset1 = newOffset2 = newOffset;
15411                                     }
15412                                 }
15413                                 }
15414                                 else {
15415                                     newOffset = ptrLeft - sliderDefaultOptions.step;
15416                                 }
15417                                 }
15418                             if(newOffset>=0){
15419                                 scope.ptrOffset(newOffset);
15420                             }
15421                         };
15422                         //Mouse Down Event                         
15423                         scope.mouseDown = function(e, ref) {
15424                             scope.ref = ref;
15425                             evFlag = true;
15426                             if (!range){
15427                                 if (newOffset)
15428                                 {
15429                                     start_x = e.clientX - newOffset;
15430                                 }
15431                                 else {
15432                                     start_x = e.clientX;
15433                                 }
15434                             } else {
15435                                 if (scope.ref === refLow) {
15436                                     start_x = e.clientX - scope.minPtrOffset;
15437                                 }
15438                                 else {
15439                                     start_x = e.clientX - scope.maxPtrOffset;
15440                                 }
15441                             }
15442                             if (disabled) {
15443                                 scope.ref= 'ngModelDisabled';
15444                                 scope.disabledStyle = {width: disableWidth + 'px', zIndex: 1};
15445                             }
15446                         };
15447                         // Mouse Move Event
15448                         scope.moveElem = function(ev) {
15449                             if (evFlag) {
15450                                 var eventX;
15451                                 eventX = ev.clientX;
15452                                 newOffset = eventX - start_x;
15453                                 scope.ptrOffset(newOffset);
15454                             }
15455                         };
15456                         scope.focus=function(ev,ref){
15457                             console.log(ref);
15458                             scope.ref=ref;
15459                         }
15460                         // Mouse Up Event
15461                         scope.mouseUp = function(ev) {
15462                             evFlag = false;
15463                             minPtr.removeClass('dragging');
15464                             maxPtr.removeClass('dragging');
15465                             singlePtr.removeClass('dragging');
15466                             $document.off('mousemove');
15467                         };
15468                         // key Up Event
15469                         scope.keyUp = function(ev) {
15470                             evFlag = false;
15471                             minPtr.removeClass('dragging');
15472                             maxPtr.removeClass('dragging');
15473                             singlePtr.removeClass('dragging');
15474                             $document.off('mousemove');
15475                         };
15476                         //Function to calculate the current PositionValue
15477                         scope.calStep = function(value, precision, step, floor) {
15478                             var decimals, remainder, roundedValue, steppedValue;
15479                             if (floor === null) {
15480                                 floor = 0;
15481                             }
15482                             if (step === null) {
15483                                 step = 1 / Math.pow(10, precision);
15484                             }
15485                             remainder = (value - floor) % step;
15486                             steppedValue = remainder > (step / 2) ? value + step - remainder : value - remainder;
15487                             decimals = Math.pow(10, precision);
15488                             roundedValue = steppedValue * decimals / decimals;
15489                             return roundedValue.toFixed(precision);
15490                         };
15491                         //Function to calculate Offset Percent
15492                         scope.percentOffset = function(offset) {
15493                             return ((offset - minOffset) / offsetRange) * 100;
15494                         };
15495                         //Function to calculate Offset position
15496                         scope.ptrOffset = function(newOffset){
15497                             var newPercent, newValue;
15498                                 newOffset = Math.max(Math.min(newOffset, maxOffset), minOffset);
15499                                 newPercent = scope.percentOffset(newOffset);
15500                                 newValue = minValue + (valueRange * newPercent / 100.0);
15501                                 if (range) {
15502                                     var rangeSliderWidth;
15503                                     if (scope.ref === refLow) {
15504                                         scope.minHandleStyle = {left: newOffset + "px"};
15505                                         scope.minNewVal = newValue;
15506                                         scope.minPtrOffset = newOffset;
15507                                         minPtr.addClass('dragging');
15508                                         if (newValue > scope.maxNewVal) {
15509                                             scope.ref = refHigh;
15510                                             maxPtr[0].focus();
15511                                             scope.maxNewVal = newValue;
15512                                             scope.maxPtrOffset = newOffset;
15513                                             maxPtr.addClass('dragging');
15514                                             minPtr.removeClass('dragging');
15515                                             scope.maxHandleStyle = {left: newOffset + "px"};
15516                                         }
15517                                     }
15518                                     else {
15519                                         scope.maxHandleStyle = {left: newOffset + "px"};
15520                                         scope.maxNewVal = newValue;
15521                                         scope.maxPtrOffset = newOffset;
15522                                         maxPtr.addClass('dragging');
15523                                         if (newValue < scope.minNewVal) {
15524                                             scope.ref = refLow;
15525                                             minPtr[0].focus();
15526                                             scope.minVal = newValue;
15527                                             scope.minPtrOffset = newOffset;
15528                                             minPtr.addClass('dragging');
15529                                             maxPtr.removeClass('dragging');
15530                                             scope.minHandleStyle = {left: newOffset + "px"};
15531                                         }
15532                                     }
15533                                     rangeSliderWidth = parseInt(scope.maxPtrOffset) - parseInt(scope.minPtrOffset);
15534                                     scope.rangeStyle = {width: rangeSliderWidth + "px", left: scope.minPtrOffset + "px"};
15535                                 }
15536                                 else {
15537                                     if (disabled && newOffset > disableWidth) {
15538                                         scope.rangeStyle = {width: newOffset + "px", zIndex: 0};
15539                                     }
15540                                     else {
15541                                         singlePtr.addClass('dragging');
15542                                         scope.rangeStyle = {width: newOffset + "px"};
15543                                     }
15544                                     scope.handleStyle = {left: newOffset + "px"};
15545                                 }
15546                                 if ((scope.precision === undefined) || (scope.step === undefined)) {
15547                                     scope.precision = sliderDefaultOptions.precision;
15548                                     scope.step = sliderDefaultOptions.step;
15549                                 }
15550                                 newValue = scope.calStep(newValue, parseInt(scope.precision), parseFloat(scope.step), parseFloat(scope.floor));
15551                                 scope[scope.ref] = newValue;
15552                         };
15553                     }
15554                 };
15555             }
15556         ]).directive('attSliderMin',[function()
15557             {
15558              return{
15559                  require: '^attSlider',
15560                  restrict: 'EA',
15561                  replace: true,
15562                  transclude: true,
15563                  templateUrl: 'app/scripts/ng_js_att_tpls/slider/minContent.html'
15564                };
15565          }
15566     ]).directive('attSliderMax',[function()
15567             {
15568              return{
15569                  require: '^attSlider',
15570                  restrict: 'EA',
15571                  replace: true,
15572                  transclude: true,
15573                  templateUrl: 'app/scripts/ng_js_att_tpls/slider/maxContent.html'
15574              };
15575          }
15576     ]);
15577 angular.module('att.abs.splitButtonDropdown', ['att.abs.utilities','att.abs.position'])
15578     .directive('attButtonDropdown', ['$document', '$parse', '$documentBind', '$timeout','$isElement', function ($document, $parse, $documentBind, $timeout,$isElement) {
15579         return {
15580             restrict: 'EA',
15581             replace: true,
15582             transclude: true,            
15583             templateUrl: 'app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdown.html',
15584             scope: {
15585                 btnText: "@",
15586                 btnType: "@",
15587                 btnLink: "@",
15588                 btnClick: "&",
15589                 toggleTitle:"@",                
15590             },
15591             controller: ['$scope', '$element', function ($scope, $element) {
15592                     
15593                 this.cSelected = 0;    
15594                 this.closeAndFocusDropdown = function () {
15595                     if ($scope.isDropDownOpen) {
15596                         $scope.$apply(function () {
15597                         $scope.isDropDownOpen = false;
15598                         angular.element($element[0].querySelector('a.dropdown-toggle'))[0].focus();                        
15599                         });
15600                     }
15601                 };             
15602                 
15603                 this.focusNext = function () {                                            
15604                     this.cSelected = this.cSelected + 1 >= this.childScopes.length ?($scope.cycleSelection === true ? 0 : this.childScopes.length-1): this.cSelected +1;
15605                     this.childScopes[this.cSelected].sFlag = true;                    
15606                     this.resetFlag(this.cSelected);                    
15607                 }; 
15608                 
15609                 this.focusPrev = function () {                        
15610                     this.cSelected = this.cSelected -1 < 0 ? ($scope.cycleSelection === true ? this.childScopes.length-1 : 0) : this.cSelected - 1 ;
15611                     this.childScopes[this.cSelected].sFlag = true;                    
15612                     this.resetFlag(this.cSelected);                    
15613                 };                 
15614                                                 
15615                 this.childScopes = [];
15616                 this.registerScope = function(childScope)
15617                 {
15618                     this.childScopes.push(childScope);                    
15619                 };
15620                 
15621                 this.resetFlag = function(index){                                        
15622                     for(var i=0; i < this.childScopes.length; i++) 
15623                     {
15624                         if(i !== index)
15625                         {
15626                             this.childScopes[i].sFlag = false;
15627                         }
15628                     }
15629                 };
15630                 
15631             }],
15632             link: function (scope, element, attr) {                
15633                 scope.isSmall = attr.small === "" ? true : false;
15634                 scope.multiselect = attr.multiselect === ""? true : false;
15635                 scope.cycleSelection = attr.cycleSelection === "" ? true : false;
15636                 scope.isDropDownOpen = false;
15637                 scope.isActionDropdown = false;
15638                
15639                 if (!(scope.btnText)) {
15640                     scope.isActionDropdown = true;
15641                 }
15642
15643                 scope.clickFxn = function () {
15644                     if (typeof scope.btnClick === "function" && !scope.btnLink) {
15645                         scope.btnClick = $parse(scope.btnClick);
15646                         scope.btnClick();
15647                     }                    
15648                     if(scope.multiselect === true)
15649                     {
15650                         scope.isDropDownOpen = false;
15651                     }
15652                 };
15653
15654                 scope.toggleDropdown = function () {
15655                     if (!(scope.btnType === 'disabled')) {
15656                         scope.isDropDownOpen = !scope.isDropDownOpen;
15657                         if (scope.isDropDownOpen) {
15658                             $timeout(function () {
15659                                 angular.element(element[0].querySelector('li'))[0].focus();
15660                             });
15661                         }
15662                     }
15663                 };
15664
15665                 scope.btnTypeSelector = function (directiveValue, attrValue) {
15666                     if (directiveValue !== "") {
15667                         scope.btnTypeFinal = directiveValue;
15668                     } else {
15669                         scope.btnTypeFinal = attrValue;
15670                     }
15671                 };
15672
15673                 var outsideClick = function(e) {
15674                     var isElement = $isElement(angular.element(e.target), element.find('ul').eq(0), $document);
15675                     if (!isElement) {
15676                         scope.isDropDownOpen = false;
15677                         scope.$apply();
15678                     }
15679                 };
15680
15681                 $documentBind.click('isDropDownOpen', outsideClick, scope);
15682
15683                 attr.$observe('btnType', function (val) {
15684                     scope.btnType = val;
15685                 });
15686                 attr.$observe('attButtonDropdown', function (val) {
15687                     attr.attButtonDropdown = val;
15688                     scope.btnTypeSelector(attr.attButtonDropdown, scope.btnType);
15689                 });
15690             }
15691         };
15692
15693             }])
15694        
15695 .directive('attButtonDropdownItem', ['$location','keymap', function ($location,keymap) {
15696         return {
15697             restrict: 'EA',
15698             require: ['^attButtonDropdown','?ngModel'],
15699             replace: true,
15700             transclude: true,            
15701             templateUrl:'app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdownItem.html',                                                 scope: {
15702                 itemLink: "@"
15703             },
15704             link: function (scope, element, attr, ctrl) {
15705                 var rootLink = angular.element(element[0].querySelector('a'));
15706                 scope.sFlag = false;
15707                 ctrl[0].registerScope(scope);
15708                 var clickOnLink = function () {
15709                     if (scope.itemLinkFinal) {
15710                         $location.url(scope.itemLinkFinal);
15711                     }
15712                 };
15713                 
15714                 if(ctrl[1]){
15715                     scope.isSelected = ctrl[1].$viewValue;
15716                 }else{
15717                     scope.isSelected = false;
15718                 }                
15719                 
15720                 element.bind('keydown', function(e) {
15721                 if (keymap.isAllowedKey(e.keyCode) || keymap.isControl(e) || keymap.isFunctionKey(e)) {
15722                     e.preventDefault();
15723                     e.stopPropagation();
15724                     switch (e.keyCode) {
15725                         case keymap.KEY.DOWN: 
15726                             ctrl[0].focusNext();                             
15727                             break;
15728                         case keymap.KEY.UP:                            
15729                             ctrl[0].focusPrev();
15730                             break;
15731                         case keymap.KEY.ENTER:                                                        
15732                             scope.selectItem();
15733                             break;
15734                         case keymap.KEY.ESC:
15735                             ctrl[0].closeAndFocusDropdown();
15736                             break;
15737                         default:
15738                             break;
15739                     }
15740                     
15741                 }
15742                     scope.$apply();
15743                 }); 
15744                                  
15745                 scope.selectItem = function()
15746                 {
15747                     if(ctrl[1]){
15748                         scope.$evalAsync(function(){ctrl[1].$setViewValue(!ctrl[1].$viewValue)});
15749                     }
15750                 }; 
15751
15752             }
15753         };
15754     }]);
15755
15756 angular.module('att.abs.splitIconButton', ['att.abs.utilities'])
15757 .constant('iconStateConstants', {
15758     MIDDLE: 'middle',
15759     LEFT: 'left',
15760     RIGHT: 'right',
15761     NEXT_TO_DROPDOWN:'next-to-dropdown',
15762     LEFT_NEXT_TO_DROPDOWN:'left-next-to-dropdown',
15763     DIR_TYPE: {
15764         LEFT: 'left',
15765         RIGHT:  'right',
15766         BUTTON: 'button'
15767     },
15768     SPLIT_ICON_BTN_EVENT_EMITTER_KEY: 'splitIconButtonTap'
15769 })
15770 .directive('expandableLine', [function(){
15771     return {
15772         restrict: 'EA',
15773         replace: true,
15774         priority: 300,
15775         require: ['^attSplitIconButton', 'expandableLine'],
15776         controller: ['$scope', function($scope){
15777             $scope.isActive = false;
15778             this.setActiveState = function(isActive){
15779                 $scope.isActive = isActive;
15780             };
15781             this.isActive = $scope.isActive;
15782             this.dirType = $scope.dirType;
15783         }],
15784         template: '<div ng-class="{\'expand-line-container\': !isActive, \'expand-line-container-active\': isActive}"> <div ng-class="{\'hovered-line\':isActive, \'vertical-line\':!isActive}"> </div></div>',
15785         scope:{
15786             dirType: '@'
15787         },
15788         link: function(scope,element,attr,ctrls) {
15789             var attSplitIconButtonCtrl = ctrls[0];
15790             var expandableLineCtrl = ctrls[1];
15791             attSplitIconButtonCtrl.addSubCtrl(expandableLineCtrl);
15792         }
15793     };
15794 }])
15795 .controller('AttSplitIconCtrl', ['$scope', function($scope){
15796     this.setType = function(type){
15797         $scope.type = type;
15798     };  
15799     this.isDropdown = function(isDropdown){
15800          $scope.isDropdown = isDropdown;
15801     };
15802     this.dropDownClicked = function(){
15803         if($scope.dropDownClicked) {
15804             $scope.dropDownClicked();
15805         }
15806     };
15807     this.dirType = $scope.dirType;
15808 }])
15809 .directive('attSplitIcon', ['$document', '$timeout','iconStateConstants','$documentBind','events', 'keymap',
15810  function($document,$timeout,iconStateConstants,$documentBind, events, keymap){
15811     return {
15812         restrict: 'EA',
15813         replace: true,
15814         priority: 200,
15815         transclude: true,
15816         require: ['^attSplitIconButton','attSplitIcon'],
15817         templateUrl: 'app/scripts/ng_js_att_tpls/splitIconButton/splitIcon.html',
15818         scope:{
15819             icon: '@',
15820             iconTitle: '@title',
15821             hoverWatch: '=',
15822             dropDownWatch: '=',
15823             dirType: '@'
15824         },
15825         controller:'AttSplitIconCtrl',
15826         link: function(scope,element,attr,ctrls){
15827             var attSplitIconButtonCtrl = ctrls[0];
15828             var attSplitIconCtrl = ctrls[1];
15829             attSplitIconButtonCtrl.addSubCtrl(attSplitIconCtrl);
15830             scope.iconStateConstants = iconStateConstants;
15831             var currentIndex = 0;
15832             var isMyElement = false;
15833             var listElements;
15834             scope.isDropdown = false;
15835             scope.isDropdownOpen = false;
15836             var outsideClick = function(e) {
15837                 if(scope.isDropdown){
15838                     if (isMyElement) {
15839                         isMyElement = false;
15840                         scope.toggleDropdown();
15841                     } else{
15842                         scope.toggleDropdown(false);
15843                     }
15844                     scope.$apply();
15845                 }
15846             };
15847             if(attr.dropDownId && attr.dropDownId !== ''){
15848                 scope.dropDownId = attr.dropDownId;
15849                 scope.isDropdown = true;
15850             }
15851             scope.$on(iconStateConstants.SPLIT_ICON_BTN_EVENT_EMITTER_KEY, function(evnt, data){
15852                 if(typeof data === 'boolean' && data) {
15853                     scope.dropDownClicked();     
15854                     /*
15855                         Check if the dropdown is open and if we are selecting one
15856                         of the items, so that when pressing enter it will trigger it.
15857                     */
15858                     if(scope.isDropDownOpen) {
15859                         listElements[currentIndex].eq(0).find('a')[0].click();
15860                     }
15861                 } else {
15862                     var e = data;
15863                     //Only trigger the keyboard event if the icon button is a dropdown type
15864                     if(scope.isDropdown) {
15865                         triggerKeyboardEvents(e);   
15866                     }
15867                 }
15868                 function triggerKeyboardEvents(e) {
15869                     switch(e.which) {
15870                         case (keymap.KEY.TAB):
15871                             scope.toggleDropdown(false);
15872                             scope.$digest();
15873                             break;
15874                         case (keymap.KEY.ESC): 
15875                             outsideClick();
15876                             break;
15877                         case (keymap.KEY.ENTER):
15878                             if (scope.isDropDownOpen) {
15879                                 listElementsInit();
15880                             }
15881                             break;
15882                         case (keymap.KEY.UP):
15883                             e.preventDefault();
15884                             events.stopPropagation(e);
15885                             if(scope.isDropDownOpen) {
15886                                 scope.previousItemInDropdown();
15887                             }
15888                             break;
15889                         case (keymap.KEY.DOWN):
15890                             e.preventDefault();
15891                             events.stopPropagation(e);
15892                             //Dropdown is open and the user taps down again
15893                             if(scope.isDropDownOpen) {
15894                                 //Now we need to go through the rows in the dropdown
15895                                 scope.nextItemInDropdown();
15896                             } else {
15897                                 isMyElement = true;
15898                                 outsideClick();
15899                                 listElementsInit();
15900                             }
15901                             break;
15902                         default:
15903                             break;
15904                     }
15905                 }
15906                 function listElementsInit() {
15907                     if(listElements === undefined) {
15908                         listElements = [];
15909                         var liTemps = element.find('li');
15910                         for(var i = 0; i < liTemps.length; i++) {
15911                             listElements.push(liTemps.eq(i));
15912                         }
15913                         listElements[currentIndex].children().eq(0).addClass('selected-item');
15914                     }
15915                 }
15916             });
15917             scope.nextItemInDropdown = function(){
15918                 if(listElements && currentIndex < listElements.length - 1){
15919                     currentIndex++;
15920                     listElements[currentIndex - 1].children().eq(0).removeClass('selected-item');
15921                     listElements[currentIndex].children().eq(0).addClass('selected-item');
15922                 }
15923             };
15924             scope.previousItemInDropdown = function(){
15925                 if(currentIndex > 0) {
15926                     currentIndex--;
15927                     listElements[currentIndex].children().eq(0).addClass('selected-item');
15928
15929                     if(currentIndex + 1 < listElements.length)
15930                         listElements[currentIndex + 1].children().eq(0).removeClass('selected-item');
15931                 }
15932             };
15933             scope.$watch('isIconHovered', function(val) {
15934                 scope.hoverWatch = val;
15935             });
15936             scope.$watch('type', function(val) {
15937                 function toggleValues(isMiddle,isNextToDropDown,isRight,isLeft,isLeftNextDropdown){
15938                     scope['isMiddle']  = isMiddle;
15939                     scope['isNextToDropDown'] = isNextToDropDown;
15940                     scope['isRight']  = isRight;
15941                     scope['isLeft'] = isLeft;
15942                     scope['isLeftNextDropdown'] = isLeftNextDropdown;
15943                 };
15944                 switch(val) {
15945                     case (scope.iconStateConstants.MIDDLE):
15946                         toggleValues(true,false,false,true,false);
15947                         break;
15948                     case (scope.iconStateConstants.LEFT):
15949                         toggleValues(false,false,false,true,false);
15950                         break;
15951                     case (scope.iconStateConstants.RIGHT):
15952                         toggleValues(false,false,true,false,false);
15953                         break;
15954                     case (scope.iconStateConstants.NEXT_TO_DROPDOWN):
15955                         toggleValues(false,true,true,true,false);
15956                         break;
15957                     case (scope.iconStateConstants.LEFT_NEXT_TO_DROPDOWN):
15958                         toggleValues(false,false,false,true,true);
15959                         break;
15960                     default:
15961                         break;
15962                 }
15963             });
15964             scope.dropDownClicked = function() {
15965                 isMyElement = true;
15966             };
15967             scope.toggleDropdown = function(val) {
15968                 if(val !== undefined) {
15969                     scope.isDropDownOpen = val;
15970                 } else {
15971                     scope.isDropDownOpen = !scope.isDropDownOpen; 
15972                 }
15973                 scope.dropDownWatch = scope.isDropDownOpen;
15974             };
15975             $documentBind.click('isDropdown', outsideClick, scope);
15976         }
15977     };
15978 }])
15979 .controller('AttSplitIconButtonCtrl',['$scope', 'iconStateConstants',function($scope,iconStateConstants){
15980     this.subCtrls = [];
15981     $scope.isLeftLineShown=true;
15982     $scope.isRightLineShown=true;
15983     $scope.childrenScopes = [];
15984     var that = this;
15985
15986     function getDirIndex(dirType) {
15987         var index = -1;
15988         for(var c in that.subCtrls) {
15989             var ctrl = that.subCtrls[c];
15990             if(ctrl.dirType === dirType) {
15991                 index = c;
15992                 break;
15993             }
15994         }
15995         return index;
15996     }
15997     this.addSubCtrl =  function(sub) {
15998         this.subCtrls.push(sub);
15999     };
16000     this.isLeftLineShown = function(isShown) {
16001         if(isShown === undefined) {
16002             return $scope.isLeftLineShown;
16003         } else {
16004             $scope.isLeftLineShown = isShown;
16005         }
16006     };
16007     this.isRightLineShown = function(isShown) {
16008         if(isShown === undefined) {
16009             return $scope.isRightLineShown;
16010         } else {
16011             $scope.isRightLineShown = isShown;
16012         }
16013     };
16014     this.setLeftLineHover = function(isHovered) {
16015         var leftLineIndex = getDirIndex(iconStateConstants.DIR_TYPE.LEFT);
16016
16017         if($scope.isLeftLineShown && this.subCtrls[leftLineIndex] && this.subCtrls[leftLineIndex].setActiveState) {
16018             this.subCtrls[leftLineIndex].setActiveState(isHovered);
16019         }
16020     };
16021     this.setRightLineHover = function(isHovered) {
16022         var rightLineIndex = getDirIndex(iconStateConstants.DIR_TYPE.RIGHT);
16023         if($scope.isRightLineShown && this.subCtrls[rightLineIndex] && this.subCtrls[rightLineIndex].setActiveState){
16024             this.subCtrls[rightLineIndex].setActiveState(isHovered);
16025         }
16026     };
16027     this.toggleLines = function(isHovered, buttonGroupCtrl, buttonCtrl, isDropDownOpen) {  
16028         var subIconButtons = buttonGroupCtrl.subIconButtons;
16029         var subIconButtonsLength = subIconButtons.length;
16030         var leftLineIndex =  getDirIndex(iconStateConstants.DIR_TYPE.LEFT);
16031         var rightLineIndex =  getDirIndex(iconStateConstants.DIR_TYPE.RIGHT);
16032         function noVerticalLineToggle() {
16033             for(var i =0; i < subIconButtonsLength; i++) {
16034                 if(subIconButtons[i] === buttonCtrl) {
16035                     if(i + 1 <= subIconButtonsLength - 1 && subIconButtons[i+1].isLeftLineShown() 
16036                             && subIconButtons[i+1].subCtrls[leftLineIndex] 
16037                             && subIconButtons[i+1].subCtrls[leftLineIndex].setActiveState) {
16038                         subIconButtons[i+1].subCtrls[leftLineIndex].setActiveState(isHovered);
16039                     }
16040                     if(i - 1 >= 0 && subIconButtons[i-1].isRightLineShown() 
16041                             && subIconButtons[i-1].subCtrls[rightLineIndex] 
16042                             && subIconButtons[i-1].subCtrls[rightLineIndex].setActiveState) {
16043                         subIconButtons[i-1].subCtrls[rightLineIndex].setActiveState(isHovered);
16044                     }
16045                     break;
16046                 }
16047             }
16048         }   
16049         if(isDropDownOpen) {
16050             /*
16051               If the button is next to the dropdown button then just keep the 
16052               buttons left line or its left neighbors right line toggled on
16053               If the button is the dropdown button don't do anything
16054               else do things normally witht the button
16055             */
16056             /*if(subIconButtons[subIconButtonsLength-1] === buttonCtrl) {
16057
16058             }
16059             else */
16060             if(subIconButtons[subIconButtonsLength-2]==buttonCtrl) {
16061                 if(subIconButtons[subIconButtonsLength-2].isLeftLineShown()) {
16062                     subIconButtons[subIconButtonsLength-2].subCtrls[leftLineIndex].setActiveState(isHovered);
16063                 } else if(subIconButtonsLength  - 3 >= 0) {
16064                     if(subIconButtons[subIconButtonsLength-3].isRightLineShown()) {
16065                         subIconButtons[subIconButtonsLength-3].subCtrls[rightLineIndex].setActiveState(isHovered);
16066                     }
16067                 }
16068             } else {
16069                 noVerticalLineToggle();
16070
16071                 if($scope.isLeftLineShown) {
16072                     this.subCtrls[leftLineIndex].setActiveState(isHovered);
16073                 }
16074                 if($scope.isRightLineShown) {
16075                     this.subCtrls[rightLineIndex].setActiveState(isHovered);
16076                 }
16077             }
16078         } else { // End of if(isDropDownOpen)
16079             //Handle Special cases where they aren't showing any vertical lines
16080             //and the dropdown isn't down
16081             if(!$scope.isLeftLineShown && !$scope.isRightLineShown) {
16082                 noVerticalLineToggle();
16083             }   
16084             if($scope.isLeftLineShown && this.subCtrls[leftLineIndex].setActiveState) {
16085                 this.subCtrls[leftLineIndex].setActiveState(isHovered);
16086             }
16087             if($scope.isRightLineShown && this.subCtrls[rightLineIndex].setActiveState){
16088                 this.subCtrls[rightLineIndex].setActiveState(isHovered);
16089             }
16090         }
16091     };
16092     this.setButtonType = function(type){
16093         var buttonIndex = getDirIndex(iconStateConstants.DIR_TYPE.BUTTON);
16094         if(this.subCtrls[buttonIndex] && this.subCtrls[buttonIndex].setType) {
16095             this.subCtrls[buttonIndex].setType(type);
16096         }
16097     };
16098 }])
16099 .directive('attSplitIconButton', ['$document', 'iconStateConstants', 'keymap',
16100     function($document, iconStateConstants, keymap){
16101     return {
16102         restrict: 'EA',
16103         replace: true,
16104         priority: 100,
16105         transclude: true,
16106         require: ['^attSplitIconButtonGroup', 'attSplitIconButton'],
16107         controller: 'AttSplitIconButtonCtrl',
16108         templateUrl: 'app/scripts/ng_js_att_tpls/splitIconButton/splitIconButton.html',
16109         scope:{
16110             icon: '@',
16111             title: '@',
16112             dropDownId: '@'
16113         },
16114         link: function(scope,element,attr,ctrls) {
16115             if(!scope.title) {
16116                 scope.title = scope.icon;
16117             }
16118             var attSplitButtonGroupCtrl = ctrls[0];
16119             var attSplitIconButtonCtrl = ctrls[1];
16120             attSplitButtonGroupCtrl.addIconButton(attSplitIconButtonCtrl);
16121             element.bind('keydown', function(e){
16122                 //Check if the key is the up or down key
16123                 if(e.which === keymap.KEY.ESC ||
16124                     e.which === keymap.KEY.DOWN ||
16125                     e.which === keymap.KEY.ENTER ||
16126                     e.which === keymap.KEY.UP ||
16127                     e.which === keymap.KEY.TAB ) {
16128                     scope.clickHandler();
16129                     scope.$broadcast(iconStateConstants.SPLIT_ICON_BTN_EVENT_EMITTER_KEY, e);
16130                 }
16131             });
16132             scope.dropDownWatch = false;
16133             scope.iconStateConstants = iconStateConstants;
16134             scope.clickHandler = function() {
16135                 attSplitButtonGroupCtrl.hideLeftLineRightButton(attSplitIconButtonCtrl);
16136             };
16137             scope.$watch('isHovered', function(val){
16138                 if(val) {
16139                     attSplitIconButtonCtrl.toggleLines(val,attSplitButtonGroupCtrl,attSplitIconButtonCtrl,attSplitButtonGroupCtrl.isDropDownOpen);
16140                 } else{
16141                     attSplitIconButtonCtrl.toggleLines(val,attSplitButtonGroupCtrl,attSplitIconButtonCtrl,attSplitButtonGroupCtrl.isDropDownOpen);
16142                 }
16143             });
16144             scope.$watch('dropDownWatch', function(val) {
16145                 attSplitButtonGroupCtrl.isDropDownOpen = val;
16146                 attSplitButtonGroupCtrl.toggleDropdownState(val);
16147             });
16148         }
16149     }
16150 }])
16151 .controller('AttSplitIconButtonGroupCtrl',   ['$scope','iconStateConstants',function($scope,iconStateConstants){
16152     this.subIconButtons = [];
16153     this.addIconButton = function(iconButton){
16154        this.subIconButtons.push(iconButton);
16155     };
16156     this.isDropDownOpen = false;
16157     this.hideLeftLineRightButton = function(btn){
16158         var numButtons = this.subIconButtons.length;
16159         var buttonLeftOfRightMost = this.subIconButtons[numButtons - 2];
16160         var rightMostButton = this.subIconButtons[numButtons -1];
16161
16162         if (btn != buttonLeftOfRightMost && btn != rightMostButton ){
16163             rightMostButton.setLeftLineHover(false);
16164         }
16165     };
16166     this.toggleDropdownState = function(isDropDownOpen){
16167         var numButtons = this.subIconButtons.length;
16168         if(numButtons > 2) {
16169             if(isDropDownOpen) {
16170                 if(this.subIconButtons[numButtons - 2].isRightLineShown()) {
16171                     this.subIconButtons[numButtons - 2].setRightLineHover(true);
16172                 } else {
16173                     this.subIconButtons[numButtons - 1].setLeftLineHover(true);
16174                 }
16175                 this.subIconButtons[numButtons - 2].setButtonType(iconStateConstants.NEXT_TO_DROPDOWN);
16176             } else {
16177                 this.subIconButtons[numButtons - 1].setLeftLineHover(false);
16178                 this.subIconButtons[numButtons - 2].setButtonType(iconStateConstants.MIDDLE);
16179             }
16180         } else {
16181             if(isDropDownOpen) {
16182                 this.subIconButtons[0].setRightLineHover(true);
16183                 this.subIconButtons[0].setButtonType(iconStateConstants.LEFT_NEXT_TO_DROPDOWN);
16184             } else {
16185                 this.subIconButtons[0].setButtonType(iconStateConstants.LEFT);
16186             }
16187         }
16188     };
16189 }])
16190 .directive('attSplitIconButtonGroup', ['$document', '$timeout',  'iconStateConstants' ,function($document,$timeout,iconStateConstants){
16191     return {
16192         restrict: 'EA',
16193         replace: true,
16194         priority: 50,
16195         transclude: true,
16196         require: 'attSplitIconButtonGroup',
16197         controller: 'AttSplitIconButtonGroupCtrl',
16198         templateUrl: 'app/scripts/ng_js_att_tpls/splitIconButton/splitIconButtonGroup.html',
16199         scope:{},
16200         link: function(scope,element,attr,ctrls){
16201             $timeout(initialize,100);
16202             function initialize(){
16203                 var subIconButtonCtrls = ctrls.subIconButtons;
16204                 var leftMostButtonIndex = 0;
16205                 var rightMostButtonIndex =subIconButtonCtrls.length-1;
16206                 //left most button config
16207                 subIconButtonCtrls[leftMostButtonIndex].setButtonType(iconStateConstants.LEFT);
16208                 subIconButtonCtrls[leftMostButtonIndex].isLeftLineShown(false);
16209                 subIconButtonCtrls[leftMostButtonIndex].isRightLineShown(true);
16210                 //right most button config
16211                 subIconButtonCtrls[rightMostButtonIndex].setButtonType(iconStateConstants.RIGHT);
16212                 subIconButtonCtrls[rightMostButtonIndex].isRightLineShown(false);
16213                 subIconButtonCtrls[rightMostButtonIndex].isLeftLineShown(false);
16214                 //middle buttons config
16215                 if(rightMostButtonIndex >= 2) {
16216                     var index = 1;
16217                     while(index < rightMostButtonIndex) {
16218                         subIconButtonCtrls[index].setButtonType(iconStateConstants.MIDDLE);
16219                         subIconButtonCtrls[index].isRightLineShown(false);
16220                         subIconButtonCtrls[index].isLeftLineShown(false);
16221                         index++;
16222                     }
16223                     var skipIndex = 2;
16224                     while(skipIndex <= rightMostButtonIndex){
16225                         if(skipIndex == rightMostButtonIndex) {
16226                             subIconButtonCtrls[skipIndex].isLeftLineShown(true);
16227                         } else {
16228                             subIconButtonCtrls[skipIndex].isRightLineShown(true);
16229                             subIconButtonCtrls[skipIndex].isLeftLineShown(true); 
16230                         } 
16231                         skipIndex = skipIndex + 2;
16232                     }
16233                 }
16234                 //reposition the dropdown
16235                 var ulElem = element.find('ul');
16236                 if(ulElem.length > 0) {
16237                     var numButtons = rightMostButtonIndex+1;
16238                     if(numButtons > 2) {
16239                         var offset = (numButtons)*34-70+(numButtons/1.5) + 0.5;
16240                         var offSetStr = offset+'px';
16241                         angular.element(ulElem).css('left',offSetStr);
16242                         angular.element(ulElem).css('border-top-left-radius','0px');
16243                     } else {
16244                         angular.element(ulElem).css('left','0px');
16245                     }
16246                 }
16247             }
16248         }
16249     }
16250 }]);
16251
16252 angular.module('att.abs.stepSlider', ['att.abs.position'])
16253         .constant('sliderConstants', {
16254             /*
16255              The MIT License (MIT)
16256              Copyright (c) 2013 Julien Valéry
16257              */
16258             SLIDER: {
16259                 settings: {
16260                     from: 1,
16261                     to: 40,
16262                     step: 1,
16263                     smooth: true,
16264                     limits: true,
16265                     value: "3",
16266                     dimension: "",
16267                     vertical: false
16268                 },
16269                 className: "jslider",
16270                 selector: ".jslider-"
16271             },
16272             EVENTS: {
16273             },
16274             COLORS: {
16275                 GREEN: 'green',
16276                 BLUE_HIGHLIGHT: 'blue',
16277                 MAGENTA: 'magenta',
16278                 GOLD: 'gold',
16279                 PURPLE: 'purple',
16280                 DARK_BLUE: 'dark-blue',
16281                 REGULAR: 'regular',
16282                 WHITE: 'white'
16283             }
16284         })
16285         .factory('utils', function () {
16286             /*
16287              The MIT License (MIT)
16288              Copyright (c) 2013 Julien Valéry
16289              */
16290             return {
16291                 offset: function (elm) {
16292                     var rawDom = elm[0];
16293                     var _x = 0;
16294                     var _y = 0;
16295                     var body = document.documentElement || document.body;
16296                     var scrollX = window.pageXOffset || body.scrollLeft;
16297                     var scrollY = window.pageYOffset || body.scrollTop;
16298                     _x = rawDom.getBoundingClientRect().left + scrollX;
16299                     _y = rawDom.getBoundingClientRect().top + scrollY;
16300                     return {left: _x, top: _y};
16301                 },
16302                 roundUpToScale: function (mousePrc, scale, cutOffWidth, cutOffIndex) {
16303                     var lowerVal;
16304                     var higherVal;
16305                     var newMousePrc;
16306                     var middle;
16307
16308                     for (var index = 1; index < scale.length; index++) {
16309                         lowerVal = scale[index - 1];
16310                         higherVal = scale[index];
16311                         middle = ((higherVal - lowerVal) * .5) + lowerVal;
16312                         /*
16313                          Handles a situation where the user clicks close to the start point of
16314                          the slider but the pointer doesn't move
16315                          */
16316                         if ((lowerVal === 0 && mousePrc <= middle) || checkEquality(lowerVal, mousePrc)) {
16317                             newMousePrc = lowerVal;
16318                             break;
16319                         }
16320                         else if (lowerVal < mousePrc && (mousePrc < higherVal ||
16321                                 checkEquality(mousePrc, higherVal)))
16322                         {
16323                             newMousePrc = higherVal;
16324                             break;
16325                         }
16326                     }
16327                     //Check if the newMousePrc is <= the cuttOffPoint
16328                     if (cutOffWidth && newMousePrc < cutOffWidth) {
16329                         return scale[cutOffIndex];
16330                     }
16331                     else {
16332                         return newMousePrc;
16333                     }
16334                     /*
16335                      Checks to see if 2 points are so close that they are
16336                      basically equal.
16337                      */
16338                     function checkEquality(point1, point2) {
16339                         var precision = 0.1;
16340                         if (Math.abs(point2 - point1) <= precision) {
16341                             return true;
16342                         }
16343                         return false;
16344                     }
16345                 },
16346                 valueForDifferentScale: function (from, to, prc, prcToValueMapper) {
16347                     var decimalPrc = prc / 100;
16348                     if (decimalPrc === 0) {
16349                         return from;
16350                     }
16351                     return prcToValueMapper[prc];
16352                 },
16353                 /* converts the default value Kbps to Mbps or Gbps */
16354                 convertToMbpsGbps: function (unitValue, unitLabel, configDecimalPlaces) {
16355                     var defaultDecimalPlaces = 3; /* this is the default decimal places as per business requirements */
16356                     if (configDecimalPlaces) {
16357                         defaultDecimalPlaces = configDecimalPlaces;
16358                     }
16359
16360                     if ((unitValue > 1024 && unitValue < 1000000) && angular.equals(unitLabel, 'Kbps')) {
16361                         unitValue = truncator((unitValue/1000), defaultDecimalPlaces);
16362                         unitLabel = 'Mbps';
16363                     } else if ((unitValue > 1024 && unitValue < 1000000) && angular.equals(unitLabel, 'Mbps')){
16364                         unitValue = truncator((unitValue/1000), defaultDecimalPlaces);
16365                         unitLabel = 'Mbps';
16366                     } else if (unitValue <= 1024 && angular.equals(unitLabel, 'Mbps')) {
16367                         unitLabel = 'Kbps';
16368                     } else {
16369                         unitLabel = 'Kbps';
16370                     }
16371
16372                     if (unitValue >= 1000000 && angular.equals(unitLabel, 'Kbps')) {
16373                         unitValue = truncator((unitValue/1000000), defaultDecimalPlaces);
16374                         unitLabel = 'Gbps';
16375                     }
16376                     return {
16377                         unitValue: unitValue, 
16378                         unitLabel: unitLabel
16379                     };
16380                     
16381                     function truncator(numToTruncate, intDecimalPlaces) {    
16382                         var cnvrtdNum = Math.pow(10, intDecimalPlaces);
16383                         return ~~(numToTruncate * cnvrtdNum)/cnvrtdNum;
16384                     }
16385                 },
16386                 getConversionFactorValue: function (value, conversion, firstDimension) {
16387                     /*
16388                      Loop through the conversion array and keep checking the
16389                      startVal
16390                      */
16391                     if (value <= conversion[0].startVal) {
16392                         return{
16393                             scaledVal: value,
16394                             scaledDimension: firstDimension
16395                         };
16396                     }
16397                     var endIndex = 0;
16398                     for (var index in conversion) {
16399                         var c = conversion[index];
16400                         if (value > c.startVal) {
16401                             endIndex = index;
16402                         }
16403                     }
16404                     var scaleFactor = conversion[endIndex].scaleFactor;
16405                     var scaledVal = value / scaleFactor;
16406                     var scaledDimension = conversion[endIndex].dimension;
16407                     return {
16408                         scaledVal: scaledVal,
16409                         scaledDimension: scaledDimension
16410                     };
16411                 }
16412             };
16413         })
16414         .factory('sliderDraggable', ['utils', function (utils) {
16415                 /*
16416                  The MIT License (MIT)
16417                  Copyright (c) 2013 Julien Valéry
16418                  */
16419                 function Draggable() {
16420                     this._init.apply(this, arguments);
16421                 }
16422                 Draggable.prototype.oninit = function () {
16423                 };
16424                 Draggable.prototype.events = function () {
16425                 };
16426                 Draggable.prototype.onmousedown = function () {
16427                     this.ptr.css({position: "absolute"});
16428                 };
16429                 Draggable.prototype.onmousemove = function (evt, x, y) {
16430                     this.ptr.css({left: x, top: y});
16431                 };
16432                 Draggable.prototype.onmouseup = function () {
16433                 };
16434                 Draggable.prototype.isDefault = {
16435                     drag: false,
16436                     clicked: false,
16437                     toclick: true,
16438                     mouseup: false
16439                 };
16440                 Draggable.prototype._init = function () {
16441                     if (arguments.length > 0) {
16442                         this.ptr = arguments[0];
16443                         this.parent = arguments[2];
16444                         if (!this.ptr) {
16445                             return;
16446                         }
16447                         this.is = {};
16448                         angular.extend(this.is, this.isDefault);
16449                         var offset = utils.offset(this.ptr);
16450                         this.d = {
16451                             left: offset.left,
16452                             top: offset.top,
16453                             width: this.ptr[0].clientWidth,
16454                             height: this.ptr[0].clientHeight
16455                         };
16456                         this.oninit.apply(this, arguments);
16457                         this._events();
16458                     }
16459                 };
16460                 Draggable.prototype._getPageCoords = function (event) {
16461                     var value = {};
16462                     if (event.targetTouches && event.targetTouches[0]) {
16463                         value = {x: event.targetTouches[0].pageX, y: event.targetTouches[0].pageY};
16464                     } else {
16465                         value = {x: event.pageX, y: event.pageY};
16466                     }
16467                     return value;
16468                 };
16469                 Draggable.prototype._bindEvent = function (ptr, eventType, handler) {
16470                     if (this.supportTouches_) {
16471                         ptr[0].attachEvent(this.events_[ eventType ], handler);
16472                     }
16473                     else {
16474                         if (ptr.bind) {
16475                             ptr.bind(this.events_[ eventType ], handler);
16476                         }
16477                     }
16478                 };
16479                 Draggable.prototype._events = function () {
16480                     var self = this;
16481                     this.supportTouches_ = 'ontouchend' in document;
16482                     this.events_ = {
16483                         "click": this.supportTouches_ ? "touchstart" : "click",
16484                         "down": this.supportTouches_ ? "touchstart" : "mousedown",
16485                         "move": this.supportTouches_ ? "touchmove" : "mousemove",
16486                         "up": this.supportTouches_ ? "touchend" : "mouseup",
16487                         "mousedown": this.supportTouches_ ? "mousedown" : "mousedown"
16488                     };
16489                     var documentElt = angular.element(window.document);
16490                     this._bindEvent(documentElt, "move", function (event) {
16491                         if (self.is.drag) {
16492                             event.stopPropagation();
16493                             event.preventDefault();
16494                             if (!self.parent.disabled) {
16495                                 self._mousemove(event);
16496                             }
16497                         }
16498                     });
16499                     this._bindEvent(documentElt, "down", function (event) {
16500                         if (self.is.drag) {
16501                             event.stopPropagation();
16502                             event.preventDefault();
16503                         }
16504                     });
16505                     this._bindEvent(documentElt, "up", function (event) {
16506                         self._mouseup(event);
16507                     });
16508                     this._bindEvent(this.ptr, "down", function (event) {
16509                         self._mousedown(event);
16510                         return false;
16511                     });
16512                     this._bindEvent(this.ptr, "up", function (event) {
16513                         self._mouseup(event);
16514                     });
16515                     this.events();
16516                 };
16517                 Draggable.prototype._mousedown = function (evt) {
16518                     this.is.drag = true;
16519                     this.is.clicked = false;
16520                     this.is.mouseup = false;
16521                     var coords = this._getPageCoords(evt);
16522                     this.cx = coords.x - this.ptr[0].offsetLeft;
16523                     this.cy = coords.y - this.ptr[0].offsetTop;
16524                     angular.extend(this.d, {
16525                         left: this.ptr[0].offsetLeft,
16526                         top: this.ptr[0].offsetTop,
16527                         width: this.ptr[0].clientWidth,
16528                         height: this.ptr[0].clientHeight
16529                     });
16530                     if (this.outer && this.outer.get(0)) {
16531                         this.outer.css({height: Math.max(this.outer.height(), $(document.body).height()), overflow: "hidden"});
16532                     }
16533                     this.onmousedown(evt);
16534                 };
16535                 Draggable.prototype._mousemove = function (evt) {
16536                     if (this.uid === 0) {
16537                         return;
16538                     }
16539                     this.is.toclick = false;
16540                     var coords = this._getPageCoords(evt);
16541                     this.onmousemove(evt, coords.x - this.cx, coords.y - this.cy);
16542                 };
16543                 Draggable.prototype._mouseup = function (evt) {
16544                     if (this.is.drag) {
16545                         this.is.drag = false;
16546                         if (this.outer && this.outer.get(0)) {
16547                             if ($.browser.mozilla) {
16548                                 this.outer.css({overflow: "hidden"});
16549                             } else {
16550                                 this.outer.css({overflow: "visible"});
16551                             }
16552                             if ($.browser.msie && $.browser.version === '6.0') {
16553                                 this.outer.css({height: "100%"});
16554                             } else {
16555                                 this.outer.css({height: "auto"});
16556                             }
16557                         }
16558                         this.onmouseup(evt);
16559                     }
16560                 };
16561                 return Draggable;
16562             }])
16563         .factory('sliderPointer', ['sliderDraggable', 'utils', function (Draggable, utils) {
16564                 /*
16565                  The MIT License (MIT)
16566                  Copyright (c) 2013 Julien Valéry
16567                  */
16568                 function SliderPointer() {
16569                     Draggable.apply(this, arguments);
16570                 }
16571                 SliderPointer.prototype = new Draggable();
16572                 SliderPointer.prototype.oninit = function (ptr, id, _constructor) {
16573                     this.uid = id;
16574                     this.parent = _constructor;
16575                     this.value = {};
16576                     this.settings = angular.copy(_constructor.settings);
16577                 };
16578                 SliderPointer.prototype.onmousedown = function (evt) {
16579                     var off = utils.offset(this.parent.domNode);
16580                     var offset = {
16581                         left: off.left,
16582                         top: off.top,
16583                         width: this.parent.domNode[0].clientWidth,
16584                         height: this.parent.domNode[0].clientHeight
16585                     };
16586                     this._parent = {
16587                         offset: offset,
16588                         width: offset.width,
16589                         height: offset.height
16590                     };
16591                     this.ptr.addClass("jslider-pointer-hover");
16592                     this.setIndexOver();
16593                 };
16594                 SliderPointer.prototype.onmousemove = function (evt, x, y) {
16595                     var coords = this._getPageCoords(evt);
16596                     //val is the percent where the slider pointer is located
16597                     var val = this.calc(coords.x);
16598                     if (!this.parent.settings.smooth) {
16599                         val = utils.roundUpToScale(val,
16600                                 this.parent.settings.scale,
16601                                 this.parent.settings.cutOffWidth,
16602                                 this.parent.settings.cutOffIndex);
16603                     }
16604                     var cutOffWidth = this.parent.settings.cutOffWidth;
16605                     if (cutOffWidth && val < cutOffWidth) {
16606                         val = cutOffWidth;
16607                     }
16608                     this._set(val);
16609                 };
16610                 SliderPointer.prototype.onmouseup = function (evt) {
16611                     if (this.settings.callback && angular.isFunction(this.settings.callback)) {
16612                         var val = this.parent.getValue();
16613                         this.settings.callback.call(this.parent, val);
16614                     }
16615                     this.ptr.removeClass("jslider-pointer-hover");
16616                 };
16617                 SliderPointer.prototype.setIndexOver = function () {
16618                     this.parent.setPointersIndex(1);
16619                     this.index(2);
16620                 };
16621                 SliderPointer.prototype.index = function (i) {
16622                 };
16623                 SliderPointer.prototype.limits = function (x) {
16624                     return this.parent.limits(x, this);
16625                 };
16626                 SliderPointer.prototype.calc = function (coords) {
16627                     var diff = coords - this._parent.offset.left;
16628                     var val = this.limits((diff * 100) / this._parent.width);
16629                     return val;
16630                 };
16631                 SliderPointer.prototype.set = function (value, opt_origin) {
16632                     this.value.origin = this.parent.round(value);
16633                     this._set(this.parent.valueToPrc(value, this), opt_origin);
16634                 };
16635                 SliderPointer.prototype._set = function (prc, opt_origin) {
16636                     if (!opt_origin) {
16637                         this.value.origin = this.parent.prcToValue(prc);
16638                     }
16639                     this.value.prc = prc;
16640                     //Sets the location of the SliderPointer
16641                     this.ptr.css({left: prc + '%'});
16642                     this.parent.redraw(this);
16643                 };
16644                 return SliderPointer;
16645             }])
16646         .factory('slider', ['sliderPointer', 'sliderConstants', 'utils', function (SliderPointer, sliderConstants, utils) {
16647                 /*
16648                  The MIT License (MIT)
16649                  Copyright (c) 2013 Julien Valéry
16650                  */
16651                 var cutOffDom;
16652                 function Slider() {
16653                     return this.init.apply(this, arguments);
16654                 }
16655                 function changeCutOffWidth(width) {
16656                     cutOffDom.css('width', width);
16657                 }
16658                 ;
16659                 Slider.prototype.changeCutOffWidth = changeCutOffWidth;
16660                 Slider.prototype.init = function (inputNode, templateNode, settings) {
16661                     this.settings = sliderConstants.SLIDER.settings;
16662                     angular.extend(this.settings, angular.copy(settings));
16663                     this.inputNode = inputNode;
16664                     this.inputNode.addClass("ng-hide");
16665                     this.settings.interval = this.settings.to - this.settings.from;
16666                     if (this.settings.calculate && $.isFunction(this.settings.calculate)) {
16667                         this.nice = this.settings.calculate;
16668                     }
16669                     if (this.settings.onstatechange && $.isFunction(this.settings.onstatechange)) {
16670                         this.onstatechange = this.settings.onstatechange;
16671                     }
16672                     this.is = {init: false};
16673                     this.o = {};
16674                     this.create(templateNode);
16675                 };
16676                 Slider.prototype.create = function (templateNode) {
16677                     var $this = this;
16678                     this.domNode = templateNode;
16679                     var off = utils.offset(this.domNode);
16680                     var offset = {
16681                         left: off.left,
16682                         top: off.top,
16683                         width: this.domNode[0].clientWidth,
16684                         height: this.domNode[0].clientHeight
16685                     };
16686                     this.sizes = {domWidth: this.domNode[0].clientWidth, domOffset: offset};
16687                     angular.extend(this.o, {
16688                         pointers: {},
16689                         labels: {
16690                             0: {
16691                                 o: angular.element(this.domNode.find('div')[5])
16692                             },
16693                             1: {
16694                                 o: angular.element(this.domNode.find('div')[6])
16695                             }
16696                         },
16697                         limits: {
16698                             0: angular.element(this.domNode.find('div')[3]),
16699                             1: angular.element(this.domNode.find('div')[5])
16700                         }
16701                     });
16702                     angular.extend(this.o.labels[0], {
16703                         value: this.o.labels[0].o.find("span")
16704                     });
16705                     angular.extend(this.o.labels[1], {
16706                         value: this.o.labels[1].o.find("span")
16707                     });
16708                     if (!$this.settings.value.split(";")[1]) {
16709                         this.settings.single = true;
16710                     }
16711                     var domNodeDivs = this.domNode.find('div');
16712                     cutOffDom = angular.element(domNodeDivs[8]);
16713                     if (cutOffDom && cutOffDom.css) {
16714                         cutOffDom.css('width', '0%');
16715                     }
16716                     var pointers = [angular.element(domNodeDivs[1]), angular.element(domNodeDivs[2])];
16717                     angular.forEach(pointers, function (pointer, key) {
16718                         $this.settings = angular.copy($this.settings);
16719                         var value = $this.settings.value.split(';')[key];
16720                         if (value) {
16721                             $this.o.pointers[key] = new SliderPointer(pointer, key, $this);
16722                             var prev = $this.settings.value.split(';')[key - 1];
16723                             if (prev && parseInt(value, 10) < parseInt(prev, 10)) {
16724                                 value = prev;
16725                             }
16726                             var value1 = value < $this.settings.from ? $this.settings.from : value;
16727                             value1 = value > $this.settings.to ? $this.settings.to : value;
16728                             $this.o.pointers[key].set(value1, true);
16729                             if (key === 0) {
16730                                 $this.domNode.bind('mousedown', $this.clickHandler.apply($this));
16731                             }
16732                         }
16733                     });
16734                     this.o.value = angular.element(this.domNode.find("i")[2]);
16735                     this.is.init = true;
16736                     angular.forEach(this.o.pointers, function (pointer) {
16737                         $this.redraw(pointer);
16738                     });
16739                 };
16740                 Slider.prototype.clickHandler = function () {
16741                     var self = this;
16742                     return function (evt) {
16743                         if (self.disabled) {
16744                             return;
16745                         }
16746                         var className = evt.target.className;
16747                         var targetIdx = 0;
16748                         if (className.indexOf('jslider-pointer-to') > 0) {
16749                             targetIdx = 1;
16750                         }
16751                         var _off = utils.offset(self.domNode);
16752                         var offset = {
16753                             left: _off.left,
16754                             top: _off.top,
16755                             width: self.domNode[0].clientWidth,
16756                             height: self.domNode[0].clientHeight
16757                         };
16758                         targetIdx = 1;
16759                         var targetPtr = self.o.pointers[targetIdx];
16760                         targetPtr._parent = {offset: offset, width: offset.width, height: offset.height};
16761                         targetPtr._mousemove(evt);
16762                         targetPtr.onmouseup();
16763                         return false;
16764                     };
16765                 };
16766                 Slider.prototype.disable = function (bool) {
16767                     this.disabled = bool;
16768                 };
16769                 Slider.prototype.nice = function (value) {
16770                     return value;
16771                 };
16772                 Slider.prototype.onstatechange = function () {
16773                 };
16774                 Slider.prototype.limits = function (x, pointer) {
16775                     if (!this.settings.smooth) {
16776                         var step = this.settings.step * 100 / (this.settings.interval);
16777                         x = Math.round(x / step) * step;
16778                     }
16779                     var another = this.o.pointers[1 - pointer.uid];
16780                     if (another && pointer.uid && x < another.value.prc) {
16781                         x = another.value.prc;
16782                     }
16783                     if (another && !pointer.uid && x > another.value.prc) {
16784                         x = another.value.prc;
16785                     }
16786                     if (x < 0) {
16787                         x = 0;
16788                     }
16789                     if (x > 100) {
16790                         x = 100;
16791                     }
16792                     var val = Math.round(x * 10) / 10;
16793                     return val;
16794                 };
16795                 Slider.prototype.setPointersIndex = function (i) {
16796                     angular.forEach(this.getPointers(), function (pointer, i) {
16797                         pointer.index(i);
16798                     });
16799                 };
16800                 Slider.prototype.getPointers = function () {
16801                     return this.o.pointers;
16802                 };
16803                 Slider.prototype.onresize = function () {
16804                     var self = this;
16805                     this.sizes = {
16806                         domWidth: this.domNode[0].clientWidth,
16807                         domHeight: this.domNode[0].clientHeight,
16808                         domOffset: {
16809                             left: this.domNode[0].offsetLeft,
16810                             top: this.domNode[0].offsetTop,
16811                             width: this.domNode[0].clientWidth,
16812                             height: this.domNode[0].clientHeight
16813                         }
16814                     };
16815                     angular.forEach(this.o.pointers, function (ptr, key) {
16816                         self.redraw(ptr);
16817                     });
16818                 };
16819                 Slider.prototype.update = function () {
16820                     this.onresize();
16821                     this.drawScale();
16822                 };
16823                 Slider.prototype.drawScale = function () {
16824                 };
16825                 Slider.prototype.redraw = function (pointer) {
16826                     if (!this.settings.smooth) {
16827                         var newMousePrc = utils.roundUpToScale(pointer.value.prc,
16828                                 this.settings.scale,
16829                                 this.settings.cutOffWidth,
16830                                 this.settings.cutOffIndex);
16831                         pointer.value.origin = newMousePrc;
16832                         pointer.value.prc = newMousePrc;
16833                     }
16834
16835                     if (!this.is.init) {
16836                         return false;
16837                     }
16838                     this.setValue();
16839                     var width = this.o.pointers[1].value.prc;
16840                     var newPos = {left: '0%', width: width + '%'};
16841                     this.o.value.css(newPos);
16842                     var htmlValue = this.nice(pointer.value.origin);
16843                     var scaledDimension = this.settings.firstDimension;
16844                     if (this.settings.stepWithDifferentScale && !this.settings.smooth) {
16845                         htmlValue = utils.valueForDifferentScale(this.settings.from,
16846                                 this.settings.to, htmlValue, this.settings.prcToValueMapper);
16847                     }
16848                     //This is the base value before the conversion
16849                     if (this.settings.realtimeCallback && angular.isFunction(this.settings.realtimeCallback)
16850                             && this.settings.cutOffVal !== undefined && pointer.uid === 1) {
16851                         this.settings.realtimeCallback(htmlValue);
16852                     }
16853                     //Need to change this to the correct value for the scale
16854                     if (this.settings.conversion) {
16855                         var conversionObj = utils.getConversionFactorValue(parseInt(htmlValue),
16856                                 this.settings.conversion,
16857                                 this.settings.firstDimension);
16858                         htmlValue = conversionObj.scaledVal;
16859                         scaledDimension = conversionObj.scaledDimension;
16860                     }
16861
16862                     htmlValue = parseFloat(htmlValue);
16863                     var tooltipLabel = utils.convertToMbpsGbps(htmlValue, scaledDimension, this.settings.decimalPlaces);
16864
16865                     this.o.labels[pointer.uid].value.html(tooltipLabel.unitValue + ' ' + tooltipLabel.unitLabel);
16866                     //Top tooltip label
16867                     this.redrawLabels(pointer);
16868                 };
16869                 Slider.prototype.redrawLabels = function (pointer) {
16870                     function setPosition(label, sizes, prc) {
16871                         sizes.margin = -sizes.label / 2;
16872                         var domSize = self.sizes.domWidth;
16873                         var label_left = sizes.border + sizes.margin;
16874                         if (label_left < 0) {
16875                             sizes.margin -= label_left;
16876                         }
16877                         if (sizes.border + sizes.label / 2 > domSize) {
16878                             sizes.margin = 0;
16879                             sizes.right = true;
16880                         } else
16881                             sizes.right = false;
16882                         //Adjust the tooltip location
16883                         sizes.margin = -((label.o[0].clientWidth / 2) - label.o[0].clientWidth / 20);
16884                         label.o.css({left: prc + "%", marginLeft: sizes.margin, right: "auto"});
16885                         if (sizes.right)
16886                             label.o.css({left: "auto", right: 0});
16887                         return sizes;
16888                     }
16889                     var self = this;
16890                     var label = this.o.labels[pointer.uid];
16891                     var prc = pointer.value.prc;
16892                     var sizes = {
16893                         label: label.o[0].offsetWidth,
16894                         right: false,
16895                         border: (prc * domSize) / 100
16896                     };
16897                     var another_label = null;
16898                     var another = null;
16899                     if (!this.settings.single) {
16900                         another = this.o.pointers[1 - pointer.uid];
16901                         another_label = this.o.labels[another.uid];
16902                         switch (pointer.uid) {
16903                             case 0:
16904                                 if (sizes.border + sizes.label / 2 > another_label.o[0].offsetLeft - this.sizes.domOffset.left) {
16905                                     another_label.o.css({visibility: "hidden"});
16906                                     another_label.value.html(this.nice(another.value.origin));
16907                                     label.o.css({visibility: "hidden"});
16908                                     prc = (another.value.prc - prc) / 2 + prc;
16909                                     if (another.value.prc !== pointer.value.prc) {
16910                                         label.value.html(this.nice(pointer.value.origin) + "&nbsp;&ndash;&nbsp;" + this.nice(another.value.origin));
16911                                         sizes.label = label.o[0].clientWidth;
16912                                         sizes.border = (prc * domSize) / 100;
16913                                     }
16914                                 } else {
16915                                     another_label.o.css({visibility: "visible"});
16916                                 }
16917                                 break;
16918                             case 1:
16919                                 if (sizes.border - sizes.label / 2 < another_label.o[0].offsetLeft - this.sizes.domOffset.left + another_label.o[0].clientWidth) {
16920                                     another_label.o.css({visibility: "hidden"});
16921                                     another_label.value.html(this.nice(another.value.origin));
16922                                     label.o.css({visibility: "visible"});
16923                                     prc = (prc - another.value.prc) / 2 + another.value.prc;
16924                                     if (another.value.prc !== pointer.value.prc) {
16925                                         label.value.html(this.nice(another.value.origin) + "&nbsp;&ndash;&nbsp;" + this.nice(pointer.value.origin));
16926                                         sizes.label = label.o[0].clientWidth;
16927                                         sizes.border = (prc * domSize) / 100;
16928                                     }
16929                                 } else {
16930                                     another_label.o.css({visibility: "visible"});
16931                                 }
16932                                 break;
16933                         }
16934                     }
16935                     sizes = setPosition(label, sizes, prc);
16936                     var domSize = self.sizes.domWidth;
16937                     //This is the 0th pointer
16938                     if (another_label) {
16939                         sizes = {
16940                             label: another_label.o[0].clientWidth,
16941                             right: false,
16942                             border: (another.value.prc * this.sizes.domWidth) / 100
16943                         };
16944                         sizes = setPosition(another_label, sizes, another.value.prc);
16945                     }
16946                 };
16947                 Slider.prototype.redrawLimits = function () {
16948                     if (this.settings.limits) {
16949                         var limits = [true, true];
16950                         for (var key in this.o.pointers) {
16951                             if (!this.settings.single || key === 0) {
16952                                 var pointer = this.o.pointers[key];
16953                                 var label = this.o.labels[pointer.uid];
16954                                 var label_left = label.o[0].offsetLeft - this.sizes.domOffset.left;
16955                                 var limit = this.o.limits[0];
16956                                 if (label_left < limit[0].clientWidth)
16957                                     limits[0] = false;
16958                                 limit = this.o.limits[1];
16959                                 if (label_left + label.o[0].clientWidth > this.sizes.domWidth - limit[0].clientWidth)
16960                                     limits[1] = false;
16961                             }
16962                         }
16963                         for (var i = 0; i < limits.length; i++) {
16964                             if (limits[i]){
16965                                 angular.element(this.o.limits[i]).addClass("animate-show");}
16966                             else{
16967                                 angular.element(this.o.limits[i]).addClass("animate-hidde");}
16968                         }
16969                     }
16970                 };
16971                 Slider.prototype.setValue = function () {
16972                     var value = this.getValue();
16973                     this.inputNode.attr("value", value);
16974                     this.onstatechange.call(this, value, this.inputNode);
16975                 };
16976                 Slider.prototype.getValue = function () {
16977                     if (!this.is.init){
16978                         return false;}
16979                     var $this = this;
16980                     var value = "";
16981                     angular.forEach(this.o.pointers, function (pointer, key) {
16982                         if (pointer.value.prc !== undefined && !isNaN(pointer.value.prc)) {
16983                             var pointerPrc = pointer.value.prc;
16984                             var myValue = $this.prcToValue(pointerPrc);
16985                             if (!$this.settings.smooth) {
16986                                 var myValue = utils.valueForDifferentScale($this.settings.from,
16987                                         $this.settings.to,
16988                                         pointerPrc,
16989                                         $this.settings.prcToValueMapper);
16990                             }
16991                             value += (key > 0 ? ";" : "") + myValue;
16992                         }
16993                     });
16994                     return value;
16995                 };
16996                 Slider.prototype.getPrcValue = function () {
16997                     if (!this.is.init)
16998                         return false;
16999                     var value = "";
17000                     $.each(this.o.pointers, function (i) {
17001                         if (this.value.prc !== undefined && !isNaN(this.value.prc))
17002                             value += (i > 0 ? ";" : "") + this.value.prc;
17003                     });
17004                     return value;
17005                 };
17006                 Slider.prototype.prcToValue = function (prc) {
17007                     var value;
17008                     if (this.settings.heterogeneity && this.settings.heterogeneity.length > 0) {
17009                         var h = this.settings.heterogeneity;
17010                         var _start = 0;
17011                         var _from = this.settings.from;
17012                         for (var i = 0; i <= h.length; i++) {
17013                             var v;
17014                             if (h[i]){
17015                                 v = h[i].split("/");}
17016                             else{
17017                                 v = [100, this.settings.to];}
17018                             if (prc >= _start && prc <= v[0]) {
17019                                 value = _from + ((prc - _start) * (v[1] - _from)) / (v[0] - _start);
17020                             }
17021                             _start = v[0];
17022                             _from = v[1];
17023                         }
17024                     }
17025                     else {
17026                         value = this.settings.from + (prc * this.settings.interval) / 100;
17027                     }
17028                     var roundedValue = this.round(value);
17029                     return roundedValue;
17030                 };
17031                 Slider.prototype.valueToPrc = function (value, pointer) {
17032                     var prc;
17033                     if (this.settings.heterogeneity && this.settings.heterogeneity.length > 0) {
17034                         var h = this.settings.heterogeneity;
17035                         var _start = 0;
17036                         var _from = this.settings.from;
17037                         for (var i = 0; i <= h.length; i++) {
17038                             var v;
17039                             if (h[i])
17040                                 v = h[i].split("/");
17041                             else
17042                                 v = [100, this.settings.to];
17043                             if (value >= _from && value <= v[1]) {
17044                                 prc = pointer.limits(_start + (value - _from) * (v[0] - _start) / (v[1] - _from));
17045                             }
17046                             _start = v[0];
17047                             _from = v[1];
17048                         }
17049                     } else {
17050                         prc = pointer.limits((value - this.settings.from) * 100 / this.settings.interval);
17051                     }
17052                     return prc;
17053                 };
17054                 Slider.prototype.round = function (value) {
17055                     value = Math.round(value / this.settings.step) * this.settings.step;
17056                     if (this.settings.round){
17057                         value = Math.round(value * Math.pow(10, this.settings.round)) / Math.pow(10, this.settings.round);}
17058                     else{
17059                         value = Math.round(value);}
17060                     return value;
17061                 };
17062                 return Slider;
17063             }])
17064         .directive('attStepSlider', [
17065             '$compile', '$templateCache', '$timeout', '$window', 'slider', 'sliderConstants', 'utils',
17066             function (compile, templateCache, timeout, win, Slider, sliderConstants, utils) {
17067                 /*
17068                  The MIT License (MIT)
17069                  Copyright (c) 2013 Julien Valéry
17070                  */
17071                 var templateUrl = 'app/scripts/ng_js_att_tpls/stepSlider/attStepSlider.html';
17072                 return {
17073                     restrict: 'AE',
17074                     require: '?ngModel',
17075                     scope: {
17076                         options: '=',
17077                         cutOff: '='
17078                     },
17079                     priority: 1,
17080                     templateUrl: templateUrl,
17081                     link: function (scope, element, attrs, ngModel) {
17082                         if (!ngModel)
17083                             return;
17084                         scope.mainSliderClass = 'step-slider';
17085                         element.after(compile(templateCache.get(templateUrl))(scope, function (clonedElement, scope) {
17086                             scope.tmplElt = clonedElement;
17087                         }));
17088                         ngModel.$render = function () {
17089                             if (ngModel.$viewValue.split && ngModel.$viewValue.split(";").length === 1) {
17090                                 ngModel.$viewValue = '0;' + ngModel.$viewValue;
17091                             } else if (typeof (ngModel.$viewValue) === 'number') {
17092                                 ngModel.$viewValue = '0;' + ngModel.$viewValue;
17093                             }
17094                             if (!ngModel.$viewValue && ngModel.$viewValue !== 0) {
17095                                 return;
17096                             }
17097                             if (typeof (ngModel.$viewValue) === 'number') {
17098                                 ngModel.$viewValue = '' + ngModel.$viewValue;
17099                             }
17100                             if (scope.slider) {
17101                                 var firstPointer = '0';
17102                                 scope.slider.getPointers()[0].set(firstPointer, true);
17103                                 if (ngModel.$viewValue.split(";")[1]) {
17104                                     var value = ngModel.$viewValue.split(";")[1];
17105                                     if (value.length >= 4) {
17106                                         value = value.substring(0, 2);
17107                                     }
17108                                     if (!scope.options.realtime)
17109                                         scope.options.callback(parseFloat(ngModel.$viewValue.split(";")[1]));
17110                                     scope.slider.getPointers()[1].set(ngModel.$viewValue.split(";")[1], true);
17111                                 }
17112                             }
17113                         };
17114                         var init = function () {
17115                             scope.from = '' + scope.options.from;
17116                             scope.to = '' + scope.options.to;
17117                             if (scope.options.calculate && typeof scope.options.calculate === 'function') {
17118                                 scope.from = scope.options.calculate(scope.from);
17119                                 scope.to = scope.options.calculate(scope.to);
17120                             }
17121                             scope.showDividers = scope.options.showDividers;
17122                             scope.COLORS = sliderConstants.COLORS;
17123                             scope.sliderColor = scope.options.sliderColor;
17124                             if (!scope.sliderColor)
17125                                 scope.sliderColor = sliderConstants.COLORS.REGULAR;
17126                             var scaleArray = scope.options.scale;
17127                             /* Make a copy of the scaleArray before converting it to percentage for the bars */
17128                             var nonPercentScaleArray = [];
17129                             /* Define variable for displaying lower range values */
17130                             var scaledUpValueArray=[];
17131                             /* Create Mapper for the percentage to value */
17132                             var prcToValueMapper = {};
17133                             for (var i in scaleArray) {
17134                                 var s = scaleArray[i];
17135                                 nonPercentScaleArray.push(s);
17136                             }
17137                             function addScaleArrayStartAndEnd() {
17138                                 if (scaleArray[0] !== 0) {
17139                                     scaleArray.splice(0, 0, 0);
17140                                 }
17141                                 if (scaleArray[scaleArray.length - 1] !== 100) {
17142                                     scaleArray.splice(scaleArray.length, 0, 100);
17143                                 }
17144                             }
17145                             function convertScaleArrayToPercentage() {
17146                                 if (scaleArray[scaleArray.length - 1] !== scope.options.to) {
17147                                     scaleArray.splice(scaleArray.length, 0, scope.options.to);
17148                                 }
17149
17150                                 if(scope.options.displayScaledvalues){
17151                                     for(var i in scaleArray){
17152                                         scaledUpValueArray.push(Math.log2(scaleArray[i]));
17153                                     }
17154                                     var maxScaledUpValue=scaledUpValueArray[scaledUpValueArray.length-1];
17155                                 }
17156
17157                                 for (var i in scaleArray) {
17158                                     var prcValue;
17159                                     var fromValueCheck = (scaleArray[i] / scope.options.from);
17160                                     var toValueCheck = (scaleArray[i] / scope.options.to);
17161
17162                                     if (scope.options.displayScaledvalues){
17163                                         prcValue = (scaledUpValueArray[i] /maxScaledUpValue)*100;
17164                                     } else {
17165                                         prcValue = ((scaleArray[i] - scope.options.from) / (scope.options.to - scope.options.from)) * 100;
17166                                     }
17167
17168                                     var realValue = scaleArray[i];
17169
17170                                     if (toValueCheck === 1) {
17171                                         prcValue = 100;
17172                                     }
17173                                     else if (fromValueCheck === 1) {
17174                                         prcValue = 0;
17175                                     }
17176                                     scaleArray[i] = prcValue;
17177                                     prcToValueMapper['' + prcValue] = realValue;
17178                                 }
17179                             }
17180                             if ((scope.options.from !== 0 || scope.options.to !== 100)
17181                                     && scope.options.smooth) {
17182                                 /*
17183                                  scale array is in real values.
17184                                  */
17185                                 addScaleArrayStartAndEnd();
17186                                 scope.options.stepWithDifferentScale = true;
17187                             }
17188                             else if ((scope.options.from !== 0 || scope.options.to !== 100)
17189                                     && !scope.options.smooth) {
17190                                 /*
17191                                  Case for different from and to values other than 0 and 100
17192                                  so we have to do some different calculations
17193                                  */
17194                                 scope.options.stepWithDifferentScale = true;
17195                                 convertScaleArrayToPercentage();
17196                                 addScaleArrayStartAndEnd();
17197                             }
17198                             else {
17199                                 /*
17200                                  This is the normal case where the from and to values are 0 and
17201                                  100 respectively.        
17202                                  */
17203                                 //Check that the scale starts at 0 and 100
17204                                 convertScaleArrayToPercentage();
17205                                 addScaleArrayStartAndEnd();
17206                             }
17207                             var decimalPlaces = 0;
17208                             if (scope.options.decimalPlaces) {
17209                                 decimalPlaces = scope.options.decimalPlaces;
17210                             }
17211                             //Modify the endDimension based on whether converison was passed in
17212                             //Also change the toStr value to scale to the last factor
17213                             scope.endDimension = scope.options.dimension;
17214                             if (scope.options.conversion) {
17215                                 //Get the dimension of the last conversion
17216                                 var lastIndex = scope.options.conversion.length - 1;
17217                                 var lastDimension = scope.options.conversion[lastIndex].dimension;
17218                                 var lastScaleFactor = scope.options.conversion[lastIndex].scaleFactor;
17219                                 scope.endDimension = ' ' + lastDimension;
17220
17221                                 var toVal = (scope.to / lastScaleFactor).toFixed(decimalPlaces);
17222                                 scope.toStr = toVal;
17223                             } else {
17224                                 scope.toStr = scope.options.to;
17225                             }
17226
17227                             var tooltipLabel = utils.convertToMbpsGbps(scope.toStr, scope.endDimension, scope.options.decimalPlaces);
17228                             scope.toStr = tooltipLabel.unitValue;
17229                             scope.endDimension = ' ' + tooltipLabel.unitLabel;
17230
17231                             var OPTIONS = {
17232                                 from: scope.options.from,
17233                                 to: scope.options.to,
17234                                 step: scope.options.step,
17235                                 smooth: scope.options.smooth,
17236                                 limits: true,
17237                                 stepWithDifferentScale: scope.options.stepWithDifferentScale,
17238                                 round: scope.options.round || false,
17239                                 value: ngModel.$viewValue,
17240                                 scale: scope.options.scale,
17241                                 nonPercentScaleArray: nonPercentScaleArray,
17242                                 prcToValueMapper: prcToValueMapper,
17243                                 firstDimension: scope.options.dimension,
17244                                 decimalPlaces: decimalPlaces,
17245                                 conversion: scope.options.conversion,
17246                                 realtimeCallback: scope.options.callback
17247                             };
17248                             if (angular.isFunction(scope.options.realtime)) {
17249                                 OPTIONS.realtimeCallback = function (value) {
17250                                     ngModel.$setViewValue(value);
17251                                     scope.options.callback(value);
17252                                 };
17253                             }
17254                             else {
17255                                 OPTIONS.callback = forceApply;
17256                             }
17257                             OPTIONS.calculate = scope.options.calculate || undefined;
17258                             OPTIONS.onstatechange = scope.options.onstatechange || undefined;
17259                             timeout(function () {
17260                                 var scaleDiv = scope.tmplElt.find('div')[7];
17261                                 if (!OPTIONS.conversion) {
17262                                     scope.tmplElt.find('div').eq(6).find('span').eq(0).css('padding-left', '10px');
17263                                     scope.tmplElt.find('div').eq(6).find('span').eq(0).css('padding-right', '15px');
17264                                 }
17265                                 scope.slider = angular.element.slider(element, scope.tmplElt, OPTIONS);
17266                                 angular.element(scaleDiv).html(scope.generateScale());
17267                                 scope.drawScale(scaleDiv);
17268                                 initListener();
17269                                 scope.$watch('options.disable', function (val) {
17270                                     if (scope.slider) {
17271                                         scope.tmplElt.toggleClass('disabled', val);
17272                                         scope.slider.disable(val);
17273                                     }
17274                                 });
17275                                 scope.$watch('cutOff', function (cutOffVal) {
17276                                     if (cutOffVal && cutOffVal > 0) {
17277                                         var cutOffPrc = (cutOffVal - scope.slider.settings.from) / (scope.slider.settings.to -
17278                                                 scope.slider.settings.from);
17279                                         cutOffPrc = cutOffPrc * 100;
17280                                         scope.isCutOffSlider = true;
17281                                         scope.slider.settings.cutOffWidth = cutOffPrc;
17282                                         //cutOffVal is the actual value of the cutoff point
17283                                         scope.cutOffVal = cutOffVal;
17284                                         if (scope.options.conversion) {
17285                                             var convertedVal = utils.getConversionFactorValue(cutOffVal, scope.options.conversion, scope.options.dimension);
17286                                             convertedVal.scaledVal = parseFloat(convertedVal.scaledVal).toFixed(scope.options.decimalPlaces);
17287                                             scope.cutOffVal = convertedVal.scaledVal + ' ' + convertedVal.scaledDimension;
17288                                         }
17289                                         scope.slider.settings.cutOffVal = cutOffVal;
17290                                         //Calculate the cutOff percentage
17291                                         scope.slider.changeCutOffWidth(cutOffPrc + '%');
17292                                         var scale = scope.slider.settings.nonPercentScaleArray;
17293                                         //Calculate where the cutOff point in relation to the scale array
17294                                         for (var i in scale) {
17295                                             if (i >= 1) {
17296                                                 var lowerVal = scale[i - 1];
17297                                                 var higherVal = scale[i];
17298                                                 if (cutOffVal > lowerVal && cutOffVal <= higherVal) {
17299                                                     scope.slider.settings.cutOffIndex = i;
17300                                                 }
17301                                             }
17302                                         }
17303                                     } else {
17304                                         scope.slider.settings.cutOffVal = 0;
17305                                     }
17306                                 });
17307                             });
17308                         };
17309                         function initListener() {
17310                             angular.element(win).bind('resize', function (event) {
17311                                 scope.slider.onresize();
17312                             });
17313                         }
17314                         scope.generateScale = function () {
17315                             if (scope.options.scale && scope.options.scale.length > 0) {
17316                                 var str = "";
17317                                 var s = scope.options.scale;
17318                                 var position = 'left';
17319                                 for (var i = 0; i < s.length; i++) {
17320                                     if (i !== 0 && i !== s.length - 1) {
17321                                         var scaledPosition = ((s[i] - scope.from) / (scope.to - scope.from)) * 100;
17322                                         if (scope.options.stepWithDifferentScale && !scope.options.smooth) {
17323                                             scaledPosition = s[i];
17324                                         }
17325                                         str += '<span style="' + position + ': ' + scaledPosition + '%"></span>';
17326                                     }
17327                                 }
17328                                 return str;
17329                             } else
17330                                 return "";
17331                             return "";
17332                         };
17333                         scope.drawScale = function (scaleDiv) {
17334                             angular.forEach(angular.element(scaleDiv).find('ins'), function (scaleLabel, key) {
17335                                 scaleLabel.style.marginLeft = -scaleLabel.clientWidth / 2;
17336                             });
17337                         };
17338                         var forceApply = function (value) {
17339                             var val = value.split(";")[1];
17340                             scope.$apply(function () {
17341                                 ngModel.$setViewValue(parseInt(val));
17342                             });
17343                             if (scope.options.callback) {
17344                                 scope.options.callback(parseInt(val));
17345                             }
17346                         };
17347                         scope.$watch('options', function (value) {
17348                             init();
17349                         });
17350                         angular.element.slider = function (inputElement, element, settings) {
17351                             if (!element.data('jslider'))
17352                                 element.data('jslider', new Slider(inputElement, element, settings));
17353                             var sliderObj = element.data('jslider');
17354                             return sliderObj;
17355                         };
17356                     }
17357                 };
17358             }]);
17359 angular.module('att.abs.steptracker', ['att.abs.transition'])
17360         .directive('steptracker', ['$timeout', function ($timeout) {
17361                 return {
17362                     // This allows dev's clickHandler to cancel an operation
17363                     priority: 100,
17364                     scope: {
17365                         sdata: "=sdata",
17366                         cstep: "=currentStep",
17367                         clickHandler: '=?',
17368                         disableClick: '=?'
17369                     },
17370                     restrict: 'EA',
17371                     replace: true,
17372                     templateUrl: 'app/scripts/ng_js_att_tpls/steptracker/step-tracker.html',
17373                     link: function (scope, elem) {
17374                         if (scope.disableClick === undefined) {
17375                             scope.disableClick = false;
17376                         }
17377                         $timeout(function () {
17378                             if (scope.cstep < 1) {
17379                                 scope.cstep = 1;
17380                             }
17381                             else if (scope.cstep > scope.sdata.length) {
17382                                 scope.cstep = scope.sdata.length;
17383                             }
17384                             var divs = elem.find('div');
17385                             var slidertracks = [];
17386                             for (var i in divs) {
17387                                 if (divs.eq(i)[0]) {
17388                                     var el = divs.eq(i)[0].className;
17389                                     if (el.indexOf('track ng-scope') > -1) {
17390                                         slidertracks.push(divs.eq(i));
17391                                     }
17392                                 }
17393                             }
17394                             var currentPage,totalPage,currentTrack = updateCurrentTrack(scope.cstep);
17395                             function updateCurrentTrack(step) {
17396                                 // Always return the step-1 because array starts at 0
17397                                 return angular.element(slidertracks[step - 1]);
17398                             }
17399                             function updateTrackWidth() {
17400                                 if (scope.cstep > 0 && scope.cstep <= scope.sdata.length - 1 && currentPage > 0) {
17401                                     var newWidth = ((currentPage / totalPage) * 100) + "%";
17402                                     currentTrack = updateCurrentTrack(scope.cstep);
17403                                     currentTrack.css('width', newWidth);
17404                                 }
17405                             }
17406                             function updatePages() {
17407                                 if (scope.cstep <= scope.sdata.length) {
17408                                     currentPage = scope.sdata[scope.cstep - 1]['currentPage'];
17409                                     totalPage = scope.sdata[scope.cstep - 1]['totalPages'];
17410                                 }
17411                             }
17412                             // dynamically add width for steps, depending on the number of steps.
17413                             scope.set_width = function (indexval) {
17414                                 var setwidth = (100 / (scope.sdata.length - 1)) + "%";
17415                                 // skip last element and add width for all other element
17416                                 if ((scope.sdata.length - 1) > indexval) {
17417                                     return {'width': setwidth};
17418                                 }
17419                             };
17420                             scope.$watch('sdata', function () {
17421                                 updatePages();
17422                                 var prevStep = scope.cstep;
17423                                 // Before anything, ensure currentPage is never below 1
17424                                 if (currentPage < 1) {
17425                                     currentPage = 1;
17426                                     if (scope.cstep !== 1) {
17427                                         // Decrease step, current track width is 0%, new step width updates
17428                                         scope.cstep--;
17429                                         updatePages();
17430                                     }
17431                                 }
17432                                 // Move to next step, reset currentPage, totalPage, and ensure previous steps are completed
17433                                 if (currentPage > totalPage) {
17434                                     if (scope.cstep > scope.sdata.length - 1) {
17435                                         scope.cstep++;
17436                                         return;
17437                                     } else {
17438                                         currentPage = totalPage;
17439                                         updateTrackWidth();
17440                                         scope.cstep++;
17441                                         updatePages();
17442                                         updateTrackWidth();
17443                                     }
17444                                 }
17445                                 if (currentPage < 1 && prevStep === scope.cstep) {
17446                                     currentPage = 1;
17447                                     if (scope.cstep > 1) {
17448                                         scope.cstep--;
17449                                         scope.sdata[scope.cstep - 1]['currentPage'] = scope.sdata[scope.cstep - 1]['totalPages'];
17450                                         scope.sdata[scope.cstep]['currentPage'] = 1;
17451                                     }
17452                                 }
17453                                 updateTrackWidth();
17454                             }, true);
17455                             //add the active class for current step
17456                             scope.activestep = function (index) {
17457                                 return (index === scope.cstep - 1);
17458                             };
17459                             //add the done class for finished step
17460                             scope.donesteps = function (index) {
17461                                 return (index < scope.cstep - 1);
17462                             };
17463                             //add the last class for final step
17464                             scope.laststep = function (index) {
17465                                 return (index === scope.sdata.length - 1);
17466                             };
17467                             scope.isIncomplete = function (index) {
17468                                 if (index === scope.cstep - 1) {
17469                                     return false;
17470                                 }
17471                                 if (index >= 0 && index < scope.sdata.length - 1) {
17472                                     var step = scope.sdata[index];
17473                                     return (step['currentPage'] <= step['totalPages']);
17474                                 }
17475                             };
17476                             //click event
17477                             scope.stepclick = function ($event, steps) {
17478                                 // If we are decreasing steps, reset all currentPage counts to 1
17479                                 if (steps < scope.cstep) {
17480                                     for (var i = scope.cstep - 1; i > steps; i--) {
17481                                         scope.sdata[i]['currentPage'] = 1;
17482                                     }
17483                                     scope.sdata[steps]['currentPage']--;
17484                                 }
17485                                 if (angular.isFunction(scope.clickHandler)) {
17486                                     scope.clickHandler($event, steps);
17487                                 }
17488                                 scope.cstep = steps + 1;
17489                                 // In the case we decremented previously from this step, we need to reset currentpage to default
17490                                 if (scope.cstep <= scope.sdata.length && scope.sdata[scope.cstep]['currentPage'] < 1) {
17491                                     scope.sdata[scope.cstep]['currentPage'] = 1;
17492                                 }
17493                                 updatePages();
17494                                 updateTrackWidth();
17495                             };
17496                         }, 100);
17497                     }
17498                 };
17499             }
17500         ])
17501         .constant('timelineConstants', {
17502             STEP_TYPE: {
17503                 ALERT: 'alert',
17504                 COMPLETED: 'completed',
17505                 CANCELLED: 'cancelled'
17506             }
17507         })
17508         .controller('AttTimelineCtrl', ['$scope', '$timeout', function ($scope, $timeout) {
17509                 var timelineBarCtrls = [];
17510                 var timelineDotCtrls = [];
17511                 this.numSteps = 0;
17512                 this.isAlternate = function () {
17513                     return $scope.alternate;
17514                 };
17515                 this.addTimelineBarCtrls = function (t) {
17516                     timelineBarCtrls.push(t);
17517                 };
17518                 this.addTimelineDotCtrls = function (b) {
17519                     timelineDotCtrls.push(b);
17520                 };
17521                 $timeout(init, 200);
17522                 function init() {
17523                     function compare(a, b) {
17524                         if (a.order < b.order) {
17525                             return -1;
17526                         }
17527                         if (a.order > b.order) {
17528                             return 1;
17529                         }
17530                         return 0;
17531                     }
17532                     timelineDotCtrls.sort(compare);
17533                     timelineBarCtrls.sort(compare);
17534                     if ($scope.$parent.animate) {
17535                         animateSequence();
17536                     }
17537                     $scope.$watch('trigger', function (val) {
17538                         if (val) {
17539                             $scope.resetTimeline();
17540                         } else {
17541                             $scope.$parent.animate = false;
17542                         }
17543                     });
17544                 }
17545                 function animateSequence() {
17546                     var dotsDuration = .25;
17547                     var timelineBarProgressDuration = .25;
17548                     if (typeof $scope.barAnimateDuration === 'number') {
17549                         timelineBarProgressDuration = $scope.barAnimateDuration;
17550                     }
17551                     var start = createAnimation(0, timelineBarProgressDuration);
17552                     function setToInactiveStates() {
17553                         for (var i in timelineDotCtrls) {
17554                             var dotCtrl = timelineDotCtrls[i];
17555                             if (i % 2 === 0) {
17556                                 dotCtrl.unhoveredStateForBelow(.25);
17557                             } else {
17558                                 dotCtrl.unhoveredStateForAbove(.25);
17559                             }
17560                             if (dotCtrl.isStop()) {
17561                                 break;
17562                             }
17563                         }
17564                     }
17565                     function createAnimation(i, duration) {
17566                         if (i === 0) {
17567                             return function () {
17568                                 if (timelineDotCtrls[i + 1].isStop() && timelineDotCtrls[i + 1].isCancelled()) {
17569                                     timelineBarCtrls[i].isCancelled(true);
17570                                 }
17571                                 timelineBarCtrls[i].animate(createAnimation(i + 1, duration), duration);
17572                             };
17573                         } else if (i === timelineBarCtrls.length - 1) {
17574                             return function () {
17575                                 //Removes the bolded text from the start
17576                                 if (timelineDotCtrls[0].isCurrentStep()) {
17577                                     timelineDotCtrls[0].isCurrentStep(false);
17578                                 }
17579                                 if (timelineDotCtrls[i].isStop()) {
17580                                     timelineDotCtrls[i - 1].shrinkAnimate(dotsDuration);
17581                                     timelineDotCtrls[i].isCurrentStep(true);
17582                                 } else {
17583                                     timelineDotCtrls[i - 1].shrinkAnimate(dotsDuration);
17584                                     timelineBarCtrls[i].animate(createAnimation(i + 1, duration), duration);
17585                                 }
17586                                 timelineDotCtrls[i].expandedAnimate(dotsDuration);
17587                                 $timeout(function () {
17588                                     setToInactiveStates();
17589                                 }, 500);
17590                             };
17591                         }
17592                         //End Dot
17593                         else if (i === timelineBarCtrls.length) {
17594                             return function () {
17595                                 //Removes the bolded text from the start
17596                                 if (timelineDotCtrls[0].isCurrentStep()) {
17597                                     timelineDotCtrls[0].isCurrentStep(false);
17598                                 }
17599                                 timelineDotCtrls[i - 1].shrinkAnimate(dotsDuration);
17600                                 timelineDotCtrls[i].expandedAnimate(dotsDuration);
17601                                 timelineDotCtrls[i].isCurrentStep(true);
17602                                 $timeout(function () {
17603                                     setToInactiveStates();
17604                                 }, 500);
17605                             };
17606                         }
17607                         else {
17608                             return function () {
17609                                 //Removes the bolded text from the start
17610                                 if (timelineDotCtrls[0].isCurrentStep()) {
17611                                     timelineDotCtrls[0].isCurrentStep(false);
17612                                 }
17613                                 if (timelineDotCtrls[i].isStop()) {
17614                                     timelineDotCtrls[i - 1].shrinkAnimate(dotsDuration);
17615                                     timelineDotCtrls[i].expandedAnimate(dotsDuration);
17616                                     timelineDotCtrls[i].isCurrentStep(true);
17617                                     $timeout(function () {
17618                                         setToInactiveStates();
17619                                     }, 500);
17620                                 } else {
17621                                     if (timelineDotCtrls[i + 1].isStop() && timelineDotCtrls[i + 1].isCancelled()) {
17622                                         timelineBarCtrls[i].isCancelled(true);
17623                                     }
17624                                     timelineDotCtrls[i - 1].shrinkAnimate(dotsDuration);
17625                                     timelineBarCtrls[i].animate(createAnimation(i + 1, duration), duration);
17626                                     timelineDotCtrls[i].expandedAnimate(dotsDuration);
17627                                 }
17628                             };
17629                         }
17630                     }
17631                     start();
17632                 }
17633             }])
17634         .directive('attTimeline', ['$timeout', '$compile', function ($timeout, $compile) {
17635                 return {
17636                     restrict: 'EA',
17637                     replace: true,
17638                     scope: {
17639                         steps: '=',
17640                         trigger: '=',
17641                         alternate: '=',
17642                         barAnimateDuration: '='
17643                     },
17644                     templateUrl: 'app/scripts/ng_js_att_tpls/steptracker/timeline.html',
17645                     controller: 'AttTimelineCtrl',
17646                     link: function (scope, element, attrs, ctrl) {
17647                         var init = function () {
17648                             var steps = scope.steps;
17649                             var middleSteps = [];
17650                             for (var i = 1; i < steps.length; i++) {
17651                                 var aStep = steps[i];
17652                                 middleSteps.push(aStep);
17653                             }
17654                             scope.middleSteps = middleSteps;
17655                             //Used in calculating the width of the loading bars
17656                             ctrl.numSteps = steps.length - 1;
17657                         };
17658                         init();
17659                         //Recompile in case of scope changes
17660                         scope.resetTimeline = function () {
17661                             scope.animate = true;
17662                             $compile(element)(scope);
17663                         };
17664                     }
17665                 };
17666             }])
17667         .controller('TimelineBarCtrl', ['$scope', function ($scope) {
17668                 this.type = 'timelinebar';
17669                 this.order = parseInt($scope.order);
17670                 this.animate = function (callback, duration) {
17671                     $scope.loadingAnimation(callback, duration);
17672                 };
17673                 this.isCancelled = function (isCancelled) {
17674                     $scope.isCancelled = isCancelled;
17675                 };
17676             }])
17677         .directive('timelineBar', ['animation', '$progressBar', function (animation, $progressBar) {
17678                 return {
17679                     restrict: 'EA',
17680                     replace: true,
17681                     templateUrl: 'app/scripts/ng_js_att_tpls/steptracker/timelineBar.html',
17682                     scope: {
17683                         order: '@'
17684                     },
17685                     require: ['^attTimeline', 'timelineBar'],
17686                     controller: 'TimelineBarCtrl',
17687                     link: function (scope, element, attrs, ctrls) {
17688                         var attTimelineCtrl = ctrls[0];
17689                         var timelineBarCtrl = ctrls[1];
17690                         attTimelineCtrl.addTimelineBarCtrls(timelineBarCtrl);
17691                         scope.isCompleted = true;
17692                         var widthPerc = (100 / attTimelineCtrl.numSteps) - 3;
17693                         element.css('width', widthPerc + '%');
17694                         var elem = element.find('div').eq(0);
17695                         animation.set(elem, {opacity: 0.0});
17696                         var updateCallback = function (selfElement) {
17697                             animation.set(elem, {opacity: 1.0});
17698                             animation.set(elem, {
17699                                 scaleX: selfElement.progress(),
17700                                 transformOrigin: "left"
17701                             });
17702                         };
17703                         scope.loadingAnimation = $progressBar(updateCallback);
17704                     }
17705                 };
17706             }])
17707         .controller('TimelineDotCtrl', ['$scope', '$timeout', 'timelineConstants', function ($scope, $timeout, timelineConstants) {
17708                 this.type = 'dot';
17709                 this.order = parseInt($scope.order);
17710                 var self = this;
17711                 $timeout(function () {
17712                     if (self.order !== 0) {
17713                         if (self.order % 2 !== 0) {
17714                             $scope.initializeAboveForAnimation();
17715                         }
17716                         else {
17717                             $scope.initializeBelowForAnimation();
17718                         }
17719                     }
17720                 });
17721                 this.expandedAnimate = function (duration) {
17722                     $scope.setColor();
17723                     $scope.expandedAnimate(duration);
17724                     if (self.order !== 0 && !$scope.isStepsLessThanFive()) {
17725                         if (self.order % 2 !== 0) {
17726                             $scope.expandContentForAbove(duration);
17727                         } else {
17728                             $scope.expandContentForBelow(duration);
17729                         }
17730                     }
17731                 };
17732                 this.unhoveredStateForAbove = function (duration) {
17733                     $scope.unhoveredStateForAbove(duration);
17734                 };
17735                 this.unhoveredStateForBelow = function (duration) {
17736                     $scope.unhoveredStateForBelow(duration);
17737                 };
17738                 this.shrinkAnimate = function (duration) {
17739                     $scope.shrinkAnimate(duration);
17740                 };
17741                 this.setExpanded = function () {
17742                     $scope.setSize(3);
17743                 };
17744                 this.isStop = function () {
17745                     return $scope.isStop;
17746                 };
17747                 this.isCancelled = function () {
17748                     return ($scope.type === timelineConstants.STEP_TYPE.CANCELLED);
17749                 };
17750                 this.isAlert = function () {
17751                     return ($scope.type === timelineConstants.STEP_TYPE.ALERT);
17752                 };
17753                 //Sets the bolded text
17754                 this.isCurrentStep = function (isCurrentStep) {
17755                     if (isCurrentStep !== undefined) {
17756                         $scope.isCurrentStep = isCurrentStep;
17757                     }
17758                     return $scope.isCurrentStep;
17759                 };
17760             }])
17761         .directive('timelineDot', ['animation', 'timelineConstants',
17762             function (animation, timelineConstants) {
17763                 return {
17764                     restrict: 'EA',
17765                     replace: true,
17766                     scope: {
17767                         order: '@',
17768                         title: '@',
17769                         description: '@',
17770                         by: '@',
17771                         date: '@',
17772                         type: '@'
17773                     },
17774                     templateUrl: 'app/scripts/ng_js_att_tpls/steptracker/timelineDot.html',
17775                     require: ['^attTimeline', 'timelineDot'],
17776                     controller: 'TimelineDotCtrl',
17777                     link: function (scope, element, attrs, ctrls) {
17778                         var attTimelineCtrl = ctrls[0];
17779                         var timelineDotCtrl = ctrls[1];
17780                         attTimelineCtrl.addTimelineDotCtrls(timelineDotCtrl);
17781                         scope.numSteps = attTimelineCtrl.numSteps + 1;
17782                         scope.isCurrentStep = false;
17783                         scope.isCompleted = false;
17784                         scope.isStop = false;
17785                         if (scope.type === timelineConstants.STEP_TYPE.ALERT || scope.type === timelineConstants.STEP_TYPE.CANCELLED) {
17786                             scope.isStop = true;
17787                         }
17788                         scope.isInactive = true;
17789                         var divs = element.find('div');
17790                         var biggerCircleElem = divs.eq(0);
17791                         var expandableCircleElem = divs.eq(2);
17792                         var infoboxElem = divs.eq(3);
17793                         var titleElem = divs.eq(5);
17794                         var contentElem = divs.eq(6);
17795                         var dateElem = divs.eq(9);
17796                         function isEmptyStep() {
17797                             if (!scope.description && !scope.by && !scope.date) {
17798                                 return true;
17799                             }
17800                             return false;
17801                         }
17802                         scope.isStepsLessThanFive = function () {
17803                             if (scope.numSteps < 5) {
17804                                 return true;
17805                             }
17806                             return false;
17807                         };
17808                         scope.titleMouseover = function (num) {
17809                             if (!scope.isStepsLessThanFive() && !isEmptyStep()) {
17810                                 if (num === 1 && scope.order % 2 === 0) {
17811                                     scope.expandContentForBelow(.25);
17812                                 }
17813                                 if (num === 2 && scope.order % 2 !== 0) {
17814                                     scope.expandContentForAbove(.25);
17815                                 }
17816                             }
17817                         };
17818                         scope.titleMouseleave = function () {
17819                             if (scope.order % 2 === 0) {
17820                                 scope.unhoveredStateForBelow(.25);
17821                             }
17822                             else {
17823                                 scope.unhoveredStateForAbove(.25);
17824                             }
17825                         };
17826                         scope.initializeAboveForAnimation = function () {
17827                             if (!scope.isStepsLessThanFive() && attTimelineCtrl.isAlternate()) {
17828                                 animation.set(contentElem, {opacity: 0});
17829                                 animation.set(dateElem, {opacity: 0});
17830                                 if (!isEmptyStep()) {
17831                                     var yOffset = contentElem[0].offsetHeight + dateElem[0].offsetHeight;
17832                                     animation.set(titleElem, {'top': yOffset});
17833                                 }
17834                             }
17835                         };
17836                         scope.expandContentForAbove = function (duration) {
17837                             if (!scope.isStepsLessThanFive() && attTimelineCtrl.isAlternate()) {
17838                                 animation.to(titleElem, duration, {'top': 0});
17839                                 animation.to(contentElem, duration, {opacity: 1});
17840                                 animation.to(dateElem, duration, {opacity: 1});
17841                             }
17842                         };
17843                         scope.unhoveredStateForAbove = function (duration) {
17844                             if (!scope.isStepsLessThanFive() && attTimelineCtrl.isAlternate()) {
17845                                 animation.set(contentElem, {opacity: 0});
17846                                 animation.set(dateElem, {opacity: 1});
17847                                 var yOffset = contentElem[0].offsetHeight;
17848                                 animation.to(titleElem, duration, {'top': yOffset});
17849                             }
17850                         };
17851                         scope.initializeBelowForAnimation = function () {
17852                             if (!scope.isStepsLessThanFive() && attTimelineCtrl.isAlternate()) {
17853                                 animation.set(contentElem, {height: '0%', opacity: 0, top: '-20px'});
17854                                 animation.set(dateElem, {opacity: 0});
17855                             }
17856                         };
17857                         scope.expandContentForBelow = function (duration) {
17858                             if (!scope.isStepsLessThanFive() && attTimelineCtrl.isAlternate()) {
17859                                 animation.set(dateElem, {opacity: 1});
17860                                 animation.to(contentElem, duration, {height: 'auto', opacity: 1, top: '0px'});
17861                             }
17862                         };
17863                         scope.unhoveredStateForBelow = function (duration) {
17864                             if (!scope.isStepsLessThanFive() && attTimelineCtrl.isAlternate()) {
17865                                 animation.to(contentElem, duration, {height: '0%', opacity: 0, top: '-20px', position: 'relative'});
17866                                 animation.set(dateElem, {opacity: 1});
17867                             }
17868                         };
17869                         /*Default Initializaztion*/
17870                         //If the info box is above and the description and date and by are empty then we have do reset its position
17871                         if (isEmptyStep() && (scope.order % 2 !== 0 && attTimelineCtrl.isAlternate())) {
17872                             infoboxElem.css('top', '-47px');
17873                         }
17874                         //Check if the order is odd and set the appropiate above or below and other effects
17875                         if (scope.order % 2 === 0 || !attTimelineCtrl.isAlternate()) {
17876                             scope.isBelowInfoBoxShown = true;
17877                         }
17878                         else {
17879                             scope.isBelowInfoBoxShown = false;
17880                         }
17881                         //modify some css for steps less than 5 and not alternating
17882                         if (scope.isStepsLessThanFive() && !attTimelineCtrl.isAlternate()) {
17883                             animation.set(dateElem, {marginTop: 10});
17884                         }
17885                         //For IE 8 fix
17886                         animation.set(biggerCircleElem, {opacity: '.5'});
17887                         //shrink the expandableCircle to we can expand it later
17888                         animation.set(expandableCircleElem, {opacity: '0.0'});
17889                         animation.set(expandableCircleElem, {scale: .10});
17890                         if (scope.order === 0) {
17891                             animation.set(expandableCircleElem, {opacity: '1.0'});
17892                             animation.set(expandableCircleElem, {scale: 1});
17893                             animation.set(biggerCircleElem, {scale: 3});
17894                             scope.isCurrentStep = true;
17895                             scope.isInactive = false;
17896                             scope.isCompleted = true;
17897                         }
17898                         scope.setColor = function () {
17899                             scope.isInactive = false;
17900                             if (scope.type === timelineConstants.STEP_TYPE.CANCELLED) {
17901                                 scope.isCancelled = true;
17902                             }
17903                             else if (scope.type === timelineConstants.STEP_TYPE.ALERT) {
17904                                 scope.isAlert = true;
17905                             }
17906                             else {
17907                                 scope.isCompleted = true;
17908                             }
17909                             if (!scope.$phase) {
17910                                 scope.$apply();
17911                             }
17912                         };
17913                         scope.setSize = function (size) {
17914                             animation.set(biggerCircle, {scale: size});
17915                         };
17916                         scope.setExpandedCircle = function () {
17917                             animation.set(expandableCircleElem, {opacity: '1.0'});
17918                             animation.set(expandableCircleElem, {scale: 1});
17919                         };
17920                         scope.expandedAnimate = function (duration) {
17921                             animation.to(biggerCircleElem, duration, {scale: 3});
17922                             animation.set(expandableCircleElem, {opacity: '1.0'});
17923                             animation.to(expandableCircleElem, duration, {scale: 1});
17924                         };
17925                         scope.shrinkAnimate = function (duration) {
17926                             animation.to(biggerCircleElem, duration, {scale: 1});
17927                         };
17928                     }
17929                 };
17930             }]);
17931 angular.module('att.abs.table', ['att.abs.utilities'])
17932 .constant('tableConfig', {
17933     //true for descending & false for ascending
17934     defaultSortPattern: false,
17935     highlightSearchStringClass: 'tablesorter-search-highlight'
17936 })
17937
17938 .directive('attTable', ['$filter', function($filter) {
17939     return {
17940         restrict: 'EA',
17941         replace: true,
17942         transclude: true,
17943         scope: {
17944             tableData: "=",
17945             viewPerPage: "=",
17946             currentPage: "=",
17947             totalPage: "=",
17948             searchCategory: "=",
17949             searchString: "="
17950         },
17951         require: 'attTable',
17952         templateUrl: 'app/scripts/ng_js_att_tpls/table/attTable.html',
17953         controller: ['$scope', function($scope) {
17954             this.headers = [];
17955             this.currentSortIndex = null;
17956             this.setIndex = function(headerScope) {
17957                 this.headers.push(headerScope);
17958             };
17959             this.getIndex = function(headerName) {
17960                 for (var i = 0; i < this.headers.length; i++) {
17961                     if (this.headers[i].headerName === headerName) {
17962                         return this.headers[i].index;
17963                     }
17964                 }
17965                 return null;
17966             };
17967             this.sortData = function(columnIndex, reverse) {
17968                 $scope.$parent.columnIndex = columnIndex;
17969                 $scope.$parent.reverse = reverse;
17970                 this.currentSortIndex = columnIndex;
17971                 $scope.currentPage = 1;
17972                 this.resetSortPattern();
17973             };
17974             this.getSearchString = function() {
17975                 return $scope.searchString;
17976             };
17977             this.resetSortPattern = function() {
17978                 for(var i = 0; i < this.headers.length; i++) {
17979                     var currentScope = this.headers[i];
17980                     if(currentScope.index !== this.currentSortIndex) {
17981                         currentScope.resetSortPattern();
17982                     }
17983                 }
17984             };
17985         }],
17986         link: function(scope, elem, attr, ctrl) {
17987             scope.searchCriteria = {};
17988             scope.$watchCollection('tableData', function(value) {
17989                 if(value && !isNaN(value.length)) {
17990                     scope.totalRows = value.length;
17991                 }
17992             });
17993             scope.$watch('currentPage', function(val) {
17994                 scope.$parent.currentPage = val;
17995             });
17996             scope.$watch('viewPerPage', function(val) {
17997                 scope.$parent.viewPerPage = val;
17998             });
17999             scope.$watch(function() {
18000                 return scope.totalRows / scope.viewPerPage;
18001             }, function(value) {
18002                 if(!isNaN(value)) {
18003                     scope.totalPage = Math.ceil(value);
18004                     scope.currentPage = 1;
18005                 }
18006             });
18007             var searchValCheck = function(val){
18008                 if(angular.isDefined(val) && val !== null && val !== ""){
18009                     return true;
18010                 }
18011             };
18012             var setSearchCriteria = function(v1,v2){
18013                 if(searchValCheck(v1) && searchValCheck(v2)){
18014                     var index = ctrl.getIndex(v2);
18015                     scope.searchCriteria = {};
18016                     if (index !== null) {
18017                         scope.searchCriteria[index] = v1;
18018                     }
18019                 }else if(searchValCheck(v1) && (!angular.isDefined(v2) || v2 === null || v2 === "")){
18020                     scope.searchCriteria = {
18021                         $: v1
18022                     };
18023                 }else {
18024                     scope.searchCriteria = {};
18025                 }
18026             };
18027             scope.$watch('searchCategory', function(newVal,oldVal) {
18028                 if(newVal !== oldVal){
18029                     setSearchCriteria(scope.searchString,newVal);
18030                 }
18031             });
18032             scope.$watch('searchString', function (newVal,oldVal) {
18033                 if(newVal !== oldVal){
18034                     setSearchCriteria(newVal,scope.searchCategory);
18035                 }
18036             });
18037             scope.$watchCollection('searchCriteria', function(val) {
18038                 scope.$parent.searchCriteria = val;
18039                 scope.totalRows = scope.tableData && ($filter('filter')(scope.tableData, val, false)).length || 0;
18040                 scope.currentPage = 1;
18041             });
18042         }
18043     };
18044 }])
18045
18046 .directive('attTableRow', [function() {
18047     return {
18048         restrict: 'EA',
18049         compile: function (elem, attr) {
18050             if (attr.type === 'header') {
18051                 elem.find('tr').eq(0).addClass('tablesorter-headerRow');
18052             } else if (attr.type === 'body') {
18053                 var html = elem.children();
18054                 if(attr.rowRepeat){
18055                     if (attr.trackBy) {
18056                         html.attr('ng-repeat', attr.rowRepeat.concat(" | orderBy : columnIndex : reverse | filter : searchCriteria : false | attLimitTo : viewPerPage : viewPerPage*(currentPage-1) track by " + attr.trackBy));
18057                     } else {
18058                         html.attr('ng-repeat', attr.rowRepeat.concat(" | orderBy : columnIndex : reverse | filter : searchCriteria : false | attLimitTo : viewPerPage : viewPerPage*(currentPage-1) track by $index"));
18059                     }
18060                 }
18061                 html.attr('ng-class', "{'alt-row': $even,'normal-row': $odd}");
18062                 elem.append(html);
18063             }
18064         }
18065     };
18066 }])
18067
18068 .directive('attTableHeader', ['tableConfig', function(tableConfig) { 
18069     return { 
18070         restrict: 'EA', 
18071         replace: true, 
18072         transclude: true, 
18073         scope: { 
18074             sortable: '@', 
18075             defaultSort: '@', 
18076             index: '@key' 
18077         }, 
18078         require: '^attTable', 
18079         templateUrl: 'app/scripts/ng_js_att_tpls/table/attTableHeader.html', 
18080         link: function(scope, elem, attr, ctrl) { 
18081             var reverse = tableConfig.defaultSortPattern; 
18082             scope.headerName = elem.text(); 
18083             scope.sortPattern = null; 
18084             ctrl.setIndex(scope); 
18085  
18086             scope.$watch(function() { 
18087                 return elem.text(); 
18088             }, function(value) { 
18089                 scope.headerName = value; 
18090             }); 
18091             scope.sort = function(sortType) { 
18092                 if(typeof sortType === 'boolean') { 
18093                     reverse = sortType; 
18094                 } 
18095                 ctrl.sortData(scope.index, reverse); 
18096                 scope.sortPattern = reverse ? 'descending' : 'ascending'; 
18097                 reverse = !reverse; 
18098             }; 
18099             scope.$watch(function() { 
18100                 return ctrl.currentSortIndex; 
18101             }, function(value) { 
18102                 if (value !== scope.index) { 
18103                     scope.sortPattern = null; 
18104                 } 
18105             }); 
18106  
18107             if (scope.sortable === undefined || scope.sortable === 'true' || scope.sortable === true) { 
18108                 scope.sortable = 'true'; 
18109             } else if (scope.sortable === false || scope.sortable === 'false') { 
18110                 scope.sortable = 'false'; 
18111             } 
18112  
18113             if(scope.sortable !== 'false') { 
18114                 if(scope.defaultSort === 'A' || scope.defaultSort === 'a') { 
18115                     scope.sort(false); 
18116                 } else if(scope.defaultSort === 'D' || scope.defaultSort === 'd') { 
18117                     scope.sort(true); 
18118                 } 
18119             } 
18120             scope.resetSortPattern = function() { 
18121                 reverse = tableConfig.defaultSortPattern; 
18122             }; 
18123         } 
18124     }; 
18125 }])
18126
18127 .directive('attTableBody', ['$filter', '$timeout', 'tableConfig', function($filter, $timeout, tableConfig) {
18128     return {
18129         restrict: 'EA',
18130         require: '^attTable',
18131         replace: true,
18132         transclude: true,
18133         templateUrl: 'app/scripts/ng_js_att_tpls/table/attTableBody.html',
18134         link: function (scope, elem, attr, ctrl) {
18135             var highlightSearchStringClass = tableConfig.highlightSearchStringClass;
18136             var searchString = "";
18137             var wrapElement = function (elem) {
18138                 var text = elem.text();
18139                 elem.html($filter('highlight')(text, searchString, highlightSearchStringClass));
18140             };
18141             var traverse = function (elem) {
18142                 var innerHtml = elem.children();
18143                 if (innerHtml.length > 0) {
18144                     for (var i = 0; i < innerHtml.length; i++) {
18145                         traverse(innerHtml.eq(i));
18146                     }
18147                 } else {
18148                     wrapElement(elem);
18149                     return;
18150                 }
18151             };
18152             var clearWrap = function (elem) {
18153                 var elems = elem.find('*');
18154                 for (var i = 0; i < elems.length; i++) {
18155                     if (elems.eq(i).attr('class') && elems.eq(i).attr('class').indexOf(highlightSearchStringClass) !== -1) {
18156                         var text = elems.eq(i).text();
18157                         elems.eq(i).replaceWith(text);
18158                     }
18159                 }
18160             };
18161             $timeout(function () {
18162                 var actualHtml = elem.children();
18163                 scope.$watch(function () {
18164                     return ctrl.getSearchString();
18165                 }, function (val) {
18166                     searchString = val;
18167                     clearWrap(elem);
18168                     if (actualHtml.length > 0) {
18169                         traverse(elem);
18170                     } else {
18171                         wrapElement(elem);
18172                     }
18173                 });
18174             }, 50);
18175         }
18176     };
18177 }]);
18178
18179 angular.module('att.abs.tableMessages', ['att.abs.utilities'])
18180     .constant('messageConstants', {
18181             TABLE_MESSAGE_TYPES: {
18182                 noMatching: 1,
18183                 errorLoading: 2,
18184                 magnifySearch: 3,
18185                 isLoading: 4},
18186         USER_MESSAGE_TYPES: {
18187             success: 1,
18188             error: 0
18189             }
18190         })
18191         .directive('attTableMessage', ['messageConstants', function(messageConstants) {
18192                 return {
18193                     restrict: 'AE',
18194                     replace: true,
18195                     transclude: true,
18196                     scope: {
18197                         msgType: '=',
18198                         onRefreshClick: '&'
18199                     },
18200                     templateUrl: 'app/scripts/ng_js_att_tpls/tableMessages/attTableMessage.html',
18201                     link: function(scope) {
18202                         scope.messageConstants = messageConstants;
18203                         scope.refreshAction = function(evt) {
18204                             scope.onRefreshClick(evt);
18205                         };
18206                     }
18207                 };
18208         }]).directive('attUserMessage', ['messageConstants', '$timeout', 'DOMHelper', function(messageConstants, $timeout, DOMHelper) {
18209             return {
18210                 restrict: 'AE',
18211                 replace: true,
18212                 transclude: true,
18213                 scope: {
18214                     thetitle: '=',
18215                     type: '=',
18216                     message: '=',
18217                     trigger: '='
18218                 },
18219                 templateUrl: 'app/scripts/ng_js_att_tpls/tableMessages/attUserMessage.html',
18220                 link: function(scope, element) {
18221                     var prevActiveElement = undefined;
18222                     var firstElement = undefined;
18223                     scope.messageConstants = messageConstants;
18224
18225                     $timeout(function() {
18226                         firstElement = DOMHelper.firstTabableElement(element[0]);
18227                     }, 10);
18228
18229                     
18230                     scope.$watch('trigger', function() {
18231                         if (scope.trigger) {
18232                             prevActiveElement = document.activeElement;
18233                             if (angular.isDefined(firstElement)) {
18234                                 firstElement.focus();
18235                             }
18236                         } else {
18237                             if (angular.isDefined(prevActiveElement)) {
18238                                 prevActiveElement.focus();
18239                             }
18240                         }
18241                     })
18242
18243                     
18244                 }
18245             };
18246     }]);
18247 angular.module('att.abs.tabs', ['att.abs.utilities'])
18248     .directive('attTabs', function () {
18249         return{
18250             restrict: 'EA',
18251             transclude: false,
18252             replace: true,
18253             scope: {
18254                 tabs: "=title"
18255             },
18256             controller: ['$scope', function ($scope) {
18257                 this.getData = function () {
18258                     return $scope.tabs;
18259                 };
18260                 this.onClickTab = function (tab) {
18261                     $scope.currentTab = tab.url;
18262                     return $scope.currentTab;
18263                 };
18264                 this.isActiveTab = function (tab) {
18265                     return (tab === $scope.currentTab);
18266                 };
18267             }],
18268             link: function (scope) {
18269                 for (var i = 0; i < scope.tabs.length; i++) {
18270                     if ((scope.tabs[i].selected) && (scope.tabs[i].url)) {
18271                         scope.currentTab = scope.tabs[i].url;
18272                     }
18273                 }
18274             }
18275         };
18276     })
18277     .directive('floatingTabs', function () {
18278         return {
18279             require: '^attTabs',
18280             restrict: 'EA',
18281             transclude: false,
18282             replace: true,
18283             scope: {
18284                 size: "@"
18285             },
18286             templateUrl: 'app/scripts/ng_js_att_tpls/tabs/floatingTabs.html',
18287             link: function (scope, elem, attr, attTabsCtrl) {
18288                 scope.tabs = attTabsCtrl.getData();
18289                 scope.onClickTab = attTabsCtrl.onClickTab;
18290                 scope.isActiveTab = attTabsCtrl.isActiveTab;
18291             }
18292         };
18293     })
18294     .directive('simplifiedTabs', function () {
18295         return {
18296             require: '^attTabs',
18297             restrict: 'EA',
18298             transclude: false,
18299             replace: true,
18300             scope: {
18301                 ctab: "=ngModel"
18302             },
18303             templateUrl: 'app/scripts/ng_js_att_tpls/tabs/simplifiedTabs.html',
18304             link: function (scope, elem, attr, attTabsCtrl) {
18305                 scope.tabs = attTabsCtrl.getData();
18306                 scope.clickTab = function (tab) {
18307                     scope.ctab = tab.id;
18308                     return scope.ctab;
18309                 };
18310                 scope.isActive = function (tab) {
18311                     return (tab === scope.ctab);
18312                 };
18313             }
18314         };
18315     })
18316     .directive('genericTabs', function () {
18317         return {
18318             require: '^attTabs',
18319             restrict: 'EA',
18320             transclude: false,
18321             replace: true,
18322             scope: {
18323                 ctab: "=ngModel"
18324             },
18325             templateUrl: 'app/scripts/ng_js_att_tpls/tabs/genericTabs.html',
18326             link: function (scope, elem, attr, attTabsCtrl) {
18327                 scope.tabs = attTabsCtrl.getData();
18328                 scope.clickTab = function (tab) {
18329                     scope.ctab = tab.id;
18330                     return scope.ctab;
18331                 };
18332                 scope.isActive = function (tab) {
18333                     return (tab === scope.ctab);
18334                 };
18335             }
18336         };
18337     })
18338     .directive('skipNavigation', function(){
18339         return{
18340             link: function(scope,elem,attr){
18341                 elem.bind('click', function(){
18342                     var skiptoBody = angular.element(elem.parent().parent().parent().parent())[0].querySelector('a.skiptoBody');
18343                     (angular.element(skiptoBody)).attr('tabindex',-1);
18344                     skiptoBody.focus();
18345                 });
18346
18347             }
18348         }
18349     })
18350     .directive('parentTab', [function () {
18351         return {
18352             restrict: 'EA',
18353             scope: {
18354                 menuItems: '=',
18355                 activeSubMenu: '=',
18356                 activeMenu: '='
18357             },
18358             controller: ['$scope', function ($scope) {
18359                 $scope.megaMenu = $scope.menuItems;
18360                 $scope.megaMenuTab;
18361                 $scope.megaMenuHoverTab;
18362                 this.setMenu = function () {
18363                     $scope.menuItems = $scope.megaMenu;
18364                     $scope.activeSubMenu.scroll=false;
18365                     for (var i = 0; i < $scope.menuItems.length; i++) {
18366                         if ($scope.menuItems[i].active) {
18367                             $scope.activeMenu = $scope.menuItems[i];
18368                         }
18369                     }
18370                     this.setSubMenuStatus(false);
18371                     $scope.$apply();
18372                 };
18373                 this.setActiveMenu = function () {
18374                     if (!($scope.megaMenuTab === undefined || $scope.megaMenuTab === null)) {
18375                         $scope.menuItems = [$scope.megaMenuTab];
18376                         $scope.megaMenuTab.scroll = true;
18377                         $scope.activeMenu = {};
18378                         $scope.activeSubMenu = $scope.megaMenuTab;
18379                         this.setSubMenuStatus(true);
18380                     }
18381                     else{
18382                         for(var i=0; i<$scope.menuItems.length; i++){
18383                             ($scope.menuItems[i].active = false);
18384                             if($scope.menuItems[i].subItems)
18385                                 for(var j=0; j<$scope.menuItems[i].subItems.length; j++){
18386                                     $scope.menuItems[i].subItems[j].active = false;
18387                                 };
18388                         };
18389                         $scope.menuItems=$scope.megaMenu;
18390                     }
18391                     $scope.$apply();
18392                 };
18393                 var checkSubMenuStatus = false;
18394                 this.setSubMenuStatus = function (value) {
18395                     checkSubMenuStatus = value;
18396                 };
18397                 this.getSubMenuStatus = function () {
18398                     return checkSubMenuStatus;
18399                 };
18400                 this.setActiveMenuTab = function (tab) {
18401                     $scope.megaMenuTab = tab;
18402                 };
18403                 this.setActiveMenuHoverTab = function (tab) {
18404                     $scope.megaMenuHoverTab = tab;
18405                 };
18406                 this.setActiveSubMenuTab = function () {
18407                     $scope.megaMenuTab = $scope.megaMenuHoverTab;
18408                 };
18409                 this.resetMenuTab = function () {
18410                     $scope.megaMenuTab = undefined;
18411                 };
18412                 this.clearSubMenu = function () {
18413                     /* Clears Sub-tems when focus shifts from Sub-menu to Mega menu*/
18414                     $scope.$evalAsync(function(){
18415                         $scope.megaMenuTab = undefined;
18416                         $scope.megaMenuHoverTab = undefined;
18417                     })
18418                 };
18419             }]
18420         };
18421     }])
18422     .directive('parentmenuTabs', [function () {
18423         return {
18424             restrict: 'EA',
18425             transclude: true,
18426             replace: true,
18427             scope: {
18428                 megaMenu: '@',
18429                 menuItems: '='
18430             },
18431             controller: ['$scope', function ($scope) {
18432                 this.getMenu = function () {
18433                     return $scope.menuItems;
18434                 };
18435                 this.setMenu = function (menuItem) {
18436                     $scope.menuItems = menuItem;
18437                 };
18438             }],
18439             templateUrl: 'app/scripts/ng_js_att_tpls/tabs/parentmenuTab.html'
18440         };
18441     }])
18442
18443     .directive('menuTabs', ["$window", "$document",'events','keymap', function (win, $document, events, keymap) {
18444         return {
18445             restrict: 'EA',
18446             transclude: true,
18447             replace: true,
18448             require: ['^?parentTab', '^?parentmenuTabs'],
18449             scope: {
18450                 activeMenu: "=",
18451                 menuItem: "=",
18452                 subMenu: "@",
18453                 subItemActive: "@",
18454                 tabName: "=?",
18455                 tabUrl: "=?"
18456             },
18457             templateUrl: function (element, attrs) {
18458                 if (attrs.megaMenu) {
18459                     return 'app/scripts/ng_js_att_tpls/tabs/menuTab.html';
18460                 }
18461                 else {
18462                     return 'app/scripts/ng_js_att_tpls/tabs/submenuTab.html';
18463                 }
18464             },
18465             link: function (scope, elem, attr, ctrl) {
18466                 var parentCtrl = ctrl[0];
18467                 var parentmenuCtrl = ctrl[1];
18468                 scope.clickInactive = true;
18469                 scope.showHoverChild = function (e) {
18470                     scope.clickInactive = false;
18471                     scope.hoverChild = ctrl[0].getSubMenuStatus();
18472                     if (e.type === "mouseover" && ctrl[0].getSubMenuStatus())
18473                     {
18474                         //scope.showChildren(e);
18475                     }
18476                     
18477                 };
18478                 scope.showChildren = function (e) {
18479                     scope.parentMenuItems = parentmenuCtrl.getMenu();
18480                     for (var i = 0; i < scope.parentMenuItems.length; i++) {
18481                         scope.parentMenuItems[i].active = false;
18482                         if (scope.parentMenuItems[i].subItems) {
18483                             for (var j = 0; j < scope.parentMenuItems[i].subItems.length; j++) {
18484                                 scope.parentMenuItems[i].subItems[j].active = false;
18485                             }
18486                         }
18487                         scope.clickInactive = true;
18488                     }
18489                     scope.menuItem.active = true;
18490                     scope.activeMenu = scope.menuItem;
18491                     e.stopPropagation();
18492                 };
18493                 scope.$watch("subItemActive", function (value) {
18494                     if (value === "true" && scope.subMenu === 'true') {
18495                         parentCtrl.setActiveMenuHoverTab(scope.menuItem);
18496                     }
18497                 });
18498                 scope.showMenuClick = function (e) {
18499                     parentCtrl.setActiveMenuTab(scope.menuItem);
18500                     e.stopPropagation();
18501                 };
18502                 scope.showSubMenuClick = function (e) {
18503                     parentCtrl.setActiveSubMenuTab();
18504                     e.stopPropagation();
18505                 };
18506                 scope.resetMenu = function (e) {
18507                     parentCtrl.resetMenuTab();
18508                     e.stopPropagation();
18509                 };
18510                 function debounce(method, delay) {
18511                     clearTimeout(method._tId);
18512                     method._tId = setTimeout(function () {
18513                         parentCtrl.setMenu();
18514                     }, delay);
18515                 }
18516                 function debounce1(method, delay) {
18517                     clearTimeout(method._tId);
18518                     method._tId = setTimeout(function () {
18519                         parentCtrl.setActiveMenu();
18520                     }, delay);
18521                 }
18522                 $document.bind('scroll', function () {
18523                    /* if (win.pageYOffset === 0) {
18524                         debounce(parentCtrl.setMenu, 100);
18525                     }
18526                     else if (win.pageYOffset > 1 && win.pageYOffset < 1500) {
18527                         debounce1(parentCtrl.setActiveMenu, 100);
18528                     }*/
18529                 });
18530                 elem.bind('keydown', function(evt){
18531                     if (!(evt.keyCode)){
18532                         evt.keyCode = evt.which;
18533                     }
18534                     if(evt.keyCode !== keymap.KEY.TAB){
18535                         events.preventDefault(evt);
18536                         events.stopPropagation(evt);
18537                     }
18538
18539                     switch (evt.keyCode) {
18540                         case keymap.KEY.ESC:
18541                             var skiptoBody;
18542                             if (!(elem.attr('mega-menu'))) {
18543                                 if (elem.attr("sub-menu") === "true") {
18544                                     /* condition true when user navigates through Sub-menu*/
18545
18546                                     skiptoBody = angular.element(elem.parent().parent().parent().parent().parent().parent().parent())[0].querySelector('a.skiptoBody');
18547                                     (angular.element(skiptoBody)).attr('tabindex',-1);
18548                                     skiptoBody.focus();
18549                                 }
18550                                 else if (elem.attr("sub-menu") === undefined) {
18551                                     skiptoBody = angular.element(elem.parent().parent().parent().parent().parent().parent().parent().parent().parent().parent())[0].querySelector('a.skiptoBody');
18552                                     (angular.element(skiptoBody)).attr('tabindex',-1);
18553                                     skiptoBody.focus();
18554                                 }
18555                             }
18556                             else
18557                             {
18558                                 if (elem.attr("menu-item") === "item") {
18559                                     /* Works when user on Mega menu*/
18560
18561                                     skiptoBody = angular.element(elem.parent().parent().parent().parent())[0].querySelector('a.skiptoBody');
18562                                     (angular.element(skiptoBody)).attr('tabindex',-1);
18563                                     skiptoBody.focus();
18564                                 }
18565                             }
18566                             break;
18567                         case keymap.KEY.RIGHT:
18568                             if (!(elem.attr('mega-menu'))) {
18569                                  var el = angular.element(elem)[0];
18570                                 if (elem.attr("sub-menu") === "true") {
18571                                     /* condition true when user navigates through Sub-menu*/
18572                                     if(el.nextElementSibling === null){ break;}
18573                                     if(el.nextElementSibling){
18574                                         el.nextElementSibling.querySelector("a").focus();
18575                                     }
18576                                     else{
18577                                         do{
18578                                             if (el && el.nextSibling){
18579                                                 el = el.nextSibling;
18580                                             }
18581                                             else{
18582                                                 break;
18583                                             }
18584                                         } while (el && el.tagName !== 'LI');
18585                                         if(el){
18586                                             if (el.querySelector("a") == null){}
18587                                             else{
18588                                             el.querySelector("a").focus();}
18589                                         }
18590                                         events.preventDefault(evt);
18591                                         events.stopPropagation(evt);
18592                                     }
18593                                 }
18594                                 else if (elem.attr("sub-menu") === undefined) {
18595                                     if(el.nextElementSibling === null) break;
18596                                     if(el.nextElementSibling){
18597                                         el.nextElementSibling.querySelector("a").focus();
18598                                     }
18599                                     else{
18600                                         do{
18601                                             if (el && el.nextSibling){
18602                                                 el = el.nextSibling;
18603                                             }
18604                                             else{
18605                                                 break;
18606                                             }
18607                                         } while (el && el.tagName !== 'LI');
18608                                         if(el){
18609                                             if (el.querySelector("a") == null){}
18610                                             else{
18611                                             el.querySelector("a").focus();}
18612                                         }
18613
18614                                     }
18615                                 }
18616                             }
18617                             else
18618                             {
18619                                 if (elem.attr("menu-item") === "item") {
18620                                     /* When user navigates through on Mega menu*/
18621
18622                                     var el = angular.element(elem)[0];
18623
18624                                         if(el.nextElementSibling){
18625                                             if(el.nextElementSibling.querySelector("span") == null){
18626                                             }
18627                                             else {
18628                                                 el.nextElementSibling.querySelector("span").focus();
18629                                             }
18630                                     }
18631                                     else{
18632                                         do{
18633                                             if (el && el.nextSibling){
18634                                                 el = el.nextSibling;
18635                                             }
18636                                             else{
18637                                                 break;
18638                                             }
18639                                         } while (el && el.tagName !== 'LI');
18640                                         if(el){
18641                                             if(el.querySelector("span") === null){}
18642                                             else {
18643                                                 el.querySelector("span").focus();
18644                                             }
18645                                         }
18646                                         events.preventDefault(evt);
18647                                         events.stopPropagation(evt);
18648                                     }
18649                                 }
18650                             }
18651                             break;
18652                         case keymap.KEY.DOWN:
18653
18654
18655                             if (elem.attr('mega-menu')) {
18656                                 /* When user navigates from top menu to Sub-menu*/
18657                                 angular.element(elem)[0].querySelectorAll(".megamenu__items")[0].querySelector("a").focus();
18658                             }
18659                             else if(elem.attr("sub-menu") === undefined) {
18660                             /*When user navigates within Sub Items*/
18661                                 var el = document.activeElement;
18662                                 if(el.nextElementSibling === null) break;
18663                                  if(el.nextElementSibling) {
18664                                     el.nextElementSibling.focus();
18665                                 }else{
18666                                      do {
18667                                          if (el && el.nextSibling){
18668                                              el = el.nextSibling;
18669                                          }
18670                                          else{
18671                                              break;
18672                                          }
18673                                      } while (el && el.tagName !== 'A');
18674                                      if(el.attributes !== null){                                        
18675                                          el.focus();
18676                                      }
18677                                      events.stopPropagation(evt);
18678                                  }
18679
18680                             }
18681                             else if (elem.attr("sub-menu")=== "true" ) {
18682                                 /* condition true when user navigates from sub menu to  Sub Item*/
18683                                 var childItems = angular.element(elem)[0].querySelector("span").querySelector('a');
18684                                 if(childItems === null) break;
18685                                 childItems.focus();
18686                             }
18687                             break;
18688
18689                         case keymap.KEY.LEFT:
18690
18691                             if (!(elem.attr('mega-menu'))) {
18692                                 var el = angular.element(elem)[0];
18693                                 if (elem.attr("sub-menu") === "true") {
18694                                     /* condition true when user navigates through Sub-menu*/
18695                                     if(el.previousElementSibling === null) break;
18696                                     if(el.previousElementSibling){
18697                                         el.previousElementSibling.querySelector("a").focus();
18698                                     }
18699                                     else{
18700                                         do{
18701                                             if (el && el.previousSibling){
18702                                                 el = el.previousSibling;
18703                                             }
18704                                             else{
18705                                                 break;
18706                                             }
18707                                         } while (el && el.tagName !== 'LI');
18708                                         if(el){
18709                                             if (el.querySelector("a") == null){}
18710                                             else{
18711                                             el.querySelector("a").focus();}
18712                                         }
18713                                         events.preventDefault(evt);
18714                                         events.stopPropagation(evt);
18715                                     }
18716
18717                                     /*el.previousElementSibling.querySelector("span").focus();
18718                                     events.stopPropagation(evt);
18719                                     break;*/
18720                                 }
18721                                 else if (elem.attr("sub-menu") === undefined) {
18722                                     if(el.previousElementSibling === null) break;
18723                                     if(el.previousElementSibling){
18724                                         el.previousElementSibling.querySelector("a").focus();
18725                                     }
18726                                     else{
18727                                         do{
18728                                             if (el && el.previousSibling){
18729                                                 el = el.previousSibling;
18730                                             }
18731                                             else{
18732                                                 break;
18733                                             }
18734                                         } while (el && el.tagName !== 'LI');
18735                                         if(el){
18736                                             if (el.querySelector("a") == null){}
18737                                             else{
18738                                             el.querySelector("a").focus();}
18739                                         }
18740                                     }
18741                                 }
18742                             }
18743                             else
18744                             {
18745                                 if (elem.attr("menu-item") === "item") {
18746                                     /* Works when user on Mega menu*/
18747
18748                                     var el = angular.element(elem)[0];
18749                                         if(el.previousElementSibling){
18750
18751                                             if(el.previousElementSibling.querySelector("span") === null){
18752                                             }
18753                                             else {
18754                                                 el.previousElementSibling.querySelector("span").focus();
18755                                             }
18756                                       
18757                                     }
18758                                     else{
18759                                         do{
18760                                             if (el && el.previousSibling){
18761                                                 el = el.previousSibling;
18762                                             }
18763                                             else{
18764                                                 break;
18765                                             }
18766                                         } while (el && el.tagName !== 'LI');
18767                                         if(el){
18768                                             if (el.querySelector("span") === null) {
18769                                             }
18770                                             else {
18771                                             el.querySelector("span").focus();
18772                                             }
18773                                         }
18774                                         events.preventDefault(evt);
18775                                         events.stopPropagation(evt);
18776                                     }
18777                                 }
18778                             }
18779                             break;
18780                         case keymap.KEY.UP:
18781
18782                             if (elem.attr("sub-menu") === "true") {
18783                                 var el = document.activeElement;
18784                                 var parent_menu = angular.element(elem.parent().parent().parent().parent())[0].querySelector("span");
18785                                 parent_menu.focus();
18786                                 parentCtrl.clearSubMenu();
18787                                 scope.menuItem.active = false;
18788                                 break;
18789                             }
18790                             else if(elem.attr("sub-menu") === undefined) {
18791                                 /* condition true when user navigates within Sub Items*/
18792                                 var el = document.activeElement;
18793                                 var parent_menu = angular.element(elem.parent().parent().parent().parent())[0].querySelector("a");                                
18794                                 if(document.activeElement === angular.element(el).parent().parent()[0].querySelectorAll('a')[0]){
18795                                     parent_menu.focus();
18796                                     break;
18797                                 };
18798
18799                                 if(el.previousElementSibling) {
18800                                     var prev_a =  el.previousElementSibling;
18801                                     (el.previousElementSibling != null)? el.previousElementSibling.focus(): parent_menu.focus();
18802                                 }else{
18803                                     do{
18804                                         if (el && el.previousSibling){
18805                                             el = el.previousSibling;
18806                                         }
18807                                         else{
18808                                             break;
18809                                         }
18810                                     } while (el && el.tagName !== 'A');
18811                                     if(el && (el.nodeType !== 3)){
18812                                         el.focus();
18813                                     }
18814                                     events.preventDefault(evt);
18815                                     events.stopPropagation(evt);
18816                                 }
18817
18818                                 break;
18819                             }
18820                         default:
18821                             break;
18822                     }
18823                 });
18824             }
18825         };
18826     }]);
18827
18828 angular.module('att.abs.tagBadges', [])
18829         .directive('tagBadges', ['$parse', '$timeout', function($parse, $timeout) {
18830                 return {
18831                     restrict: 'EA',
18832                     replace: false,
18833                     transclude: true,
18834                     templateUrl: 'app/scripts/ng_js_att_tpls/tagBadges/tagBadges.html',
18835                     scope: {
18836                         styleType: "@",
18837                         onClose: "&"
18838                     },
18839                     link: function(scope, elem, attr) {
18840                         scope.isSmall = false;
18841                         scope.isIcon = false;
18842                         scope.isColor = false;
18843                         scope.display = true;
18844                         scope.isClosable = false;
18845                         scope.isHighlight = false;
18846                         scope.customColor = false;
18847
18848                         if (attr.small === "") {
18849                             scope.isSmall = true;
18850                         }
18851                         if (scope.styleType === "icon") {
18852                             scope.isIcon = true;
18853                         }
18854                         else if (scope.styleType === "color") {
18855                             scope.isColor = true;
18856                             if(attr.color !== undefined && attr.color !== "") {
18857                                 scope.customColor = true;
18858                                 attr.$observe("color", function(val) {
18859                                     scope.border_type_borderColor = val;
18860                                     scope.background_type_backgroundColor = val;
18861                                     scope.background_type_borderColor = val;
18862                                 });
18863                             }
18864                         }
18865                         scope.activeHighlight = function(state){
18866                             if(scope.customColor){
18867                                 if(state){
18868                                     scope.isHighlight = true;
18869                                 }
18870                                 else{
18871                                     scope.isHighlight = false;
18872                                 }
18873                             }
18874                         };
18875                         if (attr.closable === "") {
18876                             scope.isClosable = true;
18877                             scope.closeMe = function() {
18878                                 scope.display = false;
18879                                 $timeout(function(){
18880                                     elem.attr("tabindex", "0");
18881                                     elem[0].focus();
18882                                     elem.bind('blur', function(){
18883                                         elem.remove();
18884                                     });
18885                                 });
18886                                 if(attr['onClose']){
18887                                     scope.onClose = $parse(scope.onClose);
18888                                     scope.onClose();
18889                                 }
18890                             };
18891                         }
18892                     }
18893                 };
18894             }]);
18895 angular.module('att.abs.textOverflow', [])
18896         .constant('textDefaultOptions', {
18897             width: '50%'
18898         })
18899 .directive('attTextOverflow', ['textDefaultOptions','$compile',function(textDefaultOptions,$compile)
18900 {
18901     return {
18902         restrict: 'A',
18903         link: function(scope, elem, attrs)
18904         {
18905             var tooltipText = elem.text();
18906             elem.addClass('text-ellipsis');
18907             attrs.$observe('attTextOverflow', function(val){
18908                 if(val){
18909                     elem.css({"width":val});
18910                 }
18911                 else{
18912                     elem.css({"width":textDefaultOptions.width});
18913                 }
18914             });
18915             if(!(elem.attr('tooltip'))){
18916                 elem.attr("tooltip", tooltipText);
18917                 elem.attr("tooltip-placement", 'above');
18918                 var newElem =  angular.element(elem);
18919                 $compile(newElem)(scope);
18920             }
18921         }
18922     };
18923 }]);
18924
18925 angular.module('att.abs.toggle', ['angular-gestures', 'att.abs.position'])
18926         .directive('attToggleTemplate', ['$compile', '$log', '$position', function ($compile, $log, $position)
18927             {
18928                 return{
18929                     restrict: 'A',
18930                     require: 'ngModel',
18931                     transclude: true,
18932                     scope: {
18933                         modelVal: "=ngModel"
18934                     },
18935                     templateUrl: 'app/scripts/ng_js_att_tpls/toggle/demoToggle.html',
18936                     link: function (scope, element, attr) {
18937                         scope.initialDragPosition = 0;
18938                         var dragStatus = 0;
18939                         var switchMovementPath = ($position.offset(element.children().eq(1).children().eq(0)).width - 1);
18940                         var updateModelVal = function () {
18941                             if (scope.attrValue === attr.ngTrueValue || scope.attrValue)
18942                             {
18943                                 scope.modelVal = false;
18944                             }
18945                             else
18946                             {
18947                                 scope.modelVal = true;
18948                             }
18949                         };
18950                         scope.updateModel = function (env) {
18951                             {
18952                                 if (dragStatus !== 1) {
18953                                     updateModelVal();
18954                                     dragStatus = 0;
18955                                 }
18956                             }
18957                             env.preventDefault();
18958                         };
18959                         scope.drag = function (e) {
18960                             dragStatus = 1;
18961                             if (e.type === 'dragstart') {
18962                                 scope.initialDragPosition = $position.position(element.children().eq(1)).left;
18963                                 element.children().eq(1).addClass('dragging');
18964                             } else if (e.type === 'drag') {
18965                                 var left = Math.min(0, Math.max(scope.initialDragPosition + e.gesture.deltaX, -switchMovementPath));
18966                                 element.children().eq(1).css({
18967                                     left: left + 'px'
18968                                 });
18969                             } else if (e.type === 'dragend') {
18970                                 var isOn = $position.position(element.children().eq(1)).left > (switchMovementPath * -1) / 2;
18971                                 element.children().eq(1).removeClass('dragging');
18972                                 TweenMax.to(element.children().eq(1), .1, {left: isOn ? 0 : (switchMovementPath * -1), ease: Power4.easeOut,
18973                                     onComplete: function () {
18974                                         element.children().eq(1).css({left: ''});
18975                                     }});
18976                                 if (isOn || (!isOn && e.gesture.direction === "left")) {
18977                                     updateModelVal();
18978                                 }
18979                                 dragStatus = 0;
18980                             }
18981
18982                             return false;
18983                         };
18984
18985                         scope.directiveValue = attr.attToggleTemplate;
18986                         scope.on = attr.trueValue;
18987                         scope.off = attr.falseValue;
18988                         var switchMovementPathPixels = ((switchMovementPath) * -1) + 'px';
18989                         scope.$watch('modelVal', function (newVal) {
18990                             scope.attrValue = newVal;
18991                             if (newVal === attr.ngTrueValue || newVal) {
18992                                 element.children().eq(1).css({
18993                                     left: '0px'
18994                                 });
18995                                 element.addClass('att-checkbox--on');
18996                                 var elem = element.find('div').find('div').eq(1);
18997                                 elem.attr("aria-checked", true);
18998                                 dragStatus = 0;
18999                             } else {
19000                                 element.children().eq(1).css({
19001                                     left: switchMovementPathPixels
19002                                 });
19003                                 element.removeClass('att-checkbox--on');
19004                                  var elem = element.find('div').find('div').eq(1);
19005                                 elem.attr("aria-checked", false);
19006                                 dragStatus = 0;
19007                             }
19008                             element.children().eq(1).css({
19009                                 left: ''
19010                             });
19011                         });
19012                     }
19013                 };
19014             }
19015         ])
19016
19017         .directive('attToggleMain', ['$compile', function ($compile)
19018             {
19019                 return{
19020                     restrict: 'A',
19021                     require: 'ngModel',
19022                     transclude: true,
19023                     replace: true,
19024                     scope: {
19025                         modelValue: "=ngModel",
19026                         trueValue: "=ngTrueValue",
19027                         falseValue: "=ngFalseValue"
19028                     },
19029                     link: function (scope, element, attr) {
19030                         var html = "";
19031                         var attrVal = "";
19032                         element.removeAttr('att-toggle-main');
19033                         scope.on = attr.ngTrueValue;
19034                         scope.off = attr.ngFalseValue;
19035                         scope.largeValue = attr.attToggleMain;
19036                         if (angular.isDefined(attr.ngTrueValue)) {
19037                             html += ' true-value="{{on}}" false-value="{{off}}"';
19038                         }
19039                         if (scope.largeValue !== undefined)
19040                         {
19041                             attrVal += ' ="{{largeValue}}"';
19042                         }
19043
19044                         element.css({display: 'none'});
19045                         var elm = angular.element('<div class="att-switch att-switch-alt" ng-class="{\'large\' : largeValue == \'large\'}" ng-model="modelValue"' + html + ' att-toggle-template' + attrVal + '>' + element.prop('outerHTML') + '</div>');
19046                         elm = $compile(elm)(scope);
19047                         element.replaceWith(elm);
19048                     }
19049                 };
19050             }]);
19051 angular.module('att.abs.treeview', [])
19052         .directive('treeView', function() {
19053             return{
19054                 restrict: 'A',
19055                 link: function(scope, elem) {
19056                     var el = elem.children('ul li');
19057                     var list = TweenMax.from(el, .2, {display: 'none', paused: true, reversed: true});
19058                     elem.attr("tabindex","0");
19059                     function toggleBranch() {
19060                         if (list.reversed())
19061                         {
19062                             list.play();
19063                         } else
19064                         {
19065                             list.reverse();
19066                         }
19067                     };
19068                     function toggleTree(e) {
19069                         e.stopPropagation();
19070                         if (angular.element(e.target).attr("tree-view") !== undefined)
19071                         {
19072                             if (elem.hasClass('minus'))
19073                             {
19074                                 elem.removeClass('minus');
19075                             }
19076                             else
19077                             {
19078                                 elem.addClass('minus');
19079                             }
19080                             toggleBranch();
19081                         }
19082                     }
19083                     elem.on('click', function(e) {
19084                         toggleTree(e);
19085                     });
19086                     elem.on('keypress', function (e) {
19087                         var activeCode = e.keyCode ? e.keyCode : e.charCode;
19088                         var keyCode = [13,32];
19089                         if (keyCode.length > 0 && ((activeCode && keyCode.indexOf(activeCode) > -1))) {
19090                             toggleTree(e);
19091                             e.preventDefault();
19092                         }
19093                     });
19094                 }
19095             };
19096         });
19097
19098 angular.module('att.abs.typeAhead', ['att.abs.tagBadges'])
19099
19100         .directive('focusMe',['$timeout', '$parse', function($timeout, $parse) {
19101             return {
19102                 link: function(scope, element, attrs) {
19103                     var model = $parse(attrs.focusMe);
19104                     scope.$watch(model, function(value) {
19105                         if (value) {
19106                             $timeout(function() {
19107                                 element[0].focus();
19108                                 scope.inputActive=true;
19109                             });
19110                         }
19111                     });
19112                     element.bind('blur', function() {
19113                          model.assign(scope, false);
19114                          scope.inputActive=false;
19115                          scope.$digest();
19116                      });
19117                 }
19118             };
19119         }])
19120
19121         .directive('typeAhead', ['$timeout','$log', function($timeout,$log) {
19122                 return {
19123                     restrict: 'EA',
19124                     templateUrl: 'app/scripts/ng_js_att_tpls/typeAhead/typeAhead.html',
19125                     replace: true,
19126                     scope: {
19127                         items: '=',
19128                         title: '@?',
19129                         titleName: '@',
19130                         subtitle: '@',
19131                         model: '=',
19132                         emailIdList:'=',
19133                         emailMessage:'='
19134                     },
19135                     link: function(scope, elem) {
19136                         if(!angular.isDefined(scope.titleName) && angular.isDefined(scope.title)){
19137                              $timeout(function(){
19138                             scope.titleName = scope.title;
19139                             $log.warn("title attribute is deprecated and title-name attribute is used instead as it is conflicting with html title attribute");
19140                              });
19141                         }
19142                         scope.lineItems = [];
19143                         scope.filteredListLength = -1;
19144                         scope.filteredList = [];
19145                         scope.setFocus = function() {
19146                         scope.clickFocus = true;
19147                         };
19148                         scope.setFocus();
19149                         scope.handleSelection = function(selectedItem,emailItem) {
19150                             scope.lineItems.push(selectedItem);
19151                             scope.emailIdList.push(emailItem);
19152                             scope.model = "";
19153                             scope.current = 0;
19154                             scope.selected = true;
19155                             scope.clickFocus = true;
19156                         };
19157                         scope.theMethodToBeCalled = function(index) {
19158                             var tempArr = scope.lineItems.slice();
19159                             scope.emailIdList.splice(index, 1);
19160                             tempArr.splice(index, 1);
19161                             $timeout(function() {
19162                                 scope.lineItems = [];
19163                                 scope.$apply();
19164                                 scope.lineItems = scope.lineItems.concat(tempArr);
19165                             });
19166                         };
19167
19168                         scope.current = 0;
19169                         scope.selected = true;
19170
19171                         scope.isCurrent = function(index, itemName,itemEmail,dropdownLength) {
19172                             if (scope.current === index) {
19173                                 scope.itemName = itemName;
19174                                 scope.itemEmail = itemEmail;
19175                             }
19176                             scope.dropdownLength=dropdownLength;
19177                             return scope.current === index;
19178                         };
19179
19180                         scope.setCurrent = function(index) {
19181                             scope.current = index;
19182                         };
19183
19184                         scope.selectionIndex = function(evt) {
19185                             if (evt.keyCode === 38 && scope.current > 0) {
19186                                evt.preventDefault();
19187                                 scope.current = scope.current - 1;
19188                                 scope.isCurrent(scope.current);
19189                             } else if (evt.keyCode === 9) {
19190                                 scope.selected = true;
19191                             } else if (evt.keyCode === 13 && scope.dropdownLength!==scope.items.length) {
19192                                 scope.handleSelection(scope.itemName,scope.itemEmail);
19193                             } else if ((evt.keyCode === 8 && scope.model.length === 0) || evt.keyCode === 46) {
19194                                 scope.theMethodToBeCalled(scope.lineItems.length - 1);
19195                             } else if (evt.keyCode === 40 && scope.current < scope.dropdownLength-1) {
19196                                 evt.preventDefault();
19197                                 scope.current = scope.current + 1;
19198                                 scope.isCurrent(scope.current);
19199                             }
19200                             elem[0].querySelector('.list-scrollable').scrollTop = (scope.current - 1) * 35;
19201                         };
19202                     }
19203                 };
19204             }]);
19205 angular.module('att.abs.verticalSteptracker', ['ngSanitize'])
19206     .directive('verticalSteptracker', [ function(){
19207         return {
19208             restrict: 'EA',
19209             transclude: true,
19210             replace: false,
19211             scope: {},
19212             template: '<div class="vertical-nav"><ul ng-transclude arial-label="step list" role="presentation" class="tickets-list-height"></ul></div>',
19213             link: function () {}
19214         };
19215     }])
19216     .directive('verticalSteptrackerStep',[ function(){
19217         return {
19218             restrict: 'EA',
19219             transclude: true,
19220             replace: false,
19221             scope: {
19222                 type: "=type",
19223                 id: "=id"
19224             },
19225             templateUrl: 'app/scripts/ng_js_att_tpls/verticalSteptracker/vertical-step-tracker.html',
19226             link: function(){}
19227          };
19228     }])
19229     .directive('attAbsLink',[ function(){
19230         return{
19231             restrict: 'EA',
19232             transclude: true,
19233             replace: false,
19234             template: '<span ng-transclude class="view-log"></span>'
19235         };
19236     }]);
19237 angular.module('att.abs.videoControls', [])
19238         .config(['$compileProvider' , function ($compileProvider) {
19239                 $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|javascript):/);
19240             }])
19241         .directive('videoControls', [function() {
19242                 return {
19243                     restrict: 'EA',
19244                     replace: true,
19245                     transclude: true,
19246                     templateUrl: 'app/scripts/ng_js_att_tpls/videoControls/videoControls.html'
19247                 };
19248             }])
19249         .directive('photoControls', [function() {
19250                 return {
19251                     restrict: 'EA',
19252                     replace: true,
19253                     transclude: true,
19254                     templateUrl: 'app/scripts/ng_js_att_tpls/videoControls/photoControls.html',
19255                     scope: {
19256                         prevLink: "@",
19257                         nextLink: "@"
19258                     },
19259                     link: function(scope, elem, attr) {
19260                         if(!attr['prevLink']){
19261                             scope.prevLink = 'javascript:void(0)';
19262                         }
19263                         if(!attr['nextLink']){
19264                             scope.nextLink = 'javascript:void(0)';
19265                         }
19266                         scope.links = {
19267                             prevLink : scope.prevLink,
19268                             nextLink : scope.nextLink
19269                         };
19270                     }
19271                 };
19272             }]);
19273 angular.module("app/scripts/ng_js_att_tpls/accordion/accordion.html", []).run(["$templateCache", function($templateCache) {
19274           $templateCache.put("app/scripts/ng_js_att_tpls/accordion/accordion.html",
19275             "<div class=\"att-accordion__group tabpanel\" ng-class=\"{'att-accordion__group att-accordion__group--open':isOpen,'att-accordion__group':!isOpen }\">\n" +
19276             "    <a  ng-show=\"showicon\" \n" +
19277             "        class=\"toggle-header att-accordion__heading att-accordion__toggle noafter\" \n" +
19278             "        aria-selected=\"{{focused}}\" \n" +
19279             "        aria-controls=\"panel{{index}}\" \n" +
19280             "        aria-expanded=\"{{isOpen}}\" \n" +
19281             "        ng-class=\"{focus: focused, selected: focused}\"         \n" +
19282             "        role=\"tab\" \n" +
19283             "        ng-click=\"toggle()\" \n" +
19284             "        accordion-transclude=\"heading\" \n" +
19285             "        style=\"cursor:pointer; text-decoration:none\">\n" +
19286             "        <span href=\"#\"><i class={{headingIconClass}}></i>&nbsp;&nbsp;{{heading}}</span>\n" +
19287             "        <i i ng-show = 'childLength > 0' ng-class=\"{'ion-ios-arrow-down':!isOpen,'ion-ios-arrow-up':isOpen }\" class=\"pull-right\"></i>\n" +
19288             "    </a>\n" +
19289             "    <div ng-show=\"!showicon\" \n" +
19290             "         ng-class=\"{focus: focused, selected: focused}\" \n" +
19291             "         style=\"text-decoration:none\" \n" +
19292             "         accordion-transclude=\"heading\"          \n" +
19293             "         role=\"tab\"  \n" +
19294             "         aria-expanded=\"{{isOpen}}\"\n" +
19295             "         aria-selected=\"{{focused}}\" \n" +
19296             "         aria-controls=\"panel{{index}}\" \n" +
19297             "         class=\"toggle-header att-accordion__heading att-accordion__toggle noafter\">\n" +
19298             "        <span>{{heading}}</span>\n" +
19299             "    </div>    \n" +
19300             "    <div aria-label=\"{{heading}}\" \n" +
19301             "         aria-hidden=\"{{!isOpen}}\" \n" +
19302             "         role=\"tabpanel\" \n" +
19303             "         collapse=\"!isOpen\" \n" +
19304             "         class=\"att-accordion__body\" \n" +
19305             "         id=\"panel{{index}}\" \n" +
19306             "         ng-transclude>\n" +
19307             "    </div>\n" +
19308             "    <div class=\"att-accordion__bottom--border\"></div>    \n" +
19309             "</div> ");
19310 }]);
19311
19312 angular.module("app/scripts/ng_js_att_tpls/accordion/accordion_alt.html", []).run(["$templateCache", function($templateCache) {
19313   $templateCache.put("app/scripts/ng_js_att_tpls/accordion/accordion_alt.html",
19314     "<div class=\"att-accordion__group tabpanel\" ng-class=\"{'att-accordion__group att-accordion__group--open':isOpen,'att-accordion__group':!isOpen }\">\n" +
19315     "    <a class=\"toggle-header att-accordion__heading att-accordion__toggle\" \n" +
19316     "       aria-selected=\"{{focused}}\" \n" +
19317     "       aria-controls=\"panel{{index}}\" \n" +
19318     "       ng-class=\"{focus: focused, selected: focused}\" \n" +
19319     "       aria-expanded=\"{{isOpen}}\" \n" +
19320     "       role=\"tab\" \n" +
19321     "       ng-click=\"toggle()\" \n" +
19322     "       accordion-transclude=\"heading\">        \n" +
19323     "    </a>\n" +
19324     "    <span>{{heading}}</span>\n" +
19325     "    <div aria-label=\"{{heading}}\" \n" +
19326     "         aria-hidden=\"{{!isOpen}}\" \n" +
19327     "         role=\"tabpanel\" \n" +
19328     "         collapse=\"!isOpen\" \n" +
19329     "         class=\"att-accordion__body\" \n" +
19330     "         id=\"panel{{index}}\" \n" +
19331     "         ng-transclude>\n" +
19332     "    </div>\n" +
19333     "</div> ");
19334 }]);
19335
19336 angular.module("app/scripts/ng_js_att_tpls/accordion/attAccord.html", []).run(["$templateCache", function($templateCache) {
19337   $templateCache.put("app/scripts/ng_js_att_tpls/accordion/attAccord.html",
19338     "<div ng-transclude></div>");
19339 }]);
19340
19341 angular.module("app/scripts/ng_js_att_tpls/accordion/attAccordBody.html", []).run(["$templateCache", function($templateCache) {
19342   $templateCache.put("app/scripts/ng_js_att_tpls/accordion/attAccordBody.html",
19343     "<div ng-transclude></div>");
19344 }]);
19345
19346 angular.module("app/scripts/ng_js_att_tpls/accordion/attAccordHeader.html", []).run(["$templateCache", function($templateCache) {
19347   $templateCache.put("app/scripts/ng_js_att_tpls/accordion/attAccordHeader.html",
19348     "<div ng-click=\"clickFunc()\">\n" +
19349     "   <div ng-transclude>\n" +
19350     "           <i class=\"ion-ios-arrow-down\"></i>\n" +
19351     "   </div>\n" +
19352     "</div>");
19353 }]);
19354
19355 angular.module("app/scripts/ng_js_att_tpls/alert/alert.html", []).run(["$templateCache", function($templateCache) {
19356   $templateCache.put("app/scripts/ng_js_att_tpls/alert/alert.html",
19357     "<div class=\"alert\" ng-class=\"{'alert-success': alertType === 'success', 'alert-warning': alertType === 'warning', 'alert-error': alertType === 'error', 'alert-info': alertType === 'info', 'alert-inplace': showTop !== 'true'}\" ng-show=\"showAlert\" ng-style=\"cssStyle\">\n" +
19358     "    <div class=\"container\">\n" +
19359     "        <a href=\"javascript:void(0)\" alt=\"close\" class=\"close-role\" ng-click=\"close()\" tabindex=\"0\" att-accessibility-click=\"32,13\">Dismiss <i class=\"icon-circle-action-close\"></i></a>\n" +
19360     "        <span ng-transclude> </span>\n" +
19361     "    </div>\n" +
19362     "</div>");
19363 }]);
19364
19365 angular.module("app/scripts/ng_js_att_tpls/boardStrip/attAddBoard.html", []).run(["$templateCache", function($templateCache) {
19366   $templateCache.put("app/scripts/ng_js_att_tpls/boardStrip/attAddBoard.html",
19367     "<div tabindex=\"0\" att-accessibility-click=\"13,32\" ng-click=\"addBoard()\" aria-label=\"Add Board\" class=\"boardstrip-item--add\">\n" +
19368     "    <i aria-hidden=\"true\" class=\"icon-add centered\"></i>\n" +
19369     "    <br/>\n" +
19370     "    <div class=\"centered\">Add board</div>\n" +
19371     "</div>");
19372 }]);
19373
19374 angular.module("app/scripts/ng_js_att_tpls/boardStrip/attBoard.html", []).run(["$templateCache", function($templateCache) {
19375   $templateCache.put("app/scripts/ng_js_att_tpls/boardStrip/attBoard.html",
19376     "<li att-board-navigation tabindex=\"0\" aria-label=\"{{boardLabel}}\" att-accessibility-click=\"13,32\" ng-click=\"selectBoard(boardIndex)\" class=\"board-item\" ng-class=\"{'selected': getCurrentIndex()===boardIndex}\">\n" +
19377     "    <div ng-transclude></div>\n" +
19378     "    <div class=\"board-caret\" ng-if=\"getCurrentIndex()===boardIndex\">\n" +
19379     "        <div class=\"board-caret-indicator\"></div>\n" +
19380     "        <div class=\"board-caret-arrow-up\"></div>\n" +
19381     "    </div>\n" +
19382     "</li>");
19383 }]);
19384
19385 angular.module("app/scripts/ng_js_att_tpls/boardStrip/attBoardStrip.html", []).run(["$templateCache", function($templateCache) {
19386   $templateCache.put("app/scripts/ng_js_att_tpls/boardStrip/attBoardStrip.html",
19387     "<div class=\"att-boardstrip\">\n" +
19388     "   <div class=\"boardstrip-reel\">\n" +
19389     "           <div class=\"prev-items\" ng-if=\"isPrevBoard()\">\n" +
19390     "                   <i tabindex=\"0\" aria-label=\"Scroll Boardstrip Left\" att-accessibility-click=\"13,32\" ng-click=\"prevBoard()\" class=\"arrow icon-arrow-left-circle\"></i>\n" +
19391     "           </div>\n" +
19392     "           <div att-add-board on-add-board=\"onAddBoard()\"></div>\n" +
19393     "           <div class=\"board-viewport\"><ul role=\"presentation\" class=\"boardstrip-container\" ng-transclude></ul></div>\n" +
19394     "           <div class=\"next-items\" ng-if=\"isNextBoard()\">\n" +
19395     "                   <i tabindex=\"0\" aria-label=\"Scroll Boardstrip Right\" att-accessibility-click=\"13,32\" ng-click=\"nextBoard()\" class=\"arrow icon-arrow-right-circle\"></i>\n" +
19396     "           </div>\n" +
19397     "   </div>\n" +
19398     "</div>");
19399 }]);
19400
19401 angular.module("app/scripts/ng_js_att_tpls/buttons/buttonDropdown.html", []).run(["$templateCache", function($templateCache) {
19402   $templateCache.put("app/scripts/ng_js_att_tpls/buttons/buttonDropdown.html",
19403     "<div class=\"att-btn-dropdown\">\n" +
19404     "    <div class=\"buttons-dropdown--small btn-group\" ng-class=\"{'open': isOpen}\" att-accessibility-click=\"13,32\" ng-click=\"toggle()\">\n" +
19405     "        \n" +
19406     "        <button role=\"menu\" class=\"button button--secondary button--small buttons-dropdown__drop dropdown-toggle\" ng-if=\"type==='dots'\" alt=\"Click for Options\" >\n" +
19407     "            \n" +
19408     "            <div class=\"circle\"></div>\n" +
19409     "            <div class=\"circle\"></div>\n" +
19410     "            <div class=\"circle\"></div>\n" +
19411     "        </button>\n" +
19412     "        <button role=\"menu\" class=\"button button--secondary button--small buttons-dropdown__drop dropdown-toggle ng-isolate-scope actions-title\" ng-if=\"type === 'actions'\" alt=\"Actions dropdown Buttons\">Actions</button>\n" +
19413     "        \n" +
19414     "\n" +
19415     "        <ul ng-class=\"{'dropdown-menu dots-dropdwn': type==='dots', 'dropdown-menu actions-dropdwn': type === 'actions'}\" ng-transclude></ul>\n" +
19416     "    </div>\n" +
19417     "    \n" +
19418     "</div>\n" +
19419     "");
19420 }]);
19421
19422 angular.module("app/scripts/ng_js_att_tpls/colorselector/colorselector.html", []).run(["$templateCache", function($templateCache) {
19423   $templateCache.put("app/scripts/ng_js_att_tpls/colorselector/colorselector.html",
19424     "<div class=\"att-radio att-color-selector__item\"  \n" +
19425     "     ng-class=\"{'att-radio--on': (iconColor === selected)}\">\n" +
19426     "    <div class=\"att-radio__indicator\" tabindex=\"0\" att-accessibility-click=\"32,13\" ng-click=\"selectedcolor(iconColor)\" \n" +
19427     "         ng-style=\"applycolor\" ng-transclude></div>\n" +
19428     "</div>");
19429 }]);
19430
19431 angular.module("app/scripts/ng_js_att_tpls/datepicker/dateFilter.html", []).run(["$templateCache", function($templateCache) {
19432   $templateCache.put("app/scripts/ng_js_att_tpls/datepicker/dateFilter.html",
19433     "<div class=\"calendar\" ng-class=\"{'monthpicker':mode === 1}\">\n" +
19434     "    <div class=\"select2-container\" ng-class=\"{'select2-container-active select2-dropdown-open': showDropdownList}\" style=\"width: 100%; z-index:0\">\n" +
19435     "        <a tabindex=\"0\" id=\"select2-choice\" class=\"select2-choice\" href=\"javascript:void(0)\" att-element-focus=\"focusInputButton\" ng-show=\"!showCalendar\" att-accessibility-click=\"13,32\" ng-click=\"showDropdown()\" ng-blur=\"focusInputButton=false\">\n" +
19436     "            <span class=\"select2-chosen\" ng-show=\"!showCalendar\">{{selectedOption}}</span>\n" +
19437     "            <input type=\"text\" ng-show=\"showCalendar\" ng-blur=\"untrackInputChange($event)\" att-input-deny=\"[^0-9\\/-]\" maxlength=\"{{maxLength}}\" ng-model=\"selectedOption\" aria-labelledby=\"select2-choice\" ng-change=\"getDropdownText()\" />\n" +
19438     "            <abbr class=\"select2-search-choice-close\"></abbr>\n" +
19439     "            <span ng-class=\"{'select2-arrow': mode !== 1, 'calendar-icon': mode === 1}\"><b></b></span>\n" +
19440     "        </a>\n" +
19441     "        <a id=\"select2-chosen\" class=\"select2-choice\" href=\"javascript:void(0)\" ng-show=\"showCalendar\">\n" +
19442     "            <span class=\"select2-chosen\" ng-show=\"!showCalendar\">{{selectedOption}}</span>\n" +
19443     "            <input type=\"text\" ng-show=\"showCalendar\" ng-blur=\"untrackInputChange($event)\" att-input-deny=\"[^0-9\\/-]\" maxlength=\"{{maxLength}}\" ng-model=\"selectedOption\" aria-labelledby=\"select2-chosen\" ng-change=\"getDropdownText()\" />\n" +
19444     "            <abbr class=\"select2-search-choice-close\"></abbr>\n" +
19445     "            <span tabindex=\"0\" ng-class=\"{'select2-arrow': mode !== 1, 'calendar-icon': mode === 1}\" att-accessibility-click=\"13,32\" ng-click=\"showDropdown()\"><b></b></span>\n" +
19446     "        </a>\n" +
19447     "    </div>\n" +
19448     "    <div class=\"select2-drop select2-drop-active select2-display-none\" ng-style=\"{display: (showDropdownList && 'block') || 'none', 'border-radius': showCalendar && '0 0 0 6px'}\" style=\"width: 100%\">\n" +
19449     "        <div  id=\"dateFilterList\" att-scrollbar ><ul class=\"select2-results options\" ng-transclude></ul></div>\n" +
19450     "           <ul class=\"select2-results sttings\" style=\"margin-top:0px\">\n" +
19451     "                   <li tabindex=\"0\" class=\"select2-result select2-highlighted greyBorder\" ng-class=\"{'select2-result-current': checkCurrentSelection('Custom Single Date')}\" att-accessibility-click=\"13,32\" ng-click=\"selectAdvancedOption('Custom Single Date')\">\n" +
19452     "                <div class=\"select2-result-label\" ng-if=\"mode !== 1\">Custom Single Date...</div>\n" +
19453     "                           <div class=\"select2-result-label\" ng-if=\"mode === 1\">Custom single month...</div>\n" +
19454     "            </li>\n" +
19455     "            <li tabindex=\"0\" class=\"select2-result select2-highlighted\" ng-class=\"{'select2-result-current': checkCurrentSelection('Custom Range')}\" att-accessibility-click=\"13,32\" ng-click=\"selectAdvancedOption('Custom Range')\">\n" +
19456     "                <div class=\"select2-result-label\" ng-if=\"mode !== 1\">Custom Range...</div>\n" +
19457     "                           <div class=\"select2-result-label\" ng-if=\"mode === 1\">Custom month range...</div>\n" +
19458     "            </li>\n" +
19459     "            <li class=\"select2-result select2-highlighted btnContainer\" ng-style=\"{display: (showCalendar && 'block') || 'none'}\">\n" +
19460     "                <button tabindex=\"0\" ng-blur=\"resetFocus($event)\" att-element-focus=\"focusApplyButton\" att-button=\"\" btn-type=\"{{applyButtonType}}\" size=\"small\" att-accessibility-click=\"13,32\" ng-click=\"apply()\">Apply</button>\n" +
19461     "                <button tabindex=\"0\" att-button=\"\" btn-type=\"secondary\" size=\"small\" att-accessibility-click=\"13,32\" ng-click=\"cancel()\">Cancel</button>\n" +
19462     "                <div>\n" +
19463     "                    <a tabindex=\"0\" href=\"javascript:void(0)\" ng-if=\"mode !== 1\" style=\"text-decoration:underline;\" att-accessibility-click=\"13,32\" ng-click=\"clear()\">Clear Dates</a>\n" +
19464     "                    <a tabindex=\"0\" href=\"javascript:void(0)\" ng-if=\"mode === 1\" style=\"text-decoration:underline;\" att-accessibility-click=\"13,32\" ng-click=\"clear()\">Clear Months</a>\n" +
19465     "                </div>\n" +
19466     "            </li>\n" +
19467     "           </ul>\n" +
19468     "    </div>\n" +
19469     "    <div class=\"datepicker-wrapper show-right\" ng-style=\"{display: (showCalendar && 'block') || 'none'}\">\n" +
19470     "        <span datepicker ng-blur=\"resetFocus($event)\" att-element-focus=\"focusSingleDateCalendar\" ng-show=\"checkCurrentSelection('Custom Single Date')\"></span>\n" +
19471     "        <span datepicker ng-blur=\"resetFocus($event)\" att-element-focus=\"focusRangeCalendar\" ng-show=\"checkCurrentSelection('Custom Range')\"></span>\n" +
19472     "    </div>\n" +
19473     "</div>\n" +
19474     "");
19475 }]);
19476
19477 angular.module("app/scripts/ng_js_att_tpls/datepicker/dateFilterList.html", []).run(["$templateCache", function($templateCache) {
19478   $templateCache.put("app/scripts/ng_js_att_tpls/datepicker/dateFilterList.html",
19479     "<li ng-click=\"!disabled && selectOption(fromDate,toDate,caption)\" att-accessibility-click=\"13,32\" ng-class=\"{'select2-result-current': checkCurrentSelection(caption)}\" class=\"select2-result select2-highlighted ng-scope\" tabindex=\"{{!disabled?'0':'-1'}}\">\n" +
19480     "                <div class=\"select2-result-label\" ng-class=\"{'disabled':disabled}\" ng-transclude></div>\n" +
19481     "</li>");
19482 }]);
19483
19484 angular.module("app/scripts/ng_js_att_tpls/datepicker/datepicker.html", []).run(["$templateCache", function($templateCache) {
19485   $templateCache.put("app/scripts/ng_js_att_tpls/datepicker/datepicker.html",
19486     "<div id=\"datepicker\" class=\"datepicker\" ng-class=\"{'monthpicker': mode === 1}\" aria-hidden=\"false\" role=\"dialog\" tabindex=\"-1\" aria-labelledby=\"datepicker\">\n" +
19487     "    <div class=\"datepicker-days\" style=\"display: block;\">\n" +
19488     "        <table class=\"table-condensed\">\n" +
19489     "            <thead>\n" +
19490     "                <tr>\n" +
19491     "                    <th id=\"month\" tabindex=\"0\" class=\"datepicker-switch\" colspan=\"{{(mode !== 1) && (currentRows[0].length - 2) || (currentRows[0].length)}}\" style=\"text-align:left\">{{currentTitle}}</th>\n" +
19492     "                    <th ng-if=\"mode !== 1\" id=\"prev\" aria-hidden=\"{{!disablePrev && 'false'|| 'true'}}\" tabindex=\"{{!disablePrev && '0'|| '-1'}}\" att-accessibility-click=\"13,32\" ng-click=\"!disablePrev && move(-1)\">\n" +
19493     "            <div class=\"icons-list\" data-size=\"medium\"><i class=\"icon-arrow-left-circle\" ng-class=\"{'disabled': disablePrev}\" alt=\"Left Arrow\"></i>\n" +
19494     "            </div><span class=\"hidden-spoken\">Previous Month</span>\n" +
19495     "            </th>\n" +
19496     "            <th ng-if=\"mode !== 1\" id=\"next\" aria-hidden=\"{{!disableNext && 'false'|| 'true'}}\" tabindex=\"{{!disableNext && '0'|| '-1'}}\" att-accessibility-click=\"13,32\" ng-click=\"!disableNext && move(1)\">\n" +
19497     "            <div class=\"icons-list\" data-size=\"medium\"><i class=\"icon-arrow-right-circle\" ng-class=\"{'disabled': disableNext}\" alt=\"Right Arrow\"></i>\n" +
19498     "            </div><span class=\"hidden-spoken\">Next Month</span>\n" +
19499     "            </th>\n" +
19500     "            </tr>\n" +
19501     "            <tr ng-if=\"labels.length > 0\">\n" +
19502     "                <th tabindex=\"-1\" class=\"dow weekday\" ng-repeat=\"label in labels\"><span>{{label.pre}}</span></th>\n" +
19503     "            </tr>\n" +
19504     "            </thead>\n" +
19505     "            <tbody>\n" +
19506     "                <tr>\n" +
19507     "                    <td id=\"datepickerBody\" att-scrollbar colspan=\"{{currentRows[0].length}}\" style=\"padding: 0px;\" headers=\"\">\n" +
19508     "                        <table ng-class=\"{'table-condensed': mode === 0, 'monthtable-condensed': mode === 1}\" style=\"padding: 0px;\">\n" +
19509     "                            <thead class=\"hidden-spoken\">\n" +
19510     "                                <tr ng-show=\"labels.length > 0\">\n" +
19511     "                                    <th id=\"{{label.post}}\" tabindex=\"-1\" class=\"dow weekday\" ng-repeat=\"label in labels\"></th>\n" +
19512     "                                </tr>\n" +
19513     "                            </thead>\n" +
19514     "                            <tbody>\n" +
19515     "                                <tr ng-repeat=\"row in currentRows\">\n" +
19516     "                                    <td headers=\"{{(mode === 0) && dt.header || 'month'}}\" att-element-focus=\"dt.focused\" aria-hidden=\"{{(!dt.oldMonth && !dt.nextMonth && !dt.disabled && 'false') || 'true'}}\" tabindex=\"{{(!dt.oldMonth && !dt.nextMonth && !dt.disabled && '0') || '-1'}}\" ng-repeat=\"dt in row\" class=\"days\" ng-class=\"{'active': dt.selected || dt.from || dt.to, 'from': dt.from, 'to': dt.to, 'range': dt.dateRange, 'prev-month ': dt.oldMonth, 'next-month': dt.nextMonth, 'disabled': dt.disabled, 'today': dt.today, 'weekend': dt.weekend}\" ng-click=\"!dt.selected && !dt.from && !dt.to && !dt.disabled && !dt.oldMonth && !dt.nextMonth && select(dt.date)\" att-accessibility-click=\"13,32\" aria-label=\"{{dt.date | date : 'EEEE, MMMM d'}}\"><span class=\"day\">{{dt.label}}</span></td>\n" +
19517     "                                </tr>\n" +
19518     "                                <tr ng-if=\"mode === 1\" class=\"divider\"><td colspan=\"{{nextRows[0].length}}\"><hr></td></tr>\n" +
19519     "                                <tr>\n" +
19520     "                                    <th id=\"month\" tabindex=\"0\" class=\"datepicker-switch internal\" colspan=\"{{nextRows[0].length}}\" style=\"text-align:left\">{{nextTitle}}</th>\n" +
19521     "                                </tr>\n" +
19522     "                                <tr ng-repeat=\"row in nextRows\">\n" +
19523     "                                    <td headers=\"{{(mode === 0) && dt.header || 'month'}}\" att-element-focus=\"dt.focused\" aria-hidden=\"{{(!dt.oldMonth && !dt.nextMonth && !dt.disabled && 'false') || 'true'}}\" tabindex=\"{{(!dt.oldMonth && !dt.nextMonth && !dt.disabled && '0') || '-1'}}\" ng-repeat=\"dt in row\" class=\"days\" ng-class=\"{'active': dt.selected || dt.from || dt.to, 'from': dt.from, 'to': dt.to, 'range': dt.dateRange, 'prev-month ': dt.oldMonth, 'next-month': dt.nextMonth, 'disabled': dt.disabled, 'today': dt.today, 'weekend': dt.weekend}\" ng-click=\"!dt.selected && !dt.from && !dt.to && !dt.disabled && !dt.oldMonth && !dt.nextMonth && select(dt.date)\" att-accessibility-click=\"13,32\" aria-label=\"{{dt.date | date : 'EEEE, MMMM d'}}\"><span class=\"day\">{{dt.label}}</span></td>\n" +
19524     "                                </tr>\n" +
19525     "                            </tbody>\n" +
19526     "                        </table>\n" +
19527     "                    </td>\n" +
19528     "                </tr>\n" +
19529     "            </tbody>\n" +
19530     "        </table>\n" +
19531     "    </div>\n" +
19532     "</div>\n" +
19533     "");
19534 }]);
19535
19536 angular.module("app/scripts/ng_js_att_tpls/datepicker/datepickerPopup.html", []).run(["$templateCache", function($templateCache) {
19537   $templateCache.put("app/scripts/ng_js_att_tpls/datepicker/datepickerPopup.html",
19538     "<div class=\"calendar\">\n" +
19539     "    <div class=\"box\" ng-class=\"{'active': isOpen}\">\n" +
19540     "        <span ng-transclude></span>\n" +
19541     "        <i class=\"calendar-icon\" tabindex=\"0\" att-accessibility-click=\"13,32\" ng-click=\"toggle()\" alt=\"Calendar Icon\"></i>\n" +
19542     "    </div>\n" +
19543     "    <div class=\"datepicker-wrapper datepicker-wrapper-display-none\" ng-style=\"{display: (isOpen && 'block') || 'none'}\" aria-hidden=\"false\" role=\"dialog\" tabindex=\"-1\">\n" +
19544     "        <span datepicker></span>\n" +
19545     "    </div>\n" +
19546     "</div>\n" +
19547     "");
19548 }]);
19549
19550 angular.module("app/scripts/ng_js_att_tpls/dividerLines/dividerLines.html", []).run(["$templateCache", function($templateCache) {
19551   $templateCache.put("app/scripts/ng_js_att_tpls/dividerLines/dividerLines.html",
19552     "<div class=\"divider-container\" ng-class=\"{'divider-container-light': lightContainer}\">\n" +
19553     "    <hr ng-class=\"{'divider-light': lightContainer}\">\n" +
19554     "</div>\n" +
19555     "\n" +
19556     "");
19557 }]);
19558
19559 angular.module("app/scripts/ng_js_att_tpls/dragdrop/fileUpload.html", []).run(["$templateCache", function($templateCache) {
19560   $templateCache.put("app/scripts/ng_js_att_tpls/dragdrop/fileUpload.html",
19561     "<label class=\"fileContainer\"><span ng-transclude></span><input type=\"file\" att-file-change></label>");
19562 }]);
19563
19564 angular.module("app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlert.html", []).run(["$templateCache", function($templateCache) {
19565   $templateCache.put("app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlert.html",
19566     "<div class=\"form-field\" ng-class=\"{'error': errorMessage, 'warning': warningMessage}\">\n" +
19567     "    <label class=\"form-field__label\" ng-class=\"{'form-field__label--show': showLabel, 'form-field__label--hide': hideLabel}\"></label>\n" +
19568     "    <div class=\"form-field-input-container\" ng-transclude></div>\n" +
19569     "</div>");
19570 }]);
19571
19572 angular.module("app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlertPrv.html", []).run(["$templateCache", function($templateCache) {
19573   $templateCache.put("app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlertPrv.html",
19574     "<div class=\"form-field\" ng-class=\"{'error':hideErrorMsg}\">\n" +
19575     "    <div class=\"form-field-input-container\" ng-transclude></div>\n" +
19576     "   <div class=\"form-field__message error\" type=\"error\" ng-show=\"hideErrorMsg\" >\n" +
19577     "           <i class=\"icon-info-alert\"></i>{{errorMessage}}\n" +
19578     "   </div>\n" +
19579     "</div>\n" +
19580     "");
19581 }]);
19582
19583 angular.module("app/scripts/ng_js_att_tpls/formField/creditCardImage.html", []).run(["$templateCache", function($templateCache) {
19584   $templateCache.put("app/scripts/ng_js_att_tpls/formField/creditCardImage.html",
19585     "<span class=\"css-sprite pull-right\">\n" +
19586     "<span class=\"hidden-spoken\">We accept</span>\n" +
19587     "<ul class=\"{{newValCCI}}\">\n" +
19588     "        <li class=\"css-sprite-mc\"><span class=\"hidden-spoken\">MasterCard</span></li>\n" +
19589     "        <li class=\"css-sprite-visa\"><span class=\"hidden-spoken\">Visa</span></li>\n" +
19590     "        <li class=\"css-sprite-amex\"><span class=\"hidden-spoken\">American Express</span></li>\n" +
19591     "        <li class=\"css-sprite-discover\"><span class=\"hidden-spoken\">Discover</span></li>                                                                                                               \n" +
19592     "</ul>\n" +
19593     "</span>\n" +
19594     "<label for=\"ccForm.card\" class=\"pull-left\">Card number</label>");
19595 }]);
19596
19597 angular.module("app/scripts/ng_js_att_tpls/formField/cvcSecurityImg.html", []).run(["$templateCache", function($templateCache) {
19598   $templateCache.put("app/scripts/ng_js_att_tpls/formField/cvcSecurityImg.html",
19599     "<div>\n" +
19600     "<button type=\"button\" class=\"btn btn-alt btn-tooltip\" style=\"padding-top:16px\" title=\"Help\"><i class=\"hidden-spoken\">Help</i></button>\n" +
19601     "<div class=\"helpertext\" role=\"tooltip\">\n" +
19602     "<div class=\"popover-title\"></div>\n" +
19603     "<div class=\"popover-content\">\n" +
19604     "    <p class=\"text-legal cvc-cc\">\n" +
19605     "        <img ng-src=\"images/{{newValI}}.png\" alt=\"{{newValIAlt}}\">\n" +
19606     "    </p>\n" +
19607     "</div>\n" +
19608     "</div>\n" +
19609     "</div>\n" +
19610     "");
19611 }]);
19612
19613 angular.module("app/scripts/ng_js_att_tpls/hourpicker/hourpicker.html", []).run(["$templateCache", function($templateCache) {
19614   $templateCache.put("app/scripts/ng_js_att_tpls/hourpicker/hourpicker.html",
19615     "<div class=\"hourpicker\">\n" +
19616     "    <div class=\"dropdown-width\">\n" +
19617     "        <div ng-model=\"showlist\" class=\"select2-container topDropDownWidth\" ng-class=\"{'select2-dropdown-open select2-container-active': showlist}\" >\n" +
19618     "            <a class=\"select2-choice\" href=\"javascript:void(0)\" id=\"customSelect\" ng-keydown=\"selectOption(selectPrevNextValue($event,options,selectedOption))\" att-accessibility-click=\"13\" ng-click=\"showDropdown()\">\n" +
19619     "                <span class=\"select2-chosen\">{{selectedOption}}</span>\n" +
19620     "                <span class=\"select2-arrow\"><b></b></span>\n" +
19621     "            </a>\n" +
19622     "        </div>             \n" +
19623     "        <div class=\"select2-display-none select2-with-searchbox select2-drop-active show-search resultTopWidth\" ng-show=\"showlist\">       \n" +
19624     "        <ul class=\"select2-results resultTopMargin\" >                       \n" +
19625     "            <li  ng-model=\"ListType\" ng-repeat=\"option in options\" att-accessibility-click=\"13\" ng-click=\"selectOption(option,$index)\" class=\"select2-results-dept-0 select2-result select2-result-selectable\"><div class=\"select2-result-label\"><span >{{option}}</span></div></li>                        \n" +
19626     "        </ul>\n" +
19627     "        </div>\n" +
19628     "    </div>\n" +
19629     "    <div ng-show=\"showDaysSelector\" class=\"customdays-width\">\n" +
19630     "        <div att-divider-lines class=\"divider-margin-f\"></div>  \n" +
19631     "        <div class=\"col-md-3 fromto-margin\">\n" +
19632     "            <div>From</div> <br>\n" +
19633     "            <div>To</div>\n" +
19634     "        </div>\n" +
19635     "        <div ng-repeat=\"day in days\">\n" +
19636     "            <div class=\"col-md-3 col-md-days\">\n" +
19637     "                <div  class=\"col-md-1 daysselect-margin\">\n" +
19638     "                    <input type=\"checkbox\" ng-model=\"daysList[day]\" title=\"Day selection {{$index}}\" att-checkbox ng-change=\"addSelectedValue(day)\">    \n" +
19639     "                </div>\n" +
19640     "                <span>{{day}}</span><br>\n" +
19641     "                \n" +
19642     "                <div class=\"dropDownMarginBottom\">\n" +
19643     "                    <div class=\"select2-container topDropDownWidth\" ng-class=\"{'select2-dropdown-open select2-container-active': FrtimeListDay[day]}\" >\n" +
19644     "                        <a class=\"select2-choice selectDropDown\" href=\"javascript:void(0)\" tabindex=\"{{daysList[day] ? '0' : '-1'}}\" att-accessibility-click=\"13\" ng-click=\"daysList[day] && showfromDayDropdown(day)\" ng-class=\"{'select2-chosen-disabled':!daysList[day]}\"  ng-keydown=\"daysList[day] && selectFromDayOption(day , selectPrevNextValue($event,fromtime,selectedFromOption[day]));daysList[day] && addSelectedValue(day);\">\n" +
19645     "                            <span class=\"select2-chosen dropDownMarginRight\" >{{selectedFromOption[day]}} <i ng-if=\"daysList[day]\" ng-class=\"FrtimeListDay[day] ? 'ion-arrow-up-b' : 'ion-arrow-down-b'\"></i></span>\n" +
19646     "                        </a>\n" +
19647     "                    </div>             \n" +
19648     "                    \n" +
19649     "                    <div class=\"select2-display-none select2-with-searchbox select2-drop-active show-search resultFromDropDown\"  ng-show=\"FrtimeListDay[day]\">       \n" +
19650     "                    <ul class=\"select2-results resultTopMargin\" >                       \n" +
19651     "                        <li ng-click=\"selectFromDayOption(day,time.value);addSelectedValue(day);\" ng-repeat=\"time in fromtime\"  class=\"select2-results-dept-0 select2-result select2-result-selectable\"><div class=\"select2-result-label\" ng-class=\"{'selectedItemInDropDown': (time.value==selectedFromOption[day])}\"><span >{{time.value}}</span></div></li>                        \n" +
19652     "                    </ul>\n" +
19653     "                    </div>\n" +
19654     "                </div>\n" +
19655     "                \n" +
19656     "                <div class=\"dropDownMarginBottom\">\n" +
19657     "                    <div class=\"select2-container topDropDownWidth\" ng-class=\"{'select2-dropdown-open select2-container-active': TotimeListDay[day]}\" >\n" +
19658     "                        <a class=\"select2-choice selectDropDown\" href=\"javascript:void(0)\" tabindex=\"{{daysList[day] ? '0' : '-1'}}\" att-accessibility-click=\"13\" ng-click=\"daysList[day] && showtoDayDropdown(day)\" ng-class=\"{'select2-chosen-disabled':!daysList[day], 'selectDropDown-error':daysList[day] && showToTimeErrorDay[day]}\"  ng-keydown=\"daysList[day] && selectToDayOption(day , selectPrevNextValue($event,totime,selectedToOption[day]));daysList[day] && addSelectedValue(day);\">\n" +
19659     "                            <span class=\"select2-chosen dropDownMarginRight\">{{selectedToOption[day]}} <i ng-if=\"daysList[day]\" ng-class=\"TotimeListDay[day] ? 'ion-arrow-up-b' : 'ion-arrow-down-b'\" ></i></span>\n" +
19660     "                        </a>\n" +
19661     "                    </div>\n" +
19662     "                    \n" +
19663     "                    <div class=\"select2-display-none select2-with-searchbox select2-drop-active show-search resultToDropDown\" ng-show=\"TotimeListDay[day]\">       \n" +
19664     "                    <ul class=\"select2-results resultTopMargin\" >                       \n" +
19665     "                        <li ng-click=\"selectToDayOption(day,time.value);addSelectedValue(day);\" ng-repeat=\"time in totime\"  class=\"select2-results-dept-0 select2-result select2-result-selectable\"><div class=\"select2-result-label\" ng-class=\"{'selectedItemInDropDown': (time.value==selectedToOption[day])}\"><span >{{time.value}}</span></div></li>                        \n" +
19666     "                    </ul>\n" +
19667     "                    </div>\n" +
19668     "                </div>\n" +
19669     "            </div>  \n" +
19670     "        </div>    \n" +
19671     "        <div att-divider-lines class=\"divider-margin-s\"></div>\n" +
19672     "    </div>\n" +
19673     "    <div ng-transclude></div>\n" +
19674     "</div>");
19675 }]);
19676
19677 angular.module("app/scripts/ng_js_att_tpls/links/readMore.html", []).run(["$templateCache", function($templateCache) {
19678   $templateCache.put("app/scripts/ng_js_att_tpls/links/readMore.html",
19679     "<div>\n" +
19680     "    <div ng-bind-html=\"textToDisplay\" ng-class=\"{'att--readMore': readFlag, 'att--readLess': !readFlag}\" ng-style=\"readLinkStyle\"></div>\n" +
19681     "    <span class=\"att--readmore__link\" ng-show=\"readMoreLink\">… <a href=\"javascript:void(0);\" ng-click=\"readMore()\" att-accessbility-click=\"32,13\">Read More</a>\n" +
19682     "    </span>\n" +
19683     "</div>\n" +
19684     "<span class=\"att--readless__link\" ng-show=\"readLessLink\">\n" +
19685     "    <a href=\"javascript:void(0);\" ng-click=\"readLess()\" att-accessbility-click=\"32,13\">Read Less</a>\n" +
19686     "</span>");
19687 }]);
19688
19689 angular.module("app/scripts/ng_js_att_tpls/loading/loading.html", []).run(["$templateCache", function($templateCache) {
19690   $templateCache.put("app/scripts/ng_js_att_tpls/loading/loading.html",
19691     "<div data-progress=\"{{progressStatus}}\" class=\"{{colorClass}}\" ng-class=\"{'att-loading-count':icon == 'count','loading--small':icon == 'small','loading': icon != 'count'}\" alt=\"Loading\">\n" +
19692     "   <div class=\"att-loading-circle\" ng-if=\"icon == 'count'\">\n" +
19693     "           <div class=\"att-loading-circle__mask att-loading-circle__full\">\n" +
19694     "                   <div class=\"att-loading-circle__fill\"></div>\n" +
19695     "           </div>\n" +
19696     "           <div class=\"att-loading-circle__mask att-loading-circle__half\">\n" +
19697     "                   <div class=\"att-loading-circle__fill\"></div>\n" +
19698     "                   <div class=\"att-loading-circle__fill att-loading-circle__fix\"></div>\n" +
19699     "           </div>\n" +
19700     "   </div>\n" +
19701     "   <div ng-class=\"{'att-loading-inset':icon == 'count','loading__inside':icon != 'count'}\"><div class=\"att-loading-inset__percentage\" ng-if=\"icon == 'count'\" alt=\"Loading with Count\"></div></div>\n" +
19702     "</div>\n" +
19703     "\n" +
19704     "");
19705 }]);
19706
19707 angular.module("app/scripts/ng_js_att_tpls/modal/backdrop.html", []).run(["$templateCache", function($templateCache) {
19708   $templateCache.put("app/scripts/ng_js_att_tpls/modal/backdrop.html",
19709     "<div class=\"overlayed\" ng-class=\"{show: animate}\" \n" +
19710     "     ng-style=\"{'z-index': 2000 + index*10,'overflow':'scroll'}\">         \n" +
19711     "</div>");
19712 }]);
19713
19714 angular.module("app/scripts/ng_js_att_tpls/modal/tabbedItem.html", []).run(["$templateCache", function($templateCache) {
19715   $templateCache.put("app/scripts/ng_js_att_tpls/modal/tabbedItem.html",
19716     "<div>\n" +
19717     "    <ul class=\"tabs_overlay\">\n" +
19718     "        <li ng-repeat=\"item in items\" class=\"tabs_overlay__item two__item\" ng-class=\"{'active':isActiveTab($index)}\" ng-click=\"clickTab($index)\">\n" +
19719     "            <i class=\"{{item.iconClass}}\"></i>\n" +
19720     "            {{item.title}} ({{item.number}})\n" +
19721     "            <a class=\"viewLink\" att-link>Show</a>\n" +
19722     "        </li>\n" +
19723     "    </ul>\n" +
19724     "</div>");
19725 }]);
19726
19727 angular.module("app/scripts/ng_js_att_tpls/modal/tabbedOverlayItem.html", []).run(["$templateCache", function($templateCache) {
19728   $templateCache.put("app/scripts/ng_js_att_tpls/modal/tabbedOverlayItem.html",
19729     "<div>\n" +
19730     "    <ul class=\"tabs_overlay\">\n" +
19731     "        <li ng-repeat=\"item in items\" class=\"tabs_overlay__item two__item\" ng-class=\"{'active':isActiveTab($index)}\" ng-click=\"clickTab($index)\">\n" +
19732     "            <i class=\"{{item.iconClass}}\"></i>\n" +
19733     "            {{item.title}} ({{item.number}})\n" +
19734     "            <a class=\"viewLink\" att-link>Show</a>\n" +
19735     "        </li>\n" +
19736     "    </ul>\n" +
19737     "</div>");
19738 }]);
19739
19740 angular.module("app/scripts/ng_js_att_tpls/modal/window.html", []).run(["$templateCache", function($templateCache) {
19741   $templateCache.put("app/scripts/ng_js_att_tpls/modal/window.html",
19742     "<div tabindex=\"-1\" role=\"dialog\" att-element-focus=\"focusModalFlag\" class=\"modals {{ windowClass }}\" ng-class=\"{show: animate}\" \n" +
19743     "     ng-style=\"{'z-index': 2010 + index*10}\"  ng-click=\"close($event)\" ng-transclude>         \n" +
19744     "</div>\n" +
19745     "");
19746 }]);
19747
19748 angular.module("app/scripts/ng_js_att_tpls/pagination/pagination.html", []).run(["$templateCache", function($templateCache) {
19749   $templateCache.put("app/scripts/ng_js_att_tpls/pagination/pagination.html",
19750     "<div class=\"pager\">\n" +
19751     "    <a tabindex=\"0\" href=\"javascript:void(0)\" class=\"pager__item--prev\" att-accessibility-click=\"13,32\" ng-click=\"prev($event)\" ng-if=\"currentPage > 1\"><i class=\"icon-arrow-left\"></i> Previous</a>\n" +
19752     "    <a tabindex=\"0\" href=\"javascript:void(0)\" class=\"pager__item pager__item--link\" ng-if=\"totalPages > 7 && currentPage > 3\" att-accessibility-click=\"13,32\" ng-click=\"selectPage(1, $event)\">1</a>\n" +
19753     "    <span class=\"pager__item\" ng-if=\"totalPages > 7 && currentPage > 3\">...</span>\n" +
19754     "    <a tabindex=\"0\" href=\"javascript:void(0)\" class=\"pager__item pager__item--link\" att-element-focus=\"isFocused(page)\" ng-repeat=\"page in pages\" ng-class=\"{'pager__item--active': checkSelectedPage(page)}\" att-accessibility-click=\"13,32\" ng-click=\"selectPage(page, $event)\">{{page}}</a>\n" +
19755     "    <span class=\"pager__item\" ng-if=\"totalPages > 7 && currentPage < totalPages - 2 && showInput !== true\">...</span>\n" +
19756     "    <span ng-show=\"totalPages > 7 && showInput === true\"><input class=\"pager__item--input\" type=\"text\" placeholder=\"...\" maxlength=\"2\" ng-model=\"currentPage\" aria-label=\"Current page count\"/></span>\n" +
19757     "    <a tabindex=\"0\" href=\"javascript:void(0)\" class=\"pager__item pager__item--link\" ng-if=\"totalPages > 7 && currentPage < totalPages - 2\" att-accessibility-click=\"13,32\" ng-click=\"selectPage(totalPages, $event)\">{{totalPages}}</a>\n" +
19758     "    <a tabindex=\"0\" href=\"javascript:void(0)\" class=\"pager__item--next\" att-accessibility-click=\"13,32\" ng-click=\"next($event)\" ng-if=\"currentPage < totalPages\">Next <i class=\"icon-arrow-right\"></i></a>\n" +
19759     "</div>");
19760 }]);
19761
19762 angular.module("app/scripts/ng_js_att_tpls/paneSelector/innerPane.html", []).run(["$templateCache", function($templateCache) {
19763   $templateCache.put("app/scripts/ng_js_att_tpls/paneSelector/innerPane.html",
19764     "<div class='inner-pane' ng-transclude></div>");
19765 }]);
19766
19767 angular.module("app/scripts/ng_js_att_tpls/paneSelector/paneGroup.html", []).run(["$templateCache", function($templateCache) {
19768   $templateCache.put("app/scripts/ng_js_att_tpls/paneSelector/paneGroup.html",
19769     "<div class='pane-group' ng-transclude></div>");
19770 }]);
19771
19772 angular.module("app/scripts/ng_js_att_tpls/paneSelector/sidePane.html", []).run(["$templateCache", function($templateCache) {
19773   $templateCache.put("app/scripts/ng_js_att_tpls/paneSelector/sidePane.html",
19774     "<div class='side-pane' ng-transclude></div>");
19775 }]);
19776
19777 angular.module("app/scripts/ng_js_att_tpls/tooltip/tooltip-popup.html", []).run(["$templateCache", function($templateCache) {
19778   $templateCache.put("app/scripts/ng_js_att_tpls/tooltip/tooltip-popup.html",
19779     "<div class=\"att-tooltip \" \n" +
19780     "     ng-class=\"{ 'att-tooltip--on': isOpen, \n" +
19781     "                'att-tooltip--dark att-tooltip--dark--hover':stylett=='dark', \n" +
19782     "                'att-tooltip--light att-tooltip--light--hover':stylett=='light',\n" +
19783     "                'att-tooltip--left':placement=='left', \n" +
19784     "                'att-tooltip--above':placement=='above', \n" +
19785     "                'att-tooltip--right':placement=='right', \n" +
19786     "                'att-tooltip--below':placement=='below'}\" \n" +
19787     "    ng-bind-html=\"content | unsafe\" ></div>");
19788 }]);
19789
19790 angular.module("app/scripts/ng_js_att_tpls/popOvers/popOvers.html", []).run(["$templateCache", function($templateCache) {
19791   $templateCache.put("app/scripts/ng_js_att_tpls/popOvers/popOvers.html",
19792     "<div class=\"att-popover popover-demo\" ng-style=\"{backgroundColor:popOverStyle}\"\n" +
19793     "     ng-class=\"{'att-tooltip--dark':popOverStyle==='grey',\n" +
19794     "                'att-pop-over--left':popOverPlacement==='left', \n" +
19795     "                'att-pop-over--above':popOverPlacement==='above', \n" +
19796     "                'att-pop-over--right':popOverPlacement==='right'}\" \n" +
19797     "    style='position: absolute; max-width: 490px;'>\n" +
19798     "    <div class=\"pop-over-caret\"\n" +
19799     "         ng-class=\"{'pop-over-caret-border--left':popOverPlacement==='left', \n" +
19800     "                'pop-over-caret-border--above':popOverPlacement==='above', \n" +
19801     "                'pop-over-caret-border--right':popOverPlacement==='right', \n" +
19802     "                'pop-over-caret-border--below':popOverPlacement==='below'}\">\n" +
19803     "    </div>\n" +
19804     "    <div class=\"pop-over-caret\" ng-style=\"popOverPlacement=='below' && {borderBottom:'6px solid ' +popOverStyle}||popOverPlacement=='left' && {borderLeft:'6px solid ' +popOverStyle}||popOverPlacement=='right' && {borderRight:'6px solid ' +popOverStyle}||popOverPlacement=='above' && {borderTop:'6px solid ' +popOverStyle}\"\n" +
19805     "         ng-class=\"{'pop-over-caret--left':popOverPlacement==='left', \n" +
19806     "                'pop-over-caret--above':popOverPlacement==='above', \n" +
19807     "                'pop-over-caret--right':popOverPlacement==='right', \n" +
19808     "                'pop-over-caret--below':popOverPlacement==='below'}\"></div>\n" +
19809     "    \n" +
19810     "    <div class=\"att-popover-content\">\n" +
19811     "   <a ng-if=\"closeable\" href=\"javascript:void(0)\" class=\"icon-close att-popover__close\" ng-click=\"closeMe();$event.preventDefault()\"></a>\n" +
19812     "        <div class=\"popover-packages__container\" ng-include=\"content\"></div>\n" +
19813     "    </div>\n" +
19814     "</div>");
19815 }]);
19816
19817 angular.module("app/scripts/ng_js_att_tpls/profileCard/addUser.html", []).run(["$templateCache", function($templateCache) {
19818   $templateCache.put("app/scripts/ng_js_att_tpls/profileCard/addUser.html",
19819     "<div  class=\"col-md-9 profile-card add-user\">\n" +
19820     "    <div class=\"atcenter\">\n" +
19821     "        <div><i class=\"icon-add\"></i></div>\n" +
19822     "        <span>add User</span>\n" +
19823     "    </div>\n" +
19824     "</div>");
19825 }]);
19826
19827 angular.module("app/scripts/ng_js_att_tpls/profileCard/profileCard.html", []).run(["$templateCache", function($templateCache) {
19828   $templateCache.put("app/scripts/ng_js_att_tpls/profileCard/profileCard.html",
19829     "<div class=\"col-md-9 profile-card\">\n" +
19830     "    <div class=\"top-block\">\n" +
19831     "       <div class=\"profile-image\">\n" +
19832     "            <img ng-if=\"image\" profile-name=\"{{profile.name}}\" ng-src=\"{{profile.img}}\" alt=\"{{profile.name}}\">\n" +
19833     "            <span ng-hide=\"image\" class=\"default-img\">{{initials}}</span>\n" +
19834     "            <p class=\"name\" tooltip-condition=\"{{profile.name}}\" height=\"true\"></p>\n" +
19835     "            <p class=\"status\">\n" +
19836     "                <span class=\"status-icon\" ng-class=\"{'icon-green':colorIcon==='green','icon-red':colorIcon==='red','icon-blue':colorIcon==='blue','icon-yellow':colorIcon==='yellow'}\">   \n" +
19837     "                </span>\n" +
19838     "                <span>{{profile.state}}<span ng-if=\"badge\" class=\"status-badge\">Admin</span></span>\n" +
19839     "            </p>\n" +
19840     "        </div>\n" +
19841     "    </div>\n" +
19842     "    <div class=\"bottom-block\">\n" +
19843     "         <div class=\"profile-details\">\n" +
19844     "            <label>Username</label>\n" +
19845     "            <p att-text-overflow=\"92%\" tooltip-condition=\"{{profile.userName}}\">{{profile.userName}}</p>\n" +
19846     "            <label>Email</label>\n" +
19847     "            <p att-text-overflow=\"92%\" tooltip-condition=\"{{profile.email}}\">{{profile.email}}</p>\n" +
19848     "            <label>Role</label>\n" +
19849     "            <p att-text-overflow=\"92%\" tooltip-condition=\"{{profile.role}}\">{{profile.role}}</p>\n" +
19850     "            <label>Last Login</label>\n" +
19851     "            <p att-text-overflow=\"92%\" tooltip-condition=\"{{profile.lastLogin}}\">{{profile.lastLogin}}</p>\n" +
19852     "         </div>\n" +
19853     "    </div>\n" +
19854     "</div>");
19855 }]);
19856
19857 angular.module("app/scripts/ng_js_att_tpls/progressBars/progressBars.html", []).run(["$templateCache", function($templateCache) {
19858   $templateCache.put("app/scripts/ng_js_att_tpls/progressBars/progressBars.html",
19859     "<div class=\"att-progress\">\n" +
19860     "    <div class=\"att-progress-value\">&nbsp;</div>\n" +
19861     "</div>");
19862 }]);
19863
19864 angular.module("app/scripts/ng_js_att_tpls/scrollbar/scrollbar.html", []).run(["$templateCache", function($templateCache) {
19865   $templateCache.put("app/scripts/ng_js_att_tpls/scrollbar/scrollbar.html",
19866     "<div class=\"scroll-bar\" style=\"position: absolute\">\n" +
19867     "    <div class=\"scroll-thumb\" style=\"position: absolute; overflow: hidden\"></div>\n" +
19868     "</div>\n" +
19869     "<div class=\"prev icons-list\" data-size=\"medium\" ng-show=\"navigation && prevAvailable\" ng-style=\"{height: scrollbarAxis === 'x' && position.height + 'px'}\">\n" +
19870     "    <a href=\"javascript:void(0);\" ng-click=\"customScroll(false)\" aria-label=\"Scroll\" aria-hidden=\"true\">\n" +
19871     "        <i ng-class=\"{'ion-ios-arrow-up': (scrollbarAxis === 'y'), 'icon-chevron-left': (scrollbarAxis === 'x')}\"></i>\n" +
19872     "    </a>\n" +
19873     "</div>\n" +
19874     "<div class=\"scroll-viewport\" ng-style=\"{height: (scrollbarAxis === 'x' && position.height + 'px') || viewportHeight, width: viewportWidth}\" style=\"position: relative; overflow: hidden\">\n" +
19875     "    <div class=\"scroll-overview\" style=\"position: absolute; display: table; width: 100%\" att-position=\"position\" ng-transclude></div>\n" +
19876     "</div>\n" +
19877     "<div class='next icons-list' data-size=\"medium\" ng-show=\"navigation && nextAvailable\" ng-style=\"{height: scrollbarAxis === 'x' && position.height + 'px'}\">\n" +
19878     "    <a href=\"javascript:void(0);\" ng-click=\"customScroll(true)\" aria-label=\"Scroll\" aria-hidden=\"true\">\n" +
19879     "        <i ng-class=\"{'ion-ios-arrow-down': (scrollbarAxis === 'y'), 'icon-chevron-right': (scrollbarAxis === 'x')}\"></i>\n" +
19880     "    </a>\n" +
19881     "</div>\n" +
19882     "");
19883 }]);
19884
19885 angular.module("app/scripts/ng_js_att_tpls/search/search.html", []).run(["$templateCache", function($templateCache) {
19886   $templateCache.put("app/scripts/ng_js_att_tpls/search/search.html",
19887     "<div class=\"select2-container show-search\" ng-class=\"{'select2-dropdown-open': (showlist && !isDisabled),'select2-container-disabled':isDisabled, 'select2-container-active': isact}\" ng-init=\"isact=false;\" style=\"width: 100%;\">\n" +
19888     "    <a href=\"javascript:void(0)\" class=\"select2-choice needsclick\" tabindex=\"0\" ng-click=\"showDropdown()\" ng-class=\"{'select2-chosen-disabled':isDisabled}\" role=\"combobox\" aria-expanded=\"{{showlist}}\" aria-owns=\"inList\" aria-label=\"{{selectedOption}} selected\" ng-focus=\"isact=true;\" ng-blur=\"isact=false;\">\n" +
19889     "        <span class=\"select2-chosen needsclick\" aria-hidden = \"true\">{{selectedOption}}</span>\n" +
19890     "        <abbr class=\"select2-search-choice-close needsclick\"></abbr>\n" +
19891     "        <span class=\"select2-arrow needsclick\" role=\"presentation\">\n" +
19892     "            <b role=\"presentation\" class=\"needsclick\"></b>\n" +    
19893     "        </span>\n" +
19894     "    </a>    \n" +
19895     "    <input class=\"select2-focusser select2-offscreen\"            \n" +
19896     "           tabindex=\"-1\" \n" +
19897     "           type=\"text\" \n" +
19898     "           aria-hidden=\"true\" \n" +
19899     "           title=\"hidden\"           \n" +
19900     "           aria-haspopup=\"true\"           \n" +
19901     "           role=\"button\">    \n" +
19902     "</div>\n" +
19903     "\n" +
19904     "<div class=\"select2-drop select2-with-searchbox select2-drop-auto-width select2-drop-active\" ng-class=\"{'select2-display-none':(!showlist || isDisabled)}\" style=\"width:100%;z-index: 10\">\n" +
19905     "    <div class=\"select2-search\">\n" +
19906     "        <label ng-if=\"!noFilter\" class=\"select2-offscreen\" aria-label=\"Inline Search Field\" aria-hidden=\"true\">Inline Search Field</label>\n" +
19907     "        <input ng-if=\"!noFilter\" ng-model=\"title\" aria-label=\"title\" typeahead=\"c.title for c in cName | filter:$viewValue:startsWith\" type=\"text\" autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"off\" spellcheck=\"false\" class=\"select2-input\" aria-autocomplete=\"list\" placeholder=\"\">\n" +
19908     "    </div>\n" +
19909     "    <ul id=\"inList\" class=\"select2-results\" role=\"listbox\">\n" +
19910     "        <li ng-show=\"filteredName.length === 0\" class=\"select2-no-results\" tabindex=\"-1\">No matches found</li>\n" +
19911     "        <li class=\"select2-results-dept-0 select2-result select2-result-selectable\" role=\"presentation\" ng-model=\"ListType\" ng-show=\"selectMsg && filteredName.length > 0\" ng-click=\"selectOption(selectMsg, '-1')\" ng-class=\"{'select2-result-current': selectedOption === selectMsg, 'hovstyle': selectedIndex === -1}\" ng-mouseover=\"hoverIn(-1)\" aria-label=\"{{selectMsg}}\" tabindex=\"-1\">\n" +
19912     "            <div ng-if=\"startsWithFilter\" class=\"select2-result-label\" ng-bind-html=\"selectMsg | unsafe\" role=\"option\">\n" +
19913     "                <span class=\"select2-match\"></span>\n" +
19914     "            </div>\n" +
19915     "            <div ng-if=\"!startsWithFilter\" class=\"select2-result-label\" ng-bind-html=\"selectMsg | highlight:title:className | unsafe\" role=\"option\">\n" +
19916     "                <span class=\"select2-match\"></span>\n" +
19917     "            </div>\n" +
19918     "        </li>\n" +
19919     "\n" +
19920     "        <li role=\"menuitem\" ng-if=\"startsWithFilter\" class=\"select2-results-dept-0 select2-result select2-result-selectable\" role=\"presentation\" ng-model=\"ListType\" ng-repeat=\"(fIndex, item) in filteredName = (cName | startsWith:title:item)\" ng-class=\"{'select2-result-current': selectedOption === item.title,'hovstyle': selectedIndex === item.index,'disable': item.disabled}\" ng-click=\"item.disabled || selectOption(item.title,item.index)\" ng-mouseover=\"hoverIn(item.index)\" aria-label=\"{{item.title}}\" tabindex=\"-1\">\n" +
19921     "            <div class=\"select2-result-label\" ng-bind-html=\"item.title | unsafe\" role=\"option\">\n" +
19922     "                <span class=\"select2-match\"></span>\n" +
19923     "            </div>\n" +
19924     "        </li>\n" +
19925     "\n" +
19926     "        <li role=\"menuitem\" ng-if=\"!startsWithFilter\" class=\"select2-results-dept-0 select2-result select2-result-selectable\" role=\"presentation\" ng-model=\"ListType\" ng-repeat=\"(fIndex, item) in filteredName = (cName | filter:title)\" ng-class=\"{'select2-result-current': selectedOption === item.title,'hovstyle': selectedIndex === item.index,'disable': item.disabled}\" ng-click=\"item.disabled || selectOption(item.title,item.index)\" ng-mouseover=\"hoverIn(item.index)\" aria-label=\"{{item.title}}\" tabindex=\"-1\">\n" +
19927     "            <div class=\"select2-result-label\" ng-bind-html=\"item.title | highlight:title:className | unsafe\" role=\"option\">\n" +
19928     "                <span class=\"select2-match\"></span>\n" +
19929     "            </div>\n" +
19930     "        </li>\n" +
19931     "    </ul>\n" +
19932     "</div>");
19933 }]);
19934
19935 angular.module("app/scripts/ng_js_att_tpls/select/select.html", []).run(["$templateCache", function($templateCache) {
19936   $templateCache.put("app/scripts/ng_js_att_tpls/select/select.html",
19937     "<div class=\"select2-container show-search\" ng-class=\"{'select2-dropdown-open': (showlist && !isDisabled),'select2-container-disabled': isDisabled, 'select2-container-active': isact}\" ng-init=\"isact=false;\">\n" +
19938     "    <span class=\"select2-choice needsclick\" tabindex=\"{{isDisabled ? -1 : 0}}\" ng-click=\"showDropdown()\" ng-class=\"{'select2-chosen-disabled':isDisabled}\" role=\"combobox\" aria-expanded=\"{{showlist}}\" aria-owns=\"inList\" aria-label=\"{{titleName}} dropdown {{selectedOption}} selected\" ng-focus=\"isact=true;\" ng-blur=\"isact=false;\">\n" +
19939     "        <span class=\"select2-chosen needsclick\" aria-hidden=\"true\" ng-bind-html=\"selectedOption | unsafe\">{{selectedOption}}</span>\n" +
19940     "        <abbr class=\"select2-search-choice-close needsclick\"></abbr>\n" +
19941     "        <span class=\"select2-arrow needsclick\" role=\"presentation\">\n" +
19942     "            <b role=\"presentation\" class=\"needsclick\"></b>\n" +
19943     "        </span>\n" +
19944     "    </span>    \n" +
19945     "    <input class=\"select2-focusser select2-offscreen\"            \n" +
19946     "           tabindex=\"-1\" \n" +
19947     "           type=\"text\" \n" +
19948     "           aria-hidden=\"true\" \n" +
19949     "           title=\"hidden\"           \n" +
19950     "           aria-haspopup=\"true\"           \n" +
19951     "           role=\"button\">    \n" +
19952     "</div>\n" +
19953     "\n" +
19954     "<div class=\"select2-drop select2-with-searchbox select2-drop-auto-width select2-drop-active\" ng-class=\"{'select2-display-none':(!showlist || isDisabled)}\" style=\"width:100%;z-index: 10\">\n" +
19955     "    <div class=\"select2-search\">\n" +
19956     "        <label ng-if=\"!noFilter\" class=\"select2-offscreen\" aria-label=\"Inline Search Field\" aria-hidden=\"true\">Inline Search Field</label>\n" +
19957     "        <input ng-if=\"!noFilter\" ng-model=\"title\" aria-label=\"title\" typeahead=\"c.title for c in cName | filter:$viewValue:startsWith\" type=\"text\" autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"off\" spellcheck=\"false\" class=\"select2-input\" aria-autocomplete=\"list\" placeholder=\"\">\n" +
19958     "    </div>\n" +
19959     "    <ul id=\"inList\" class=\"select2-results\" role=\"listbox\">\n" +
19960     "        <li ng-if=\"!noFilter\" ng-show=\"filteredName.length === 0\" class=\"select2-no-results\" tabindex=\"-1\">No matches found</li>\n" +
19961     "        <li ng-if=\"!noFilter\" class=\"select2-results-dept-0 select2-result select2-result-selectable\" role=\"presentation\" ng-model=\"ListType\" ng-show=\"selectMsg && filteredName.length > 0\" ng-click=\"selectOption(selectMsg, '-1')\" ng-class=\"{'select2-result-current': selectedOption === selectMsg, 'hovstyle': selectedIndex === -1}\" ng-mouseover=\"hoverIn(-1)\" aria-label=\"{{selectMsg}}\" tabindex=\"-1\">\n" +
19962     "            <div ng-if=\"startsWithFilter\" class=\"select2-result-label\" ng-bind-html=\"selectMsg | unsafe\" role=\"option\">\n" +
19963     "                <span class=\"select2-match\"></span>\n" +
19964     "            </div>\n" +
19965     "            <div ng-if=\"!startsWithFilter\" class=\"select2-result-label\" ng-bind-html=\"selectMsg | highlight:title:className | unsafe\" role=\"option\">\n" +
19966     "                <span class=\"select2-match\"></span>\n" +
19967     "            </div>\n" +
19968     "        </li>\n" +
19969     "\n" +
19970     "        <li  role=\"menuitem\"  ng-if=\"startsWithFilter\" class=\"select2-results-dept-0 select2-result select2-result-selectable\" ng-model=\"ListType\" ng-repeat=\"(fIndex, item) in filteredName = (cName | startsWith:title:item)\" ng-class=\"{'select2-result-current': selectedOption === item.title,'hovstyle': selectedIndex === item.index,'disable': item.disabled}\" ng-click=\"item.disabled || selectOption(item.title,item.index)\" ng-mouseover=\"hoverIn(item.index)\"  tabindex=\"-1\">\n" +
19971     "            <div class=\"select2-result-label\" ng-bind-html=\"item.title | unsafe\" role=\"option\">\n" +
19972     "                <span class=\"select2-match\"></span>\n" +
19973     "            </div>\n" +
19974     "        </li>\n" +
19975     "\n" +
19976     "        <li role=\"menuitem\" ng-if=\"!startsWithFilter\" class=\"select2-results-dept-0 select2-result select2-result-selectable\" ng-model=\"ListType\" ng-repeat=\"(fIndex, item) in filteredName = (cName | filter:title)\" ng-class=\"{'select2-result-current': selectedOption === item.title,'hovstyle': selectedIndex === item.index,'disable': item.disabled}\" ng-click=\"item.disabled || selectOption(item.title,item.index)\" ng-mouseover=\"hoverIn(item.index)\"  tabindex=\"-1\">\n" +
19977     "            <div class=\"select2-result-label\" ng-bind-html=\"item.title | highlight:title:className | unsafe\" role=\"option\">\n" +
19978     "                <span class=\"select2-match\"></span>\n" +
19979     "            </div>\n" +
19980     "        </li>\n" +
19981     "    </ul>\n" +
19982     "</div>");
19983 }]);
19984
19985 angular.module("app/scripts/ng_js_att_tpls/select/textDropdown.html", []).run(["$templateCache", function($templateCache) {
19986   $templateCache.put("app/scripts/ng_js_att_tpls/select/textDropdown.html",
19987     "<div tabindex=\"0\" class=\"text-dropdown\">\n" +
19988     "   <div class=\"dropdown\" ng-class=\"{'not-visible': isActionsShown}\" ng-click=\"toggle()\">\n" +
19989     "           <span class=\"action--selected\" ng-bind=\"currentAction\"></span>\n" +
19990     "           <i ng-class=\"isActionsShown ? 'ion-arrow-up-b' : 'ion-arrow-down-b'\"></i>\n" +
19991     "   </div>\n" +
19992     "   <ul ng-class=\"isActionsShown ? 'actionsOpened' : 'actionsClosed'\" ng-show=\"isActionsShown\">\n" +
19993     "           <li ng-class=\"{'highlight': selectedIndex==$index}\" ng-repeat=\"action in actions track by $index\" ng-click=\"chooseAction($event, action, $index)\" ng-mouseover=\"hoverIn($index)\">{{action}}<i ng-class=\"{'icon-included-checkmark': isCurrentAction(action)}\" att-accessibility-click=\"13,32\"></i></li>\n" +
19994     "   </ul>\n" +
19995     "</div>");
19996 }]);
19997
19998 angular.module("app/scripts/ng_js_att_tpls/slider/maxContent.html", []).run(["$templateCache", function($templateCache) {
19999   $templateCache.put("app/scripts/ng_js_att_tpls/slider/maxContent.html",
20000     "<div class=\"att-slider__label att-slider__label--max att-slider__label--below\" ng-transclude></div>");
20001 }]);
20002
20003 angular.module("app/scripts/ng_js_att_tpls/slider/minContent.html", []).run(["$templateCache", function($templateCache) {
20004   $templateCache.put("app/scripts/ng_js_att_tpls/slider/minContent.html",
20005     "<div class=\"att-slider__label att-slider__label--min att-slider__label--below\" ng-transclude></div>");
20006 }]);
20007
20008 angular.module("app/scripts/ng_js_att_tpls/slider/slider.html", []).run(["$templateCache", function($templateCache) {
20009   $templateCache.put("app/scripts/ng_js_att_tpls/slider/slider.html",
20010     "<div class=\"att-slider\" ng-mousemove=\"moveElem($event)\" ng-mouseup=\"mouseUp($event)\">\n" +
20011     "    <div class=\"att-slider__track\">\n" +
20012     "        <div class=\"att-slider__range att-slider__range--disabled\" ng-style=\"disabledStyle\"></div>\n" +
20013     "        <div class=\"att-slider__range\" ng-style=\"rangeStyle\"></div>\n" +
20014     "    </div>\n" +
20015     "    <div class=\"att-slider__handles-container\">\n" +
20016     "       <div role=\"menuitem\" aria-label=\"{{ngModelSingle}}\" class=\"att-slider__handle\" ng-style=\"handleStyle\" ng-mousedown=\"mouseDown($event,'ngModelSingle')\" ng-mousemove=\"moveElem($event)\" ng-mouseup=\"mouseUp($event)\" tabindex=\"0\" ng-keydown=\"keyDown($event,'ngModelSingle')\"></div>\n" +
20017     "       <div role=\"menuitem\" aria-label=\"Minimum Value- {{ngModelLow}}\" class=\"att-slider__handle\" ng-style=\"minHandleStyle\" ng-mousedown=\"mouseDown($event,'ngModelLow')\" ng-focus=\"focus($event,'ngModelLow')\" ng-mousemove=\"moveElem($event)\" ng-mouseup=\"mouseUp($event)\" tabindex=\"0\" ng-keyup=\"keyUp($event,'ngModelLow')\" ng-keydown=\"keyDown($event,'ngModelLow')\"></div>\n" +
20018     "       <div role=\"menuitem\" aria-label=\"Maximum Value- {{ngModelHigh}}\" class=\"att-slider__handle\" ng-style=\"maxHandleStyle\" ng-mousedown=\"mouseDown($event,'ngModelHigh')\" ng-focus=\"focus($event,'ngModelHigh')\" ng-mousemove=\"moveElem($event)\" ng-mouseup=\"mouseUp($event)\" tabindex=\"0\" ng-keyup=\"keyUp($event,'ngModelHigh')\" ng-keydown=\"keyDown($event,'ngModelHigh')\"></div>\n" +
20019     "    </div>\n" +
20020     "    <div ng-transclude></div>\n" +
20021     "</div>");
20022 }]);
20023
20024 angular.module("app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdown.html", []).run(["$templateCache", function($templateCache) {
20025   $templateCache.put("app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdown.html",
20026     "<div class=\" btn-group\" \n" +
20027     "     ng-class=\"{'buttons-dropdown--large':!isSmall, \n" +
20028     "                 'buttons-dropdown--small':isSmall, \n" +
20029     "                 'action-dropdown':(isActionDropdown), \n" +
20030     "                 'open':isDropDownOpen}\">\n" +
20031     "    <a tabindex=\"0\" href=\"javascript:void(0)\" class=\"button btn buttons-dropdown__split\" \n" +
20032     "       ng-class=\"{'button--primary':(btnType==undefined || btnType=='primary'), \n" +
20033     "                   'button--secondary':btnType=='secondary', \n" +
20034     "                   'button--disabled':btnType=='disabled', \n" +
20035     "                   'button--small':isSmall}\" \n" +
20036     "       ng-if=\"!isActionDropdown\"\n" +
20037     "       ng-click=\"btnType==='disabled'?undefined:clickFxn()\" att-accessibility-click=\"13,32\">{{btnText}}</a>\n" +
20038     "    <a tabindex=\"0\" href=\"javascript:void(0)\" role=\"button\" aria-label=\"Toggle Dropdown\" aria-haspopup=\"true\" class=\"button buttons-dropdown__drop dropdown-toggle\" \n" +
20039     "       ng-class=\"{'button--primary':(btnType==undefined || btnType=='primary'), \n" +
20040     "               'button--secondary':btnType=='secondary', \n" +
20041     "               'button--disabled':btnType=='disabled', \n" +
20042     "               'button--small':isSmall}\" ng-click=\"toggleDropdown()\" att-accessibility-click=\"13,32\">{{toggleTitle}} </a>\n" +
20043     "    <ul class=\"dropdown-menu\" ng-class=\"{'align-right':multiselect ===true}\" aria-expanded=\"{{isDropDownOpen}}\" ng-click=\"hideDropdown()\" role=\"menu\" ng-transclude></ul>\n" +
20044     "</div>  ");
20045 }]);
20046
20047 angular.module("app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdownItem.html", []).run(["$templateCache", function($templateCache) {
20048   $templateCache.put("app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdownItem.html",
20049     "<li role=\"menuitem\" att-element-focus=\"sFlag\" tabindex=\"0\" ng-transclude></li>");
20050 }]);
20051
20052 angular.module("app/scripts/ng_js_att_tpls/splitIconButton/splitIcon.html", []).run(["$templateCache", function($templateCache) {
20053   $templateCache.put("app/scripts/ng_js_att_tpls/splitIconButton/splitIcon.html",
20054     "<div class='split-icon-button-container'>\n" +
20055     "\n" +
20056     "   <div class='split-icon-button' ng-class=\"{'icon-with-chevron': isRight && !isMiddle && !isLeftNextDropdown && !isNextToDropDown, 'split-icon-button-middle':isMiddle, 'split-icon-button-right':isRight, 'split-icon-button-left':isLeft, 'split-icon-button-left-dropdown': isLeftNextDropdown ,'split-icon-button-next-dropdown': isNextToDropDown,'split-icon-button-dropdown': isDropDownOpen,'split-icon-button-hover':isIconHovered || isDropDownOpen}\" ng-mouseover='isIconHovered = true;' ng-mouseleave='isIconHovered = false;' tabindex=\"-1\" att-accessibility-click=\"13,32\" ng-click='dropDownClicked();'>\n" +
20057     "           <a class='{{icon}}' title='{{iconTitle}}' tabindex=\"0\"></a>\n" +
20058     "           <i ng-if=\"isRight && !isMiddle && !isLeftNextDropdown && !isNextToDropDown\" \n" +
20059     "                   ng-class=\"isDropDownOpen ? 'ion-arrow-up-b' : 'ion-arrow-down-b'\"> </i>\n" +
20060     "   </div> \n" +
20061     "\n" +
20062     "    <ul ng-if='isDropdown' class='dropdown-menu {{dropDownId}}' ng-show='\n" +
20063     "    isDropDownOpen' ng-click='toggleDropdown(false)' role=\"presentation\" ng-transclude>\n" +
20064     "    </ul>\n" +
20065     "\n" +
20066     "</div>");
20067 }]);
20068
20069 angular.module("app/scripts/ng_js_att_tpls/splitIconButton/splitIconButton.html", []).run(["$templateCache", function($templateCache) {
20070   $templateCache.put("app/scripts/ng_js_att_tpls/splitIconButton/splitIconButton.html",
20071     "<div>\n" +
20072     "   <div ng-if='isLeftLineShown' dir-type='{{iconStateConstants.DIR_TYPE.LEFT}}' expandable-line></div>\n" +
20073     "   <div ng-click='clickHandler()' att-split-icon icon='{{icon}}' title='{{title}}' dir-type='{{iconStateConstants.DIR_TYPE.BUTTON}}' hover-watch='isHovered' drop-down-watch='dropDownWatch' drop-down-id='{{dropDownId}}'>\n" +
20074     "           <div ng-transclude>\n" +
20075     "           </div>\n" +
20076     "   </div>\n" +
20077     "   <div ng-if='isRightLineShown' dir-type='{{iconStateConstants.DIR_TYPE.RIGHT}}' expandable-line></div>\n" +
20078     "</div>");
20079 }]);
20080
20081 angular.module("app/scripts/ng_js_att_tpls/splitIconButton/splitIconButtonGroup.html", []).run(["$templateCache", function($templateCache) {
20082   $templateCache.put("app/scripts/ng_js_att_tpls/splitIconButton/splitIconButtonGroup.html",
20083     "<div ng-transclude>\n" +
20084     "</div>");
20085 }]);
20086
20087 angular.module("app/scripts/ng_js_att_tpls/stepSlider/attStepSlider.html", []).run(["$templateCache", function($templateCache) {
20088   $templateCache.put("app/scripts/ng_js_att_tpls/stepSlider/attStepSlider.html",
20089     "<span ng-class=\"mainSliderClass\">\n" +
20090     "    <table>\n" +
20091     "        <tr>\n" +
20092     "            <td>\n" +
20093     "                <div class=\"jslider-bg\">\n" +
20094     "                    <i class=\"l\"></i>\n" +
20095     "                    <i class=\"r\"></i>\n" +
20096     "                    <i class=\"v\" ng-class=\"{'step-slider-green':sliderColor == COLORS.GREEN, 'step-slider-blue': sliderColor == COLORS.BLUE_HIGHLIGHT, 'step-slider-magenta': sliderColor == COLORS.MAGENTA, 'step-slider-gold': sliderColor == COLORS.GOLD, 'step-slider-purple': sliderColor == COLORS.PURPLE, 'step-slider-dark-blue': sliderColor == COLORS.DARK_BLUE, 'step-slider-regular': sliderColor == COLORS.REGULAR, 'step-slider-white': sliderColor == COLORS.WHITE, 'cutoff-slider': isCutOffSlider}\"></i>\n" +
20097     "                </div>\n" +
20098     "                <div class=\"jslider-pointer\" id=\"left-pointer\"></div>\n" +
20099     "                <div class=\"jslider-pointer jslider-pointer-to\" ng-class=\"{'step-slider-green':sliderColor == COLORS.GREEN, 'step-slider-blue': sliderColor == COLORS.BLUE_HIGHLIGHT, 'step-slider-magenta': sliderColor == COLORS.MAGENTA, 'step-slider-gold': sliderColor == COLORS.GOLD, 'step-slider-purple': sliderColor == COLORS.PURPLE, 'step-slider-dark-blue': sliderColor == COLORS.DARK_BLUE, 'step-slider-regular': sliderColor == COLORS.REGULAR, 'step-slider-white':sliderColor == COLORS.WHITE ,'cutoff-slider': isCutOffSlider}\"></div>\n" +
20100     "                <div class=\"jslider-label\"><span ng-bind=\"from\"></span><span ng-bind=\"options.dimension\"></span></div>\n" +
20101     "                <div class=\"jslider-label jslider-label-to\"><span ng-bind=\"toStr\"></span><span ng-bind=\"endDimension\"></span></div>\n" +
20102     "                <div class=\"jslider-value\" id=\"jslider-value-left\"><span></span>{{options.dimension}}</div>\n" +
20103     "                <div class=\"jslider-value jslider-value-to\"><span></span>{{toolTipDimension}}</div>\n" +
20104     "                <div class=\"jslider-scale\" ng-class=\"{'show-dividers': showDividers, 'cutoff-slider-dividers':isCutOffSlider}\">\n" +
20105     "                </div>\n" +
20106     "                <div class=\"jslider-cutoff\">\n" +
20107     "                    <div class=\"jslider-label jslider-label-cutoff\">\n" +
20108     "                        <span ng-bind=\"cutOffVal\"></span>\n" +
20109     "                    </div>\n" +
20110     "                </div>\n" +
20111     "            </td>\n" +
20112     "        </tr>\n" +
20113     "    </table>\n" +
20114     "</span>\n" +
20115     "");
20116 }]);
20117
20118 angular.module("app/scripts/ng_js_att_tpls/steptracker/step-tracker.html", []).run(["$templateCache", function($templateCache) {
20119   $templateCache.put("app/scripts/ng_js_att_tpls/steptracker/step-tracker.html",
20120     "<div class=\"steptracker1\">\n" +
20121     "    <div class=\"steptracker-bg\">\n" +
20122     "        <div tabindex=\"0\" ng-click=\"stepclick($event, $index);\" att-accessibility-click=\"13,23\" class=\"steptracker-track size-onethird\" ng-repeat=\"step in sdata\"\n" +
20123     "             ng-style=\"set_width($index)\"\n" +
20124     "             ng-class=\"{'last':laststep($index),'done':donesteps($index),'active':activestep($index), 'incomplete': isIncomplete($index), 'disabled': disableClick}\">\n" +
20125     "            <div class=\"circle\">{{($index) + 1}}<span>{{step.title}}</span></div>\n" +
20126     "            <div ng-if=\"!laststep($index)\" class=\"track\"></div>\n" +
20127     "        </div>\n" +
20128     "    </div>\n" +
20129     "</div>");
20130 }]);
20131
20132 angular.module("app/scripts/ng_js_att_tpls/steptracker/step.html", []).run(["$templateCache", function($templateCache) {
20133   $templateCache.put("app/scripts/ng_js_att_tpls/steptracker/step.html",
20134     "<div class=\"steptracker1\">\n" +
20135     "    <div class=\"steptracker-bg\">\n" +
20136     "        <div class=\"steptracker-track size-onethird\" \n" +
20137     "             ng-class=\"{'last':laststep($index),'done':donesteps($index),'active':activestep($index)}\">\n" +
20138     "            <div class=\"circle\" tabindex=\"0\" \n" +
20139     "                 ng-click=\"stepclick($event, $index);\" \n" +
20140     "                 att-accessibility-click=\"13,23\">{{($index) + 1}}<span>{{step.title}}</span></div>\n" +
20141     "            <div ng-if=\"!laststep($index)\" class=\"track\"></div>\n" +
20142     "        </div>\n" +
20143     "    </div>\n" +
20144     "</div>\n" +
20145     "");
20146 }]);
20147
20148 angular.module("app/scripts/ng_js_att_tpls/steptracker/timeline.html", []).run(["$templateCache", function($templateCache) {
20149   $templateCache.put("app/scripts/ng_js_att_tpls/steptracker/timeline.html",
20150     "<div class='att-timeline'>\n" +
20151     "   <div timeline-dot order='0' title='{{steps[0].title}}' description='{{steps[0].description}}' by='{{steps[0].by}}' date='{{steps[0].date}}' type='{{steps[0].type}}'></div>\n" +
20152     "\n" +
20153     "   <div ng-repeat=\"m in middleSteps track by $index\">\n" +
20154     "           <div timeline-bar order='{{$index}}'></div>\n" +
20155     "           <div timeline-dot order='{{$index + 1}}' title='{{m.title}}' description='{{m.description}}' by='{{m.by}}' date='{{m.date}}' type='{{m.type}}'>\n" +
20156     "           </div>\n" +
20157     "   </div>\n" +
20158     "\n" +
20159     "</div>");
20160 }]);
20161
20162 angular.module("app/scripts/ng_js_att_tpls/steptracker/timelineBar.html", []).run(["$templateCache", function($templateCache) {
20163   $templateCache.put("app/scripts/ng_js_att_tpls/steptracker/timelineBar.html",
20164     "<div class='timeline-bar'>\n" +
20165     "   <div class='progress-bar' ng-class=\"{'completed-color':isCompleted,'cancelled-color':isCancelled,'alert-color':isAlert}\">\n" +
20166     "   </div>\n" +
20167     "   <hr></hr>\n" +
20168     "</div>");
20169 }]);
20170
20171 angular.module("app/scripts/ng_js_att_tpls/steptracker/timelineDot.html", []).run(["$templateCache", function($templateCache) {
20172   $templateCache.put("app/scripts/ng_js_att_tpls/steptracker/timelineDot.html",
20173     "<div class='timeline-dot'>\n" +
20174     "\n" +
20175     "   <div class='bigger-circle' ng-class=\"{'completed-color':isCompleted,'cancelled-color':isCancelled,'alert-color':isAlert}\">\n" +
20176     "   </div>\n" +
20177     "\n" +
20178     "   <div class='inactive-circle'>\n" +
20179     "   </div>\n" +
20180     "\n" +
20181     "   <div class='expandable-circle' ng-class=\"{'completed-color':isCompleted,'cancelled-color':isCancelled,'alert-color':isAlert}\">\n" +
20182     "   </div>\n" +
20183     "\n" +
20184     "   <div ng-class=\"{'below-info-box':isBelowInfoBoxShown, 'above-info-box': !isBelowInfoBoxShown}\" tabindex=\"0\">\n" +
20185     "           \n" +
20186     "           <div ng-if='isBelowInfoBoxShown' class='vertical-line'>\n" +
20187     "           </div>\n" +
20188     "\n" +
20189     "           <div class='info-container' ng-init='isContentShown=false'>\n" +
20190     "                   <div ng-class=\"{'current-step-title':isCurrentStep, 'title':!isCurrentStep,'completed-color-text':isCompleted,'cancelled-color-text':isCancelled,'alert-color-text':isAlert, 'inactive-color-text':isInactive}\" ng-mouseover='titleMouseover(1)' ng-mouseleave='titleMouseleave()' ng-bind='title' ></div>\n" +
20191     "                   <div class='content'>\n" +
20192     "                           <div class='description' ng-bind='description'></div>\n" +
20193     "                           <div class='submitter' ng-bind='by'></div>\n" +
20194     "                   </div>\n" +
20195     "                   <div class='date' ng-mouseover='titleMouseover(2)' ng-mouseleave='titleMouseleave()' ng-bind='date'></div>\n" +
20196     "           </div>\n" +
20197     "\n" +
20198     "           <div ng-if='!isBelowInfoBoxShown' class='vertical-line'>\n" +
20199     "           </div>\n" +
20200     "   </div>\n" +
20201     "\n" +
20202     "</div>");
20203 }]);
20204
20205 angular.module("app/scripts/ng_js_att_tpls/table/attTable.html", []).run(["$templateCache", function($templateCache) {
20206   $templateCache.put("app/scripts/ng_js_att_tpls/table/attTable.html",
20207     "<table class=\"tablesorter tablesorter-default\" ng-transclude></table>\n" +
20208     "");
20209 }]);
20210
20211 angular.module("app/scripts/ng_js_att_tpls/table/attTableBody.html", []).run(["$templateCache", function($templateCache) {
20212   $templateCache.put("app/scripts/ng_js_att_tpls/table/attTableBody.html",
20213     "<td ng-transclude></td>\n" +
20214     "");
20215 }]);
20216
20217 angular.module("app/scripts/ng_js_att_tpls/table/attTableHeader.html", []).run(["$templateCache", function($templateCache) { 
20218   $templateCache.put("app/scripts/ng_js_att_tpls/table/attTableHeader.html", 
20219     "<th role=\"columnheader\" scope=\"col\" aria-live=\"polite\" aria-sort=\"{{sortPattern !== 'null' && '' || sortPattern}}\" aria-label=\"{{headerName}} {{sortable !== 'false' && ': activate to sort' || ' '}} {{sortPattern !== 'null' && '' || sortPattern}}\" tabindex=\"{{sortable !== 'false' && '0' || '-1'}}\" class=\"tablesorter-header\" ng-class=\"{'tablesorter-headerAsc': sortPattern === 'ascending', 'tablesorter-headerDesc': sortPattern === 'descending', 'tablesort-sortable': sortable !== 'false', 'sorter-false': sortable === 'false'}\" att-accessibility-click=\"13,32\" ng-click=\"(sortable !== 'false') && sort();\"><div class=\"tablesorter-header-inner\" ng-transclude></div></th>"); 
20220 }]);
20221
20222 angular.module("app/scripts/ng_js_att_tpls/tableMessages/attTableMessage.html", []).run(["$templateCache", function($templateCache) {
20223   $templateCache.put("app/scripts/ng_js_att_tpls/tableMessages/attTableMessage.html",
20224     "<div class=\"att-table-message\">\n" +
20225     "   <div class=\"message\" ng-if=\"msgType==messageConstants.TABLE_MESSAGE_TYPES.noMatching\">\n" +
20226     "      <div class=\"img-magnify-glass\"></div> \n" +
20227     "      <div>\n" +
20228     "         <div ng-transclude></div>\n" +
20229     "      </div>\n" +
20230     "   </div>\n" +
20231     "   <div class=\"message\" ng-if=\"msgType==messageConstants.TABLE_MESSAGE_TYPES.errorLoading\">\n" +
20232     "      <div class=\"img-oops-exclamation\" tabindex=\"0\" aria-label=\"Oops! The information could not load at this time. Please click link to refresh the page.\"></div> \n" +
20233     "      <div>Oops!</div>\n" +
20234     "      <div>The information could not load at this time.</div>\n" +
20235     "      <div>Please <a href=\"javascript:void(0)\" ng-click=\"refreshAction($event)\">refresh the page</a>\n" +
20236     "      </div>\n" +
20237     "   </div>\n" +
20238     "   <div class=\"message\" ng-if=\"msgType==messageConstants.TABLE_MESSAGE_TYPES.magnifySearch\">\n" +
20239     "      <div class=\"img-magnify-glass\"></div>\n" +
20240     "      <div>\n" +
20241     "         <p class=\"title\" tabindex=\"0\">Please input values to <br/> begin your search.</p>\n" +
20242     "      </div>\n" +
20243     "   </div>\n" +
20244     "   <div class=\"message loading-message\" ng-if=\"msgType==messageConstants.TABLE_MESSAGE_TYPES.isLoading\">\n" +
20245     "      <div class=\"img-loading-dots\"></div>\n" +
20246     "      <div ng-transclude></div>\n" +
20247     "   </div>\n" +
20248     "</div>");
20249 }]);
20250
20251 angular.module("app/scripts/ng_js_att_tpls/tableMessages/attUserMessage.html", []).run(["$templateCache", function($templateCache) {
20252   $templateCache.put("app/scripts/ng_js_att_tpls/tableMessages/attUserMessage.html",
20253     "<div class=\"att-user-message\">\n" +
20254     "  <div ng-class=\"type==messageConstants.USER_MESSAGE_TYPES.error && trigger ? 'message-wrapper-error' : 'hidden'\">\n" +
20255     "      <div class=\"message-icon-error\"> <i class=\"icon-info-alert\"></i> </div>\n" +
20256     "\n" +
20257     "      <div class=\"message-body-wrapper\">\n" +
20258     "        <div class=\"message-title-error\" ng-if=\"thetitle && thetitle.length > 0\"> <span ng-bind=\"thetitle\" tabindex=\"0\" aria-label=\"{{thetitle}}\"></span> </div>\n" +
20259     "        <div class=\"message-msg\" ng-bind=\"message\" ng-if=\"message && message.length > 0\" tabindex=\"0\"></div>\n" +
20260     "        <div class=\"message-bottom\">\n" +
20261     "           <div ng-transclude></div>\n" +
20262     "        </div>\n" +
20263     "      </div>\n" +
20264     "\n" +
20265     "   </div>\n" +
20266     "  <div ng-class=\"type==messageConstants.USER_MESSAGE_TYPES.success && trigger ? 'message-wrapper-success' : 'hidden'\">\n" +
20267     "      <div class=\"message-icon-success\"> <i class=\"icon-included-checkmark\"></i></div>\n" +
20268     "\n" +
20269     "      <div class=\"message-body-wrapper\">\n" +
20270     "        <div class=\"message-title-success\" ng-if=\"thetitle && thetitle.length > 0\" >\n" +
20271     "          <span ng-bind=\"thetitle\" tabindex=\"0\" aria-label=\"{{thetitle}}\"></span>\n" +
20272     "        </div>\n" +
20273     "        <div class=\"message-msg\" ng-bind=\"message\" ng-if=\"message && message.length > 0\" tabindex=\"0\"></div>\n" +
20274     "        <div class=\"message-bottom\">\n" +
20275     "           <div ng-transclude></div>\n" +
20276     "        </div>\n" +
20277     "      </div>\n" +
20278     "\n" +
20279     "   </div>\n" +
20280     "</div>\n" +
20281     "");
20282 }]);
20283
20284 angular.module("app/scripts/ng_js_att_tpls/tabs/floatingTabs.html", []).run(["$templateCache", function($templateCache) {
20285   $templateCache.put("app/scripts/ng_js_att_tpls/tabs/floatingTabs.html",
20286     "<ul ng-class=\"{'tabsbid': size === 'large', 'tabsbid--small': size === 'small'}\">\n" +
20287     " <li ng-repeat=\"tab in tabs\" ng-class=\"{'tabsbid__item tabsbid__item--active': isActiveTab(tab.url), 'tabsbid__item': !isActiveTab(tab.url)}\" ng-click=\"onClickTab(tab)\">\n" +
20288     "        <a class=\"tabsbid__item-link\" href=\"{{tab.url}}\" tabindex=\"0\" att-accessibility-click=\"32,13\">{{tab.title}}</a>\n" +
20289     "  </li>\n" +
20290     "</ul>");
20291 }]);
20292
20293 angular.module("app/scripts/ng_js_att_tpls/tabs/genericTabs.html", []).run(["$templateCache", function($templateCache) {
20294   $templateCache.put("app/scripts/ng_js_att_tpls/tabs/genericTabs.html",
20295     "<ul ng-class=\"{'tabsbid': size === 'large', 'tabsbid--small': size === 'small'}\">\n" +
20296     "    <li ng-repeat=\"tab in tabs\" ng-class=\"{'tabsbid__item tabsbid__item--active': isActive(tab.id), 'tabsbid__item': !isActive(tab.id),'tabs__item--active': isActive(tab.id)}\" ng-click=\"clickTab(tab)\">\n" +
20297     "           <a class=\"tabsbid__item-link\" href=\"{{tab.url}}\" tabindex=\"0\" att-accessibility-click=\"32,13\">{{tab.title}}</a>\n" +
20298     "    </li>\n" +
20299     "</ul>\n" +
20300     "");
20301 }]);
20302
20303 angular.module("app/scripts/ng_js_att_tpls/tabs/menuTab.html", []).run(["$templateCache", function($templateCache) {
20304   $templateCache.put("app/scripts/ng_js_att_tpls/tabs/menuTab.html",
20305     "<li class=\"megamenu__item\" ng-mouseover=\"showHoverChild($event)\" ng-class=\"{'tabs__item--active': menuItem.active==true && !hoverChild==true}\">\n" +
20306     "    <span role=\"menuitem\" att-accessibility-click=\"13,32\" tabindex=\"0\" ng-click=\"showChildren($event);!clickInactive||resetMenu($event)\">{{tabName}}</span>\n" +
20307     "    <div ng-transclude></div>\n" +
20308     "</li>\n" +
20309     "");
20310 }]);
20311
20312 angular.module("app/scripts/ng_js_att_tpls/tabs/parentmenuTab.html", []).run(["$templateCache", function($templateCache) {
20313   $templateCache.put("app/scripts/ng_js_att_tpls/tabs/parentmenuTab.html",
20314     "<div ng-class=\"{'megamenu-tabs': megaMenu,'submenu-tabs': !megaMenu}\">\n" +
20315     "    <ul class=\"megamenu__items\" role=\"presentation\" ng-transclude>\n" +
20316     "    </ul>\n" +
20317     "</div>");
20318 }]);
20319
20320 angular.module("app/scripts/ng_js_att_tpls/tabs/simplifiedTabs.html", []).run(["$templateCache", function($templateCache) {
20321   $templateCache.put("app/scripts/ng_js_att_tpls/tabs/simplifiedTabs.html",
20322     "<div class=\"simplified-tabs\">\n" +
20323     "<ul class=\"simplified-tabs__items\" role=\"tablist\">\n" +
20324     "    <li ng-repeat=\"tab in tabs\" role=\"tab\" class=\"simplified-tabs__item\" ng-class=\"{'tabs__item--active': isActive(tab.id)}\" ng-click=\"clickTab(tab)\" tabindex=\"0\" att-accessibility-click=\"32,13\">{{tab.title}}</li>\n" +
20325     "    <li class=\"tabs__pointer\"></li>\n" +
20326     "</ul>\n" +
20327     "</div>");
20328 }]);
20329
20330 angular.module("app/scripts/ng_js_att_tpls/tabs/submenuTab.html", []).run(["$templateCache", function($templateCache) {
20331   $templateCache.put("app/scripts/ng_js_att_tpls/tabs/submenuTab.html",
20332     "<li class=\"tabsbid__item megamenu__item\" ng-class=\"{'subMenuHover': menuItem.active==true}\">\n" +
20333     "<a ng-href=\"{{tabUrl}}\" role=\"menuitem\" ng-if=\"subMenu === true\" ng-mouseover=\"!subMenu || showChildren($event)\" ng-focus=\"!subMenu ||showChildren($event)\" tabindex=\"{{subMenu=='true'?0:-1}}\" ng-click=\"!subMenu ||showMenuClick($event) ; subMenu ||showSubMenuClick($event)\" att-accessibility-click=\"13,32\">{{tabName}}</a>\n" +
20334     "<a  ng-href=\"{{tabUrl}}\" role=\"menuitem\" ng-if=\"!menuItem.leafNode && subMenu !== true\" ng-mouseover=\"!subMenu || showChildren($event)\" ng-focus=\"!subMenu ||showChildren($event)\" tabindex=\"{{subMenu=='true'?0:-1}}\" ng-click=\"!subMenu ||showMenuClick($event) ; subMenu ||showSubMenuClick($event)\" att-accessibility-click=\"13,32\">{{tabName}}</a>\n" +
20335     "<span ng-transclude></span>\n" +
20336     "</li>\n" +
20337     "");
20338 }]);
20339
20340 angular.module("app/scripts/ng_js_att_tpls/tagBadges/tagBadges.html", []).run(["$templateCache", function($templateCache) {
20341   $templateCache.put("app/scripts/ng_js_att_tpls/tagBadges/tagBadges.html",
20342     "<div class=\"tags__item\" \n" +
20343     "     ng-class=\"{'tags__item--small':isSmall, \n" +
20344     "                 'tags__item--color':isColor, \n" +
20345     "                 'tags__item--cloud':!isClosable && !isColor,'active':applyActiveClass}\"\n" +
20346     "     ng-if=\"display\" \n" +
20347     "     ng-style=\"{borderColor: border_type_borderColor, background: isHighlight?'#bbb':undefined, color: isHighlight?'#444':undefined }\"\n" +
20348     "     ng-mousedown=\"activeHighlight(true)\" role=\"presentation\" ng-mouseup=\"activeHighlight(false)\">\n" +
20349     "    <i class=\"icon-filter tags__item--icon\" ng-if=\"isIcon\">&nbsp;</i>\n" +
20350     "    <i class=\"tags__item--color-icon\" ng-if=\"isColor\" ng-style=\"{backgroundColor: background_type_backgroundColor, borderColor: background_type_borderColor}\"></i>\n" +
20351     "    <span class=\"tags__item--title\" role=\"presentation\"  tabindex=0  ng-mousedown=\"activeHighlight(true)\" ng-mouseup=\"activeHighlight(false)\" ng-transclude></span>\n" +
20352     "    <a href=\"javascript:void(0)\" title=\"Dismiss Link\" class=\"tags__item--action\" ng-click=\"closeMe();$event.preventDefault()\" ng-if=\"isClosable\"\n" +
20353     "       ng-style=\"{color: (isHighlight && '#444') || '#888' , borderLeft: (isHighlight && '1px solid #444')|| '1px solid #888' }\">\n" +
20354     "        <i class=\"icon-erase\">&nbsp;</i>\n" +
20355     "    </a>\n" +
20356     "</div>");
20357 }]);
20358
20359 angular.module("app/scripts/ng_js_att_tpls/toggle/demoToggle.html", []).run(["$templateCache", function($templateCache) {
20360   $templateCache.put("app/scripts/ng_js_att_tpls/toggle/demoToggle.html",
20361     "<span ng-transclude></span>\n" +
20362     "<div class=\"att-switch-content\" hm-drag = \"drag($event)\" att-accessibility-click=\"13,32\" ng-click=\"updateModel($event)\" hm-dragstart=\"alert('hello')\" hm-dragend=\"drag($event)\" ng-class=\"{'large' : directiveValue == 'large'}\"  style=\"-webkit-user-select: none; -webkit-user-drag: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\">\n" +
20363     "    <div class=\"att-switch-onText\" ng-style=\"\" ng-class=\"{'icon-included-checkmark ico' : on === undefined,'large' : directiveValue == 'large'}\">{{on}}<span class=\"hidden-spoken\">{{directiveValue}} when checked.</span></div>\n" +
20364     "    <div class=\"att-switch-thumb\" tabindex=\"0\" title=\"Toggle switch\" role=\"checkbox\"  ng-class=\"{'large' : directiveValue == 'large'}\"></div>\n" +
20365     "    <div class=\"att-switch-offText\" ng-class=\"{'icon-erase ico' : on === undefined,'large' : directiveValue == 'large'}\">{{off}}<span class=\"hidden-spoken\">{{directiveValue}} when unchecked.</span></div>\n" +
20366     "</div>\n" +
20367     "");
20368 }]);
20369
20370 angular.module("app/scripts/ng_js_att_tpls/typeAhead/typeAhead.html", []).run(["$templateCache", function($templateCache) {
20371   $templateCache.put("app/scripts/ng_js_att_tpls/typeAhead/typeAhead.html",
20372     "<div class=\"typeahead mainContainerOuter\">\n" +
20373     "    <span class=\"message\">To</span>\n" +
20374     "    <div class='maincontainer' ng-click=\"setFocus()\" ng-focus=\"inputActive=true\" ng-class =\"{'typeahed_active':inputActive || (lineItems.length && inputActive)}\">\n" +
20375     "        <span tag-badges closable ng-repeat =\"lineItem in lineItems track by $index\" on-close=\"theMethodToBeCalled($index)\" >{{lineItem}}</span>\n" +
20376     "        <input type=\"text\"  focus-me=\"clickFocus\" ng-focus=\"inputActive=true\" ng-model=\"model\" ng-keydown=\"selected = false; selectionIndex($event)\"/><br/> \n" +
20377     "    </div>\n" +
20378     "    <div ng-hide=\"!model.length || selected\">\n" +
20379     "        <div class=\"filtercontainer list-scrollable\" ng-show=\"( items | filter:model).length\">\n" +
20380     "            <div  class=\"item\" ng-repeat=\"item in items| filter:model track by $index\"  ng-click=\"handleSelection(item[titleName],item[subtitle])\" att-accessibility-click=\"13,32\" ng-class=\"{active:isCurrent($index,item[titleName],item[subtitle],( items | filter:model).length)}\"ng-mouseenter=\"setCurrent($index)\">\n" +
20381     "                <span class=\"title\" >{{item[titleName]}}</span>\n" +
20382     "                <span class=\"subtitle\">{{item[subtitle]}}</span>\n" +
20383     "            </div>  \n" +
20384     "        </div>\n" +
20385     "    </div>\n" +
20386     "   \n" +
20387     "    <div class=\"textAreaEmailContentDiv\">\n" +
20388     "        <span class=\"message\">Message</span>\n" +
20389     "        <textarea rows=\"4\" cols=\"50\" role=\"textarea\" class=\"textAreaEmailContent\" ng-model=\"emailMessage\">To send \n" +
20390     " a text, picture, or video message1 to a wireless device from your email:my message.</textarea>\n" +
20391     "        \n" +
20392     "    </div>\n" +
20393     "    \n" +
20394     "</div>\n" +
20395     "");
20396 }]);
20397
20398 angular.module("app/scripts/ng_js_att_tpls/verticalSteptracker/vertical-step-tracker.html", []).run(["$templateCache", function($templateCache) {
20399   $templateCache.put("app/scripts/ng_js_att_tpls/verticalSteptracker/vertical-step-tracker.html",
20400     "<li>\n" +
20401     "    <i ng-class=\"{'icon-tickets-active' : type == 'actual' && id =='Active','icon-tickets-referred' : type == 'actual' && id =='Requested Closed','icon-ticket-regular' : type == 'progress' && id =='In Progress','icon-tickets-contested' : type == 'actual' && id =='Contested','icon-tickets-returned' : type == 'actual' && id =='Deferred','icon-tickets-closed' : type == 'actual' && id =='Ready to Close','icon-tickets-cleared' : type == 'actual' && id =='Cleared'}\"></i>\n" +
20402     "    <span ng-transclude></span>\n" +
20403     "</li>\n" +
20404     "        \n" +
20405     "");
20406 }]);
20407
20408 angular.module("app/scripts/ng_js_att_tpls/videoControls/photoControls.html", []).run(["$templateCache", function($templateCache) {
20409   $templateCache.put("app/scripts/ng_js_att_tpls/videoControls/photoControls.html",
20410     "<div>\n" +
20411     "    <a title=\"{{links.prevLink}}\" aria-label=\"Previous Link\"  ng-href=\"{{links.prevLink}}\"><i alt=\"previous\" class=\"icon-arrow-left\">&nbsp;</i></a>\n" +
20412     "    <span ng-transclude></span>\n" +
20413     "    <a title=\"{{links.nextLink}}\" aria-label=\"Next Link\"  ng-href=\"{{links.nextLink}}\"><i alt=\"next\" class=\"icon-arrow-right\">&nbsp;</i></a>\n" +
20414     "</div>");
20415 }]);
20416
20417 angular.module("app/scripts/ng_js_att_tpls/videoControls/videoControls.html", []).run(["$templateCache", function($templateCache) {
20418   $templateCache.put("app/scripts/ng_js_att_tpls/videoControls/videoControls.html",
20419     "<div class=\"video-player\">\n" +
20420     "    <div class=\"video-player__control video-player__play-button\">\n" +
20421     "        <a class=\"video-player__button gigant-play\" data-toggle-buttons=\"icon-play, icon-pause\" data-target=\"i\"><i class=\"icon-play\"  alt=\"Play/Pause Button\"></i></a>\n" +
20422     "    </div>\n" +
20423     "    <div class=\"video-player__control video-player__track\">\n" +
20424     "\n" +
20425     "        <div class=\"video-player__track--inner\">\n" +
20426     "            <div class=\"video-player__track--loaded\" style=\"width: 75%\"></div>\n" +
20427     "            <div class=\"video-player__track--played\" style=\"width: 40%\">\n" +
20428     "                <div class=\"att-tooltip att-tooltip--on att-tooltip--dark att-tooltip--above video-player__track-tooltip\" ng-transclude></div>\n" +
20429     "                <div class=\"video-player__track-handle\"></div>\n" +
20430     "            </div>\n" +
20431     "        </div>\n" +
20432     "    </div>\n" +
20433     "    <a class=\"video-player__time\" ng-transclude></a>\n" +
20434     "    <div class=\"video-player__control video-player__volume_icon\">\n" +
20435     "        <a class=\"video-player__button\" data-toggle-buttons=\"icon-volume-mute, icon-volume-up\" data-target=\"i\"><i class=\"icon-volume-up\" alt=\"Volume Button\"></i></a>\n" +
20436     "    </div>\n" +
20437     "    <ul class=\"video-player__control video-player__volume\">\n" +
20438     "        <li class=\"video-player__volume-bar video-player__volume-bar--full\">&nbsp;</li>\n" +
20439     "        <li class=\"video-player__volume-bar video-player__volume-bar--full\">&nbsp;</li>\n" +
20440     "        <li class=\"video-player__volume-bar\">&nbsp;</li>\n" +
20441     "        <li class=\"video-player__volume-bar\">&nbsp;</li>\n" +
20442     "        <li class=\"video-player__volume-bar\">&nbsp;</li>\n" +
20443     "    </ul>\n" +
20444     "    <div class=\"video-player__control video-player__toggle-fullscreen-button\">\n" +
20445     "        <a class=\"video-player__button\" data-toggle-buttons=\"icon-full-screen, icon-normal-screen\" data-target=\"i\"><i class=\"icon-full-screen\" alt=\"Full Screen Button\">&nbsp;</i></a>\n" +
20446     "    </div>\n" +
20447     "</div>");
20448 }]);
20449
20450 return {}
20451 })(angular, window);