nexus site path corrected
[portal.git] / ecomp-portal-FE / client / bower_components_external / angular.att.abs-2.17.0 / 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
7887                         scope.setFocus = false;
7888
7889                         var handleKeydown = function (ev) {
7890                             var boolFlag = true;
7891                             switch (ev.keyCode)
7892                             {
7893                                 case keys.enter:
7894                                     ev.preventDefault();
7895                                     scope.toggle();
7896                                     scope.$apply();
7897                                     break;
7898                                 case keys.up:
7899                                 case keys.left:
7900                                     ev.preventDefault();
7901                                     accordionCtrl.cycle(scope, false);
7902                                     break;
7903                                 case keys.down:
7904                                 case keys.right:
7905                                     ev.preventDefault();
7906                                     accordionCtrl.cycle(scope, true);
7907                                     break;
7908                                 default:
7909                                     boolFlag = false;
7910                                     break;
7911                             }
7912                             ev.stopPropagation();
7913                             return boolFlag;
7914                         };
7915
7916                         if (angular.isUndefined(scope.isOpen)) {
7917                             scope.isOpen = false;
7918                         }
7919
7920                         tab.bind("keydown", handleKeydown);
7921
7922                         accordionCtrl.addGroup(scope);
7923
7924                         if (scope.index === 0) {
7925                             scope.focused = true;
7926                         }
7927
7928                         accordionGroupCtrl.toggle = scope.toggle = function () {
7929                             scope.isOpen = !scope.isOpen;
7930                             accordionCtrl.focus(scope);
7931                             return scope.isOpen;
7932                         };
7933
7934                         scope.$watch('isOpen', function (value) {
7935                             if (value) {
7936                                 accordionCtrl.closeOthers(scope);
7937                             }
7938                         });
7939
7940                         scope.$watch("focused", function (value) {
7941                             if (!!value) {
7942                                 tab.attr("tabindex", "0");
7943                                 if(scope.setFocus){
7944                                     tab[0].focus();
7945                                 }
7946                             }
7947                             else{
7948                                 scope.setFocus = false;
7949                                 tab.attr("tabindex", "-1");
7950                             }
7951                         });
7952                     }
7953                 };
7954             }])
7955 // Use accordion-heading below an accordion-group to provide a heading containing HTML
7956 // <accordion-group>
7957 //   <accordion-heading>Heading containing HTML - <img src="..."></accordion-heading>
7958 // </accordion-group>
7959         .directive('accordionToggle', function () {
7960             return{
7961                 restrict: 'EA',
7962                 require: '^accordionGroup',
7963                 scope: {
7964                     expandIcon: '@',
7965                     collapseIcon: '@'
7966                 },
7967                 link: function (scope, element, attr, accordionCtrl)
7968                 {
7969                     var setIcon = function (isOpen) {
7970                         if (scope.expandIcon && scope.collapseIcon)
7971                         {
7972                             if (isOpen) {
7973                                 element.removeClass(scope.expandIcon);
7974                                 element.addClass(scope.collapseIcon);
7975                             }
7976                             else {
7977                                 element.removeClass(scope.collapseIcon);
7978                                 element.addClass(scope.expandIcon);
7979                             }
7980                         }
7981                     };
7982                     element.bind('click', function ()
7983                     {
7984                         accordionCtrl.toggle();
7985                         scope.$apply();
7986                     });
7987                     scope.$watch(function () {
7988                         return accordionCtrl.isIsOpen();
7989                     }, function (value) {
7990                         setIcon(value);
7991                     });
7992                 }
7993             };
7994         }).directive('accordionHeading', function () {
7995     return {
7996         restrict: 'EA',
7997         transclude: true,
7998         template: '',
7999         require: '^accordionGroup',
8000         compile: function (element, attr, transclude) {
8001             var link = function (scope, element, attr, accordionGroupCtrl) {
8002                 // Pass the heading to the accordion-group controller
8003                 // so that it can be transcluded into the right place in the template
8004                 // [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat]
8005                 transclude(scope, function (clone) {
8006                     element.append(clone);
8007                     accordionGroupCtrl.setHeading(element);
8008                 });
8009             };
8010             return link;
8011         }
8012     };
8013 })
8014 // Use in the accordion-group template to indicate where you want the heading to be transcluded
8015 // You must provide the property on the accordion-group controller that will hold the transcluded element
8016         .directive('accordionTransclude', function () {
8017             return {
8018                 require: '^accordionGroup',
8019                 link: function (scope, element, attr, controller) {
8020                     scope.$watch(function () {
8021                         return controller[attr.accordionTransclude];
8022                     }, function (heading) {
8023                         if (heading) {
8024                             element.find("span").eq(0).prepend(heading);
8025                         }
8026                     });
8027                 }
8028             };
8029         })
8030         .directive('attGoTop', ['$scrollTo', function ($scrollTo) {
8031                 return {
8032                     restrict: 'A',
8033                     transclude: false,
8034                     link: function (scope, elem, attrs)
8035                     {
8036                         elem.bind('click', function ()
8037                         {
8038                             $scrollTo(0, attrs["attGoTop"]);
8039                         });
8040                     }
8041                 };
8042             }])
8043         .directive('attGoTo', ['$anchorScroll', '$location', function ($anchorScroll, $location) {
8044                 return {
8045                     restrict: 'A',
8046                     transclude: false,
8047                     link: function (scope, elem, attrs)
8048                     {
8049                         elem.bind('click', function ()
8050                         {
8051                             var newHash = attrs["attGoTo"];
8052                             if ($location.hash() !== newHash)
8053                             {
8054                                 $location.hash(attrs["attGoTo"]);
8055                             }
8056                             else
8057                             {
8058                                 $anchorScroll();
8059                             }
8060                         });
8061                     }
8062                 };
8063             }])
8064         .directive('freeStanding', function () {
8065             return {
8066                 restrict: 'EA',
8067                 transclude: true,
8068                 replace: true,
8069                 scope: true,
8070                 template: "<div><span class='att-accordion__freestanding' ng-show='showAccordion'></span>\n" +
8071                         "<div class='section-toggle'>\n" +
8072                         "<button class='section-toggle__button' ng-click='fsToggle()'>\n" +
8073                         "    {{btnText}}<i style='font-size:0.875rem' ng-class='{\"icon-chevron-up\": showAccordion,\"icon-chevron-down\": !showAccordion, }'></i> \n" +
8074                         "</button>\n" +
8075                         "</div></div>",
8076                 compile: function (element, attr, transclude)
8077                 {
8078                     var link = function (scope, elem, attrs) {
8079                         scope.content = "";
8080                         transclude(scope, function (clone)
8081                         {
8082                             elem.find("span").append(clone);
8083                         });
8084                         scope.showAccordion = false;
8085                         scope.btnText = scope.showAccordion ? attrs.hideMsg : attrs.showMsg;
8086                         scope.fsToggle = function ()
8087                         {
8088                             scope.showAccordion = !scope.showAccordion;
8089                             scope.btnText = scope.showAccordion ? attrs.hideMsg : attrs.showMsg;
8090                         };
8091                     };
8092                     return link;
8093                 }
8094             };
8095         }).directive('expanders', function () {
8096     return{
8097         restrict: 'EA',
8098         replace: true,
8099         transclude: true,
8100         template: "<div ng-transclude></div>",
8101         controller: ['$scope', function ($scope){
8102                 var bodyScope = null;
8103                 this.setScope = function (scope) {
8104                     bodyScope = scope;
8105                 };
8106                 this.toggle = function () {
8107                     $scope.isOpen = bodyScope.isOpen = !bodyScope.isOpen;
8108                     return bodyScope.isOpen;
8109                 };
8110             }],
8111         link: function (scope)
8112         {
8113             scope.isOpen = false;
8114         }
8115     };
8116 }).directive('expanderHeading', function () {
8117     return{
8118         require: "^expanders",
8119         restrict: 'EA',
8120         replace: true,
8121         transclude: true,
8122         scope: true,
8123         template: "<div style='padding:10px !important' ng-transclude></div>"
8124     };
8125 }).directive('expanderBody', function () {
8126     return{
8127         restrict: 'EA',
8128         require: "^expanders",
8129         replace: true,
8130         transclude: true,
8131         scope: {},
8132         template: "<div collapse='!isOpen'><div ng-transclude></div></div>",
8133         link: function (scope, elem, attr, myCtrl) {
8134             scope.isOpen = false;
8135             myCtrl.setScope(scope);
8136         }
8137     };
8138 }).directive('expanderToggle', function () {
8139     return{
8140         restrict: 'EA',
8141         require: "^expanders",
8142         scope: {
8143             expandIcon: '@',
8144             collapseIcon: '@'
8145         },
8146         link: function (scope, element, attr, myCtrl)
8147         {
8148             var isOpen = false;
8149             var setIcon = function () {
8150                 if (scope.expandIcon && scope.collapseIcon)
8151                 {
8152                     if (isOpen) {
8153                         element.removeClass(scope.expandIcon);
8154                         element.addClass(scope.collapseIcon);
8155                     }
8156                     else {
8157                         element.removeClass(scope.collapseIcon);
8158                         element.addClass(scope.expandIcon);
8159                     }
8160                 }
8161             };
8162             element.bind("keydown", function (e) {
8163                 if (e.keyCode === 13)
8164                 {
8165                     scope.toggleit();
8166                 }
8167             });
8168             element.bind('click', function ()
8169             {
8170                 scope.toggleit();
8171             });
8172             scope.toggleit = function ()
8173             {
8174                 isOpen = myCtrl.toggle();
8175                 setIcon();
8176                 scope.$apply();
8177             };
8178             setIcon();
8179         }
8180     };
8181 }).directive('collapse', ['$transition', function ($transition) {
8182         // CSS transitions don't work with height: auto, so we have to manually change the height to a
8183         // specific value and then once the animation completes, we can reset the height to auto.
8184         // Unfortunately if you do this while the CSS transitions are specified (i.e. in the CSS class
8185         // "collapse") then you trigger a change to height 0 in between.
8186         // The fix is to remove the "collapse" CSS class while changing the height back to auto - phew!
8187         var props = {
8188             open: {
8189                 marginTop: null,
8190                 marginBottom: null,
8191                 paddingTop: null,
8192                 paddingBottom: null,
8193                 display: 'block'
8194             },
8195             closed: {
8196                 marginTop: 0,
8197                 marginBottom: 0,
8198                 paddingTop: 0,
8199                 paddingBottom: 0,
8200                 display: 'none'
8201             }
8202         };
8203         var fixUpHeight = function (scope, element, height) {
8204             // We remove the collapse CSS class to prevent a transition when we change to height: auto
8205             element.removeClass('collapse');
8206             element.css({height: height});
8207             //adjusting for any margin or padding
8208             if (height === 0) {
8209                 element.css(props.closed);
8210             } else {
8211                 element.css(props.open);
8212             }
8213             // It appears that  reading offsetWidth makes the browser realise that we have changed the
8214             // height already :-/
8215             element.addClass('collapse');
8216         };
8217         return {
8218             link: function (scope, element, attrs) {
8219                 var isCollapsed;
8220                 var initialAnimSkip = true;
8221                 scope.$watch(function () {
8222                     return element[0].scrollHeight;
8223                 }, function () {
8224                     //The listener is called when scrollHeight changes
8225                     //It actually does on 2 scenarios:
8226                     // 1. Parent is set to display none
8227                     // 2. angular bindings inside are resolved
8228                     //When we have a change of scrollHeight we are setting again the correct height if the group is opened
8229                     if (element[0].scrollHeight !== 0 && !isCollapsed) {
8230                         if (initialAnimSkip) {
8231                             fixUpHeight(scope, element, element[0].scrollHeight + 'px');
8232                         } else {
8233                             fixUpHeight(scope, element, 'auto');
8234                         }
8235                     }
8236                 });
8237                 var currentTransition;
8238                 var doTransition = function (change) {
8239                     if (currentTransition) {
8240                         currentTransition.cancel();
8241                     }
8242                     currentTransition = $transition(element, change);
8243                     currentTransition.then(
8244                             function () {
8245                                 currentTransition = undefined;
8246                             },
8247                             function () {
8248                                 currentTransition = undefined;
8249                             }
8250                     );
8251                     return currentTransition;
8252                 };
8253                 var expand = function () {
8254                     scope.postTransition = true;
8255                     if (initialAnimSkip) {
8256                         initialAnimSkip = false;
8257                         if (!isCollapsed) {
8258                             fixUpHeight(scope, element, 'auto');
8259                         }
8260                     } else {
8261                         doTransition(angular.extend({height: element[0].scrollHeight + 'px'}, props.open))
8262                                 .then(function () {
8263                                     // This check ensures that we don't accidentally update the height if the user has closed
8264                                     // the group while the animation was still running
8265                                     if (!isCollapsed)
8266                                     {
8267                                         fixUpHeight(scope, element, 'auto');
8268                                     }
8269                                 });
8270                     }
8271                     isCollapsed = false;
8272                 };
8273                 var collapse = function () {
8274                     isCollapsed = true;
8275                     if (initialAnimSkip) {
8276                         initialAnimSkip = false;
8277                         fixUpHeight(scope, element, 0);
8278                     } else {
8279                         fixUpHeight(scope, element, element[0].scrollHeight + 'px');
8280                         doTransition(angular.extend({height: 0}, props.closed)).then(function () {
8281                             scope.postTransition = false;
8282                         });
8283                     }
8284                 };
8285                 scope.$watch(attrs.collapse, function (value) {
8286                     if (value) {
8287                         collapse();
8288                     } else {
8289                         expand();
8290                     }
8291                 });
8292             }
8293         };
8294     }])
8295         .directive('attAccord', function () {
8296             return {
8297                 restrict: 'EA',
8298                 transclude: true,
8299                 replace: true,
8300                 scope: {},
8301                 controller: 'AttAccordCtrl',
8302                 templateUrl: 'app/scripts/ng_js_att_tpls/accordion/attAccordHeader.html'
8303             };
8304         })
8305         .controller('AttAccordCtrl', [function () {
8306                 this.type = 'attAccord';
8307                 this.headerCtrl;
8308                 this.bodyCtrl;
8309                 var isOpen = true;
8310                 this.toggleBody = function () {
8311                     if (isOpen) {
8312                         this.expandBody();
8313                     }
8314                     else {
8315                         this.collapseBody();
8316                     }
8317                     isOpen = !isOpen;
8318                 };
8319                 this.expandBody = function () {
8320                     this.bodyCtrl.expand();
8321                 };
8322                 this.collapseBody = function () {
8323                     this.bodyCtrl.collapse();
8324                 };
8325             }])
8326         .controller('AttAccordHeaderCtrl', [function () {
8327                 this.type = 'header';
8328             }])
8329         .directive('attAccordHeader', ['keymap', 'events', function (keymap, events) {
8330             return {
8331                 restrict: 'EA',
8332                 transclude: true,
8333                 replace: true,
8334                 require: ['^attAccord', 'attAccordHeader'],
8335                 controller: 'AttAccordHeaderCtrl',
8336                 templateUrl: 'app/scripts/ng_js_att_tpls/accordion/attAccordHeader.html',
8337                 link: function (scope, element, attr, ctrls) {
8338                     var attAccordCtrl = ctrls[0];
8339                     var attAccordHeaderCtrl = ctrls[1];
8340                     attAccordCtrl.headerCtrl = attAccordHeaderCtrl;
8341                     var tab = element.children().eq(0);
8342                         
8343                     scope.clickFunc = function () {
8344                         attAccordCtrl.toggleBody();
8345                     };
8346
8347                     var handleKeydown = function (ev) {
8348                         var boolFlag = true;
8349                         switch (ev.keyCode)
8350                         {
8351                             case keymap.KEY.ENTER:
8352                                 ev.preventDefault();
8353                                 scope.clickFunc();
8354                                 scope.$apply();
8355                                 break;
8356                             default:
8357                                 boolFlag = false;
8358                                 break;
8359                         }
8360                         ev.stopPropagation();
8361                         return boolFlag;
8362                     };
8363                         
8364                     if (angular.isUndefined(scope.isOpen)) {
8365                         scope.isOpen = false;
8366                     }
8367
8368                     tab.bind("keydown", handleKeydown);
8369                 }
8370             };
8371         }])
8372         .controller('AttAccordBodyCtrl', ['$scope', function ($scope) {
8373                 this.type = 'body';
8374                 this.expand = function () {
8375                     $scope.expand();
8376                 };
8377                 this.collapse = function () {
8378                     $scope.collapse();
8379                 };
8380             }])
8381         .directive('attAccordBody', ['$timeout', '$height', function ($timeout, $height) {
8382                 return {
8383                     restrict: 'EA',
8384                     transclude: true,
8385                     replace: true,
8386                     require: ['^attAccord', 'attAccordBody'],
8387                     controller: 'AttAccordBodyCtrl',
8388                     templateUrl: 'app/scripts/ng_js_att_tpls/accordion/attAccordBody.html',
8389                     link: function (scope, element, attr, ctrls) {
8390                         var attAccordCtrl = ctrls[0];
8391                         var attAccordBodyCtrl = ctrls[1];
8392                         attAccordCtrl.bodyCtrl = attAccordBodyCtrl;
8393                         var originalHeight;
8394                         $timeout(function () {
8395                             originalHeight = element[0].offsetHeight;
8396                             $height(element, 0, 0, 0);
8397                         });
8398                         scope.expand = function () {
8399                             $height(element, 0.05, originalHeight, 1);
8400                         };
8401                         scope.collapse = function () {
8402                             $height(element, 0.25, 0, 0);
8403                         };
8404                     }
8405                 };
8406             }]);
8407 angular.module('att.abs.alert', [])
8408 .directive('attAlert', [function()
8409 {
8410     return {
8411         restrict:'EA',
8412         replace : true,
8413         transclude : true,
8414         scope: {
8415             alertType : "@type",
8416             showTop : "@topPos",
8417             showAlert : "="
8418         },
8419        templateUrl : 'app/scripts/ng_js_att_tpls/alert/alert.html',
8420        link: function(scope)
8421         {
8422             if(scope.showTop === 'true'){
8423                 scope.cssStyle = {'top':'50px'};
8424             }
8425             else{
8426                scope.cssStyle = {'top':'0px'};
8427             }
8428            scope.close = function(){
8429                scope.showAlert = false;
8430             };
8431         }
8432     };
8433 }]);
8434
8435 angular.module('att.abs.boardStrip', ['att.abs.utilities'])
8436 .constant('BoardStripConfig', {
8437     'maxVisibleBoards': 4,
8438     'boardsToScroll': 1,
8439     /* These parameters are non-configurable and remain unaltered, until there is a change in corresponding SCSS */
8440     'boardLength': 140,
8441     'boardMargin': 15
8442 })
8443 .directive('attBoard', [function() {
8444     return {
8445         restrict: 'AE',
8446         replace: true,
8447         transclude: true,
8448         require: '^attBoardStrip',
8449         scope : {
8450             boardIndex : '=',
8451             boardLabel : '='
8452         },
8453         templateUrl: 'app/scripts/ng_js_att_tpls/boardStrip/attBoard.html',
8454         link: function(scope, element, attrs, ctrls) {
8455
8456             var parentCtrl = ctrls;
8457
8458             scope.getCurrentIndex = function() {
8459                 return parentCtrl.getCurrentIndex();
8460             };
8461             scope.selectBoard = function(boardIndex) {
8462                 if (!isNaN(boardIndex)) {
8463                     parentCtrl.setCurrentIndex(boardIndex);
8464                 }
8465             };
8466             scope.isInView = function(boardIndex) {
8467                 return parentCtrl.isInView(boardIndex);
8468             };
8469         }
8470     };
8471 }])
8472 .directive('attBoardStrip', ['BoardStripConfig', '$timeout', '$ieVersion', function(BoardStripConfig, $timeout, $ieVersion) {
8473     return {
8474         restrict: 'AE',
8475         replace: true,
8476         transclude: true,
8477         scope: {
8478             currentIndex: '=selectedIndex',
8479             boardsMasterArray : '=',
8480             onAddBoard : '&?'
8481         },
8482         templateUrl: 'app/scripts/ng_js_att_tpls/boardStrip/attBoardStrip.html',
8483         controller: function($scope) {
8484             if(!angular.isDefined($scope.boardsMasterArray)){
8485                 $scope.boardsMasterArray = [];
8486             }
8487
8488             this.rectifyMaxVisibleBoards = function() {
8489                 if (this.maxVisibleIndex >= $scope.boardsMasterArray.length) {
8490                     this.maxVisibleIndex = $scope.boardsMasterArray.length - 1;
8491                 }
8492
8493                 if (this.maxVisibleIndex < 0) {
8494                     this.maxVisibleIndex = 0;
8495                 }
8496             };
8497
8498             this.resetBoardStrip = function(){
8499                 $scope.currentIndex = 0;
8500
8501                 this.maxVisibleIndex = BoardStripConfig.maxVisibleBoards-1;
8502                 this.minVisibleIndex = 0;
8503
8504                 this.rectifyMaxVisibleBoards();
8505             };
8506
8507
8508             if ($scope.currentIndex > 0) {
8509                 var index = $scope.currentIndex;
8510                 this.resetBoardStrip();
8511                 if (index > $scope.boardsMasterArray.length) {
8512                     $scope.currentIndex = $scope.boardsMasterArray.length-1;
8513                 } else {
8514                     $scope.currentIndex = index;
8515                 }
8516             } else {
8517                 this.resetBoardStrip();
8518             }
8519             
8520
8521             this.getCurrentIndex = function() {
8522                 return $scope.currentIndex;
8523             };
8524             this.setCurrentIndex = function(indx) {
8525                 $scope.currentIndex = indx;
8526             };
8527
8528             this.isInView = function(index) {
8529                 return (index <= this.maxVisibleIndex && index >= this.minVisibleIndex);
8530             };
8531
8532             this.getBoardsMasterArrayLength = function() {
8533                 return $scope.boardsMasterArray.length;
8534             };
8535         },
8536         link: function(scope, element, attrs, ctrl) {
8537                         var ieVersion = $ieVersion();
8538
8539                         var oldTimeout;
8540                         var animationTimeout = 1000;
8541                         
8542                         if(ieVersion && ieVersion < 10) {
8543                                 animationTimeout = 0;
8544                         }
8545
8546                         var getBoardViewportWidth = function (numberOfVisibleBoards) {
8547                                 return numberOfVisibleBoards * (BoardStripConfig.boardLength + BoardStripConfig.boardMargin);
8548                         };
8549                         if(element[0].querySelector(".board-viewport")) {
8550                                 angular.element(element[0].querySelector(".board-viewport")).css({"width": getBoardViewportWidth(BoardStripConfig.maxVisibleBoards) + "px"});
8551                         }
8552
8553                         var getBoardstripContainerWidth = function (totalNumberOfBoards) {
8554                                 return totalNumberOfBoards * (BoardStripConfig.boardLength + BoardStripConfig.boardMargin);
8555                         };
8556                         if(element[0].querySelector(".boardstrip-container")) {
8557                                 angular.element(element[0].querySelector(".boardstrip-container")).css({"width": getBoardstripContainerWidth(ctrl.getBoardsMasterArrayLength()) + "px"});
8558                                 angular.element(element[0].querySelector(".boardstrip-container")).css({"left": "0px"});
8559                         }
8560
8561                         var calculateAndGetBoardstripContainerAdjustment = function () {
8562
8563                                 var calculatedAdjustmentValue;
8564
8565                                 if(ctrl.getBoardsMasterArrayLength() <= BoardStripConfig.maxVisibleBoards) {
8566                                         calculatedAdjustmentValue = 0;
8567                                 }
8568                                 else{
8569                                         calculatedAdjustmentValue = (ctrl.minVisibleIndex * (BoardStripConfig.boardLength + BoardStripConfig.boardMargin))* -1;
8570                                 }
8571                                 
8572                                 return calculatedAdjustmentValue;
8573                         };
8574
8575             var updateBoardsTabIndex = function(boardArray, minViewIndex, maxViewIndex) {
8576                 for (var i = 0; i < boardArray.length; i++) {
8577                     angular.element(boardArray[i]).attr('tabindex', '-1');
8578                 }
8579                 for (var i = minViewIndex; i <= maxViewIndex; i++) {
8580                     angular.element(boardArray[i]).attr('tabindex', '0');
8581                 }
8582             };
8583                         
8584             scope.$watchCollection('boardsMasterArray', function(newVal, oldVal){
8585                 if(newVal !== oldVal){
8586                                         /* When a board is removed */
8587                                         if(newVal.length < oldVal.length){
8588                                                 ctrl.resetBoardStrip();
8589                                                 $timeout(function(){
8590                                                         
8591                                                         var currentBoardArray = element[0].querySelectorAll('[att-board]');
8592                                                         if(currentBoardArray.length !== 0) {
8593
8594                                                                 var oldContainerAdjustment = angular.element(element[0].querySelector(".boardstrip-container"))[0].style.left;
8595                                                                 var containerAdjustment = calculateAndGetBoardstripContainerAdjustment();
8596                                                                 if(oldContainerAdjustment !== containerAdjustment+'px') {
8597                                                                         angular.element(element[0].querySelector(".boardstrip-container")).css({"left": containerAdjustment + "px"});
8598
8599                                                                         $timeout.cancel(oldTimeout);
8600                                                                         oldTimeout = $timeout(function(){
8601                                                                                 currentBoardArray[0].focus();
8602                                                                         }, animationTimeout);
8603                                                                 }
8604                                                                 else{
8605                                                                         currentBoardArray[0].focus();
8606                                                                 }
8607                                                         }
8608                                                         else{
8609                                                                 element[0].querySelector('div.boardstrip-item--add').focus();
8610                                                         }
8611                                                         
8612                                                         angular.element(element[0].querySelector(".boardstrip-container")).css({"width": getBoardstripContainerWidth(ctrl.getBoardsMasterArrayLength()) + "px"});
8613                                                 });
8614                                         }
8615                                         /* When a board is added */
8616                                         else {
8617                                                 ctrl.maxVisibleIndex = ctrl.getBoardsMasterArrayLength()-1;
8618                                                 ctrl.minVisibleIndex = Math.max(ctrl.maxVisibleIndex - BoardStripConfig.maxVisibleBoards + 1, 0);
8619
8620                                                 ctrl.setCurrentIndex(ctrl.maxVisibleIndex);
8621
8622                                                 $timeout(function(){
8623                                                         angular.element(element[0].querySelector(".boardstrip-container")).css({"width": getBoardstripContainerWidth(ctrl.getBoardsMasterArrayLength()) + "px"});
8624                                                         
8625                                                         var oldContainerAdjustment = angular.element(element[0].querySelector(".boardstrip-container"))[0].style.left;
8626                                                         var containerAdjustment = calculateAndGetBoardstripContainerAdjustment();
8627                                                         var currentBoardArray = element[0].querySelectorAll('[att-board]');
8628                                                         if(oldContainerAdjustment !== containerAdjustment+'px') {
8629                                                                 angular.element(element[0].querySelector(".boardstrip-container")).css({"left": containerAdjustment + "px"});
8630                                                                 
8631                                                                 $timeout.cancel(oldTimeout);
8632                                                                 oldTimeout = $timeout(function(){
8633                                                                         currentBoardArray[currentBoardArray.length-1].focus();
8634                                                                 }, animationTimeout);
8635                                                         }
8636                                                         else{
8637                                                                 currentBoardArray[currentBoardArray.length-1].focus();
8638                                                         }
8639                             /* Update tabindecies to ensure keyboard navigation behaves correctly */
8640                             updateBoardsTabIndex(currentBoardArray, ctrl.minVisibleIndex, ctrl.maxVisibleIndex);
8641                                                 });
8642                                         }
8643                 }
8644             });
8645
8646             scope.nextBoard = function() {
8647                 ctrl.maxVisibleIndex += BoardStripConfig.boardsToScroll;
8648                 ctrl.rectifyMaxVisibleBoards();
8649                 ctrl.minVisibleIndex = ctrl.maxVisibleIndex - (BoardStripConfig.maxVisibleBoards-1);
8650
8651                                 $timeout.cancel(oldTimeout);
8652                                 angular.element(element[0].querySelector(".boardstrip-container")).css({"left": calculateAndGetBoardstripContainerAdjustment() + "px"});
8653
8654                 $timeout(function(){
8655                     var currentBoardArray = element[0].querySelectorAll('[att-board]');
8656
8657                     /* Remove tabindex from non-visible boards */
8658                     updateBoardsTabIndex(currentBoardArray, ctrl.minVisibleIndex, ctrl.maxVisibleIndex);
8659
8660                     if (!(scope.isNextBoard())) {
8661                         try {
8662                             currentBoardArray[currentBoardArray.length-1].focus();
8663                         } catch(e) {}
8664                     }
8665                 }, animationTimeout);
8666             };
8667             scope.prevBoard = function() {
8668
8669                 ctrl.minVisibleIndex -= BoardStripConfig.boardsToScroll;
8670                 if (ctrl.minVisibleIndex < 0) {
8671                     ctrl.minVisibleIndex = 0;
8672                 }
8673
8674                 ctrl.maxVisibleIndex = ctrl.minVisibleIndex + BoardStripConfig.maxVisibleBoards-1;
8675                 ctrl.rectifyMaxVisibleBoards();
8676
8677                                 $timeout.cancel(oldTimeout);
8678                                 angular.element(element[0].querySelector(".boardstrip-container")).css({"left": calculateAndGetBoardstripContainerAdjustment() + "px"});
8679
8680                 $timeout(function(){
8681                     var currentBoardArray = element[0].querySelectorAll('[att-board]');
8682
8683                     /* Remove tabindex from non-visible boards */
8684                     updateBoardsTabIndex(currentBoardArray, ctrl.minVisibleIndex, ctrl.maxVisibleIndex);
8685
8686                     if (ctrl.minVisibleIndex === 0) {
8687                         try {
8688                             element[0].querySelector('div.boardstrip-item--add').focus();
8689                         } catch (e) {} /* IE8 may throw exception */
8690                     }
8691                 });
8692             };
8693
8694             scope.isPrevBoard = function() {
8695                 return (ctrl.minVisibleIndex > 0);
8696             };
8697             scope.isNextBoard = function() {
8698                 return (ctrl.getBoardsMasterArrayLength()-1 > ctrl.maxVisibleIndex);
8699             };
8700         }
8701     };
8702 }])
8703 .directive('attAddBoard', ['BoardStripConfig', '$parse', '$timeout', function(BoardStripConfig, $parse, $timeout) {
8704     return {
8705         restrict: 'AE',
8706         replace: true,
8707         require: '^attBoardStrip',
8708         scope : {
8709             onAddBoard : '&?'
8710         },
8711         templateUrl: 'app/scripts/ng_js_att_tpls/boardStrip/attAddBoard.html',
8712         link: function(scope, element, attrs, ctrls) {
8713             var parentCtrl = ctrls;
8714             scope.addBoard = function() {
8715                 if (attrs['onAddBoard'] ) {
8716                     scope.onAddBoard = $parse(scope.onAddBoard);
8717                     scope.onAddBoard();
8718                 }
8719             };
8720         }
8721     };
8722 }])
8723 .directive('attBoardNavigation', ['keymap', 'events', function(keymap, events) {
8724     return {
8725         restrict: 'AE',
8726         link: function(scope, elem) {
8727
8728             var prevElem = keymap.KEY.LEFT;
8729             var nextElem = keymap.KEY.RIGHT;
8730
8731             elem.bind('keydown', function (ev) {
8732
8733                 if (!(ev.keyCode)) {
8734                     ev.keyCode = ev.which;
8735                 }
8736
8737                 switch (ev.keyCode) {
8738                 case nextElem:
8739                     events.preventDefault(ev);
8740                     events.stopPropagation(ev);
8741
8742                     if (elem[0].nextElementSibling && parseInt(angular.element(elem[0].nextElementSibling).attr('tabindex')) >= 0) {
8743                         angular.element(elem[0])[0].nextElementSibling.focus();
8744                     } else {
8745                         /* IE8 fix */
8746                         var el = angular.element(elem[0])[0];
8747                         do {
8748                             if (el.nextSibling){
8749                                 el = el.nextSibling;
8750                             }
8751                             else{
8752                                 break;
8753                             }
8754                         } while (el && el.tagName !== 'LI');
8755
8756                         if (el.tagName && el.tagName === 'LI' && parseInt(angular.element(el).attr('tabindex')) >= 0){
8757                             el.focus();
8758                         }
8759                     }
8760
8761                     break;
8762                 case prevElem:
8763                     events.preventDefault(ev);
8764                     events.stopPropagation(ev);
8765
8766                     if (elem[0].previousElementSibling && parseInt(angular.element(elem[0].previousElementSibling).attr('tabindex')) >= 0) {
8767                         angular.element(elem[0])[0].previousElementSibling.focus();
8768                     } else {
8769                         /* IE8 fix */
8770                         var el1 = angular.element(elem[0])[0];
8771                         do {
8772                             if (el1.previousSibling){
8773                                 el1 = el1.previousSibling;
8774                             }
8775                             else{
8776                                 break;
8777                             }
8778                         } while (el1 && el1.tagName !== 'LI');
8779
8780                         if (el1.tagName && el1.tagName === 'LI' && parseInt(angular.element(el).attr('tabindex')) >= 0){
8781                             el1.focus();
8782                         }
8783                     }
8784                     break;
8785                 default:
8786                     break;
8787                 }
8788             });
8789         }
8790     };
8791 }]);
8792
8793 angular.module('att.abs.breadCrumbs', [])
8794     .constant("classConstant",{
8795             "defaultClass" : "breadcrumbs__link",
8796             "activeClass": "breadcrumbs__link--active"
8797         })
8798     .directive('attCrumb', ['classConstant', function(classConstant) {
8799         return {
8800             restrict: 'A',
8801             link: function(scope, elem, attr) {
8802                 elem.addClass(classConstant.defaultClass);
8803                 if(attr.attCrumb === 'active'){
8804                      elem.addClass(classConstant.activeClass);
8805                 }
8806                if(!elem.hasClass('last')){
8807                    elem.after('<i class="breadcrumbs__item"></i>');
8808                }
8809             }
8810         };
8811     }
8812 ]);
8813 angular.module('att.abs.buttons', ['att.abs.position', 'att.abs.utilities'])
8814         .constant('btnConfig', {
8815             btnClass: 'button',
8816             btnPrimaryClass: 'button--primary',
8817             btnSecondaryClass: 'button--secondary',
8818             btnDisabledClass: 'button--inactive',
8819             btnSmallClass: 'button--small'
8820         })
8821         .directive('attButton', ['btnConfig', function (btnConfig) {
8822                 return {
8823                     restrict: 'A',
8824                     link: function (scope, element, attrs) {
8825                         element.addClass(btnConfig.btnClass);
8826                         if (attrs.size === 'small') {
8827                             element.addClass(btnConfig.btnSmallClass);
8828                         }
8829                         attrs.$observe('btnType', function (value) {
8830                             if (value === 'primary') {
8831                                 element.addClass(btnConfig.btnPrimaryClass);
8832                                 element.removeClass(btnConfig.btnSecondaryClass);
8833                                 element.removeClass(btnConfig.btnDisabledClass);
8834                                 element.removeAttr('disabled');
8835                             } else if (value === 'secondary') {
8836                                 element.addClass(btnConfig.btnSecondaryClass);
8837                                 element.removeClass(btnConfig.btnPrimaryClass);
8838                                 element.removeClass(btnConfig.btnDisabledClass);
8839                                 element.removeAttr('disabled');
8840                             } else if (value === 'disabled') {
8841                                 element.addClass(btnConfig.btnDisabledClass);
8842                                 element.removeClass(btnConfig.btnPrimaryClass);
8843                                 element.removeClass(btnConfig.btnSecondaryClass);
8844                                 element.attr('disabled', 'disabled');
8845                             }
8846                         });
8847                     }
8848                 };
8849             }])
8850         .directive('attButtonLoader', [function () {
8851                 return {
8852                     restrict: 'A',
8853                     replace: false,
8854                     scope: {
8855                         size: '@'
8856                     },
8857                     template: '<div ng-class="{\'button--loading\': size === \'large\',\'button--loading__small\': size === \'small\'}"><i></i><i class="second__loader"></i><i></i></div>',
8858                     link: function (scope, element) {
8859                         element.addClass('button button--inactive');
8860                     }
8861                 };
8862             }])
8863         .directive('attButtonHero', [function () {
8864                 return {
8865                     restrict: 'A',
8866                     replace: false,
8867                     transclude: true,
8868                     scope: {
8869                         icon: '@'
8870                     },
8871                     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>',
8872                     link: function (scope, element) {
8873                         element.addClass('button button--hero');
8874                         element.attr("tabindex", "0");
8875                     }
8876                 };
8877             }])
8878         .directive('attBtnDropdown', ['$document', '$timeout', '$isElement', '$documentBind', 'keymap', 'events', function ($document, $timeout, $isElement, $documentBind, keymap, events) {
8879                 return {
8880                     restrict: 'EA',
8881                     scope: {
8882                         type: "@dropdowntype"
8883                     },
8884                     replace: true,
8885                     transclude: true,
8886                     templateUrl: 'app/scripts/ng_js_att_tpls/buttons/buttonDropdown.html',
8887                     link: function (scope, element) {
8888                         scope.isOpen = false;
8889                         var currentIndex = -1;
8890                         // Capture all the li elements after compilation
8891                         var list = [], button = undefined;
8892                         $timeout(function() {
8893                             list = element.find('li');
8894                             button = element.find('button')[0];
8895                         }, 10);
8896                         var toggle = scope.toggle = function (show) {
8897                             if (angular.isUndefined(show) || show === '') {
8898                                 scope.isOpen = !scope.isOpen;
8899                             }
8900                             else {
8901                                 scope.isOpen = show;
8902                             }
8903                         };
8904                         var selectNext = function() {
8905                             if (currentIndex+1 < list.length) {
8906                                 currentIndex++;
8907                                 list[currentIndex].focus();
8908                             }
8909                         };
8910                         var selectPrev = function() {
8911                             if (currentIndex-1 >= 0) {
8912                                 currentIndex--;
8913                                 list[currentIndex].focus();
8914                             }
8915                         };
8916                         element.bind("keydown", function($event) {
8917                             var keyCode = $event.keyCode;
8918                             if (keymap.isAllowedKey(keyCode) || keymap.isControl($event) || keymap.isFunctionKey($event)) {
8919                                 switch (keyCode) {
8920                                     case keymap.KEY.ENTER:
8921                                         if (currentIndex > 0) {
8922                                             button.focus();
8923                                             scope.$apply();
8924                                         }
8925                                         break;
8926                                     case keymap.KEY.ESC:
8927                                         toggle(false);
8928                                         currentIndex = -1;
8929                                         button.focus();
8930                                         scope.$apply();
8931                                         break;
8932                                     case keymap.KEY.DOWN:
8933                                         selectNext();
8934                                         scope.$apply();
8935                                         events.preventDefault($event);
8936                                         events.stopPropagation($event);
8937                                         break;
8938                                     case keymap.KEY.UP:
8939                                         selectPrev();
8940                                         scope.$apply();
8941                                         events.preventDefault($event);
8942                                         events.stopPropagation($event);
8943                                         break;
8944                                     default:
8945                                         break;
8946                                 }
8947                             } else if (keyCode === keymap.KEY.TAB) {
8948                                 toggle(false);
8949                                 currentIndex = -1;
8950                                 scope.$apply();
8951                             }
8952                         });
8953                         var outsideClick = function (e) {
8954                             var isElement = $isElement(angular.element(e.target), element, $document);
8955                             if (!isElement) {
8956                                 toggle(false);
8957                                 currentIndex = -1;
8958                                 for (var i = 0; i < list.length; i++) {
8959                                     angular.element(list[i]).removeClass('selected');
8960                                 }
8961                                 button.focus();
8962                                 scope.$apply();
8963                             }
8964                         };
8965                         $documentBind.click('isOpen', outsideClick, scope);
8966                     }
8967                 };
8968             }]);
8969 angular.module('att.abs.checkbox', [])
8970 .constant("attCheckboxConfig", {
8971     activeClass : "att-checkbox--on",
8972     disabledClass : "att-checkbox--disabled"
8973 })
8974 .directive('checkboxLimit', function () {
8975 return {
8976     scope: {
8977         checkboxLimit:'=',
8978         selectLimit:'@?',
8979         maxSelected:'&?'
8980     },
8981     restrict: 'A',
8982     require:'checkboxLimit',
8983     controller: ['$scope',function($scope)
8984     {
8985         $scope.limit=true;
8986         this.getMaxLimits=function(){
8987             return $scope.limit;
8988         };
8989         this.setMaxLimits=function(value){
8990             $scope.limit=value;
8991         };
8992         this.maxCheckboxSelected=function(){
8993             $scope.maxSelected();
8994         };
8995     }],
8996     link: function (scope, element, attribute, ctrl) {
8997         scope.$watch('checkboxLimit', function()
8998         {
8999             var countTrue = 0;
9000             for (var keys in scope.checkboxLimit) {
9001                 if (scope.checkboxLimit.hasOwnProperty(keys) && scope.checkboxLimit[keys]) {
9002                         countTrue = countTrue + 1;
9003                 }
9004             };
9005             if(countTrue>=parseInt(scope.selectLimit)){
9006                 ctrl.setMaxLimits(false);
9007             }
9008             else{
9009                 ctrl.setMaxLimits(true);
9010             }
9011             }, true);
9012     }
9013 };
9014 })
9015 .directive('attCheckbox', ['$compile', "attCheckboxConfig", function ($compile, attCheckboxConfig) {
9016     return {
9017         scope: {},
9018         restrict: 'A',
9019         require: ['ngModel','^?checkboxLimit'],
9020         link: function (scope, element, attribute, ctrl) {
9021             var ngCtrl = ctrl[0];
9022             var checkboxLimitCtrl = ctrl[1];
9023             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);
9024             element.css({display:'none'});
9025             element.wrap(parentDiv);
9026             element.parent().append('<div class="att-checkbox__indicator"></div>');
9027             element.parent().attr("title", attribute.title);
9028             element.parent().attr("aria-label", attribute.title);
9029             element.parent().attr("id", attribute.id);
9030             element.removeAttr("id");
9031             //element.removeAttr("title");
9032             //model -> UI
9033             ngCtrl.$render = function () {
9034                 var selected = ngCtrl.$modelValue ? true : false;
9035                 element.parent().toggleClass(attCheckboxConfig.activeClass, selected);
9036                 element.parent().attr("aria-checked", selected);
9037             };
9038
9039             //ui->model
9040             scope.updateModel = function (evt) {
9041                 if (!scope.disabled) {
9042                     ngCtrl.$setViewValue(element.parent().hasClass(attCheckboxConfig.activeClass) ? false : true);
9043                     if(checkboxLimitCtrl && !(checkboxLimitCtrl.getMaxLimits())){
9044                         if(!ngCtrl.$modelValue){
9045                             ngCtrl.$render();
9046                         }
9047                         else{
9048                             checkboxLimitCtrl.maxCheckboxSelected();
9049                             ngCtrl.$setViewValue(element.parent().hasClass(attCheckboxConfig.activeClass) ? true : false);
9050                         }
9051                     }
9052                     else{
9053                         ngCtrl.$render();
9054                     }
9055                 }
9056                 evt.preventDefault();
9057             };
9058
9059             attribute.$observe('disabled', function(val) {
9060                 scope.disabled = (val || val === "disabled" || val === "true");
9061                 element.parent().toggleClass(attCheckboxConfig.disabledClass, scope.disabled);
9062                 element.parent().attr("tabindex", scope.disabled ? "-1" : "0");
9063             });
9064         }
9065     };
9066 }])
9067 .directive('checkboxGroup', ['$compile',function($compile) {
9068     return {
9069         scope:{
9070             checkboxGroup: "=",
9071             checkboxGroupValue: "=?"
9072         },
9073         restrict: 'A',
9074         link: function(scope, element, attribute){
9075                 scope.checkboxState = 'none';
9076                 if (scope.checkboxGroupValue === undefined) {
9077                     scope.checkboxGroupValue = "indeterminate";
9078                 }
9079                 element.css({display:'none'});
9080                 element.wrap($compile('<div tabindex="0" role="checkbox" att-accessibility-click="13,32" ng-click="updateModel($event)" class="att-checkbox"></div>')(scope));
9081                 element.parent().append('<div class="att-checkbox__indicator"></div>');
9082                 element.parent().attr("title", attribute.title);
9083                 element.parent().attr("aria-label", attribute.title);
9084                 scope.$watch('checkboxState', function(val) {
9085                     if (val === 'all') {
9086                         element.parent().addClass('att-checkbox--on');
9087                         element.parent().removeClass('att-checkbox--indeterminate');
9088                         element.parent().attr("aria-checked", true);
9089                     }
9090                     else if (val === 'none') {
9091                         element.parent().removeClass('att-checkbox--on');
9092                         element.parent().removeClass('att-checkbox--indeterminate');
9093                         element.parent().attr("aria-checked", false);
9094                     }
9095                     else if (val === 'indeterminate') {
9096                         element.parent().removeClass('att-checkbox--on');
9097                         element.parent().addClass('att-checkbox--indeterminate');
9098                         element.parent().attr("aria-checked", true);
9099                     }
9100                 });
9101                 scope.updateModel = function(evt){
9102                     if (element.parent().hasClass('att-checkbox--on')) {
9103                             element.parent().removeClass('att-checkbox--on');
9104                             for (var keys in scope.checkboxGroup) {
9105                                 if (scope.checkboxGroup.hasOwnProperty(keys)) {
9106                                     scope.checkboxGroup[keys] = false;
9107                                 }
9108                             };
9109                             }
9110                     else {
9111                         element.parent().addClass('att-checkbox--on');
9112                         for (var key in scope.checkboxGroup) {
9113                             if (scope.checkboxGroup.hasOwnProperty(key)) {
9114                                 scope.checkboxGroup[key] = true;
9115                             }
9116                         };
9117                     }
9118                     evt.preventDefault();
9119                 };
9120                 scope.$watch('checkboxGroupValue', function (value) {
9121                     if (value===false) {
9122                             element.parent().removeClass('att-checkbox--on');
9123                             for (var keys in scope.checkboxGroup) {
9124                                 if (scope.checkboxGroup.hasOwnProperty(keys)) {
9125                                         scope.checkboxGroup[keys] = false;
9126                                 }
9127                             };
9128                             }
9129                     else if (value === true){
9130                         element.parent().addClass('att-checkbox--on');
9131                         for (var key in scope.checkboxGroup) {
9132                             if (scope.checkboxGroup.hasOwnProperty(key)) {
9133                                     scope.checkboxGroup[key] = true;
9134                             }
9135                         };
9136                     }
9137                 });
9138             scope.$watch('checkboxGroup', function(){
9139                 var countTrue = 0;
9140                 var countFalse = 0;
9141                 var count = 0;
9142                 for (var keys in scope.checkboxGroup) {
9143                     if (scope.checkboxGroup.hasOwnProperty(keys)) {
9144                         count = count + 1;
9145                         if (scope.checkboxGroup[keys]) {
9146                             countTrue = countTrue + 1;
9147                         }
9148                         else if (!scope.checkboxGroup[keys]) {
9149                             countFalse = countFalse + 1;
9150                         }
9151                     }
9152                 };
9153                 if (count === countTrue) {
9154                     scope.checkboxState = "all";
9155                      scope.checkboxGroupValue=true;
9156                 }
9157                 else if (count === countFalse) {
9158                     scope.checkboxState = "none";
9159                     scope.checkboxGroupValue=false;
9160                 }
9161                 else {
9162                     scope.checkboxState = "indeterminate";
9163                     scope.checkboxGroupValue="indeterminate";
9164                 }
9165                 }, true);
9166         }
9167     };
9168 }]);
9169
9170 angular.module('att.abs.colorselector', [])
9171     .directive('colorSelectorWrapper', [function() {
9172         return {
9173             scope: {
9174                 selected: '=',
9175                 iconColor: '@'
9176                 
9177             },
9178             restrict: 'AE',
9179             transclude: true,
9180             templateUrl: 'app/scripts/ng_js_att_tpls/colorselector/colorselector.html',
9181             link: function(scope) {
9182                 scope.applycolor = {'background-color': scope.iconColor};
9183                 scope.selectedcolor = function(iconColor) {
9184                     scope.selected = iconColor;
9185                 };
9186             }
9187         };
9188      }])
9189     .directive('colorSelector', ['$compile', function($compile) {
9190         return{
9191             restrict: 'A',
9192             scope: {
9193                 colorSelector: '@',                
9194                 ngModel: '='
9195             },
9196             link: function(scope, element, attr) {
9197                 element.removeAttr('color-selector');
9198                 var colorTitle = attr.title;
9199                 var wrapcont = angular.element('<color-selector-wrapper selected="ngModel" title="' + colorTitle + '" icon-color="{{colorSelector}}">' + element.prop('outerHTML') + '</color-selector-wrapper>');
9200                 var newWrapcont = $compile(wrapcont)(scope);
9201                 element.replaceWith(newWrapcont);
9202             }
9203         };
9204     }]);
9205 angular.module('att.abs.datepicker', ['att.abs.position', 'att.abs.utilities'])
9206
9207 .constant('datepickerConfig', {
9208     dateFormat: 'MM/dd/yyyy',
9209     dayFormat: 'd',
9210     monthFormat: 'MMMM',
9211     yearFormat: 'yyyy',
9212     dayHeaderFormat: 'EEEE',
9213     dayTitleFormat: 'MMMM yyyy',
9214     disableWeekend: false,
9215     disableSunday: false,
9216     startingDay: 0,
9217     minDate: null,
9218     maxDate: null,
9219     mode: 0,
9220     dateFilter: {
9221         defaultText: 'Select from list'
9222     },
9223     datepickerEvalAttributes: ['dateFormat', 'dayFormat', 'monthFormat', 'yearFormat', 'dayHeaderFormat', 'dayTitleFormat', 'disableWeekend', 'disableSunday', 'startingDay', 'mode'],
9224     datepickerWatchAttributes: ['min', 'max']
9225 })
9226
9227 .factory('datepickerService', ['datepickerConfig', 'dateFilter', function (datepickerConfig, dateFilter) {
9228     var setAttributes = function (attr, elem) {
9229         if (angular.isDefined(attr) && attr !== null && angular.isDefined(elem) && elem !== null) {
9230             var attributes = datepickerConfig.datepickerEvalAttributes.concat(datepickerConfig.datepickerWatchAttributes);
9231             for (var key in attr) {
9232                 var val = attr[key];
9233                 if (attributes.indexOf(key) !== -1 && angular.isDefined(val)) {
9234                     elem.attr(key.toSnakeCase(), key);
9235                 }
9236             }
9237         }
9238     };
9239
9240     var bindScope = function (attr, scope) {
9241         if (angular.isDefined(attr) && attr !== null && angular.isDefined(scope) && scope !== null) {
9242             var evalFunction = function (key, val) {
9243                 scope[key] = scope.$parent.$eval(val);
9244             };
9245
9246             var watchFunction = function (key, val) {
9247                 scope.$parent.$watch(val, function (value) {
9248                     scope[key] = value;
9249                 });
9250                 scope.$watch(key, function (value) {
9251                     scope.$parent[val] = value;
9252                 });
9253             };
9254
9255             var evalAttributes = datepickerConfig.datepickerEvalAttributes;
9256             var watchAttributes = datepickerConfig.datepickerWatchAttributes;
9257             for (var key in attr) {
9258                 var val = attr[key];
9259                 if (evalAttributes.indexOf(key) !== -1 && angular.isDefined(val)) {
9260                     evalFunction(key, val);
9261                 } else if (watchAttributes.indexOf(key) !== -1 && angular.isDefined(val)) {
9262                     watchFunction(key, val);
9263                 }
9264             }
9265         }
9266     };
9267
9268     var validateDateString = function (dateString, dateFormat) {
9269         if (dateString && dateFormat) {
9270             var delimiter;
9271             if (dateFormat.indexOf('/') !== -1) {
9272                 delimiter = '/';
9273             } else if (dateFormat.indexOf('-') !== -1) {
9274                 delimiter = '-';
9275             } else if (dateFormat.indexOf('.') !== -1) {
9276                 delimiter = '.';
9277             }
9278
9279             var dateStringArray = dateString.split(delimiter);
9280             var dateFormatArray = dateFormat.split(delimiter);
9281             if (dateStringArray.length !== dateFormatArray.length) {
9282                 return false;
9283             }
9284
9285             for (var i = 0; i < dateStringArray.length; i++) {
9286                 dateStringArray[i] = dateStringArray[i].lPad(dateFormatArray[i].length, '0');
9287             }
9288             var intermediateDateString = dateStringArray.join(delimiter);
9289
9290             var actualDateString = dateFilter(new Date(intermediateDateString), dateFormat);
9291             return intermediateDateString === actualDateString;
9292         }
9293     };
9294
9295     return {
9296         setAttributes: setAttributes,
9297         bindScope: bindScope,
9298         validateDateString: validateDateString
9299     };
9300 }])
9301
9302 .controller('DatepickerController', ['$scope', '$attrs', 'dateFilter', 'datepickerConfig', function($scope, $attrs, dateFilter, dtConfig) {
9303     var format = {
9304         date: getValue($attrs.dateFormat, dtConfig.dateFormat),
9305         day: getValue($attrs.dayFormat, dtConfig.dayFormat),
9306         month: getValue($attrs.monthFormat, dtConfig.monthFormat),
9307         year: getValue($attrs.yearFormat, dtConfig.yearFormat),
9308         dayHeader: getValue($attrs.dayHeaderFormat, dtConfig.dayHeaderFormat),
9309         dayTitle: getValue($attrs.dayTitleFormat, dtConfig.dayTitleFormat),
9310         disableWeekend: getValue($attrs.disableWeekend, dtConfig.disableWeekend),
9311         disableSunday: getValue($attrs.disableSunday, dtConfig.disableSunday)
9312     },
9313     startingDay = getValue($attrs.startingDay, dtConfig.startingDay);
9314     $scope.mode = getValue($attrs.mode, dtConfig.mode);
9315
9316     $scope.minDate = dtConfig.minDate ? $scope.resetTime(dtConfig.minDate) : null;
9317     $scope.maxDate = dtConfig.maxDate ? $scope.resetTime(dtConfig.maxDate) : null;
9318
9319     function getValue(value, defaultValue) {
9320         return angular.isDefined(value) ? $scope.$parent.$eval(value) : defaultValue;
9321     }
9322
9323     function getDaysInMonth(year, month) {
9324         return new Date(year, month, 0).getDate();
9325     }
9326
9327     function getDates(startDate, n) {
9328         var dates = [];
9329         var current = startDate, i = 0;
9330         while (i < n) {
9331             dates[i++] = new Date(current);
9332             current.setDate(current.getDate() + 1);
9333         }
9334         return dates;
9335     }
9336
9337     var compare = this.compare = function(date1, date2) {
9338         return (new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate()));
9339     };
9340
9341     function isSelected(dt) {
9342         if (dt && angular.isDate($scope.currentDate) && compare(dt, $scope.currentDate) === 0) {
9343             return true;
9344         }
9345         return false;
9346     }
9347
9348     function isFromDate(dt) {
9349         if (dt && angular.isDate($scope.fromDate) && compare(dt, $scope.fromDate) === 0) {
9350             return true;
9351         }
9352         return false;
9353     }
9354
9355     function isToDate(dt) {
9356         if (dt && angular.isDate($scope.fromDate) && angular.isDate($scope.currentDate) && compare(dt, $scope.currentDate) === 0) {
9357             return true;
9358         }
9359         return false;
9360     }
9361
9362     function isDateRange(dt) {
9363         if (dt && angular.isDate($scope.fromDate) && angular.isDate($scope.currentDate) && (compare(dt, $scope.fromDate) >= 0) && (compare(dt, $scope.currentDate) <= 0)) {
9364             return true;
9365         }
9366         return false;
9367     }
9368
9369     function isWeekend(date) {
9370         if (dateFilter(date, format.dayHeader) === "Saturday" || dateFilter(date, format.dayHeader) === "Sunday") {
9371             return true;
9372         }
9373         return false;
9374     }
9375
9376     function isToday(date) {
9377         if (compare(date, $scope.resetTime(new Date())) === 0) {
9378             return true;
9379         }
9380         return false;
9381     }
9382     function isFocused(date) {
9383         if (date && angular.isDate($scope.focusedDate) && compare(date, $scope.focusedDate) === 0) {
9384             return true;
9385         }
9386         return false;
9387     }
9388
9389     var isDisabled = this.isDisabled = function(date) {
9390         if (format.disableWeekend === true && (dateFilter(date, format.dayHeader) === "Saturday" || dateFilter(date, format.dayHeader) === "Sunday")) {
9391             return true;
9392         }
9393         if (format.disableSunday === true && (dateFilter(date, format.dayHeader) === "Sunday")) {
9394             return true;
9395         }
9396         return (($scope.minDate && compare(date, $scope.minDate) < 0) || ($scope.maxDate && compare(date, $scope.maxDate) > 0));
9397     };
9398
9399
9400     function isMinDateAvailable(startDate, endDate) {
9401        return ($scope.minDate && $scope.minDate.getTime() >= startDate.getTime()) && ($scope.minDate.getTime() <= endDate.getTime());
9402     }
9403
9404     function isMaxDateAvailable(startDate, endDate) {
9405         return ($scope.maxDate && $scope.maxDate.getTime() >= startDate.getTime()) && ($scope.maxDate.getTime() <= endDate.getTime());
9406     }
9407
9408     function getLabel(label) {
9409         if (label)
9410         {
9411             var labelObj = {
9412                 pre: label.substr(0, 3),
9413                 post: label
9414             };
9415             return labelObj;
9416         }
9417         return;
9418     }
9419     function makeDate(dateobj) {
9420         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};
9421     }
9422
9423     this.modes = [
9424         {
9425             name: 'day',
9426             getVisibleDates: function(date, calendar) {
9427                 var year = date.getFullYear(), month = date.getMonth(), firstDayOfMonth = new Date(year, month, 1), lastDayOfMonth = new Date(year, month+1, 0);
9428                 var difference = startingDay - firstDayOfMonth.getDay(),
9429                         numDisplayedFromPreviousMonth = (difference > 0) ? 7 - difference : -difference,
9430                         firstDate = new Date(firstDayOfMonth), numDates = 0;
9431
9432                 if (numDisplayedFromPreviousMonth > 0) {
9433                     firstDate.setDate(-numDisplayedFromPreviousMonth + 1);
9434                     numDates += numDisplayedFromPreviousMonth; // Previous
9435                 }
9436                 numDates += getDaysInMonth(year, month + 1); // Current
9437                 numDates += (7 - numDates % 7) % 7; // Next
9438
9439                 var days = getDates(firstDate, numDates), labels = [];
9440                 for (var i = 0; i < numDates; i++) {
9441                     var dt = new Date(days[i]);
9442                     days[i] = makeDate({date:dt,
9443                                 formatDay:format.day,
9444                                 formatHeader:format.dayHeader,
9445                                 isFocused:isFocused(dt),
9446                                 isSelected:isSelected(dt),
9447                                 isFromDate:isFromDate(dt),
9448                                 isToDate:isToDate(dt),
9449                                 isDateRange:isDateRange(dt),
9450                                 oldMonth:(new Date(dt.getFullYear(), dt.getMonth(), 1, 0, 0, 0).getTime() < new Date(year, month, 1, 0, 0, 0).getTime()),
9451                                 newMonth:(new Date(dt.getFullYear(), dt.getMonth(), 1, 0, 0, 0).getTime() > new Date(year, month, 1, 0, 0, 0).getTime()),
9452                                 isDisabled:isDisabled(dt),
9453                                 isToday:isToday(dt),
9454                                 isWeakend:isWeekend(dt)});
9455                 }
9456                 for (var j = 0; j < 7; j++) {
9457                     labels[j] = getLabel(dateFilter(days[j].date, format.dayHeader));
9458                 }
9459                 if (calendar === 'top') {
9460                     $scope.disablePrevTop = isMinDateAvailable(firstDayOfMonth, lastDayOfMonth);
9461                     $scope.disableNextTop = isMaxDateAvailable(firstDayOfMonth, lastDayOfMonth);
9462                 } else if (calendar === 'bottom') {
9463                     $scope.disablePrevBottom = isMinDateAvailable(firstDayOfMonth, lastDayOfMonth);
9464                     $scope.disableNextBottom = isMaxDateAvailable(firstDayOfMonth, lastDayOfMonth);
9465                 } else {
9466                     $scope.disablePrevTop = $scope.disablePrevBottom = isMinDateAvailable(firstDayOfMonth, lastDayOfMonth);
9467                     $scope.disableNextTop = $scope.disableNextBottom = isMaxDateAvailable(firstDayOfMonth, lastDayOfMonth);
9468                 }
9469                 $scope.disablePrev = $scope.disablePrevTop || $scope.disablePrevBottom;
9470                 $scope.disableNext = $scope.disableNextTop || $scope.disableNextBottom;
9471                 return {objects: days, title: dateFilter(date, format.dayTitle), labels: labels};
9472             },
9473             split: 7,
9474             step: {months: 1}
9475         },
9476         {
9477             name: 'month',
9478             getVisibleDates: function(date) {
9479                 var months = [], labels = [], year = date.getFullYear();
9480                 for (var i = 0; i < 12; i++) {
9481                    var dt = new Date(year,i,1);
9482                     months[i] = makeDate({date:dt,
9483                                 formatDay:format.month,
9484                                 formatHeader:format.month,
9485                                 isFocused:isFocused(dt),
9486                                 isSelected:isSelected(dt),
9487                                 isFromDate:isFromDate(dt),
9488                                 isToDate:isToDate(dt),
9489                                 isDateRange:isDateRange(dt),
9490                                 oldMonth:false,
9491                                 newMonth:false,
9492                                 isDisabled:isDisabled(dt),
9493                                 isToday:isToday(dt),
9494                                 isWeakend:false});
9495                 }
9496                 return {objects: months, title: dateFilter(date, format.year), labels: labels};
9497             },
9498             split:3,
9499             step: {years: 1}
9500         }
9501     ];
9502
9503 }])
9504
9505 .directive('datepicker', ['$timeout', function ($timeout) {
9506     return {
9507         restrict: 'EA',
9508         replace: true,
9509         transclude: true,
9510         templateUrl: 'app/scripts/ng_js_att_tpls/datepicker/datepicker.html',
9511         scope: {
9512             currentDate: "=?current",
9513             fromDate: "=?from"
9514         },
9515         require: 'datepicker',
9516         controller: 'DatepickerController',
9517         link: function(scope, element, attrs, ctrl) {
9518             var datepickerCtrl = ctrl;
9519             var selected, calendarSelected = false;
9520             scope.focusedDate;
9521
9522             scope.resetTime = function(date) {
9523                 var dt;
9524                 if (!isNaN(new Date(date))) {
9525                     dt = new Date(date);
9526                     if(scope.mode === 1){
9527                         dt = new Date(dt.getFullYear(), dt.getMonth());
9528                     }else{
9529                         dt = new Date(dt.getFullYear(), dt.getMonth(), dt.getDate());
9530                     }
9531                 } else {
9532                     return null;
9533                 }
9534                 return dt;
9535             };
9536
9537             if (attrs.min) {
9538                 scope.$parent.$watch(attrs.min, function(value) {
9539                     scope.minDate = value ? scope.resetTime(value) : null;
9540                     refill();
9541                 });
9542             }
9543             if (attrs.max) {
9544                 scope.$parent.$watch(attrs.max, function(value) {
9545                     scope.maxDate = value ? scope.resetTime(value) : null;
9546                     refill();
9547                 });
9548             }
9549
9550             // Split array into smaller arrays
9551             function split(arr, size) {
9552                 var arrays = [];
9553                 while (arr.length > 0) {
9554                     arrays.push(arr.splice(0, size));
9555                 }
9556                 return arrays;
9557             }
9558             var moveMonth = function(selectedDate, direction) {
9559                 var step = datepickerCtrl.modes[scope.mode].step;
9560                 selectedDate.setDate(1);
9561                 selectedDate.setMonth(selectedDate.getMonth() + direction * (step.months || 0));
9562                 selectedDate.setFullYear(selectedDate.getFullYear() + direction * (step.years || 0));
9563
9564                 return selectedDate;
9565             };
9566
9567             function refill(date) {
9568                 if (angular.isDate(date) && !isNaN(date)) {
9569                     selected = new Date(date);
9570                 } else {
9571                     if (!selected) {
9572                         selected = new Date();
9573                     }
9574                 }
9575
9576                 if (selected) {
9577                     var selectedCalendar;
9578                     if(scope.mode === 1){
9579                         selected = new Date();
9580                         selectedCalendar = moveMonth(angular.copy(selected), -1);
9581                     } else {
9582                         selectedCalendar = angular.copy(selected);
9583                     }
9584
9585                     var currentMode = datepickerCtrl.modes[scope.mode];
9586                     var currentData = currentMode.getVisibleDates(selectedCalendar, 'top');
9587                     scope.currentRows = split(currentData.objects, currentMode.split);
9588                     scope.currentTitle = currentData.title;
9589                     scope.labels = currentData.labels || [];
9590
9591                     var nextData = currentMode.getVisibleDates(moveMonth(angular.copy(selectedCalendar), 1), 'bottom');
9592                     scope.nextRows = split(nextData.objects, currentMode.split);
9593                     scope.nextTitle = nextData.title;
9594                 }
9595             }
9596
9597             var selectCurrentDate = function(date) {
9598                 var dt = new Date(date.getFullYear(), date.getMonth(), date.getDate());
9599                 scope.currentDate = dt;
9600             };
9601
9602             var selectFromDate = function(date) {
9603                 var dt = new Date(date.getFullYear(), date.getMonth(), date.getDate());
9604                 scope.fromDate = dt;
9605             };
9606
9607             scope.select = function(date) {
9608                 calendarSelected = true;
9609                 if(attrs.from) {
9610                     if(!(angular.isDate(scope.fromDate) && angular.isDate(scope.currentDate))) {
9611                         if(angular.isDate(scope.fromDate)) {
9612                             selectCurrentDate(date);
9613                         } else if(!angular.isDate(scope.fromDate)) {
9614                             selectFromDate(date);
9615                         }
9616                     }
9617                 } else {
9618                     selectCurrentDate(date);
9619                 }
9620                 scope.focusedDate = date;
9621             };
9622
9623             var swapDate = function(fromDate, currentDate) {
9624                 selectFromDate(currentDate);
9625                 $timeout(function () {
9626                     calendarSelected = true;
9627                     scope.focusedDate = currentDate;
9628                     selectCurrentDate(fromDate);
9629                 });
9630             };
9631
9632             scope.move = function(direction) {
9633                 selected = moveMonth(angular.copy(selected), direction);
9634                 refill();
9635             };
9636
9637             scope.$watch('currentDate', function (value) {
9638                 if(angular.isDate(value) && !isNaN(value) && datepickerCtrl.isDisabled(value)) {
9639                     scope.currentDate = null;
9640                     return;
9641                 }
9642
9643                 if (attrs.from && !isNaN(value) && !isNaN(scope.fromDate) && datepickerCtrl.compare(value, scope.fromDate) < 0) {
9644                         swapDate(scope.fromDate, value);
9645                         return;
9646                 }
9647
9648                 if (calendarSelected) {
9649                     refill();
9650                     calendarSelected = false;
9651                 } else {
9652                     if (angular.isDefined(value) && value !== null) {
9653                         refill(value);
9654                     } else {
9655                         refill();
9656                     }
9657                 }
9658                 scope.focusedDate = undefined;
9659             });
9660
9661             scope.$watch('fromDate', function (value) {
9662                 if(angular.isDate(value) && !isNaN(value) && datepickerCtrl.isDisabled(value)) {
9663                     scope.fromDate = null;
9664                     return;
9665                 }
9666                 if (attrs.from) {
9667                     if (!isNaN(scope.currentDate) && !isNaN(value) && datepickerCtrl.compare(scope.currentDate, value) < 0) {
9668                         swapDate(value, scope.currentDate);
9669                         return;
9670                     }
9671                     if (calendarSelected) {
9672                         refill();
9673                         calendarSelected = false;
9674                     } else {
9675                         if (angular.isDefined(value) && value !== null) {
9676                             refill(value);
9677                         } else {
9678                             refill();
9679                         }
9680                     }
9681                 }
9682                 scope.focusedDate = undefined;
9683             });
9684         }
9685     };
9686 }])
9687 .directive('datepickerPopup', ['$document', 'datepickerService', '$isElement', '$documentBind', function($document, datepickerService, $isElement, $documentBind) {
9688     var link = function (scope, elem, attr) {
9689         datepickerService.bindScope(attr, scope);
9690
9691         scope.isOpen = false;
9692
9693         var toggle = scope.toggle = function (show) {
9694             if(show === true || show === false) {
9695                 scope.isOpen = show;
9696             } else {
9697                 scope.isOpen = !scope.isOpen;
9698             }
9699         };
9700
9701         scope.$watch('current', function () {
9702             toggle(false);
9703         });
9704
9705         var outsideClick = function (e) {
9706             var isElement = $isElement(angular.element(e.target), elem, $document);
9707             if(!isElement) {
9708                 toggle(false);
9709                 scope.$apply();
9710             }
9711         };
9712
9713         $documentBind.click('isOpen', outsideClick, scope);
9714     };
9715
9716     return {
9717         restrict: 'EA',
9718         replace: true,
9719         transclude: true,
9720         templateUrl: 'app/scripts/ng_js_att_tpls/datepicker/datepickerPopup.html',
9721         scope: {
9722             current: "=current"
9723         },
9724         compile: function (elem, attr) {
9725             var wrapperElement = elem.find('span').eq(1);
9726             wrapperElement.attr('current', 'current');
9727             datepickerService.setAttributes(attr, wrapperElement);
9728
9729             return link;
9730         }
9731     };
9732 }])
9733
9734 .directive('attDatepicker', ['$log', function($log) {
9735     return {
9736         restrict: 'A',
9737         require: 'ngModel',
9738         scope: {},
9739         controller: ['$scope', '$element', '$attrs', '$compile', 'datepickerConfig', 'datepickerService', function($scope, $element, $attrs, $compile, datepickerConfig, datepickerService) {
9740             var dateFormatString = angular.isDefined($attrs.dateFormat) ? $scope.$parent.$eval($attrs.dateFormat) : datepickerConfig.dateFormat;
9741             var selectedDateMessage = '<div class="sr-focus hidden-spoken" tabindex="-1">the date you selected is {{$parent.current | date : \'' + dateFormatString + '\'}}</div>';
9742
9743             $element.removeAttr('att-datepicker');
9744             $element.removeAttr('ng-model');
9745             $element.attr('ng-model', '$parent.current');
9746             $element.attr('aria-describedby', 'datepicker');
9747             $element.attr('format-date', dateFormatString);
9748             $element.attr('att-input-deny', '[^0-9\/-]');
9749             $element.attr('maxlength', 10);
9750
9751             var wrapperElement = angular.element('<div></div>');
9752             wrapperElement.attr('datepicker-popup', '');
9753             wrapperElement.attr('current', 'current');
9754
9755             datepickerService.setAttributes($attrs, wrapperElement);
9756             datepickerService.bindScope($attrs, $scope);
9757
9758             wrapperElement.html('');
9759             wrapperElement.append($element.prop('outerHTML'));
9760             if (navigator.userAgent.match(/MSIE 8/) === null) {
9761                 wrapperElement.append(selectedDateMessage);
9762             }
9763             var elm = wrapperElement.prop('outerHTML');
9764             elm = $compile(elm)($scope);
9765             $element.replaceWith(elm);
9766         }],
9767         link: function(scope, elem, attr, ctrl) {
9768             if (!ctrl) {
9769                 // do nothing if no ng-model
9770                 $log.error("ng-model is required.");
9771                 return;
9772             }
9773
9774             scope.$watch('current', function(value) {
9775                 ctrl.$setViewValue(value);
9776             });
9777             ctrl.$render = function() {
9778                 scope.current = ctrl.$viewValue;
9779             };
9780         }
9781     };
9782 }])
9783
9784 .directive('formatDate', ['dateFilter', 'datepickerService', function(dateFilter, datepickerService) {
9785     return {
9786         restrict: 'A',
9787         require: 'ngModel',
9788         link: function(scope, elem, attr, ctrl) {
9789             var formatDate = "";
9790             attr.$observe('formatDate', function (value) {
9791                 formatDate = value;
9792             });
9793             var dateToString = function(value) {
9794                 if (value) {
9795                     ctrl.$setValidity('invalidDate', true);
9796                     return dateFilter(value, formatDate);
9797                 } else {
9798                     ctrl.$setValidity('invalidDate', false);
9799                     return elem.val();
9800                 }
9801             };
9802             var stringToDate = function(value) {
9803                 if(datepickerService.validateDateString(value, formatDate)) {
9804                     ctrl.$setValidity('invalidDate', true);
9805                     return new Date(value);
9806                 } else {
9807                     ctrl.$setValidity('invalidDate', false);
9808                     return null;
9809                 }
9810             };
9811             ctrl.$formatters.unshift(dateToString);
9812             ctrl.$parsers.unshift(stringToDate);
9813         }
9814     };
9815 }])
9816
9817 .directive('attDateFilter', ['$document', 'dateFilter', 'datepickerConfig', 'datepickerService', '$isElement', '$documentBind', function($document, dateFilter, datepickerConfig, datepickerService, $isElement, $documentBind) {
9818
9819     var link = function (scope, elem, attr, ctrl) {
9820         datepickerService.bindScope(attr, scope);
9821
9822         scope.selectedOption = datepickerConfig.dateFilter.defaultText;
9823         scope.showDropdownList = false;
9824         scope.showCalendar = false;
9825         scope.applyButtonType = "disabled";
9826
9827         scope.currentSelection = "";
9828         var dateFormatString = angular.isDefined(attr.dateFormat) ? scope.$parent.$eval(attr.dateFormat) : datepickerConfig.dateFormat;
9829         var inputChange = false;
9830
9831         var setDropdownText = function(value) {
9832             if(inputChange) {
9833                 return;
9834             }
9835
9836             var fromDateText = dateFormatString.toUpperCase();
9837             var currentDateText = dateFormatString.toUpperCase();
9838
9839             if(!isNaN(new Date(scope.fromDate))) {
9840                 fromDateText = dateFilter(scope.fromDate, dateFormatString);
9841             }
9842             if(!isNaN(new Date(scope.currentDate))) {
9843                 currentDateText = dateFilter(scope.currentDate, dateFormatString);
9844             }
9845
9846             if(value === 'Custom Single Date') {
9847                 ctrl.$setValidity('invalidDate', true);
9848                 scope.maxLength = 10;
9849                 scope.selectedOption = currentDateText;
9850             } else if(value === 'Custom Range') {
9851                 ctrl.$setValidity('invalidDate', true);
9852                 ctrl.$setValidity('invalidDateRange', true);
9853                 scope.maxLength = 21;
9854                 scope.selectedOption = fromDateText + '-' + currentDateText;
9855             }
9856         };
9857
9858         var clear = scope.clear = function(partial) {
9859             scope.fromDate = undefined;
9860             scope.currentDate = undefined;
9861             scope.applyButtonType = "disabled";
9862             if(!partial) {
9863                 ctrl.$setValidity('invalidDate', true);
9864                 ctrl.$setValidity('invalidDateRange', true);
9865                 setDropdownText(scope.currentSelection);
9866             }
9867         };
9868
9869         var showCalendar = function() {
9870             scope.showCalendar = true;
9871         };
9872
9873         var hideCalendar = function() {
9874             scope.showCalendar = false;
9875             if(scope.currentSelection !== 'Custom Single Date' && scope.currentSelection !== 'Custom Range') {
9876                 clear(true);
9877             }
9878         };
9879
9880         var showDropdown = scope.showDropdown = function (show) {
9881             if(show === true || show === false) {
9882                 scope.showDropdownList = show;
9883             } else {
9884                 scope.showDropdownList = !scope.showDropdownList;
9885             }
9886
9887             if (!scope.showDropdownList) {
9888                 scope.focusInputButton = true;
9889                 hideCalendar();
9890             } else {
9891                 if (scope.currentSelection === 'Custom Single Date' || scope.currentSelection === 'Custom Range') {
9892                     showCalendar();
9893                 }
9894             }
9895         };
9896
9897         scope.resetTime = function(date) {
9898             var dt;
9899             if (!isNaN(new Date(date))) {
9900                 dt = new Date(date);
9901             } else {
9902                 return null;
9903             }
9904             return new Date(dt.getFullYear(), dt.getMonth(), dt.getDate());
9905         };
9906
9907         scope.getDropdownText = function () {
9908             inputChange = true;
9909             var dropdownText = scope.selectedOption;
9910
9911             if (scope.currentSelection === 'Custom Single Date') {
9912                 if (!isNaN(new Date(dropdownText)) && datepickerService.validateDateString(dropdownText, dateFormatString)) {
9913                     ctrl.$setValidity('invalidDate', true);
9914                     scope.fromDate = undefined;
9915                     scope.currentDate = new Date(dropdownText);
9916                 } else {
9917                     ctrl.$setValidity('invalidDate', false);
9918                     clear(true);
9919                 }
9920             } else if (scope.currentSelection === 'Custom Range') {
9921                 if (dropdownText.indexOf('-') !== -1 && (dropdownText.split('-').length === 2 || dropdownText.split('-').length === 6)) {
9922                     ctrl.$setValidity('invalidDateRange', true);
9923                     var resultDropdownText = dropdownText.split('-');
9924                     if (resultDropdownText.length === 2) {
9925                         resultDropdownText[0] = resultDropdownText[0].trim();
9926                         resultDropdownText[1] = resultDropdownText[1].trim();
9927                     } else if (resultDropdownText.length === 6) {
9928                         var firstDateString = resultDropdownText[0].trim() + '-' + resultDropdownText[1].trim() + '-' + resultDropdownText[2].trim();
9929                         var secondDateString = resultDropdownText[3].trim() + '-' + resultDropdownText[4].trim() + '-' + resultDropdownText[5].trim();
9930                         resultDropdownText[0] = firstDateString;
9931                         resultDropdownText[1] = secondDateString;
9932                     }
9933
9934                     if (!isNaN(new Date(resultDropdownText[0])) && !isNaN(new Date(resultDropdownText[1])) && datepickerService.validateDateString(resultDropdownText[0], dateFormatString) && datepickerService.validateDateString(resultDropdownText[1], dateFormatString)) {
9935                         ctrl.$setValidity('invalidDate', true);
9936                         var fromDate = new Date(resultDropdownText[0]);
9937                         var currentDate = new Date(resultDropdownText[1]);
9938                         if(fromDate.getTime() < currentDate.getTime()) {
9939                             ctrl.$setValidity('invalidDateRange', true);
9940                             scope.fromDate = fromDate;
9941                             scope.currentDate = currentDate;
9942                         } else {
9943                             ctrl.$setValidity('invalidDateRange', false);
9944                             clear(true);
9945                         }
9946                     } else {
9947                         ctrl.$setValidity('invalidDate', false);
9948                         clear(true);
9949                     }
9950                 } else {
9951                     ctrl.$setValidity('invalidDateRange', false);
9952                     clear(true);
9953                 }
9954             }
9955         };
9956
9957         scope.untrackInputChange = function() {
9958             inputChange = false;
9959         };
9960
9961         scope.selectAdvancedOption = function (value, notClearFlag) {
9962             scope.currentSelection = value;
9963             if(!notClearFlag){
9964                 clear();
9965                 showCalendar();
9966             }
9967             scope.$watch('currentDate', function(val) {
9968                 if(!isNaN(new Date(val))) {
9969                     scope.applyButtonType = "primary";
9970                     setDropdownText(value);
9971                     if (!inputChange) {
9972                         scope.focusApplyButton = true;
9973                     }
9974                 }
9975             });
9976             scope.$watch('fromDate', function(val) {
9977                 if(!isNaN(new Date(val))) {
9978                     setDropdownText(value);
9979                 }
9980             });
9981             if (value === 'Custom Single Date') {
9982                 scope.focusSingleDateCalendar = true;
9983             } else if (value === 'Custom Range') {
9984                 scope.focusRangeCalendar = true;
9985             }
9986         };
9987
9988         scope.resetFocus = function () {
9989             scope.focusSingleDateCalendar = false;
9990             scope.focusRangeCalendar = false;
9991             scope.focusApplyButton = false;
9992         };
9993
9994         scope.apply = function() {
9995             scope.dateRange.selection = scope.selectedOption;
9996             if(!isNaN(new Date(scope.fromDate))) {
9997                 scope.from = scope.fromDate;
9998                 scope.dateRange.from = scope.fromDate;
9999             } else {
10000                 scope.from = undefined;
10001                 scope.dateRange.from = undefined;
10002             }
10003             if(!isNaN(new Date(scope.currentDate))) {
10004                 scope.current = scope.currentDate;
10005                 scope.dateRange.current = scope.currentDate;
10006             } else {
10007                 scope.current = undefined;
10008                 scope.dateRange.current = undefined;
10009             }
10010
10011             showDropdown();
10012         };
10013
10014         scope.$watchCollection(function() {
10015             return scope.dateRange;
10016         }, function(value) {
10017             if(ctrl) {
10018                 var finalDateRange = angular.copy(value);
10019                 ctrl.$setViewValue(finalDateRange);
10020             }
10021         });
10022
10023         ctrl.$render = function () {
10024             if (ctrl.$viewValue) {
10025                 var inputRange = ctrl.$viewValue;
10026                 scope.selectedOption = inputRange.selection;
10027                 scope.fromDate = inputRange.from;
10028                 scope.currentDate = inputRange.current;
10029                 if (scope.fromDate !== undefined && scope.currentDate !== undefined) {
10030                     scope.selectAdvancedOption('Custom Range', true);
10031                     scope.dateRange.from = scope.fromDate;
10032                     scope.dateRange.current = scope.currentDate;
10033                 } else if (scope.currentDate !== undefined) {
10034                     scope.selectAdvancedOption('Custom Single Date', true);
10035                     scope.dateRange.from = undefined;
10036                     scope.dateRange.current = scope.currentDate;
10037                 }
10038             }
10039         };
10040         
10041         scope.cancel = function() {
10042             scope.currentSelection = "";
10043             scope.selectedOption = datepickerConfig.dateFilter.defaultText;
10044             showDropdown();
10045         };
10046
10047         var outsideClick = function (e) {
10048             var isElement = $isElement(angular.element(e.target), elem, $document);
10049             if(!isElement) {
10050                 scope.cancel();
10051                 scope.$apply();
10052             }
10053         };
10054         $documentBind.click('showDropdownList', outsideClick, scope);
10055     };
10056
10057     return {
10058         restrict: 'EA',
10059         scope: {
10060             from: '=?from',
10061             current: "=?current"
10062         },
10063         replace: true,
10064         require: '?ngModel',
10065         transclude:true,
10066         templateUrl: 'app/scripts/ng_js_att_tpls/datepicker/dateFilter.html',
10067         controller:['$scope', '$element', '$attrs',function($scope){
10068             $scope.dateRange = {
10069                 selection: undefined,
10070                 from: undefined,
10071                 current: undefined
10072             };
10073             this.selectOption = function (fromDate,toDate,caption) {
10074                 $scope.selectedOption = caption;
10075                 $scope.currentSelection =caption;
10076                 $scope.dateRange.selection = caption;
10077                 $scope.dateRange.current = $scope.resetTime(toDate);
10078                 $scope.dateRange.from = $scope.resetTime(fromDate);
10079                 $scope.showDropdown();
10080         };
10081          $scope.checkCurrentSelection=this.checkCurrentSelection = function(value) {
10082             if(value === $scope.currentSelection) {
10083                 return true;
10084             }
10085             return false;
10086         };
10087         }],
10088         compile: function(elem, attr) {
10089             var singleDateCalendar = elem.find('span').eq(4);
10090             var rangeCalendar = elem.find('span').eq(5);
10091             rangeCalendar.attr('from', 'fromDate');
10092             singleDateCalendar.attr('current', 'currentDate');
10093             rangeCalendar.attr('current', 'currentDate');
10094             datepickerService.setAttributes(attr, singleDateCalendar);
10095             datepickerService.setAttributes(attr, rangeCalendar);
10096
10097             return link;
10098         }
10099     };
10100 }])
10101 .directive('attDateFilterList',function(){
10102     return{
10103         restrict:'EA',
10104         scope:{
10105             fromDate:'=fromDate',
10106             toDate:'=toDate',
10107             caption:'=caption',
10108             disabled:'=disabled'
10109         },
10110         require:'^attDateFilter',
10111         transclude:true,
10112         replace:true,
10113         templateUrl:'app/scripts/ng_js_att_tpls/datepicker/dateFilterList.html',
10114         link:function(scope,elem,attr,ctrl){
10115             scope.selectOption=function(fromDate,toDate,caption){
10116                 ctrl.selectOption(fromDate,toDate,caption);
10117             };
10118             scope.checkCurrentSelection=ctrl.checkCurrentSelection;
10119         }
10120     };
10121 });
10122 angular.module('att.abs.devNotes', [])
10123
10124   .directive('attDevNotes', function() {
10125     return {
10126       restrict: 'EA',
10127       transclude: true,
10128       scope: {},
10129       controller: function($scope){
10130         var panes = $scope.panes = [];
10131         $scope.select = function(pane)
10132         {
10133             angular.forEach(panes, function(pane)
10134             {
10135                 pane.selected = false;
10136             });
10137             pane.selected = true;
10138         };
10139         this.addPane = function(pane) {
10140             if (panes.length === 0) {
10141                 $scope.select(pane);
10142             }
10143           panes.push(pane);
10144         };
10145       },
10146       template:'<div>'+
10147         '<ul class="tabs">' +
10148             '<li ng-repeat="pane in panes" ng-class="{active:pane.selected}">'+
10149               '<a href="javascript:void(0)" ng-click="select(pane)">{{pane.title}}</a>' +
10150             '</li>' +
10151           '</ul>' +
10152           '<div ng-transclude></div>'+
10153           '</div>',
10154           replace: true
10155     };
10156   })
10157
10158   .directive('pane', function() {
10159     return {
10160       require: '^attDevNotes',
10161       restrict: 'EA',
10162       transclude: true,
10163       scope: {
10164           title: '@'
10165       },
10166       link: function(scope, element, attrs, tabsCtrl) {
10167         tabsCtrl.addPane(scope);
10168       },
10169       template:
10170         '<div class="tab-pane" ng-class="{active: selected}">' +
10171         '<pre ng-class="{\'language-markup\':title==\'HTML\',\'language-javascript\':title==\'JavaScript\',\'language-json\':title==\'JSON\'}"  class=" line-numbers">' +
10172          '<code ng-transclude></code>' +
10173          '</pre>' +
10174         '</div>',
10175       replace: true
10176     };
10177   });
10178
10179 angular.module('att.abs.dividerLines', [])
10180         .directive('attDividerLines', [function()
10181             {
10182                 return {
10183                     scope: {
10184                         attDividerLines: '@'
10185                     },
10186                     restrict: 'A',
10187                     replace: true,
10188                     templateUrl: 'app/scripts/ng_js_att_tpls/dividerLines/dividerLines.html',
10189                     link: function(scope, element, attribute)
10190                     {
10191                         scope.lightContainer = attribute.attDividerLines;
10192                     }
10193                 };
10194             }]);
10195
10196 angular.module('att.abs.dragdrop', [])
10197         .directive('attFileDrop', ['$parse', function($parse) {
10198                 return {
10199                     restrict: 'A',
10200                     scope: {
10201                         fileModel : '=',
10202                         onDrop : '&',
10203                         attFileDrop : '&'
10204                     },
10205                     controller: ['$scope', '$attrs', function($scope, $attrs){
10206                         if($attrs.attFileDrop!==""){
10207                             $scope.onDrop=$scope.attFileDrop;
10208                         }
10209                         this.onDrop = $scope.onDrop;
10210                     }],
10211                     link: function(scope, element) {
10212                         element.addClass('dragdrop');
10213                         element.bind(
10214                             'dragover',
10215                             function(e) {
10216                                 if(e.originalEvent){
10217                                     e.dataTransfer = e.originalEvent.dataTransfer;
10218                                 }
10219                                 e.dataTransfer.dropEffect = 'move';
10220                                 // allows us to drop
10221                                 if (e.preventDefault) {
10222                                     e.preventDefault();
10223                                 }
10224                                 element.addClass('dragdrop-over');
10225                                 return false;
10226                             }
10227                         );
10228                         element.bind(
10229                             'dragenter',
10230                             function(e) {
10231                                 // allows us to drop
10232                                 if (e.preventDefault) {
10233                                     e.preventDefault();
10234                                 }
10235                                 element.addClass('dragdrop-over');
10236                                 return false;
10237                             }
10238                         );
10239                         element.bind(
10240                             'dragleave',
10241                             function() {
10242                                 element.removeClass('dragdrop-over');
10243                                 return false;
10244                             }
10245                         );
10246                         element.bind(
10247                             'drop',
10248                             function(e) {
10249                                 // Stops some browsers from redirecting.
10250                                 if(e.preventDefault) {
10251                                     e.preventDefault();
10252                                 }
10253                                 if (e.stopPropagation) {
10254                                     e.stopPropagation();
10255                                 }
10256                                 if(e.originalEvent){
10257                                     e.dataTransfer = e.originalEvent.dataTransfer;
10258                                 }
10259                                 element.removeClass('dragdrop-over');
10260                                 if(e.dataTransfer.files && e.dataTransfer.files.length > 0){
10261                                     scope.fileModel = e.dataTransfer.files[0];
10262                                     scope.$apply();
10263                                     if(typeof scope.onDrop === "function"){
10264                                         scope.onDrop = $parse(scope.onDrop);
10265                                         scope.onDrop();
10266                                     }
10267                                 }
10268                                 return false;
10269                             }
10270                         );
10271                     }
10272                 };
10273             }])
10274         .directive('attFileLink', [ function() {
10275                 return {
10276                     restrict: 'EA',
10277                     require: '^?attFileDrop',
10278                     replace: true,
10279                     transclude: true,
10280                     templateUrl: 'app/scripts/ng_js_att_tpls/dragdrop/fileUpload.html',
10281                     scope: {
10282                         fileModel : '=?',
10283                         onFileSelect : '&',
10284                         attFileLink : '&'
10285                     },
10286                     controller: ['$scope', '$parse', function($scope, $parse){
10287                         this.setFileModel= function(fileModel){
10288                             if($scope.takeFileModelFromParent){
10289                                 $scope.$parent.fileModel = fileModel;
10290                                 $scope.$parent.$apply();
10291                             }
10292                             else{
10293                                 $scope.fileModel = fileModel;
10294                                 $scope.$apply();
10295                             }
10296                         };
10297                         this.callbackFunction= function(){
10298                             if(typeof $scope.onFileSelect === "function"){
10299                                 $scope.onFileSelect = $parse($scope.onFileSelect);
10300                                 $scope.onFileSelect();
10301                             }
10302                         };
10303                       
10304                     }],
10305                     link: function(scope, element, attr, attFileDropCtrl) {
10306                         scope.takeFileModelFromParent = false;
10307                         if(!(attr.fileModel) && attFileDropCtrl){
10308                             scope.takeFileModelFromParent = true;
10309                         }
10310                         if(attr.attFileLink!==""){
10311                             scope.onFileSelect=scope.attFileLink;
10312                         }
10313                         else if(!(attr.onFileSelect) && attFileDropCtrl){
10314                             scope.onFileSelect = attFileDropCtrl.onDrop;
10315                         }
10316                     }
10317                 };
10318             }])
10319         .directive('attFileChange', ['$log','$rootScope',function($log,$rootScope) {
10320                 return {
10321                     restrict: 'A',
10322                     require: '^attFileLink',
10323                     link: function(scope, element, attr, attFileLinkCtrl) {
10324                         element.bind('change',changeFileModel);
10325                         function changeFileModel(e) {
10326                             if (e.target.files && e.target.files.length > 0) {
10327                                 attFileLinkCtrl.setFileModel(e.target.files[0]);
10328                                 attFileLinkCtrl.callbackFunction();
10329                             }
10330                             else {
10331                                 var strFileName = e.target.value;
10332                                 try {
10333                                     var objFSO = new ActiveXObject("Scripting.FileSystemObject");
10334                                     attFileLinkCtrl.setFileModel(objFSO.getFile(strFileName));
10335                                     attFileLinkCtrl.callbackFunction();
10336                                 }
10337                                 catch (e) {
10338                                     var errMsg = "Error: Please follow the guidelines of Drag and Drop component on Sandbox demo page.";
10339                                     $log.error(errMsg);
10340                                     $rootScope.$broadcast('att-file-link-failure', errMsg);
10341                                 }
10342                             }
10343                         }
10344                     }
10345                 };
10346             }]);
10347 angular.module("att.abs.drawer", ['att.abs.utilities'])
10348 .directive('attDrawer', ['$document', '$timeout', 'DOMHelper', function ($document, $timeout, DOMHelper) {
10349         return {
10350             restrict: 'EA',
10351             replace: true,
10352             transclude: true,
10353             scope: {
10354                 drawerOpen: "=?",
10355                 drawerAutoClose: "&?"
10356             },
10357             template: '<div><div class="att-drawer" ng-transclude></div><div ng-class="{\'drawer-backdrop\':drawerOpen}"></div></div>',
10358             link: function ($scope, element, attrs) {
10359                 var param = {};
10360                 // First Element in Drawer component
10361                 var firstElement = undefined;
10362                 // Element drawer is toggled from
10363                 var drawerLaunchingElement = undefined;
10364                 // Override default parameters
10365                 param.side = attrs.drawerSlide || 'top';
10366                 param.speed = attrs.drawerSpeed || '0.25';
10367                 param.size = attrs.drawerSize || '300px';
10368                 param.zindex = attrs.drawerZindex || 1000;
10369                 param.className = attrs.drawerClass || 'att-drawer';
10370                 var slider = element.eq(0).children()[0];
10371                 var content = angular.element(slider).children()[0];
10372                 slider.className = param.className;
10373                 /* Style setup */
10374                 slider.style.transitionDuration = param.speed + 's';
10375                 slider.style.webkitTransitionDuration = param.speed + 's';
10376                 slider.style.zIndex = param.zindex;
10377                 slider.style.position = 'fixed';
10378                 slider.style.width = 0;
10379                 slider.style.height = 0;
10380                 slider.style.transitionProperty = 'width, height';
10381                 if(param.side==='right' || param.side==='left'){
10382                     slider.style.height = attrs.drawerCustomHeight || '100%';
10383                     slider.style.top = attrs.drawerCustomTop ||  '0px';
10384                     slider.style.bottom = attrs.drawerCustomBottom ||  '0px';
10385                     slider.style.right = attrs.drawerCustomRight ||  '0px';
10386                 }
10387                 else if(param.side==='top' || param.side==='bottom'){
10388                     slider.style.width = attrs.drawerCustomWidth || '100%';
10389                     slider.style.left = attrs.drawerCustomLeft || '0px';
10390                     slider.style.top = attrs.drawerCustomTop || '0px';
10391                     slider.style.right = attrs.drawerCustomRight || '0px';
10392                 }
10393                 $timeout(function() {
10394                     firstElement = DOMHelper.firstTabableElement(element[0]);
10395                 }, 10, false);
10396                 /* Closed */
10397                 function drawerClose(slider, param) {
10398                     if (slider && slider.style.width !== 0 && slider.style.height !== 0){
10399                         content.style.display = 'none';
10400                         if(param.side==='right' || param.side==='left'){
10401                             slider.style.width = '0px';
10402                         }
10403                         else if(param.side==='top' || param.side==='bottom'){
10404                             slider.style.height = '0px';
10405                         }
10406                     }
10407                     $scope.drawerOpen = false;
10408                     // Shift focus
10409                     if (angular.isDefined(drawerLaunchingElement) && drawerLaunchingElement != null) {
10410                         drawerLaunchingElement.focus();
10411                     }
10412                 }
10413                 /* Open */
10414                 function drawerOpen(slider, param) {
10415                     // Before opening drawer, find the focused element
10416                     drawerLaunchingElement = document.activeElement;
10417                     if (slider.style.width !== 0 && slider.style.height !== 0){
10418                         if(param.side==='right' || param.side==='left'){
10419                             slider.style.width = param.size;
10420                         }
10421                         else if(param.side==='top' || param.side==='bottom'){
10422                             slider.style.height = param.size;
10423                         }
10424                         $timeout(function() {
10425                             content.style.display = 'block';
10426                             // Shift focus
10427                             if (angular.isDefined(firstElement) && firstElement != null) {
10428                                 firstElement.focus();
10429                             }
10430                         },(param.speed * 1000));
10431                     }
10432                 }
10433                 function isFunction(functionToCheck) {
10434                     var getType = {};
10435                     return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
10436                 }
10437                 /*
10438                 * Watchers
10439                 * */
10440                 if(attrs.drawerSize) {
10441                     $scope.$watch(function() {
10442                         return attrs.drawerSize;
10443                     }, function(newVal) {
10444                         param.size = newVal;
10445                         if($scope.drawerOpen) {
10446                             drawerOpen(slider,param);
10447                         }
10448                     });
10449                 }
10450                 $scope.$watch("drawerOpen", function (value){
10451                     if (!!value) {
10452                         // Open
10453                         drawerOpen(slider,param);
10454                     } else {
10455                         // Close
10456                         drawerClose(slider,param);
10457                     }
10458                 });
10459                 // close panel on location change
10460                 if($scope.drawerAutoClose) {
10461                     $scope.$on("$locationChangeStart", function(){
10462                         drawerClose(slider, param);
10463                         if(isFunction($scope.drawerAutoClose)) {
10464                             $scope.drawerAutoClose();
10465                         }
10466                     });
10467                     $scope.$on("$stateChangeStart", function(){
10468                         drawerClose(slider, param);
10469                         if(isFunction($scope.drawerAutoClose)) {
10470                             $scope.drawerAutoClose();
10471                         }
10472                     });
10473                 }
10474             }
10475         };
10476     }
10477 ]);
10478 angular.module('att.abs.message', [])
10479
10480 .directive('attMessages', [function() {
10481     return {
10482         restrict: 'EA',
10483         scope: {
10484             messageType: '=?'
10485         },
10486         controller: ['$scope', '$element', '$attrs', function($scope, $element, $attrs) {
10487             $scope.messageScope = [];
10488             this.registerScope = function(messageScope) {
10489                 $scope.messageScope.push(messageScope);
10490             };
10491             $scope.$parent.$watchCollection($attrs['for'], function(errors) {
10492                 for (var key in errors) {
10493                     if (errors[key]) {
10494                         $scope.error = key;
10495                         break;
10496                     } else {
10497                         $scope.error = null;
10498                     }
10499                 }
10500                 for (var i = 0; i < $scope.messageScope.length; i++) {
10501                     if($scope.messageScope[i].when === $scope.error) {
10502                         $scope.messageScope[i].show();
10503                         $scope.setMessageType($scope.messageScope[i].type);
10504                     } else {
10505                         $scope.messageScope[i].hide();
10506                     }
10507                 }
10508                 if($scope.error === null) {
10509                     $scope.setMessageType(null);
10510                 }
10511             });
10512             $scope.setMessageType = this.setMessageType = function(messageType) {
10513                 if($attrs.messageType) {
10514                     $scope.messageType = messageType;
10515                 }
10516             };
10517         }]
10518     };
10519 }])
10520
10521 .directive('attMessage', [function() {
10522     return {
10523         restrict: 'EA',
10524         scope: {},
10525         require: '^attMessages',
10526         link: function(scope, elem, attr, ctrl) {
10527             ctrl.registerScope(scope);
10528             scope.when = attr.when || attr.attMessage;
10529             scope.type = attr.type;
10530             scope.show = function() {
10531                 elem.css({display: 'block'});
10532             };
10533             scope.hide = function() {
10534                 elem.css({display: 'none'});
10535             };
10536             scope.hide();
10537         }
10538     };
10539 }]);
10540
10541 angular.module('att.abs.formField', ['att.abs.message', 'att.abs.utilities'])
10542 .directive('attFormField', [function() {
10543     return {
10544         priority: 101,
10545         restrict: 'A',
10546         controller:function() {
10547         },
10548         link: function(scope, elem, attr) {
10549             elem.wrap('<div class="form-field"></div>');
10550             elem.parent().append('<label class="form-field__label">' + attr.placeholder || attr.attFormField + '</label>');
10551             elem.wrap('<div class="form-field-input-container"></div>');
10552
10553             elem.bind('keyup', function() {
10554                 if (this.value !== '') {
10555                     elem.parent().parent().find('label').addClass('form-field__label--show').removeClass('form-field__label--hide');
10556                 } else {
10557                     elem.parent().parent().find('label').addClass('form-field__label--hide').removeClass('form-field__label--show');
10558                 }
10559             });
10560
10561             elem.bind('blur', function() {
10562                 if (this.value === '') {
10563                     elem.parent().parent().find('label').removeClass('form-field__label--hide');
10564                 }
10565             });
10566         }
10567     };
10568 }])
10569 .directive('attFormFieldValidation', ['$compile', '$log', function($compile, $log) {
10570     return {
10571         priority: 102,
10572         scope: {},
10573         restrict: 'A',
10574         require: ['?ngModel', '?attFormField'],
10575         link: function(scope, elem, attr, ctrl) {
10576             var ngCtrl = ctrl[0];
10577             var attFormFieldCtrl = ctrl[1];
10578             scope.valid = "";
10579             if (!ngCtrl) {
10580                 $log.error("att-form-field-validation :: ng-model directive is required.");
10581                 return;
10582             }
10583             if (!attFormFieldCtrl) {
10584                 $log.error("att-form-field-validation :: att-form-field directive is required.");
10585                 return;
10586             }
10587
10588             elem.parent().append($compile(angular.element('<i class="icon-info-alert error" ng-show="valid===false">&nbsp;</i>'))(scope));
10589             elem.parent().append($compile(angular.element('<i class="icon-info-success success" ng-show="valid===true">&nbsp;</i>'))(scope));
10590
10591             scope.$watch('valid', function(value) {
10592                 if (value) {
10593                     elem.parent().parent().addClass('success');
10594                 } else if (value === false) {
10595                     elem.parent().parent().addClass('error');
10596                 } else {
10597                     elem.parent().parent().removeClass('success').removeClass('error');
10598                 }
10599             });
10600
10601             elem.bind('keyup', function() {
10602                 if (ngCtrl.$valid) {
10603                     scope.valid = true;
10604                 } else if (ngCtrl.$invalid) {
10605                     scope.valid = false;
10606                 } else {
10607                     scope.valid = "";
10608                 }
10609                 scope.$apply();
10610             });
10611         }
10612     };
10613 }])
10614 .directive('attFormFieldValidationAlert', ['$timeout', function($timeout) {
10615         return {
10616         scope: {
10617             messageType: '=?'
10618         },
10619         restrict: 'EA',
10620         replace: true,
10621         transclude: true,
10622         templateUrl: 'app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlert.html',
10623         link: function(scope, elem, attr, ctrl) {
10624             scope.showLabel = false;
10625             scope.hideLabel = false;
10626             scope.errorMessage = false;
10627             scope.warningMessage = false;
10628             var checkMessageType = function() {
10629                 var messageType = scope.messageType;
10630                 if (messageType === 'error') {
10631                     scope.errorMessage = true;
10632                     scope.warningMessage = false;
10633                 } else if (messageType === 'warning') {
10634                     scope.errorMessage = false;
10635                     scope.warningMessage = true;
10636                 } else {
10637                     scope.errorMessage = false;
10638                     scope.warningMessage = false;
10639                 }
10640             };
10641             var oldIE = navigator.userAgent.toLowerCase().indexOf('msie 8.0') !== -1;
10642             elem.find('label').text(elem.find('input').attr('placeholder'));
10643             elem.find('input').bind('keyup', function() {
10644                 if (this.value !== '') {
10645                     scope.showLabel = true;
10646                     scope.hideLabel = false;
10647                     if (oldIE) {
10648                         elem.find('label').css({top: '-20px'});
10649                     }
10650                 } else {
10651                     scope.showLabel = false;
10652                     scope.hideLabel = true;
10653                     if (oldIE) {
10654                         elem.find('label').css({top: '0px'});
10655                     }
10656                 }
10657                 checkMessageType();
10658                 scope.$apply();
10659             });
10660
10661             elem.find('input').bind('blur', function() {
10662                 if (this.value === '') {
10663                     scope.showLabel = false;
10664                     scope.hideLabel = false;
10665                 }
10666                 scope.$apply();
10667             });
10668             $timeout(function() {
10669                 checkMessageType();
10670             }, 100);
10671         }
10672     };
10673 }])
10674 .constant("CoreFormsUiConfig", {
10675             phoneMask: '(___) ___-____'
10676         })
10677 .directive('attPhoneMask', ['$parse', 'CoreFormsUiConfig', function($parse, CoreFormsUiConfig) {
10678                 return {
10679                     require: 'ngModel',
10680                     scope: {
10681                         ngModel: '='
10682                     },
10683                     link: function(scope, iElement, iAttrs, ctrl) {
10684                         var B = navigator.userAgent.toLowerCase(), C = B.indexOf("android") > -1,
10685                                 oldIE = B.indexOf('msie 8.0') !== -1;;
10686                         var A = '';
10687                         var validPhoneNumber = false;
10688                         if (C) {
10689                             A = "__________";
10690                         }
10691                         else {
10692                             A = CoreFormsUiConfig.phoneMask;
10693                         }
10694                         iElement.attr("maxlength", A.length);
10695                         var checkValidity = function(unmaskedValue) {
10696                         var valid = false;
10697                         if (unmaskedValue){
10698                         valid = (unmaskedValue.length === 10);}
10699                         ctrl.$setValidity('invalidPhoneNumber', validPhoneNumber);
10700                         ctrl.$setValidity('mask', valid);
10701                         return valid;
10702                         };
10703                         
10704                         var handleKeyup = function() {
10705                             var E,D = ctrl.$modelValue;
10706                             if (!D.length) {
10707                                 return;
10708                             }
10709                             var L, K, G, J, I;
10710                             J = [];
10711                             G = A.split("");
10712                             I = G.length;
10713                             L = D.substring(0, A.length);
10714                             K = D.replace(/[^0-9]/g, "").split("");
10715                             for (E = 0; E < I; E++) {
10716                                 J.push(G[E] === "_" ? K.shift() : G[E]);
10717                                 if (K.length === 0) {
10718                                     break;
10719                                 }
10720                             }
10721                             D = J.join("");
10722                             if (D === '('){
10723                                 D = '';}
10724                             ctrl.$setViewValue(D);
10725                             ctrl.$render();
10726                             return D;
10727                         };
10728
10729
10730                         // since we are only allowing 0-9, why even let the keypress go forward?
10731                         // also added in delete... in case they want to delete :)
10732                         var handlePress = function(e) {
10733                             if (e.which) {
10734                                 if ((e.which < 48 || e.which > 57) && (e.which < 96 || e.which > 105)) {
10735                                          if (e.which !== 8 && e.which !== 9 && e.which !== 46 && e.which !== 13 && e.which !== 37 && e.which !== 39 &&
10736                                             // Allow: Ctrl+V/v
10737                                             (e.ctrlKey !== true && (e.which !== '118' || e.which !== '86'))&&
10738                                              // Allow: Ctrl+C/c
10739                                             (e.ctrlKey !== true && (e.which !== '99' || e.which !== '67'))&&
10740                                             // Allow: Ctrl+X/x
10741                                             (e.ctrlKey !== true && (e.which !== '120' || e.which !== '88')))
10742                                             {
10743                                                 e.preventDefault ? e.preventDefault() : e.returnValue = false;
10744                                                 iElement.attr("aria-label","Only numbers are allowed");
10745                                                 validPhoneNumber = false;
10746                                             }}
10747                                 else{
10748                                         iElement.removeAttr("aria-label");
10749                                         validPhoneNumber = true;
10750                                     }
10751                                    }
10752                             scope.$apply();
10753                         };
10754                         // i moved this out because i thought i might need focus as well..
10755                         // to handle setting the model as the view changes
10756                         var parser = function(fromViewValue) {
10757                             var letters = /^[A-Za-z]+$/;
10758                             var numbers = /^[0-9]+$/;
10759                             if(fromViewValue.match(letters))
10760                                 {validPhoneNumber = false;}
10761                             if(fromViewValue.match(numbers))
10762                                 {validPhoneNumber = true;}
10763                             var clean = "";
10764                             if (fromViewValue && fromViewValue.length > 0) {
10765                                 clean = fromViewValue.replace(/[^0-9]/g, '');
10766                             }
10767                             checkValidity(clean);
10768                             return clean;
10769                         };
10770
10771                         //to handle reading the model and formatting it
10772                         var formatter = function(fromModelView) {
10773                             var input = '';
10774                             checkValidity(fromModelView);
10775                             if (fromModelView){
10776                                 input = handleKeyup();}
10777                             return input;
10778                         };
10779                         ctrl.$parsers.push(parser);
10780                         ctrl.$formatters.push(formatter);
10781                         iElement.bind('keyup', handleKeyup);
10782                         iElement.bind('keydown', handlePress);
10783                         iElement.bind('input', function(e){
10784                             handleKeyup(e);
10785                             handlePress(e);
10786                         });
10787                     }
10788                 };
10789 }])
10790 .constant('validationTypeInt', {
10791             validationNum: {'number':'1','text':'2','email':'3'}
10792         })        
10793 .directive('attFormFieldPrv', [ 'keyMapAc', 'validationTypeInt', function( keyMapAc, validationTypeInt ) {
10794     return {
10795         priority: 101,
10796         restrict: 'AE',
10797                 controller:['$scope', function($scope) {
10798                         this.showHideErrorMessage = function ( booleanValue ){
10799                                 if(  $scope.$$prevSibling != null && angular.isDefined( $scope.$$prevSibling )
10800                                         && angular.isDefined( $scope.$$prevSibling.hideErrorMsg ) ){
10801                                         $scope.$$prevSibling.hideErrorMsg = booleanValue;
10802                                         $scope.$apply();
10803                                 }
10804                         };
10805                         this.findAllowedCharactor = function( keyCode ){
10806                                 var keyMapSc = keyMapAc.keys;
10807                                 if( angular.isDefined( $scope.allowedSpecialCharacters )
10808                                                 && angular.isDefined( $scope.allowedSpecialCharacters.length )
10809                                                 && $scope.allowedSpecialCharacters.length > 0 ){
10810                                         var allowedCharList = $scope.allowedSpecialCharacters;
10811                                         var charFound = false;
10812                                         for( var i=0 ; i < allowedCharList.length ; i++){
10813                                                 if( allowedCharList[i] === keyMapSc[keyCode] ){
10814                                                         charFound = true;
10815                                                         break;
10816                                                 }
10817                                         }
10818                                         return charFound;
10819                                 }else{
10820                                         return false;
10821                                 }
10822                         };
10823                         this.validateText = function( validationType, allowedChars, validationInput, outputSpecialChars ){
10824                                 if( angular.isDefined( allowedChars ) &&  allowedChars.length === 0 ){
10825                                         var expAlphanumeric = /^[a-zA-Z0-9]*$/i;
10826                                         return expAlphanumeric.test( validationInput );
10827                                 }else{
10828                                         var expAlphanumericSpecialChar = '^[a-zA-Z0-9' + outputSpecialChars + ']*$';
10829                                         var regularExp = new RegExp( expAlphanumericSpecialChar, 'i' );
10830                                         return regularExp.test( validationInput );
10831                                 }
10832                         };
10833                         this.validateNumber = function( validationType, allowedChars, validationInput, outputSpecialChars ){
10834                                 if( angular.isDefined( allowedChars ) &&  allowedChars.length === 0 ){
10835                                         var expNumber = /^[0-9\.]+$/;
10836                                         return expNumber.test( validationInput );
10837                                 }else{
10838                                         var expNumberSpecial = '^[0-9\.' + outputSpecialChars + ']*$';
10839                                         var regularExp = new RegExp( expNumberSpecial, 'i' );
10840                                         return regularExp.test( validationInput );
10841                                 }
10842                         };
10843                         this.validateEmail = function( validationType, allowedChars, validationInput, outputSpecialChars ){
10844                                 if( angular.isDefined( allowedChars ) &&  allowedChars.length === 0 ){
10845                                         var expEmail = /(([a-zA-Z0-9\-?\.?]+)@(([a-zA-Z0-9\-_]+\.)+)([a-z]{2,3}))+$/;
10846                                         return expEmail.test( validationInput );
10847                                 }else{
10848                                         var expEmailSpecial = '(([a-z' + outputSpecialChars + 'A-Z0-9\-?\.?]+)@(([a-z'
10849                                                 + outputSpecialChars + 'A-Z0-9\-_]+\.)+)([' + outputSpecialChars + 'a-z]{2,3}))+$';
10850                                         var regularExp = new RegExp( expEmailSpecial, 'i' );
10851                                         return regularExp.test( validationInput );
10852                                 }
10853                         };
10854                         this.validateInput = function( validationType, allowedChars, validationInput ){
10855                                 var outputSpecialChars = '';
10856                                 var result = false;
10857                                 if( angular.isDefined( allowedChars ) && angular.isDefined( allowedChars.length )
10858                                         && allowedChars.length > 0 ){
10859                                         for( var i = 0; i < allowedChars.length; i++){
10860                                                 outputSpecialChars += '\\'+allowedChars[i];
10861                                         }
10862                                 }
10863                                 switch ( validationTypeInt.validationNum[ validationType ] ) {
10864                                         case validationTypeInt.validationNum["text"]:
10865                                                 result = this.validateText( validationType, allowedChars, validationInput, outputSpecialChars  );
10866                                                 break;
10867                                         case validationTypeInt.validationNum["number"]:
10868                                                 result = this.validateNumber( validationType, allowedChars, validationInput, outputSpecialChars  );
10869                                                 break;
10870                                         case validationTypeInt.validationNum["email"]:
10871                                                 result = this.validateEmail( validationType, allowedChars, validationInput, outputSpecialChars  );
10872                                                 break;
10873                                         default:
10874                                                 break;
10875                                 }
10876                                 return result;
10877                         };
10878         }],
10879         link: function(scope, elem, attr ) {
10880             elem.parent().prepend('<label class="form-field__label">' + attr.placeholder + '</label>');
10881             elem.wrap('<div class="form-field-input-container"></div>');
10882                         elem.parent().parent().find('label').addClass('form-field__label--show');
10883         }
10884     };
10885 }])
10886 .directive('attFormFieldValidationPrv', [ 'keyMapAc','validationTypeInt' , function( keyMapAc, validationTypeInt ) {
10887     return {
10888         priority: 202,
10889         scope: {
10890             validationType: '=',
10891             allowedChars: '='
10892                 },
10893         restrict: 'A',
10894         require: ['?ngModel', '^attFormFieldPrv'],
10895         link: function(scope, elem, attr, ctrl) {
10896             var attFormFieldCtrl = ctrl[1];
10897             elem.bind('keyup', function() {
10898                                 /* email validation has tobe done on keyup */
10899                                 if( attFormFieldCtrl.validateInput( scope.validationType, scope.allowedChars, elem[0].value ) ){
10900                                         attFormFieldCtrl.showHideErrorMessage(false);
10901                                 }
10902                                 else{
10903                                         attFormFieldCtrl.showHideErrorMessage(true);
10904                                 }
10905             });
10906                         var keyMapSc = keyMapAc.keyRange;
10907                         var allowedKeys = keyMapAc.allowedKeys;
10908                         var validateTextCode = function( charFound,event ){
10909                                 var resultOne = (event.which < keyMapSc['startNum'] || event.which > keyMapSc['endNum'] );
10910                                 var resultTwo = (event.which < keyMapSc['startCapitalLetters'] || event.which > keyMapSc['endCapitalLetters'] );
10911                                 var resultThree = (event.which < keyMapSc['startSmallLetters'] || event.which > keyMapSc['endSmallLetters'] );
10912                                 var result = ( resultOne && resultTwo &&  resultThree );
10913                                 return ( result && ( !charFound )  );
10914                         };
10915                         var validateNumberCode = function( charFound,event ){
10916                                 return ( ( event.which < keyMapSc['startNum'] || event.which > keyMapSc['endNum'] ) &&   ( !charFound ) );
10917                         };
10918                         var validateEmailCode = function( charFound,event ){
10919                                 var condOne = String.fromCharCode( event.which ) !== '-' && String.fromCharCode( event.which ) !== '_';
10920                                 var condTwo = String.fromCharCode( event.which ) !== '@' && String.fromCharCode( event.which ) !== '.';
10921                                 var ifAllowedChars = condOne && condTwo;
10922                                 var ifCharRange = validateTextCode( charFound,event );
10923                                 return (  ( !charFound ) && ifAllowedChars && ifCharRange );
10924                         };
10925                         var validateSwitch = function( validationTypeSwitch, charFound, event ){
10926                                 switch ( validationTypeSwitch ) {
10927                                                 case validationTypeInt.validationNum["text"]:
10928                                                         /* 97-122 65-90 48-57 if keyCode is outside range of alphanumeric chars and not found in list then prevent */
10929                                                         if( validateTextCode( charFound, event ) ){
10930                                                                 return true;
10931                                                         }
10932                                                         break;
10933                                                 case validationTypeInt.validationNum["number"]:
10934                                                         /* if key code is outside number range and notfound then prevent */
10935                                                         if( validateNumberCode( charFound, event ) ){
10936                                                                 return true;
10937                                                         }
10938                                                         break;
10939                                                 case validationTypeInt.validationNum["email"]:
10940                                                         /* if keyCode is outside charactor/number range and not _-@. then prevent */
10941                                                         if( validateEmailCode( charFound, event ) ){
10942                                                                 return true;
10943                                                         }
10944                                                         break;
10945                                                 default:
10946                                                         break;
10947                                 }
10948                                 return false;
10949                         };
10950                         /* key stroke prevention has to be happen on numeric and alphanumeric fields */
10951                         elem.bind('keypress', function( event ){
10952                                 if(!(event.which)){
10953                                     if(event.keyCode){
10954                                         event.which = event.keyCode;
10955                                     }
10956                                     else if(event.charCode){
10957                                         event.which = event.charCode;
10958                                     }
10959                                 }
10960                                 var charFound = attFormFieldCtrl.findAllowedCharactor( event.which );
10961                                 var insideCondOne = ( angular.isDefined( scope.validationType ) && scope.validationType !== '');
10962                                 var insideCondTwo = ( event.which !== allowedKeys['TAB']
10963                                         && event.which !== allowedKeys['BACKSPACE'] && event.which!== allowedKeys['DELETE'] );
10964                                 var goInside = insideCondOne && insideCondTwo;
10965                                 if( goInside && validateSwitch( validationTypeInt.validationNum[ scope.validationType ], charFound, event ) ){
10966                                         event.preventDefault();
10967                                 }
10968                         });
10969         }
10970     };
10971 }])
10972 .directive('attFormFieldValidationAlertPrv', [ function() {
10973         return {
10974                         restrict: 'A',
10975                         scope : { errorMessage : '=' },
10976                         transclude: true,
10977                         templateUrl: 'app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlertPrv.html',
10978                         link: function( scope ) {
10979                                 scope.errorMessage = scope.errorMessage;
10980                                 if( angular.isDefined( scope.$parent.hideErrorMsg ) ){
10981                                         scope.hideErrorMsg = scope.$parent.hideErrorMsg;
10982                                 }
10983                                 else{
10984                                         scope.hideErrorMsg = true;
10985                                 }
10986                         }
10987                 };
10988 }])
10989 //Credit card validation directives starts here
10990 .factory('Cards', [function() {
10991         var defaultFormat = /(\d{1,4})/g;
10992         var defaultInputFormat = /(?:^|\s)(\d{4})$/;
10993         var cards = [
10994             {
10995                 type: 'discover',
10996                 pattern: /^(6011|65|64[4-9]|622)/,
10997                 format: defaultFormat,
10998                 inputFormat: defaultInputFormat,
10999                 length: [16],
11000                 cvcLength: [3],
11001                 cvcSecurityImg: 'visaI',
11002                 zipLength: [5],
11003                 luhn: true
11004             },
11005             {
11006                 type: 'mc',
11007                 pattern: /^5[1-5]/,
11008                 format: defaultFormat,
11009                 inputFormat: defaultInputFormat,
11010                 length: [16],
11011                 cvcLength: [3],
11012                 cvcSecurityImg: 'visaI',
11013                 zipLength: [5],
11014                 luhn: true
11015             },
11016             {
11017                 type: 'amex',
11018                 pattern: /^3[47]/,
11019                 format: /(\d{1,4})(\d{1,6})?(\d{1,5})?/,
11020                 inputFormat: /^(\d{4}|\d{4}\s\d{6})$/,
11021                 length: [15],
11022                 cvcLength: [4],
11023                 cvcSecurityImg: 'amexI',
11024                 zipLength: [5],
11025                 luhn: true
11026             },
11027             {
11028                 type: 'visa',
11029                 pattern: /^4/,
11030                 format: defaultFormat,
11031                 inputFormat: defaultInputFormat,
11032                 length: [16],
11033                 cvcLength: [3],
11034                 cvcSecurityImg: 'visaI',
11035                 zipLength: [5],
11036                 luhn: true
11037             }
11038         ];
11039
11040         var _fromNumber = function(num) {
11041             var card, i, len;
11042
11043             num = (num + '').replace(/\D/g, '');
11044
11045             for (i = 0, len = cards.length; i < len; i++) {
11046
11047                 card = cards[i];
11048
11049                 if (card.pattern.test(num)) {
11050                     return card;
11051                 }
11052
11053             }
11054         };
11055
11056         var _fromType = function(type) {
11057             var card, i, len;
11058
11059             for (i = 0, len = cards.length; i < len; i++) {
11060
11061                 card = cards[i];
11062
11063                 if (card.type === type) {
11064                     return card;
11065                 }
11066
11067             }
11068         };
11069
11070         return {
11071             fromNumber: function(val) {
11072                 return _fromNumber(val);
11073             },
11074             fromType: function(val) {
11075                 return _fromType(val);
11076             },
11077             defaultFormat: function() {
11078                 return defaultFormat;
11079             },
11080             defaultInputFormat: function() {
11081                 return defaultInputFormat;
11082             }
11083         };
11084
11085     }])
11086 .factory('_Validate', ['Cards', '$parse', function(Cards, $parse) {
11087         var __indexOf = [].indexOf || function(item)
11088         {
11089             for (var i = 0, l = this.length; i < l; i++)
11090             {
11091                 if (i in this && this[i] === item)
11092                 {
11093                     return i;
11094                 }
11095             }
11096             return -1;
11097         };
11098
11099         var _luhnCheck = function(num) {
11100             var digit, digits, odd, sum, i, len;
11101
11102             odd = true;
11103             sum = 0;
11104             digits = (num + '').split('').reverse();
11105
11106             for (i = 0, len = digits.length; i < len; i++) {
11107
11108                 digit = digits[i];
11109                 digit = parseInt(digit, 10);
11110
11111                 if ((odd = !odd)) {
11112                     digit *= 2;
11113                 }
11114
11115                 if (digit > 9) {
11116                     digit -= 9;
11117                 }
11118
11119                 sum += digit;
11120
11121             }
11122
11123             return sum % 10 === 0;
11124         };
11125
11126         var _validators = {};
11127
11128         _validators['cvc'] = function(cvc, ctrl, scope, attr) {
11129             var ref, ref1;
11130
11131             // valid if empty - let ng-required handle empty
11132             if ((angular.isUndefined(cvc)) || (cvc === null) || (cvc.length === 0))
11133             {
11134                 return true;
11135             }
11136
11137             if (!/^\d+$/.test(cvc)) {
11138                 return false;
11139             }
11140
11141             var type;
11142             if (attr.paymentsTypeModel) {
11143                 var typeModel = $parse(attr.paymentsTypeModel);
11144                 type = typeModel(scope);
11145             }
11146
11147             if (type)
11148             {
11149                 ref1 = Cards.fromType(type);
11150                 return (ref = cvc.length, __indexOf.call((ref1 !== null) ? ref1.cvcLength : void 0, ref)) >= 0;
11151             }
11152             else
11153             {
11154                 return cvc.length >= 3 && cvc.length <= 4;
11155             }
11156         };
11157         _validators['zip'] = function(zip, ctrl, scope, attr) {
11158             var ref, ref1;
11159
11160             // valid if empty - let ng-required handle empty
11161             if ((angular.isUndefined(zip)) || (zip === null) || (zip.length === 0))
11162             {
11163                 return true;
11164             }
11165
11166             if (!/^\d+$/.test(zip)) {
11167                 return false;
11168             }
11169
11170             var type;
11171             if (attr.paymentsTypeModel) {
11172                 var typeModel = $parse(attr.paymentsTypeModel);
11173                 type = typeModel(scope);
11174             }
11175             if (type)
11176             {
11177                 ref1 = Cards.fromType(type);
11178                 return (ref = zip.length, __indexOf.call(ref1 !== null ? ref1.zipLength : void 0, ref)) >= 0;
11179             }
11180             else
11181             {
11182                 return zip.length < 6;
11183             }
11184         };
11185         _validators['card'] = function(num, ctrl, scope, attr) {
11186             var card, ref, typeModel;
11187
11188             if (attr.paymentsTypeModel) {
11189                 typeModel = $parse(attr.paymentsTypeModel);
11190             }
11191
11192             var clearCard = function() {
11193                 if (typeModel) {
11194                     typeModel.assign(scope, null);
11195                 }
11196                 ctrl.$card = null;
11197             };
11198
11199             // valid if empty - let ng-required handle empty
11200             if ((angular.isUndefined(num)) || (num === null) || (num.length === 0)) {
11201                 clearCard();
11202                 return true;
11203             }
11204
11205             num = (num + '').replace(/\s+|-/g, '');
11206
11207             if (!/^\d+$/.test(num)) {
11208                 clearCard();
11209                 return false;
11210             }
11211
11212             card = Cards.fromNumber(num);
11213             if (!card) {
11214                 clearCard();
11215                 return false;
11216             }
11217             ctrl.$card = angular.copy(card);
11218
11219             if (typeModel) {
11220                 typeModel.assign(scope, card.type);
11221             }
11222
11223             ret = (ref = num.length, __indexOf.call(card.length, ref) >= 0) && (card.luhn === false || _luhnCheck(num));
11224             return ret;
11225         };
11226         return function(type, val, ctrl, scope, attr) {
11227             if (!_validators[type]) {
11228
11229                 types = Object.keys(_validators);
11230
11231                 errstr = 'Unknown type for validation: "' + type + '". ';
11232                 errstr += 'Should be one of: "' + types.join('", "') + '"';
11233
11234                 throw errstr;
11235             }
11236             return _validators[type](val, ctrl, scope, attr);
11237         };
11238     }])
11239 .factory('_ValidateWatch', ['_Validate', function(_Validate) {
11240
11241         var _validatorWatches = {};
11242
11243         _validatorWatches['cvc'] = function(type, ctrl, scope, attr) {
11244             if (attr.paymentsTypeModel) {
11245                 scope.$watch(attr.paymentsTypeModel, function(newVal, oldVal) {
11246                     if (newVal !== oldVal) {
11247                         var valid = _Validate(type, ctrl.$modelValue, ctrl, scope, attr);
11248                         ctrl.$setValidity(type, valid);
11249                     }
11250                 });
11251             }
11252         };
11253         _validatorWatches['zip'] = function(type, ctrl, scope, attr) {
11254             if (attr.paymentsTypeModel) {
11255                 scope.$watch(attr.paymentsTypeModel, function(newVal, oldVal) {
11256                     if (newVal !== oldVal) {
11257                         var valid = _Validate(type, ctrl.$modelValue, ctrl, scope, attr);
11258                         ctrl.$setValidity(type, valid);
11259                     }
11260                 });
11261             }
11262         };
11263         return function(type, ctrl, scope, attr) {
11264             if (_validatorWatches[type]) {
11265                 return _validatorWatches[type](type, ctrl, scope, attr);
11266             }
11267         };
11268     }])
11269 .directive('validateCard', ['$window', '_Validate', '_ValidateWatch', function($window, _Validate, _ValidateWatch) {
11270         return {
11271             restrict: 'A',
11272             require: 'ngModel',
11273             link: function(scope, elem, attr, ctrl) {
11274
11275                 var type = attr.validateCard;
11276                 _ValidateWatch(type, ctrl, scope, attr);
11277                 var validateFn = function(val) {
11278                     var valid = _Validate(type, val, ctrl, scope, attr);
11279                     ctrl.$setValidity(type, valid);
11280                     if (type === 'card')
11281                     {
11282                         if (ctrl.$card === null)
11283                         {
11284                             if ((val == null) || (val === "") || (val === ''))
11285                             {
11286                                 scope.invalidCardError = '';
11287                                 scope.invalidCard = "";
11288                             }
11289                             else if (val.length >= 1)
11290                             {
11291                                 scope.invalidCardError = 'error';
11292                                 scope.invalidCard = "The number entered is not a recognized credit card number.";
11293                             }
11294                         }
11295                         else
11296                         {
11297                             if (!valid)
11298                             {
11299                                 if (ctrl.$card.length.indexOf(val.length) >= 0)
11300                                 {
11301                                     scope.invalidCardError = 'error';
11302                                     scope.invalidCard = "The number entered is not a recognized credit card number.";
11303                                 }
11304                                 else
11305                                 {
11306                                     scope.invalidCardError = '';
11307                                     scope.invalidCard = "";
11308                                 }
11309                             }
11310                             else
11311                             {
11312                                 scope.invalidCardError = '';
11313                                 scope.invalidCard = "";
11314                             }
11315                         }
11316                         elem.bind("blur", function()
11317                         {
11318                             if ((!valid) || (ctrl.$card === null))
11319                             {
11320                                 scope.invalidCardError = 'error';
11321                                 scope.invalidCard = "The number entered is not a recognized credit card number.";
11322                             }
11323                             else
11324                             {
11325                                 scope.invalidCardError = '';
11326                                 scope.invalidCard = "";
11327                             }
11328                         });
11329                     }
11330                     return valid ? val : undefined;
11331                 };
11332                 ctrl.$formatters.push(validateFn);
11333                 ctrl.$parsers.push(validateFn);
11334             }
11335         };
11336     }])
11337 .directive('creditCardImage', function() {
11338     return{
11339         templateUrl: 'app/scripts/ng_js_att_tpls/formField/creditCardImage.html',
11340         replace: false,
11341         transclude: false,
11342         link: function(scope, element, attr)
11343         {
11344             scope.$watch(attr.creditCardImage, function(newVal, oldVal)
11345             {
11346                 if (newVal !== oldVal)
11347                 {
11348                     scope.cvc = '';
11349                     if (!angular.isUndefined(newVal) && newVal !== null)
11350                     {
11351                         scope.newValCCI = 'show-' + newVal;
11352                     }
11353                     if (newVal === null)
11354                     {
11355                         scope.newValCCI = '';
11356                     }
11357                 }
11358             });
11359         }
11360     };
11361 })
11362 .directive('securityCodeImage', ['$document', function($document) {
11363         return{
11364             templateUrl: 'app/scripts/ng_js_att_tpls/formField/cvcSecurityImg.html',
11365             replace: false,
11366             transclude: false,
11367             link: function(scope, element, attr)
11368             {
11369                 scope.$watch(attr.securityCodeImage, function(newVal, oldVal)
11370                 {
11371                     if (newVal !== oldVal)
11372                     {
11373                         if (!angular.isUndefined(newVal) && newVal !== null)
11374                         {
11375                             if (newVal === 'amexI')
11376                             {
11377                                 scope.newValI = 'ccv2-security-amex';
11378                                 scope.newValIAlt = "The 4 digit CVC security code is on the front of the card.";
11379                                 scope.cvcPlaceholder = "4 digits";
11380                                 scope.cvcMaxlength = 4;
11381                             }
11382                             else if (newVal === 'visaI')
11383                             {
11384                                 scope.newValI = 'ccv2-security';
11385                                 scope.newValIAlt = "The CVC security code is on the back of your card right after the credit card number.";
11386                                 scope.cvcPlaceholder = "3 digits";
11387                                 scope.cvcMaxlength = 3;
11388                             }
11389                         }
11390                         if (newVal === null)
11391                         {
11392                             scope.newValI = 'ccv2-security';
11393                             scope.cvcPlaceholder = "3 digits";
11394                             scope.cvcMaxlength = 3;
11395                             scope.newValIAlt = "The CVC security code is on the back of your card right after the credit card number.";
11396                         }
11397
11398                     }
11399                 });
11400                 element.bind("click", function(ev) {
11401                     ev.preventDefault();
11402                     if (element.find("button").hasClass("active")) {
11403                         element.find("button").removeClass("active");
11404                     }
11405                     else {
11406                         element.find("button").addClass("active");
11407                     }
11408                 });
11409
11410                 var window = angular.element($document);
11411                 window.bind("click", function(ev) {
11412                     var targetClassname = ev.target.className;
11413                     if ((targetClassname !== "btn btn-alt btn-tooltip active")) {
11414                         if (element.find("button").hasClass("active")) {
11415                             element.find("button").removeClass("active");
11416                         }
11417                     }
11418
11419                 });
11420             }
11421         };
11422     }]);
11423
11424 angular.module('att.abs.hourpicker', ['att.abs.utilities'])
11425     .constant('hourpickerConfig', {
11426         days: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
11427         customOption: 'Custom'
11428     })
11429
11430 .controller('hourPickerController', ['$scope', function ($scope) {
11431
11432     $scope.options = [];
11433     this.setOptions = function (value, fromtime, totime, preselect, uncheckedFromTime, uncheckedToTime) {
11434         $scope.options.push(value);
11435
11436         if (preselect !== undefined) {
11437             $scope.preselect = preselect;
11438         }
11439
11440         var daycount;
11441
11442         if (fromtime !== undefined) {
11443             $scope.fromtime = fromtime;
11444             for (daycount in $scope.days) {
11445                 if ($scope.days.hasOwnProperty(daycount)) {
11446                     $scope.FrtimeList[$scope.days[daycount]] = {};
11447                     if (uncheckedFromTime !== undefined) {
11448                         $scope.FrtimeList[$scope.days[daycount]].value = uncheckedFromTime;
11449                         $scope.selectedFromOption[$scope.days[daycount]] = uncheckedFromTime;
11450                     } else {
11451                         $scope.FrtimeList[$scope.days[daycount]].value = fromtime[0].value;
11452                         $scope.selectedFromOption[$scope.days[daycount]] = fromtime[0].value;
11453                     }
11454                 }
11455             }
11456         }
11457         if (totime !== undefined) {
11458             $scope.totime = totime;
11459             for (daycount in $scope.days) {
11460                 if ($scope.days.hasOwnProperty(daycount)) {
11461                     $scope.TotimeList[$scope.days[daycount]] = {};
11462                     if (uncheckedToTime !== undefined) {
11463                         $scope.TotimeList[$scope.days[daycount]].value = uncheckedToTime;
11464                         $scope.selectedToOption[$scope.days[daycount]] = uncheckedToTime;
11465                     } else {
11466                         $scope.TotimeList[$scope.days[daycount]].value = totime[0].value;
11467                         $scope.selectedToOption[$scope.days[daycount]] = totime[0].value;
11468                     }
11469                     $scope.showToTimeErrorDay[$scope.days[daycount]] = false;
11470                 }
11471             }
11472         }
11473
11474         if (uncheckedFromTime !== undefined) {
11475             $scope.uncheckedFromTime = uncheckedFromTime;
11476         }
11477         if (uncheckedToTime !== undefined) {
11478             $scope.uncheckedToTime = uncheckedToTime;
11479         }
11480     };
11481
11482     this.getSelectedOption = function () {
11483         return $scope.selectedOption;
11484     };
11485
11486     this.setToTimeErrorDay = function (day, flag) {
11487         $scope.showToTimeErrorDay[day] = flag;
11488     };
11489 }])
11490
11491 .directive('attHourpickerOption', [function () {
11492     return {
11493         restrict: 'EA',
11494         require: '^attHourpicker',
11495         scope: {
11496             option: "=option",
11497             fromtime: "=fromtime",
11498             totime: "=totime",
11499             preselect: "=preselect",
11500             uncheckedFromTime: "=",
11501             uncheckedToTime: "="
11502         },
11503         link: function (scope, element, attr, ctrl) {
11504             ctrl.setOptions(scope.option,
11505                 scope.fromtime,
11506                 scope.totime,
11507                 scope.preselect,
11508                 scope.uncheckedFromTime,
11509                 scope.uncheckedToTime);
11510         }
11511     };
11512 }])
11513
11514 .directive('attHourpicker', ["hourpickerConfig", "$document", "$log", "$documentBind", "$timeout", function (hourpickerConfig, $document, $log, $documentBind, $timeout) {
11515     return {
11516         require: 'ngModel',
11517         restrict: 'EA',
11518         controller: 'hourPickerController',
11519         transclude: true,
11520         scope: {
11521             model: "=ngModel",
11522             resetFlag: "=?"
11523         },
11524         templateUrl: 'app/scripts/ng_js_att_tpls/hourpicker/hourpicker.html',
11525         link: function (scope, element, attr, ctrl) {
11526             var flag = false;
11527             scope.isFromDropDownOpen = false;
11528             scope.isToDropDownOpen = false;
11529             var dropDownOpenValue = "";
11530             var custTime = {};
11531             scope.days = hourpickerConfig.days;
11532             scope.daysList = {};
11533             scope.FrtimeList = {};
11534             scope.FrtimeListDay = {};
11535             scope.TotimeListDay = {};
11536             scope.selectedFromOption = {};
11537             scope.selectedToOption = {};
11538             scope.TotimeList = {};
11539             scope.selectedIndex = 0;
11540             scope.selectedOption = "Select from list";
11541             scope.customTime = [];
11542
11543             scope.resetFlag = false;
11544             scope.showToTimeErrorDay = {};
11545             scope.validatedCustomPreselect = [];
11546
11547             scope.$watch('resetFlag', function (newVal, oldVal) {
11548                 if (newVal !== oldVal) {
11549                     if (newVal && scope.selectedOption === hourpickerConfig.customOption) {
11550                         //disable and reset all days checkbox
11551                         for (day in scope.daysList) {
11552                             if (scope.daysList.hasOwnProperty(day)) {
11553                                 scope.daysList[day] = false;
11554                                 scope.addSelectedValue(day);
11555                             }
11556                         }
11557                         scope.preselectUpdateFxn(scope.preselect);
11558                     }
11559                     scope.resetFlag = false;
11560                 }
11561             });
11562
11563             scope.$watch('selCategory', function (value) {
11564                 if (value) {
11565                     ctrl.$setViewValue(value);
11566                 }
11567             }, true);
11568
11569             scope.updateData = function (value) {
11570                 if (value.constructor === Array) {
11571                     scope.showDaysSelector = true;
11572                     scope.selectedOption = hourpickerConfig.customOption;
11573                     for (var arry in value) {
11574                         if (value.hasOwnProperty(arry)) {
11575                             var day = value[arry].day;
11576                             
11577                             if (typeof value[arry].preEnabled === 'boolean' && value[arry].preEnabled) {
11578                                 scope.daysList[day] = true;
11579                             } else {
11580                                 scope.daysList[day] = false;
11581                             }
11582                             
11583                             for (var fromcount in scope.fromtime) {
11584                                 if (scope.fromtime[fromcount].value === value[arry].FromTime && !scope.uncheckedFromTime) {
11585                                     scope.FrtimeList[day].value = scope.fromtime[fromcount].value;
11586                                     scope.selectedFromOption[day] = scope.FrtimeList[day].value;
11587                                 }
11588                             }
11589                             for (var tocount in scope.totime) {
11590                                 if (scope.totime[tocount].value === value[arry].ToTime && !scope.uncheckedToTime) {
11591                                     scope.TotimeList[day].value = scope.totime[tocount].value;
11592                                     scope.selectedToOption[day] = scope.TotimeList[day].value;
11593                                 }
11594                             }
11595                             
11596                             scope.addSelectedValue(day, value[arry].FromTime, value[arry].ToTime);
11597
11598                             //for IE8 Fix
11599                             if (parseInt(arry) + 1 === value.length) {
11600                                 break;
11601                             }
11602                         }
11603                     }
11604                 } else {
11605                     scope.selectOption(value.day);
11606                 }
11607             };
11608
11609             scope.$watch('preselect', function (value) {
11610                 scope.preselectUpdateFxn(value);
11611             });
11612
11613             scope.preselectUpdateFxn = function (value) {
11614                 if (value !== undefined) {
11615                     if (scope.options) {
11616                         value = scope.validatePreselectData(value);
11617                     }
11618                     if (value === "") {
11619                         return;
11620                     }
11621                     scope.updateData(value);
11622                 }
11623             };
11624
11625             scope.validatePreselectData = function (value) {
11626                 if (value.constructor === Array) {
11627                     for (var arry in value) {
11628                         if (value.hasOwnProperty(arry)) {
11629                             var day = value[arry].day;
11630                             var isDayFound = false;
11631                             var isFrmFound = false;
11632                             var isToFound = false;
11633                             for (var daycount in scope.days) {
11634                                 if (scope.days[daycount] === day) {
11635                                     isDayFound = true;
11636                                     break;
11637                                 }
11638                             }
11639                             if (!isDayFound) {
11640                                 value.splice(arry, 1);
11641                                 continue;
11642                             }
11643                             for (var fromcount in scope.fromtime) {
11644                                 if (scope.fromtime[fromcount].value === value[arry].FromTime) {
11645                                     isFrmFound = true;
11646                                     break;
11647                                 }
11648                             }
11649                             if (!isFrmFound) {
11650                                 value[arry].FromTime = scope.fromtime[0].value;
11651                             }
11652                             for (var tocount in scope.totime) {
11653                                 if (scope.totime[tocount].value === value[arry].ToTime) {
11654                                     isToFound = true;
11655                                     break;
11656                                 }
11657                             }
11658                             if (!isToFound) {
11659                                 value[arry].ToTime = scope.totime[0].value;
11660                             }
11661
11662                             if (typeof value[arry].preEnabled === 'boolean' && value[arry].preEnabled) {
11663                                 value[arry].preEnabled = true;
11664                             } else {
11665                                 value[arry].preEnabled = false;
11666                             }
11667                             
11668                             scope.validatedCustomPreselect[day] = {};
11669                             scope.validatedCustomPreselect[day].FromTime = value[arry].FromTime;
11670                             scope.validatedCustomPreselect[day].ToTime = value[arry].ToTime;
11671
11672                             //for IE8 Fix
11673                             if (parseInt(arry) + 1 === value.length) {
11674                                 break;
11675                             }
11676                         }
11677                     }
11678                 } else {
11679                     var isOptionFound = false;
11680                     for (var optcount in scope.options) {
11681                         if (scope.options[optcount] === value.day) {
11682                             isOptionFound = true;
11683                             break;
11684                         }
11685                     }
11686                     if (!isOptionFound) {
11687                         value = "";
11688                     }
11689                 }
11690                 return value;
11691             };
11692
11693             scope.selectPrevNextValue = function ($event, arrayValues, currValue) {
11694
11695                 var value;
11696                 var index = 0;
11697                 if ($event.keyCode === 38) {
11698                     value = -1;
11699                 } else if ($event.keyCode === 40) {
11700                     value = 1;
11701                 } else {
11702                     return currValue;
11703                 }
11704
11705                 if (arrayValues.indexOf(currValue) !== -1) {
11706                     index = arrayValues.indexOf(currValue) + value;
11707                 } else {
11708                     for (var count in arrayValues) {
11709                         if (arrayValues[count].value === currValue) {
11710                             index = parseInt(count) + value;
11711                             break;
11712                         }
11713                     }
11714                 }
11715
11716                 if (index === arrayValues.length) {
11717                     index = index - 1;
11718                 } else if (index === -1) {
11719                     index = index + 1;
11720                 }
11721
11722                 $event.preventDefault();
11723                 if (arrayValues[index].value) {
11724                     return arrayValues[index].value;
11725                 } else {
11726                     return arrayValues[index];
11727                 }
11728             };
11729
11730             scope.showDropdown = function () {
11731                 scope.showlist = !scope.showlist;
11732                 flag = !flag;
11733             };
11734
11735             scope.showfromDayDropdown = function (value) {
11736                 //close dropdown if any other From drop down is opened
11737                 for (count in scope.FrtimeListDay) {
11738                     if (count !== value && scope.FrtimeListDay[count]) {
11739                         scope.FrtimeListDay[count] = false;
11740                     }
11741                 }
11742                 for (count in scope.TotimeListDay) {
11743                     if (scope.TotimeListDay[count]) {
11744                         scope.TotimeListDay[count] = false;
11745                     }
11746                 }
11747                 scope.FrtimeListDay[value] = !scope.FrtimeListDay[value];
11748                 flag = !flag;
11749                 scope.showlist = false;
11750
11751                 //save model value so we can close current dropdown on click of other part of the document
11752                 if (scope.FrtimeListDay[value]) {
11753                     scope.isFromDropDownOpen = true;
11754                     dropDownOpenValue = value;
11755                 } else {
11756                     scope.isFromDropDownOpen = false;
11757                 }
11758
11759                 $timeout(function () {
11760                     if (scope.FrtimeListDay[value]) {
11761                         var daysContainerDIV = angular.element(element)[0].querySelector(".customdays-width");
11762                         var containerUL = angular.element(daysContainerDIV.querySelector('.select2-container-active')).parent()[0].querySelector("ul");
11763                         var selectedElemTopPos = angular.element(containerUL.querySelector('.selectedItemInDropDown'))[0].offsetTop;
11764                         angular.element(containerUL)[0].scrollTop = selectedElemTopPos;
11765                     }
11766                 });
11767             };
11768
11769             scope.showtoDayDropdown = function (value) {
11770                 //close dropdown if any other To drop down is opened
11771                 for (count in scope.TotimeListDay) {
11772                     if (count !== value && scope.TotimeListDay[count]) {
11773                         scope.TotimeListDay[count] = false;
11774                     }
11775                 }
11776                 for (count in scope.FrtimeListDay) {
11777                     if (scope.FrtimeListDay[count]) {
11778                         scope.FrtimeListDay[count] = false;
11779                     }
11780                 }
11781                 scope.TotimeListDay[value] = !scope.TotimeListDay[value];
11782                 flag = !flag;
11783                 scope.showlist = false;
11784
11785                 //save model value so we can close current dropdown on click of other part of the document
11786                 if (scope.TotimeListDay[value]) {
11787                     scope.isToDropDownOpen = true;
11788                     dropDownOpenValue = value;
11789
11790                 } else {
11791                     scope.isToDropDownOpen = false;
11792                 }
11793
11794                 $timeout(function () {
11795                     if (scope.TotimeListDay[value]) {
11796                         var daysContainerDIV = angular.element(element)[0].querySelector(".customdays-width");
11797                         var containerUL = angular.element(daysContainerDIV.querySelector('.select2-container-active')).parent()[0].querySelector("ul");
11798                         var selectedElemTopPos = angular.element(containerUL.querySelector('.selectedItemInDropDown'))[0].offsetTop;
11799                         angular.element(containerUL)[0].scrollTop = selectedElemTopPos;
11800                     }
11801                 });
11802             };
11803
11804             scope.selectFromDayOption = function (day, value) {
11805                 scope.selectedFromOption[day] = value;
11806                 scope.FrtimeList[day].value = value;
11807                 scope.FrtimeListDay[day] = false;
11808                 scope.isFromDropDownOpen = false;
11809             };
11810
11811             scope.selectToDayOption = function (day, value) {
11812                 scope.selectedToOption[day] = value;
11813                 scope.TotimeList[day].value = value;
11814                 scope.TotimeListDay[day] = false;
11815                 scope.isToDropDownOpen = false;
11816             };
11817
11818             scope.addSelectedValue = function (value, fromtime, totime) {
11819                 var count, len;
11820                 if (scope.daysList[value] !== undefined && !scope.daysList[value]) {
11821                     for (count = 0, len = scope.customTime.length; count < len; count++) {
11822                         if (scope.customTime[count].day === value) {
11823                             if (scope.uncheckedFromTime) {
11824                                 scope.selectedFromOption[scope.customTime[count].day] = scope.uncheckedFromTime;
11825                             } else {
11826                                 scope.selectedFromOption[scope.customTime[count].day] = scope.FrtimeList[scope.customTime[count].day].value;
11827                             }
11828
11829                             if (scope.uncheckedToTime) {
11830                                 scope.selectedToOption[scope.customTime[count].day] = scope.uncheckedToTime;
11831                             } else {
11832                                 scope.selectedToOption[scope.customTime[count].day] = scope.TotimeList[scope.customTime[count].day].value;
11833                             }
11834
11835                             scope.customTime.splice(count, 1);
11836                             break;
11837                         }
11838                     }
11839                 } else {
11840                     if (scope.selectedFromOption[value] === scope.uncheckedFromTime) {
11841
11842                         if (angular.isDefined(scope.validatedCustomPreselect[value])) {
11843                             scope.selectedFromOption[value] = scope.validatedCustomPreselect[value].FromTime;
11844                             fromtime = scope.validatedCustomPreselect[value].FromTime;
11845                             scope.FrtimeList[value].value = scope.validatedCustomPreselect[value].FromTime;
11846                         } else {
11847                             scope.selectedFromOption[value] = scope.fromtime[0].value;
11848                             fromtime = scope.fromtime[0].value;
11849                             scope.FrtimeList[value].value = scope.fromtime[0].value;
11850                         }
11851
11852                     }
11853
11854                     if (scope.selectedToOption[value] === scope.uncheckedToTime) {
11855
11856                         if (angular.isDefined(scope.validatedCustomPreselect[value])) {
11857                             scope.selectedToOption[value] = scope.validatedCustomPreselect[value].ToTime;
11858                             totime = scope.validatedCustomPreselect[value].ToTime;
11859                             scope.TotimeList[value].value = scope.validatedCustomPreselect[value].ToTime;
11860                         } else {
11861                             scope.selectedToOption[value] = scope.totime[0].value;
11862                             totime = scope.totime[0].value;
11863                             scope.TotimeList[value].value = scope.totime[0].value;
11864                         }
11865                     }
11866
11867                     custTime["day"] = value;
11868                     custTime["FromTime"] = scope.FrtimeList[value].value;
11869                     custTime["ToTime"] = scope.TotimeList[value].value;
11870
11871                     for (count = 0, len = scope.customTime.length; count < len; count++) {
11872                         if (scope.customTime[count].day === value) {
11873                             scope.customTime[count].FromTime = custTime["FromTime"];
11874                             scope.customTime[count].ToTime = custTime["ToTime"];
11875                             break;
11876                         }
11877                     }
11878                     if (count === len) {
11879                         var x = angular.copy(custTime);
11880                         scope.customTime.push(x);
11881                     }
11882                 }
11883                 scope.selCategory = scope.customTime;
11884             };
11885
11886
11887             var outsideClick = function () {
11888                 if (scope.showlist) {
11889                     scope.$apply(function () {
11890                         scope.showlist = false;
11891                     });
11892                 }
11893             };
11894
11895             $documentBind.click('showlist', outsideClick, scope);
11896
11897             var outsideClickFromDropdown = function () {
11898                 scope.$apply(function () {
11899                     if (scope.isFromDropDownOpen) {
11900                         scope.FrtimeListDay[dropDownOpenValue] = false;
11901                         scope.isFromDropDownOpen = false;
11902                     }
11903                 });
11904             };
11905
11906             $documentBind.click('isFromDropDownOpen', outsideClickFromDropdown, scope);
11907
11908             var outsideClickToDropdown = function () {
11909                 scope.$apply(function () {
11910                     if (scope.isToDropDownOpen) {
11911                         scope.TotimeListDay[dropDownOpenValue] = false;
11912                         scope.isToDropDownOpen = false;
11913                     }
11914                 });
11915             };
11916
11917             $documentBind.click('isToDropDownOpen', outsideClickToDropdown, scope);
11918
11919             scope.selectOption = function (sItem) {
11920
11921                 if (sItem === hourpickerConfig.customOption) {
11922                     scope.showDaysSelector = true;
11923                     scope.selCategory = scope.customTime;
11924                 } else {
11925                     scope.showDaysSelector = false;
11926                     var fromTime = /[0-9]\s?am/i.exec(sItem);
11927                     var toTime = /[0-9]\s?pm/i.exec(sItem);
11928                     scope.selCategory = {
11929                         day: sItem,
11930                         FromTime: fromTime === null ? 'NA' : fromTime[0],
11931                         ToTime: toTime === null ? 'NA' : toTime[0]
11932                     };
11933                 }
11934
11935                 scope.showlist = false;
11936                 flag = false;
11937                 scope.selectedOption = sItem;
11938             };
11939         }
11940     };
11941 }])
11942
11943 .directive('attHourpickerValidator', ['hourpickerConfig', function (hourpickerConfig) {
11944     return {
11945         restrict: 'A',
11946         require: ['attHourpicker', 'ngModel'],
11947         link: function (scope, element, attr, ctrl) {
11948
11949             var attHourpickerCtrl = ctrl[0];
11950             var ngModelCtrl = ctrl[1];
11951
11952             //required format [h:MM tt] like '1:10 PM'
11953             var convertTimeStrngToMilitaryFormat = function (time) {
11954                 var hours = Number(time.match(/^(\d+)/)[1]);
11955                 var minutes = Number(time.match(/:(\d+)/)[1]);
11956                 var AMPM = (time.match(/\s(.*)$/)[1]).toUpperCase();
11957                 if (AMPM === 'PM' && hours < 12) {
11958                     hours = hours + 12;
11959                 }
11960                 if (AMPM === 'AM' && hours === 12) {
11961                     hours = hours - 12;
11962                 }
11963                 var sHours = hours.toString();
11964                 var sMinutes = minutes.toString();
11965                 if (hours < 10) {
11966                     sHours = '0' + sHours;
11967                 }
11968                 if (minutes < 10) {
11969                     sMinutes = '0' + sMinutes;
11970                 }
11971                 return parseInt(sHours + sMinutes, 10);
11972             };
11973
11974             var compareTimeStrings = function (fromTimeString, toTimeString) {
11975                 var fromMilitaryTime = convertTimeStrngToMilitaryFormat(fromTimeString);
11976                 var toMilitaryTime = convertTimeStrngToMilitaryFormat(toTimeString);
11977                 return (toMilitaryTime - fromMilitaryTime);
11978             };
11979
11980             var validateCustomData = function (finalDataModal) {
11981
11982                 if (attHourpickerCtrl.getSelectedOption() === hourpickerConfig.customOption) {
11983
11984                     var errorDaysCount = 0;
11985
11986                     for (var item in finalDataModal) {
11987                         if (finalDataModal.hasOwnProperty(item)) {
11988                             if (compareTimeStrings(finalDataModal[item].FromTime, finalDataModal[item].ToTime) <= 0) {
11989                                 attHourpickerCtrl.setToTimeErrorDay(finalDataModal[item].day, true);
11990                                 errorDaysCount++;
11991                             } else {
11992                                 attHourpickerCtrl.setToTimeErrorDay(finalDataModal[item].day, false);
11993                             }
11994                         }
11995                     }
11996
11997                     if (errorDaysCount > 0) {
11998                         //validation error
11999                         ngModelCtrl.$setValidity('validationStatus', false);
12000                         return [];
12001                     } else {
12002                         //validation successful
12003                         ngModelCtrl.$setValidity('validationStatus', true);
12004                         return finalDataModal;
12005                     }
12006                 } else {
12007                     //default case no validation
12008                     ngModelCtrl.$setValidity('validationStatus', true);
12009                     return finalDataModal;
12010                 }
12011
12012             };
12013
12014             ngModelCtrl.$parsers.unshift(validateCustomData);
12015         }
12016     };
12017 }]);
12018 angular.module('att.abs.iconButtons', [])
12019         .constant('buttonConfig', {
12020             activeClass: 'active--button',
12021             toggleEvent: 'click'
12022         })
12023         .directive('attIconBtnRadio', ['buttonConfig', function(buttonConfig) {
12024                 var activeClass = buttonConfig.activeClass || 'active--button';
12025                 var toggleEvent = buttonConfig.toggleEvent || 'click';
12026                 return {
12027                     require: 'ngModel',
12028                     link: function(scope, element, attrs, ngModelCtrl) {
12029                         element.attr("tabindex","0");
12030                         element.append("<span class='hidden-spoken'>"+attrs.attIconBtnRadio+"</span>");
12031                         //model -> UI
12032                         ngModelCtrl.$render = function() {
12033                             element.parent().toggleClass(activeClass, angular.equals(ngModelCtrl.$modelValue, attrs.attIconBtnRadio));
12034                         };
12035                         //ui->model
12036                         element.parent().bind(toggleEvent, function() {
12037                             if (!element.parent().hasClass(activeClass)) {
12038                                 scope.$apply(function() {
12039                                     ngModelCtrl.$setViewValue(attrs.attIconBtnRadio);
12040                                     ngModelCtrl.$render();
12041                                 });
12042                             }
12043                         });
12044                     }
12045                 };
12046             }])
12047         .directive('attIconBtnCheckbox', ['buttonConfig', function(buttonConfig) {
12048                 var activeClass = buttonConfig.activeClass || 'active--button';
12049                 var toggleEvent = buttonConfig.toggleEvent || 'click';
12050                 return {
12051                     require: 'ngModel',
12052                     link: function(scope, element, attrs, ngModelCtrl) {
12053                         element.attr("tabindex","0");
12054                         element.append("<span class='hidden-spoken'>"+attrs.attIconBtnCheckbox+"</span>");
12055                         function getTrueValue() {
12056                             var trueValue = scope.$eval(attrs.btnCheckboxTrue);
12057                             return angular.isDefined(trueValue) ? trueValue : true;
12058                         }
12059                         function getFalseValue() {
12060                             var falseValue = scope.$eval(attrs.btnCheckboxFalse);
12061                             return angular.isDefined(falseValue) ? falseValue : false;
12062                         }
12063                         //model -> UI
12064                         ngModelCtrl.$render = function() {
12065                             element.parent().toggleClass(activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue()));
12066                         };
12067                         //ui->model
12068                         element.parent().bind(toggleEvent, function() {
12069                             scope.$apply(function() {
12070                                 ngModelCtrl.$setViewValue(element.parent().hasClass(activeClass) ? getFalseValue() : getTrueValue());
12071                                 ngModelCtrl.$render();
12072                             });
12073                         });
12074                     }
12075                 };
12076             }]);
12077
12078 angular.module('att.abs.links', ['ngSanitize'])
12079         .directive('attLink', [function() {
12080                 return {
12081                     restrict: 'A',
12082                     link: function(scope, elem) {
12083                         elem.addClass('link');
12084                         if(!(elem.attr('href'))){
12085                             elem.attr("tabindex", "0");
12086                         }
12087                     }
12088                 };
12089             }])
12090         .directive('attLinkVisited', [function() {
12091                 return {
12092                     restrict: 'A',
12093                     link: function(scope, elem) {
12094                         elem.addClass('link--visited');
12095                         if(!(elem.attr('href'))){
12096                             elem.attr("tabindex", "0");
12097                         }
12098                     }
12099                 };
12100             }])
12101         .directive('attReadmore', ['$timeout',function($timeout) {
12102                 return {
12103                     restrict: 'A',
12104                     scope: {
12105                         lines:"@noOfLines",
12106                         textModel: "=",
12107                         //attribute to use readmore inside accordion
12108                         isOpen: "="
12109                     },
12110                     templateUrl: 'app/scripts/ng_js_att_tpls/links/readMore.html',
12111                     link: function(scope, elem) {
12112                         var height = 1;
12113                         scope.$watch('textModel', function(val){
12114                             if(!val){
12115                                 scope.textToDisplay = '';
12116                                 scope.readMoreLink = false;
12117                                 scope.readLessLink = false;
12118                                 scope.readFlag = false;
12119                             }
12120                             else{
12121                                 if (typeof String.prototype.trim !== 'function') {
12122                                     String.prototype.trim = function() {
12123                                        return this.replace(/^\s+|\s+$/g, '');
12124                                     };
12125                                 }
12126                                 scope.textToDisplay = val.trim();
12127                                 scope.readFlag = true;
12128                                 $timeout(function() {
12129                                     var readElem = elem[0].children[0].children[0];
12130                                     if(height===1){
12131                                         if(window.getComputedStyle){
12132                                             height = parseInt(scope.lines) * parseFloat(window.getComputedStyle(readElem,null).getPropertyValue("height"));
12133                                         }
12134                                         else {
12135                                             height = parseInt(scope.lines) * parseFloat(readElem.currentStyle.height);
12136                                         }
12137                                         scope.elemHeight = height;
12138                                         scope.readLinkStyle = {'height': scope.elemHeight + 'px'};
12139                                     }
12140                                 });
12141                                 scope.readMoreLink = true;
12142                                 scope.readLessLink = false;
12143                             }
12144                         });
12145                         // Code to use readmore inside accordion
12146                         var parentElem = elem.parent();
12147                         if (parentElem.hasClass('att-accordion__body')) {
12148                             scope.$watch('isOpen', function(val) {
12149                                 if (!val) {
12150                                     scope.readMoreLink = true;
12151                                     scope.readLessLink = false;
12152                                     scope.readLinkStyle = {'height': scope.elemHeight + 'px'};
12153                                     scope.readFlag = true;
12154                                 }
12155                             });
12156                         }
12157                         scope.readMore = function() {
12158                             scope.readMoreLink = false;
12159                             scope.readLessLink = true;
12160                             scope.readLinkStyle = {'height': 'auto'};
12161                             scope.readFlag = false;
12162                             var moreLink = angular.element(elem).children().eq(1).find('a')[0];
12163                             $timeout(function()
12164                              {
12165                                 moreLink.focus();
12166                              });
12167                         };
12168                         scope.readLess = function() {
12169                             scope.readMoreLink = true;
12170                             scope.readLessLink = false;
12171                             scope.readLinkStyle = {'height': scope.elemHeight + 'px'};
12172                             scope.readFlag = true;
12173                             var readLessLink = angular.element(elem).children().eq(0).find('a')[0];
12174                             $timeout(function()
12175                              {
12176                                 readLessLink.focus();
12177                              });
12178                         };
12179                     }
12180                 };
12181             }])
12182         .directive('attLinksList', [function() {
12183                 return {
12184                     restrict: 'A',
12185                     controller: function() {
12186                     },
12187                     link: function(scope, elem) {
12188                         elem.addClass('links-list');
12189                     }
12190                 };
12191             }])
12192         .directive('attLinksListItem', [function() {
12193                 return {
12194                     restrict: 'A',
12195                     require: '^attLinksList',
12196                     link: function(scope, elem) {
12197                         elem.addClass('links-list__item');
12198                         if(!(elem.attr('href'))){
12199                             elem.attr("tabindex", "0");
12200                         }
12201                     }
12202                 };
12203             }]);
12204 angular.module('att.abs.loading', [])
12205         .directive('attLoading', ['$window',function($window) {
12206                 return {
12207                     restrict: 'A',
12208                     replace: true,
12209                     scope: {
12210                         icon: '@attLoading',
12211                         progressStatus: '=?',
12212                         colorClass: '=?'
12213                     },
12214                     templateUrl: 'app/scripts/ng_js_att_tpls/loading/loading.html',
12215                     link: function(scope, element) {
12216                         var progressvalue = scope.progressStatus;
12217                         scope.progressStatus = Math.min(100, Math.max(0, progressvalue));
12218                         if($window.navigator.userAgent.indexOf("MSIE 8.")!==-1){
12219                             var shiftX = 0, shiftY = scope.progressStatus * 36;
12220                             element.css({
12221                                 'background-position-x' : shiftX,
12222                                 'background-position-y' : -shiftY
12223                             });
12224                         }
12225                     }
12226             };
12227         }]);
12228 angular.module('att.abs.modal', ['att.abs.utilities'])
12229 /**
12230  * A helper, internal data structure that acts as a map but also allows getting / removing
12231  * elements in the LIFO order
12232  */
12233   .factory('$$stackedMap', function () {
12234     return {
12235       createNew: function () {
12236         var stack = [];
12237
12238         return {
12239           add: function (key, value) {
12240             stack.push({
12241               key: key,
12242               value: value
12243             });
12244           },
12245           get: function (key) {
12246             for (var i = 0; i < stack.length; i++) {
12247               if (key === stack[i].key) {
12248                 return stack[i];
12249               }
12250             }
12251           },
12252           keys: function() {
12253             var keys = [];
12254             for (var i = 0; i < stack.length; i++) {
12255               keys.push(stack[i].key);
12256             }
12257             return keys;
12258           },
12259           top: function () {
12260             return stack[stack.length - 1];
12261           },
12262           remove: function (key) {
12263             var idx = -1;
12264             for (var i = 0; i < stack.length; i++) {
12265               if (key === stack[i].key) {
12266                 idx = i;
12267                 break;
12268               }
12269             }
12270             return stack.splice(idx, 1)[0];
12271           },
12272           removeTop: function () {
12273             return stack.splice(stack.length - 1, 1)[0];
12274           },
12275           length: function () {
12276             return stack.length;
12277           }
12278         };
12279       }
12280     };
12281   })
12282
12283 /**
12284  * A helper directive for the $modal service. It creates a backdrop element.
12285  */
12286   .directive('modalBackdrop', ['$timeout', function ($timeout) {
12287     return {
12288       restrict: 'EA',
12289       replace: true,
12290       templateUrl: 'app/scripts/ng_js_att_tpls/modal/backdrop.html',
12291       link: function (scope) {
12292         scope.animate = false;
12293         //trigger CSS transitions
12294         $timeout(function () {
12295           scope.animate = true;
12296         });
12297     }
12298     };
12299   }])
12300
12301   .directive('modalWindow', ['$modalStack','$timeout','$document', function ($modalStack,$timeout,$document) {
12302     return {
12303       restrict: 'EA',
12304       scope: {
12305         index: '@',
12306                 modalTitle: '@?'
12307       },
12308       replace: true,
12309       transclude: true,
12310       templateUrl: 'app/scripts/ng_js_att_tpls/modal/window.html',
12311       link: function (scope, element, attrs) {
12312         scope.windowClass = attrs.windowClass || '';
12313                 if (attrs['modalTitle'] && attrs['modalTitle']!=="") {
12314                         element[0].setAttribute('aria-label', attrs['modalTitle']);
12315                         element[0].removeAttribute('modal-title');
12316                 }
12317         $timeout(function () {
12318             // trigger CSS transitions
12319             scope.focusModalFlag = true;
12320             scope.animate = true;
12321         });
12322                 $document.on('focus keydown', function(e){
12323                     if (e.which ===9) {
12324                         String.prototype.contains = function(it) {
12325                             return this.indexOf(it) !== -1;
12326                         };
12327                         if (element[0] !== e.target && !element[0].contains( e.target )) {
12328                                 element[0].focus();
12329                         }
12330                         }
12331                 });
12332         scope.close = function (evt) {
12333             var modal = $modalStack.getTop();
12334             if (modal && modal.value.backdrop && modal.value.backdrop != 'static'  && (evt.target === evt.currentTarget)) {
12335             // Check if preventDefault exists due to lack of support for IE8
12336             if (evt.preventDefault) {
12337               evt.preventDefault();
12338               evt.stopPropagation();
12339           } else {
12340               evt.returnValue = false;
12341             }
12342             $modalStack.dismiss(modal.key, 'backdrop click');
12343           }
12344         };
12345       }
12346     };
12347   }])
12348
12349   .factory('$modalStack', ['$document', '$compile', '$rootScope', '$$stackedMap', 'events', 'keymap',
12350     function ($document, $compile, $rootScope, $$stackedMap, events, keymap) {
12351       var OPENED_MODAL_CLASS = 'modal-open';
12352       var backdropjqLiteEl, backdropDomEl;
12353       var backdropScope = $rootScope.$new(true);
12354       var openedWindows = $$stackedMap.createNew();
12355       var $modalStack = {};
12356       var modalLaunchingElement = undefined;
12357       function backdropIndex() {
12358         var topBackdropIndex = -1;
12359         var opened = openedWindows.keys();
12360         for (var i = 0; i < opened.length; i++) {
12361           if (openedWindows.get(opened[i]).value.backdrop) {
12362             topBackdropIndex = i;
12363           }
12364         }
12365         return topBackdropIndex;
12366       }
12367
12368       $rootScope.$watch(backdropIndex, function(newBackdropIndex){
12369         backdropScope.index = newBackdropIndex;
12370       });
12371
12372       function removeModalWindow(modalInstance) {
12373
12374         var body = $document.find('body').eq(0);
12375         var html = $document.find('html').eq(0);
12376         var modalWindow = openedWindows.get(modalInstance).value;
12377         //clean up the stack
12378         openedWindows.remove(modalInstance);
12379         ////remove window DOM element
12380         modalWindow.modalDomEl.remove();
12381         body.toggleClass(OPENED_MODAL_CLASS, openedWindows.length() > 0);
12382         html.css({overflow: 'scroll'});
12383
12384         //remove backdrop if no longer needed
12385         if (backdropDomEl && backdropIndex() == -1) {
12386           backdropDomEl.remove();
12387           backdropDomEl = undefined;
12388         }
12389         //destroy scope
12390         modalWindow.modalScope.$destroy();
12391           
12392         // Shift focus
12393         if (angular.isDefined(modalLaunchingElement) && modalLaunchingElement != null) {
12394             modalLaunchingElement.focus();
12395         }
12396       }
12397       $document.bind('keydown', function (evt) {
12398         var modal;
12399         if (evt.which === 27) {
12400           modal = openedWindows.top();
12401           if (modal && modal.value.keyboard) {
12402             $rootScope.$apply(function () {
12403               $modalStack.dismiss(modal.key);
12404             });
12405           }
12406         } else if (evt.keyCode === keymap.KEY.BACKSPACE) {
12407           var doPrevent = false;
12408           var d = evt.srcElement || evt.target;
12409           var type;
12410           if (d.type === undefined) { 
12411                 doPrevent = true;
12412           } else if (d.tagName.toUpperCase() === 'INPUT' && 
12413             ( (type = d.type.toUpperCase()) === 'TEXT' || 
12414               type === 'PASSWORD' || 
12415               type === 'FILE' ||
12416               type === 'SEARCH' ||
12417               type === 'EMAIL' ||
12418               type === 'NUMBER' ||
12419               type === 'DATE' ||
12420               type === 'TEL' ||
12421               type === 'URL' ||
12422               type === 'TIME')
12423             || d.tagName.toUpperCase() === 'TEXTAREA') {
12424                 doPrevent = d.readOnly || d.disabled;
12425           } else {
12426             doPrevent = true;
12427           }
12428           if (doPrevent) {
12429               events.preventDefault(evt);
12430           }
12431         }
12432       });
12433
12434       $modalStack.open = function (modalInstance, modal) {
12435           openedWindows.add(modalInstance, {
12436           deferred: modal.deferred,
12437           modalScope: modal.scope,
12438           backdrop: modal.backdrop,
12439           keyboard: modal.keyboard
12440         });
12441         
12442         //Before opening modal, find the focused element
12443         modalLaunchingElement = document.activeElement;
12444         
12445         var body = $document.find('body').eq(0);
12446         var html = $document.find('html').eq(0);
12447
12448         if (backdropIndex() >= 0 && !backdropDomEl) {
12449             backdropjqLiteEl = angular.element('<div modal-backdrop></div>');
12450             backdropDomEl = $compile(backdropjqLiteEl)(backdropScope);
12451             body.append(backdropDomEl);
12452         }
12453         var angularDomEl = angular.element('<div modal-window></div>');
12454         angularDomEl.attr('window-class', modal.windowClass);
12455         angularDomEl.attr('index', openedWindows.length() - 1);
12456                 angularDomEl.attr('modal-title', modal.modalTitle);
12457         angularDomEl.html(modal.content);
12458
12459         var modalDomEl = $compile(angularDomEl)(modal.scope);
12460         openedWindows.top().value.modalDomEl = modalDomEl;
12461         body.append(modalDomEl);
12462         body.addClass(OPENED_MODAL_CLASS);
12463         html.css({overflow: 'hidden'});
12464       };
12465
12466       $modalStack.close = function (modalInstance, result) {
12467         var modal = openedWindows.get(modalInstance);
12468         if (modal) {
12469           modal.value.deferred.resolve(result);
12470           removeModalWindow(modalInstance);
12471         }
12472       };
12473
12474       $modalStack.dismiss = function (modalInstance, reason) {
12475         var modalWindow = openedWindows.get(modalInstance).value;
12476         if (modalWindow) {
12477           modalWindow.deferred.reject(reason);
12478           removeModalWindow(modalInstance);
12479         }
12480       };
12481
12482       $modalStack.getTop = function () {
12483         return openedWindows.top();
12484       };
12485
12486       return $modalStack;
12487     }])
12488
12489   .provider('$modal', function () {
12490
12491     var $modalProvider = {
12492       options: {
12493         //can be also false or 'static'
12494         backdrop: true,
12495         keyboard: true
12496       },
12497       $get: ['$injector', '$rootScope', '$q', '$http', '$templateCache', '$controller', '$modalStack',
12498         function ($injector, $rootScope, $q, $http, $templateCache, $controller, $modalStack) {
12499             var $modal = {};
12500             function getTemplatePromise(options) {
12501             return options.template ? $q.when(options.template) :
12502               $http.get(options.templateUrl, {cache: $templateCache}).then(function (result) {
12503                 return result.data;
12504               });
12505           }
12506
12507           function getResolvePromises(resolves) {
12508             var promisesArr = [];
12509             angular.forEach(resolves, function (value) {
12510               if (angular.isFunction(value) || angular.isArray(value)) {
12511                 promisesArr.push($q.when($injector.invoke(value)));
12512               }
12513             });
12514             return promisesArr;
12515           }
12516           $modal.open = function (modalOptions) {
12517             var modalResultDeferred = $q.defer();
12518             var modalOpenedDeferred = $q.defer();
12519
12520             //prepare an instance of a modal to be injected into controllers and returned to a caller
12521             var modalInstance = {
12522               result: modalResultDeferred.promise,
12523               opened: modalOpenedDeferred.promise,
12524               close: function (result) {
12525                 $modalStack.close(modalInstance, result);
12526               },
12527               dismiss: function (reason) {
12528                 $modalStack.dismiss(modalInstance, reason);
12529               }
12530             };
12531             //merge and clean up options
12532             modalOptions = angular.extend({}, $modalProvider.options, modalOptions);
12533             modalOptions.resolve = modalOptions.resolve || {};
12534
12535             //verify options
12536             if (!modalOptions.template && !modalOptions.templateUrl) {
12537               throw new Error('One of template or templateUrl options is required.');
12538             }
12539
12540             var templateAndResolvePromise =
12541               $q.all([getTemplatePromise(modalOptions)].concat(getResolvePromises(modalOptions.resolve)));
12542               templateAndResolvePromise.then(function(tplAndVars) {
12543               var modalScope = (modalOptions.scope || $rootScope).$new();
12544               modalScope.$close = modalInstance.close;
12545               modalScope.$dismiss = modalInstance.dismiss;
12546
12547               var ctrlInstance, ctrlLocals = {};
12548               var resolveIter = 1;
12549
12550               //controllers
12551               if (modalOptions.controller) {
12552                 ctrlLocals.$scope = modalScope;
12553                 ctrlLocals.$modalInstance = modalInstance;
12554                 angular.forEach(modalOptions.resolve, function (value, key) {
12555                   ctrlLocals[key] = tplAndVars[resolveIter++];
12556                 });
12557
12558                 ctrlInstance = $controller(modalOptions.controller, ctrlLocals);
12559               }
12560
12561               $modalStack.open(modalInstance, {
12562                 scope: modalScope,
12563                 deferred: modalResultDeferred,
12564                 content: tplAndVars[0],
12565                 backdrop: modalOptions.backdrop,
12566                 keyboard: modalOptions.keyboard,
12567                 windowClass: modalOptions.windowClass,
12568                                 modalTitle: modalOptions.modalTitle
12569               });
12570
12571             }, function(reason) {
12572               modalResultDeferred.reject(reason);
12573             });
12574
12575             templateAndResolvePromise.then(function () {
12576               modalOpenedDeferred.resolve(true);
12577             }, function () {
12578               modalOpenedDeferred.reject(false);
12579             });
12580
12581             return modalInstance;
12582           };
12583
12584           return $modal;
12585         }]
12586     };
12587
12588     return $modalProvider;
12589   })
12590
12591 .directive("simpleModal", ["$modal", function($modal) {
12592         return {
12593             restrict: 'EA',
12594             scope: {
12595                 simpleModal: '@',
12596                 backdrop:'@',
12597                 keyboard:'@',
12598                 modalOk:'&',
12599                 modalCancel:'&',
12600                 windowClass:'@',
12601                 controller:'@',
12602                                 modalTitle: '@?'
12603             },
12604             link: function(scope, elm) {
12605                 elm.bind('click', function(ev) {
12606                     ev.preventDefault();
12607                     if (angular.isDefined(elm.attr("href")) && elm.attr("href") !== "") {
12608                         scope.simpleModal = elm.attr("href");
12609                     }
12610
12611                     scope.backdrop === "false" ? scope.backdropclick = 'static' : scope.backdropclick = true;
12612                     scope.keyboard === "false" ? scope.keyboardev = false : scope.keyboardev = true;
12613
12614                     $modal.open({
12615                         templateUrl: scope.simpleModal,
12616                         backdrop:scope.backdropclick,
12617                         keyboard:scope.keyboardev,
12618                         windowClass:scope.windowClass,
12619                         controller: scope.controller,
12620                                                 modalTitle: scope.modalTitle
12621                     }).result.then(scope.modalOk, scope.modalCancel);
12622                 });
12623             }
12624         };
12625     }])
12626
12627 .directive('tabbedItem', ['$modal', '$log',function ($modal, $log){
12628     return {
12629         restrict: 'AE',
12630         replace: true,
12631         scope: {
12632             items: "=items",
12633             controller: "@",
12634             templateId:"@",
12635                         modalTitle: '@?'
12636         },
12637         templateUrl: 'app/scripts/ng_js_att_tpls/modal/tabbedItem.html',
12638         controller: ['$scope', '$rootScope', '$attrs', function ($scope) {
12639                 $scope.clickTab = function (index) {
12640                     for (var i = 0; i < $scope.items.length; i++) {
12641                         if (i === index) {
12642                             $scope.items[i].isTabOpen = true;
12643                             $scope.items[i].showData = true;
12644                         }
12645                         else {
12646                             $scope.items[i].isTabOpen = false;
12647                             $scope.items[i].showData = false;
12648                         }
12649                     }
12650                     var modalInstance = $modal.open({
12651                         templateUrl: $scope.templateId,
12652                         controller: $scope.controller,
12653                         windowClass: 'tabbedOverlay_modal',
12654                                                 modalTitle: $scope.modalTitle,
12655                         resolve: {
12656                             items: function () {
12657                                 return $scope.items;
12658                             }
12659                         }
12660                     });
12661                     modalInstance.result.then(function (selectedItem) {
12662                         $scope.selected = selectedItem;
12663                     }, function () {
12664                         $log.info('Modal dismissed at: ' + new Date());
12665                     });
12666                 };
12667                 $scope.isActiveTab = function (index) {
12668                     return $scope.items && $scope.items[index] && $scope.items[index].isTabOpen;
12669                 };
12670             }]
12671                 };
12672 }])
12673
12674 .directive('tabbedOverlay', [function () {
12675     return {
12676         restrict: 'AE',
12677         replace: true,
12678         scope: {
12679             items: "="
12680         },
12681         transclude: true,
12682         templateUrl: 'app/scripts/ng_js_att_tpls/modal/tabbedOverlayItem.html',
12683         controller: ['$scope', function ($scope) {
12684                 $scope.clickTab = function (index) {
12685                     for (var i = 0; i < $scope.items.length; i++) {
12686                         if (i === index) {
12687                             $scope.items[i].isTabOpen = true;
12688                             $scope.items[i].showData = true;
12689                         }
12690                         else {
12691                             $scope.items[i].isTabOpen = false;
12692                             $scope.items[i].showData = false;
12693                         }
12694                     }
12695                 };
12696                 $scope.isActiveTab = function (index) {
12697                     return $scope.items && $scope.items[index] && $scope.items[index].isTabOpen;
12698                 };
12699             }]
12700     };
12701 }]);
12702 angular.module('att.abs.pagination', ['att.abs.utilities'])
12703 .directive('attPagination', [ function() {
12704      return {
12705         restrict: 'EA',
12706         scope: {
12707             totalPages: '=',
12708             currentPage: '=',
12709             showInput: '=',
12710             clickHandler: '=?'
12711         },
12712         replace: true,
12713         templateUrl: 'app/scripts/ng_js_att_tpls/pagination/pagination.html',
12714         link: function(scope) {
12715             scope.focusedPage;
12716             scope.$watch('totalPages', function(value) {
12717                 if(angular.isDefined(value) && value !== null){
12718                     scope.pages = [];
12719                     if (value < 1) {
12720                         scope.totalPages = 1;
12721                         return;
12722                     }
12723                     if (value <= 7) {
12724                         for (var i = 1; i <= value; i++) {
12725                             scope.pages.push(i);
12726                         }
12727                     } else if (value > 7) {
12728                         var midVal = Math.ceil(value / 2);
12729                         scope.pages = [midVal - 1, midVal, midVal + 1];
12730                     }
12731                     currentPageChanged(1);
12732                 }
12733             });
12734             scope.$watch('currentPage', function(value) {
12735                 currentPageChanged(value);
12736             });
12737             var callbackHandler = function(num) {
12738                 if (angular.isFunction(scope.clickHandler)){
12739                     scope.clickHandler(num);
12740                 }
12741             };
12742             function currentPageChanged(value) {
12743                 if (angular.isDefined(value) && value !== null) {
12744                     if (!value || value < 1) {
12745                         value = 1;
12746                     }
12747                     if (value > scope.totalPages) {
12748                         value = scope.totalPages;
12749                     }
12750                     if(scope.currentPage !== value) {
12751                         scope.currentPage = value;
12752                         callbackHandler(scope.currentPage);
12753                     }
12754                     if (scope.totalPages > 7) {
12755                         if (value < scope.pages[0] && value > 3) {
12756                             scope.pages = [value, value + 1, value + 2];
12757                         } else if (value > scope.pages[2] && value < scope.totalPages - 2) {
12758                            scope.pages = [value - 2, value - 1, value];
12759                         } else if (value <= 3) {
12760                              scope.pages = [1, 2, 3];
12761                         } else if (value >= scope.totalPages - 2) {
12762                              scope.pages = [scope.totalPages - 2, scope.totalPages - 1, scope.totalPages];
12763                         }
12764                     }
12765                 }
12766             }
12767             scope.next = function(event) {
12768                 event.preventDefault();
12769                 if (scope.currentPage < scope.totalPages) {
12770                     scope.currentPage += 1;
12771                     callbackHandler(scope.currentPage);
12772                 }
12773             };
12774             scope.prev = function(event) {
12775                 event.preventDefault();
12776                 if (scope.currentPage > 1) {
12777                     scope.currentPage -= 1;
12778                     callbackHandler(scope.currentPage);
12779                 }
12780             };
12781             scope.selectPage = function(value, event) {
12782                 event.preventDefault();
12783                 scope.currentPage = value;
12784                 scope.focusedPage = value;
12785                 callbackHandler(scope.currentPage);
12786             };
12787             scope.checkSelectedPage = function(value) {
12788                 if(scope.currentPage === value) {
12789                     return true;
12790                 }
12791                 return false;
12792             };
12793             scope.isFocused = function(page) {
12794                  return scope.focusedPage === page;
12795             };
12796         }
12797     };
12798 }]);
12799
12800 angular.module('att.abs.paneSelector',['att.abs.utilities'])
12801 .constant('paneGroupConstants',{
12802     SIDE_WIDTH_DEFAULT: '33%',
12803     INNER_PANE_DEFAULT: '67%',
12804     SIDE_PANE_ID: 'sidePane',
12805     NO_DRILL_DOWN: 'none'
12806 })
12807 .factory('animation', function(){
12808     return TweenLite;
12809 }).directive('attPaneAccessibility',['keymap','$window',function(keymap,$window) {
12810         return{
12811             restrict: 'A',
12812             require: ['^?sidePane','^?innerPane'],
12813             link: function (scope, elem,attr,ctrl) {
12814                 var sidepaneCtrl = ctrl[0],innerPaneCtrl = ctrl[1],ieFlag=false;
12815                 scope.ie = (function () {
12816                     var undef,v = 3,div = document.createElement('div'),
12817                             all = div.getElementsByTagName('i');
12818                     while (
12819                             div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i>< ![endif]-->',
12820                             all[0]
12821                             );
12822                     return v > 4 ? v : undef;
12823                 }());
12824                  if(scope.ie === 8){
12825                         ieFlag = true;
12826                     }
12827                     else{
12828                         ieFlag = false;
12829                     }
12830                 elem.bind('keydown',function(ev){
12831                     if (keymap.isAllowedKey(ev.keyCode) || keymap.isControl(ev) || keymap.isFunctionKey(ev)) {
12832                         ev.preventDefault();
12833                         ev.stopPropagation();
12834                         var el;
12835                     switch (ev.keyCode) {
12836                         case keymap.KEY.DOWN:
12837                             el = angular.element(elem[0])[0];
12838                             if(el && el.nextElementSibling){
12839                                 el.nextElementSibling.focus();
12840                             }
12841                             /*IE8 fix*/
12842                             if(ieFlag){
12843                                 do {
12844                                     if (el && el.nextSibling){
12845                                         el = el.nextSibling;
12846                                     }
12847                                     else{
12848                                         break;
12849                                     }
12850                                 } while (el && el.tagName !== 'DIV');
12851                                 el.focus();
12852                             }
12853                             break;
12854                         case keymap.KEY.UP:
12855                             el = angular.element(elem[0])[0];
12856                             if(el && el.previousElementSibling){
12857                                 el.previousElementSibling.focus();
12858                             }
12859                              /*IE8 fix*/
12860                              if(ieFlag){
12861                                 do {
12862                                     if (el && el.previousSibling){
12863                                         el = el.previousSibling;
12864                                     }
12865                                     else{
12866                                         break;
12867                                     }
12868                                 } while (el && el.tagName !== 'DIV');
12869                                 el.focus();
12870                             }
12871                             break;
12872                         case keymap.KEY.RIGHT:
12873                             if(angular.isDefined(sidepaneCtrl)){
12874                                 el = sidepaneCtrl.getElement()[0];
12875                             }
12876                             if(angular.isDefined(innerPaneCtrl)){
12877                                 el = innerPaneCtrl.getElement()[0];
12878                             }
12879                             do {
12880                                 if (el && el.nextElementSibling){
12881                                     el = el.nextElementSibling;
12882                                 }
12883                                 else{
12884                                     break;
12885                                 }
12886                             }while(window.getComputedStyle(el, null).getPropertyValue("display") === 'none');
12887                             /*IE8 fix*/
12888                             if(ieFlag){
12889                                 do {
12890                                     if (el && el.nextSibling){
12891                                         el = el.nextSibling;
12892                                     }
12893                                     else{
12894                                         break;
12895                                     }
12896                                 }while ((el && el.tagName == 'DIV') && el.currentStyle['display'] == 'none');
12897                             }
12898                            if (el){
12899                             el.querySelector("[att-pane-accessibility]").focus();
12900                         }
12901                         break;
12902                         case keymap.KEY.LEFT:
12903                             if(angular.isDefined(sidepaneCtrl)){
12904                                 el = sidepaneCtrl.getElement()[0];
12905                             }
12906                             if(angular.isDefined(innerPaneCtrl)){
12907                                 el = innerPaneCtrl.getElement()[0];
12908                             }
12909                             do {
12910                                 if (el && el.previousElementSibling){
12911                                     el = el.previousElementSibling;
12912                                 }
12913                                 else{
12914                                     break;
12915                                 }
12916                                 }while (window.getComputedStyle(el, null).getPropertyValue("display") == 'none');
12917                            
12918                             /*IE8 fix*/
12919                             if(ieFlag){
12920                                 do {
12921                                     if (el && el.previousSibling){
12922                                         el = el.previousSibling;
12923                                     }
12924                                     else{
12925                                         break;
12926                                     }
12927                                 }while((el && el.tagName == 'DIV') && el.currentStyle['display'] == 'none');   
12928                             }
12929                             if (el){
12930                             el.querySelector("[att-pane-accessibility]").focus();
12931                         }
12932                         break;
12933                         default:
12934                             break;
12935                         }
12936                     }
12937                 });
12938             }
12939         };
12940 }])
12941 .directive('sideRow', [function(){
12942     return {
12943         restrict: 'A',
12944         replace:true,
12945         require: ['^sidePane','^paneGroup'],
12946         link: function(scope,element,attr,ctrls){
12947             var sidePaneCtrl = ctrls[0];
12948             var paneGroupCtrl = ctrls[1];
12949             if(scope.$first){
12950                 /*
12951                 Reset the sidePaneId array if a new
12952                 set of ngRepeat data appeared
12953                 */
12954                 sidePaneCtrl.sidePaneIds = [];
12955             }
12956             var paneId =attr['paneId'];
12957             var drillDownTo = attr['drillDownTo'];
12958             sidePaneCtrl.sidePaneRows.push({'paneId':paneId, 'drillDownTo':drillDownTo});
12959             element.on('click', function(){
12960                 sidePaneCtrl.currentSelectedRowPaneId = paneId;
12961                 paneGroupCtrl.slideOutPane(paneId,true);
12962             });
12963         }
12964     };
12965 }])
12966 .controller('SidePaneCtrl',['$scope', '$element','animation', 'paneGroupConstants',
12967  function($scope,$element,animation, paneGroupConstants){
12968         this.getElement = function(){
12969             return $element;
12970         };
12971         this.sidePaneTracker = {};
12972         this.currentWidth = paneGroupConstants.SIDE_WIDTH_DEFAULT;
12973         this.paneId = paneGroupConstants.SIDE_PANE_ID;
12974         this.currentSelectedRowPaneId;
12975         this.drillDownToMapper = {};
12976         this.sidePaneRows = [];
12977         this.init = function(){
12978             var sidePaneRows = this.sidePaneRows;
12979             if(sidePaneRows){
12980                 for(var index in sidePaneRows){
12981                     if (sidePaneRows.hasOwnProperty(index)) {
12982                         var paneId = sidePaneRows[index].paneId;
12983                         var drillDownTo = sidePaneRows[index].drillDownTo;
12984                         this.drillDownToMapper[paneId] = drillDownTo;
12985                         if(index == 0){
12986                             this.currentSelectedRowPaneId = paneId;
12987                             this.sidePaneTracker[paneId] = [];
12988                         }
12989                     }
12990                 }
12991             }
12992         };
12993         this.getSidePanesList = function(){
12994             return this.sidePaneTracker[this.currentSelectedRowPaneId];
12995         };
12996         this.addToSidePanesList = function(newPaneId){
12997             if(this.sidePaneTracker[this.currentSelectedRowPaneId] === undefined){
12998                 this.sidePaneTracker[this.currentSelectedRowPaneId] = [];
12999             }
13000             else if(newPaneId){
13001                 this.sidePaneTracker[this.currentSelectedRowPaneId].push(newPaneId);
13002             }
13003         };
13004         this.setWidth = function(val){
13005             if(val){
13006                 this.currentWidth = val;
13007             }
13008             animation.set($element,{width:this.currentWidth});
13009         };
13010         this.resizeWidth = function(val){
13011             if(val){
13012                 this.currentWidth = val;
13013             }
13014             animation.to($element,.5,{width:val});
13015         };
13016
13017 }])
13018 .directive('sidePane', ['paneGroupConstants', function(paneGroupConstants){
13019     return {
13020         restrict: 'EA',
13021         transclude: true,
13022         replace: true,
13023         templateUrl: 'app/scripts/ng_js_att_tpls/paneSelector/sidePane.html',
13024         require: ['^paneGroup', 'sidePane'],
13025         controller: 'SidePaneCtrl',
13026         scope:{},
13027         link: function(scope,element,attr, ctrls){
13028             var paneGroupCtrl = ctrls[0];
13029             var sidePaneCtrl = ctrls[1];
13030             paneGroupCtrl.addPaneCtrl(paneGroupConstants.SIDE_PANE_ID, sidePaneCtrl);
13031         }
13032     };
13033 }])
13034 .directive('drillDownRow', ['$parse', 'paneGroupConstants',function($parse,paneGroupConstants){
13035     return {
13036         restrict: 'A',
13037         replace:true,
13038         require: ['^innerPane','^paneGroup'],
13039         link: function(scope,element,attr,ctrls){
13040             var innerPaneCtrl = ctrls[0];
13041             var paneGroupCtrl = ctrls[1];
13042             element.on('click', function(){
13043                     var drillDownTo = innerPaneCtrl.drillDownTo;
13044                     if(innerPaneCtrl.drillDownTo !== paneGroupConstants.NO_DRILL_DOWN){
13045                         paneGroupCtrl.slideOutPane(drillDownTo);
13046                     }
13047                     element[0].focus();
13048             });
13049         }
13050     };
13051 }])
13052 .controller('InnerPaneCtrl', ['$scope', '$element','animation', 'paneGroupConstants',
13053         function($scope,$element,animation,paneGroupConstants){
13054         this.getElement = function(){
13055             return $element;
13056         };
13057         this.paneId = $scope.paneId;
13058         this.drillDownTo;
13059         this.currentWidth = paneGroupConstants.INNER_PANE_DEFAULT;
13060         this.setWidth = function(val){
13061             if(val){
13062                 this.currentWidth = val;
13063             }
13064             animation.set($element,{width:this.currentWidth});
13065         };
13066         this.resizeWidth = function(val,callback){
13067             animation.to($element,.25,{width:val,onComplete: callback});
13068         };
13069         this.displayNone = function(){
13070             animation.set($element, {display:'none'});
13071         };
13072         this.displayBlock = function(){
13073             animation.set($element,{display:'block'});
13074             if(this){
13075                 this.hideRightBorder();
13076             }
13077         };
13078         this.floatLeft = function(){
13079             animation.set($element,{float:'left'});
13080         };
13081         this.hideLeftBorder = function(){
13082             animation.set($element, {borderLeftWidth: '0px'});
13083         };
13084         this.showLeftBorder = function(){
13085             animation.set($element,{borderLeftWidth: '1px'});
13086         };
13087         this.hideRightBorder = function(){
13088             animation.set($element,{borderRightWidth: '0px'});
13089         };
13090         this.showRightBorder = function(){
13091             animation.set($element, {borderRightWidth: '1px'});
13092         };
13093         this.slideFromRight = function(){
13094             animation.set($element, {float:'right'});
13095             animation.set($element, {width: this.currentWidth});
13096         };
13097         this.startOpen = function(){
13098             return $scope.startOpen;
13099         };
13100 }])
13101 .directive('innerPane', function(){
13102     return {
13103         restrict: 'EA',
13104         replace: true,
13105         transclude: true,
13106         templateUrl: 'app/scripts/ng_js_att_tpls/paneSelector/innerPane.html',
13107         require: ['^paneGroup', 'innerPane'],
13108         controller: 'InnerPaneCtrl',
13109         scope:{
13110                 paneId:'@'
13111         },
13112         link: function(scope,element,attr,ctrls){
13113             if(attr.startOpen === ""){
13114                 scope.startOpen  = true;
13115             }
13116             var paneGroupCtrl = ctrls[0];
13117             var innerPaneCtrl = ctrls[1];
13118             paneGroupCtrl.addPaneCtrl(scope.paneId,innerPaneCtrl);
13119         }
13120     };
13121 })
13122 .controller('PaneGroupCtrl', ['$scope', '$element', 'paneGroupConstants',function($scope,$element,paneGroupConstants){
13123         this.panes = {};
13124         this.accountLevelPaneModel = [];
13125         this.title = $scope.title;
13126         this.init = function(){
13127                 var sidePane = this.panes[paneGroupConstants.SIDE_PANE_ID];
13128                 if(sidePane){
13129                     sidePane.init();
13130
13131                     //Show the other panes that may be set to startOpen
13132                     //numOpen starts at 1 because of the side pane
13133                     var numOpen = 1;
13134                     var key;
13135                     for(key in this.panes){
13136                         if(this.panes[key].startOpen && this.panes[key].startOpen()){
13137                                 numOpen++;
13138                         }
13139                     }
13140                     var width;
13141                     if(numOpen >= 3){
13142                         width = ((100/numOpen)) + '%';
13143                     }
13144                     if(this.panes[sidePane.currentSelectedRowPaneId])
13145                     {
13146                         if(width){
13147                             sidePane.setWidth(width);
13148                             this.panes[sidePane.currentSelectedRowPaneId].setWidth(width);
13149                         }
13150                         else{
13151                             sidePane.setWidth();
13152                             this.panes[sidePane.currentSelectedRowPaneId].setWidth();
13153                         }
13154                         this.panes[sidePane.currentSelectedRowPaneId].displayBlock();
13155                         for(key in this.panes){
13156                             if(key !== paneGroupConstants.SIDE_PANE_ID && key !== sidePane.currentSelectedRowPaneId){
13157                                 this.panes[key].displayNone();
13158                             }
13159                                 this.panes[key].drillDownTo = sidePane.drillDownToMapper[key];
13160                         }
13161                     }
13162                     openOtherPanesOnStart(sidePane, this.panes);
13163                 }
13164
13165                 function openOtherPanesOnStart(sidePane, panes){
13166                     //Build an array of the panes that need to be out
13167                     var otherPanesStartOpened = [];
13168                     var index;
13169                     for(index in sidePane.sidePaneRows){
13170                         if (sidePane.sidePaneRows.hasOwnProperty(index)) {
13171                             var pane = sidePane.sidePaneRows[index];
13172
13173                             //Skip the first pane row since we handled it in the begining
13174                             if(index > 0 && panes[pane.paneId].startOpen && panes[pane.paneId].startOpen()){
13175                                     otherPanesStartOpened.push(pane);
13176                                     //Remember the panes that are opened for the first pane row Index
13177                                     sidePane.addToSidePanesList(pane.paneId);
13178                             }
13179                         }
13180                     }
13181
13182                     if(width){
13183                         for(index in otherPanesStartOpened){
13184                             if (otherPanesStartOpened.hasOwnProperty(index)) {
13185                                 var paneId = otherPanesStartOpened[index].paneId;
13186                                 var paneCtrl = panes[paneId];
13187                                 if(paneCtrl && paneCtrl.setWidth && paneCtrl.displayBlock){
13188                                     paneCtrl.setWidth(width);
13189                                     paneCtrl.displayBlock();
13190                                 }
13191                             }
13192                         }
13193                     }
13194
13195                 }
13196         };
13197
13198         /*
13199           Resets all the panels to their original positions at the end of a sidebar click
13200           By setting the sideBar to its default width
13201           Setting all panes to float left and displaynone
13202           Setting the pane that was clicked to default width and slide right
13203         */
13204
13205         this.resetPanes = function(){
13206             for(var key in this.panes){
13207                 if(this.panes.hasOwnProperty(key)){
13208                     var pane = this.panes[key];
13209                     if(pane && (pane.paneId !== paneGroupConstants.SIDE_PANE_ID)){
13210                             pane.floatLeft();
13211                             pane.displayNone();
13212                     }
13213                 }
13214             }
13215
13216             if(this.panes[paneGroupConstants.SIDE_PANE_ID]){
13217                 this.panes[paneGroupConstants.SIDE_PANE_ID].setWidth(paneGroupConstants.SIDE_WIDTH_DEFAULT);
13218             }
13219         };
13220
13221         this.addPaneCtrl = function(paneId,paneCtrl){
13222             this.panes[paneId] = paneCtrl;
13223         };
13224
13225         this._slideOutPane = function(paneId,isFromSidePane){
13226                 this.resetPanes();
13227                 //Check current side pane stack to see how many panes are already open for that side pane choice
13228                 //then add the new pane that needs to be there
13229                 var panesList;
13230                 if(isFromSidePane){
13231
13232                     //Check if the side pane id has already been clicked
13233                     if(this.panes[paneGroupConstants.SIDE_PANE_ID]){
13234                         panesList = this.panes[paneGroupConstants.SIDE_PANE_ID].getSidePanesList();
13235                     }
13236                     if(!panesList){
13237                         if(this.panes && this.panes[paneGroupConstants.SIDE_PANE_ID] && this.panes[paneId]){
13238                             this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId = paneId;
13239                             this.panes[paneGroupConstants.SIDE_PANE_ID].addToSidePanesList();
13240
13241                             this.panes[paneId].slideFromRight();
13242                             this.panes[paneId].displayBlock();
13243
13244                             this.panes[paneId].setWidth(paneGroupConstants.INNER_PANE_DEFAULT);
13245                         }
13246                     }
13247                     else if(this.panes && this.panes[paneGroupConstants.SIDE_PANE_ID]){
13248                                 //Restore the panes based on the panelist
13249                         if(panesList.length === 0 && this.panes[paneId]){
13250                             //Only one pane is out
13251                             this.panes[paneGroupConstants.SIDE_PANE_ID].setWidth(paneGroupConstants.SIDE_WIDTH_DEFAULT);
13252                             this.panes[paneId].displayBlock();
13253                             this.panes[paneId].setWidth(paneGroupConstants.INNER_PANE_DEFAULT);
13254                         }
13255                         else{
13256                             //Multiple panes out
13257                             var numPanes = panesList.length + 2;
13258                             var width = ((100/numPanes)) + '%';
13259                             this.panes[paneGroupConstants.SIDE_PANE_ID].setWidth(width);
13260
13261                             //Set the sidePanes pane
13262                             //set the panes children list
13263                             if(this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId]){
13264                                 this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId].displayBlock();
13265                                 this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId].setWidth(width);
13266                             }
13267                             for(var i in panesList){
13268                                 if(this.panes[panesList[i]]){
13269                                         this.panes[panesList[i]].displayBlock();
13270                                         this.panes[panesList[i]].setWidth(width);
13271                                 }
13272                             }
13273                         }
13274                     }
13275                 }
13276                 else{
13277
13278                     //Have to check the paneId that was given and where it is drilling down to
13279                     var isPaneInStack = false;
13280                     var stackPaneList;
13281                     if(this.panes[paneGroupConstants.SIDE_PANE_ID]){
13282                         stackPaneList = this.panes[paneGroupConstants.SIDE_PANE_ID].getSidePanesList();
13283                     }
13284                     for(var j in stackPaneList){
13285                         if(stackPaneList.hasOwnProperty(j)){
13286                             var pId = stackPaneList[j];
13287                             if(pId === paneId){
13288                                 isPaneInStack = true;
13289                                 break;
13290                             }
13291                         }
13292                     }
13293                     if(!isPaneInStack && this.panes[paneGroupConstants.SIDE_PANE_ID]){
13294                         this.panes[paneGroupConstants.SIDE_PANE_ID].addToSidePanesList(paneId);
13295                     }
13296                     var sidePanesListLength;
13297                     if(this.panes[paneGroupConstants.SIDE_PANE_ID]){
13298                         sidePanesListLength = this.panes[paneGroupConstants.SIDE_PANE_ID].getSidePanesList().length;
13299                     }
13300                     var numberPanes = sidePanesListLength + 2;
13301                     var widthToSet = ((100/numberPanes)) + '%';
13302                     if(this.panes[paneGroupConstants.SIDE_PANE_ID]){
13303                         this.panes[paneGroupConstants.SIDE_PANE_ID].setWidth(widthToSet);
13304                     }
13305                     var slideInPaneId;
13306
13307                     if(this.panes[paneGroupConstants.SIDE_PANE_ID]){
13308                             slideInPaneId = this.panes[paneGroupConstants.SIDE_PANE_ID].getSidePanesList()[sidePanesListLength - 1];
13309                     }
13310
13311                     var that = this;
13312
13313                     if(that.panes[paneGroupConstants.SIDE_PANE_ID]){
13314                             panesList = that.panes[paneGroupConstants.SIDE_PANE_ID].getSidePanesList();
13315                     }
13316
13317                     for(var p in panesList){
13318                         if(panesList.hasOwnProperty(p)){
13319                             var paneListPaneId = panesList[p];
13320                             var pane = this.panes[paneListPaneId];
13321                             if(paneListPaneId !== slideInPaneId && pane){
13322                                     pane.setWidth(widthToSet);
13323                                     pane.displayBlock();
13324                                     pane.floatLeft();
13325                             }
13326                         }
13327                     }
13328
13329                     if(this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId]){
13330                             this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId].displayBlock();
13331                             this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId].showRightBorder();
13332
13333                             this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId].resizeWidth(widthToSet,function(){
13334
13335                                     if(that.panes[slideInPaneId] && that.panes[that.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId]){
13336                                             that.panes[that.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId].hideRightBorder();
13337                                             that.panes[slideInPaneId].setWidth(widthToSet);
13338                                             that.panes[slideInPaneId].slideFromRight();
13339                                             that.panes[slideInPaneId].displayBlock();
13340                                             that.panes[slideInPaneId].floatLeft();
13341                                     }
13342
13343                             });
13344                     }
13345                 }
13346         };
13347
13348         this.slideOutPane = function(paneId,isFromSidePane){
13349             this._slideOutPane(paneId,isFromSidePane);
13350         };
13351 }])
13352 .directive('paneGroup', ['$timeout',function($timeout){
13353         return {
13354                 restrict: 'EA',
13355                 transclude: true,
13356                 replace: true,
13357                 templateUrl: 'app/scripts/ng_js_att_tpls/paneSelector/paneGroup.html',
13358                 scope:{
13359                 },
13360                 controller: 'PaneGroupCtrl',
13361                 link: function(scope,element,attr,ctrl){
13362                         $timeout(initialize,100);
13363                         function initialize(){
13364                                 ctrl.init();
13365                         }
13366                 }
13367         };
13368 }]);
13369 angular.module('att.abs.tooltip', ['att.abs.position', 'att.abs.utilities', 'ngSanitize'])
13370         // The default options tooltip and popover.
13371         .constant('tooltipDefaultOptions', {
13372             placement: 'above',
13373             animation: false,
13374             popupDelay: 0,
13375             stylett: 'dark',
13376             appendToBody: true
13377         })
13378
13379         /**
13380          * The $tooltip service creates tooltip- and popover-like directives as well as
13381          * houses global options for them.
13382          */
13383         .provider('$tooltip', ['tooltipDefaultOptions', function(tooltipDefaultOptions) {
13384
13385             // Default hide triggers for each show trigger
13386             var triggerMap = {
13387                 'mouseenter': 'mouseleave',
13388                 'click': 'click',
13389                 'focus': 'blur',
13390                 'mouseover':'mouseout'
13391             };
13392
13393             // The options specified to the provider globally.
13394             var globalOptions = {};
13395
13396             this.options = function(value) {
13397                 angular.extend(globalOptions, value);
13398             };
13399
13400             /**
13401              * This allows you to extend the set of trigger mappings available. E.g.:
13402              *
13403              *   $tooltipProvider.setTriggers( 'openTrigger': 'closeTrigger' );
13404              */
13405             this.setTriggers = function(triggers) {
13406                 angular.extend(triggerMap, triggers);
13407             };
13408
13409             /**
13410              * This is a helper function for translating camel-case to snake-case.
13411              */
13412             function snakeCase(name) {
13413                 var regexp = /[A-Z]/g;
13414                 var separator = '-';
13415                 return name.replace(regexp, function(letter, pos) {
13416                     return (pos ? separator : '') + letter.toLowerCase();
13417                 });
13418             }
13419
13420             /**
13421              * Returns the actual instance of the $tooltip service.
13422              */
13423             this.$get = ['$window', '$compile', '$timeout', '$parse', '$document', '$position', '$interpolate', '$attElementDetach', function($window, $compile, $timeout, $parse, $document, $position, $interpolate, $attElementDetach) {
13424                     return function (type, prefix, defaultTriggerShow) {
13425                         var options = angular.extend({}, tooltipDefaultOptions, globalOptions);
13426                         /**
13427                          * Returns an object of show and hide triggers.
13428                          *
13429                          * If a trigger is supplied,
13430                          * it is used to show the tooltip; otherwise, it will use the `trigger`
13431                          * option passed to the `$tooltipProvider.options` method; else it will
13432                          * default to the trigger supplied to this directive factory.
13433                          *
13434                          * The hide trigger is based on the show trigger. If the `trigger` option
13435                          * was passed to the `$tooltipProvider.options` method, it will use the
13436                          * mapped trigger from `triggerMap` or the passed trigger if the map is
13437                          * undefined; otherwise, it uses the `triggerMap` value of the show
13438                          * trigger; else it will just use the show trigger.
13439                          */
13440                         function getTriggers(trigger) {
13441                             var show = trigger || options.trigger || defaultTriggerShow;
13442                             var hide = triggerMap[show] || show;
13443                             return {
13444                                 show: show,
13445                                 hide: hide
13446                             };
13447                         }
13448
13449                         var directiveName = snakeCase(type);
13450
13451                         var startSym = $interpolate.startSymbol();
13452                         var endSym = $interpolate.endSymbol();
13453
13454                         return {
13455                             restrict: 'EA',
13456                             scope: true,
13457                             link: function (scope, element, attrs) {
13458                                 /* Allows a developer to force element to be non-tabable */
13459                                 if (!element.attr('tabindex')) {
13460                                     element.attr('tabindex', '0');
13461                                 } 
13462
13463                                 var isElementHovered = false;
13464                                 element.bind('mouseenter', function(){
13465                                     isElementHovered = true;
13466                                     element.removeAttr('title');
13467                                 });
13468                                 element.bind('mouseleave', function(){
13469                                     isElementHovered = false;
13470                                     setTooltipAriaLabel();
13471                                 });
13472
13473                                 /* We store our attributes on our scope so any user of $tooltip service can access attributes */
13474                                 scope.parentAttrs = attrs;
13475                                 var template =
13476                                         '<div ' + directiveName + '-popup ' +
13477                                         'title="' + startSym + 'tt_title' + endSym + '" ' +
13478                                         'content="' + startSym + 'tt_content' + endSym + '" ' +
13479                                         'placement="' + startSym + 'tt_placement' + endSym + '" ' +
13480                                         'animation="tt_animation()" ' +
13481                                         'is-open="tt_isOpen" ' +
13482                                         'stylett="' + startSym + 'tt_style' + endSym + '" ' +
13483                                         '>' +
13484                                         '</div>';
13485
13486                                 var tooltip = $compile(template)(scope);
13487                                 var transitionTimeout;
13488                                 var popupTimeout;
13489                                 var $body;
13490                                 var appendToBody = angular.isDefined(options.appendToBody) ? options.appendToBody : false;
13491                                 var triggers = getTriggers(undefined);
13492                                 var hasRegisteredTriggers = false;
13493                                 var hasEnableExp = angular.isDefined(attrs[prefix + 'Enable']);
13494                                 var tooltipOffset = 0;
13495                                 var tooltipAriaLabelDefined = false;
13496
13497                                 // By default, the tooltip is not open.
13498                                 // add ability to start tooltip opened
13499                                 scope.tt_isOpen = false;
13500
13501                                 //Adding a scope watch, to remove the created popup from DOM, incase it is updated outside the provider code.
13502                                 scope.$watch('tt_isOpen', function(newVal, oldVal){
13503                                     if(newVal !== oldVal && !newVal){
13504                                         $attElementDetach(tooltip[0]);
13505                                     }
13506                                 });
13507
13508                                 function toggleTooltipBind() {
13509                                     if (!scope.tt_isOpen) {
13510                                         showTooltipBind();
13511                                     } else {
13512                                         hideTooltipBind();
13513                                     }
13514                                 }
13515
13516                                 // Show the tooltip with delay if specified, otherwise show it immediately
13517                                 function showTooltipBind() {
13518                                     if (hasEnableExp && !scope.$eval(attrs[prefix + 'Enable'])) {
13519                                         return;
13520                                     }
13521                                     if (scope.tt_popupDelay) {
13522                                         popupTimeout = $timeout(show, scope.tt_popupDelay);
13523                                     } else {
13524                                         scope.$apply(show);
13525                                     }
13526                                 }
13527
13528                                 function hideTooltipBind() {
13529                                     scope.$apply(function() {
13530                                         hide();
13531                                     });
13532                                 }
13533
13534                                 // Show the tooltip popup element.
13535                                 function show() {
13536                                     var position,
13537                                             ttWidth,
13538                                             ttHeight,
13539                                             ttPosition;
13540
13541                                     // Don't show empty tooltips.
13542                                     if (!scope.tt_content) {
13543                                         return;
13544                                     }
13545
13546                                     // If there is a pending remove transition, we must cancel it, lest the
13547                                     // tooltip be mysteriously removed.
13548                                     if (transitionTimeout) {
13549                                         $timeout.cancel(transitionTimeout);
13550                                     }
13551
13552                                     // Set the initial positioning.
13553                                     tooltip.css({top: 0, left: 0, display: 'block', 'z-index': 9999});
13554
13555                                     // Now we add it to the DOM because need some info about it. But it's not
13556                                     // visible yet anyway.
13557                                     if (appendToBody) {
13558                                         $body = $body || $document.find('body');
13559                                         $body.append(tooltip);
13560                                     } else {
13561                                         element.after(tooltip);
13562                                     }
13563
13564                                     // Get the position of the directive element.
13565                                     position = appendToBody ? $position.offset(element) : $position.position(element);
13566
13567                                     // Get the height and width of the tooltip so we can center it.
13568                                     ttWidth = tooltip.prop('offsetWidth');
13569                                     ttHeight = tooltip.prop('offsetHeight');
13570
13571                                     // Calculate the tooltip's top and left coordinates to center it with
13572                                     // this directive.
13573                                     var ttArrowOffset = 10;
13574                                     switch (scope.tt_placement) {
13575                                         case 'right':
13576                                             if(appendToBody){
13577                                                 ttPosition = {
13578                                                     top: position.top + position.height / 2 - ttHeight / 2,
13579                                                     left: (position.left + position.width) + tooltipOffset
13580                                                 };
13581                                             }else{
13582                                                 ttPosition = {
13583                                                     top: position.top + position.height / 2 - ttHeight / 2,
13584                                                     left: (position.left + position.width + ttArrowOffset) + tooltipOffset
13585                                                 };
13586                                             }
13587                                             break;
13588                                         case 'below':
13589                                             if(appendToBody){
13590                                                 ttPosition = {
13591                                                     top: (position.top + position.height) + tooltipOffset,
13592                                                     left: position.left + position.width / 2 - ttWidth / 2
13593                                                 };
13594                                             }else{
13595                                                 ttPosition = {
13596                                                     top: (position.top + position.height + ttArrowOffset) + tooltipOffset,
13597                                                     left: position.left + position.width / 2 - ttWidth / 2
13598                                                 };
13599                                             }
13600                                             break;
13601                                         case 'left':
13602                                             if(appendToBody){
13603                                                 ttPosition = {
13604                                                     top: position.top + position.height / 2 - ttHeight / 2,
13605                                                     left: (position.left - ttWidth) - tooltipOffset
13606                                                 };
13607                                             }else{
13608                                                 ttPosition = {
13609                                                     top: position.top + position.height / 2 - ttHeight / 2,
13610                                                     left: (position.left - ttWidth - ttArrowOffset) - tooltipOffset
13611                                                 };
13612                                             }
13613                                             break;
13614                                         default:
13615                                             if(appendToBody){
13616                                                 ttPosition = {
13617                                                     top: (position.top - ttHeight) - tooltipOffset,
13618                                                     left: position.left + position.width / 2 - ttWidth / 2
13619                                                 };
13620                                             }else{
13621                                                 ttPosition = {
13622                                                     top: (position.top - ttHeight - ttArrowOffset) - tooltipOffset,
13623                                                     left: position.left + position.width / 2 - ttWidth / 2
13624                                                 };
13625                                             }
13626                                             break;
13627                                     }
13628
13629                                     ttPosition.top += 'px';
13630                                     ttPosition.left += 'px';
13631
13632                                     // Now set the calculated positioning.
13633                                     tooltip.css(ttPosition);
13634
13635                                     // And show the tooltip.
13636                                     scope.tt_isOpen = true;
13637                                 }
13638
13639                                 // Hide the tooltip popup element.
13640                                 function hide() {
13641                                     // First things first: we don't show it anymore.
13642                                     scope.tt_isOpen = false;
13643
13644                                     //if tooltip is going to be shown after delay, we must cancel this
13645                                     $timeout.cancel(popupTimeout);
13646
13647                                     // And now we remove it from the DOM. However, if we have animation, we
13648                                     // need to wait for it to expire beforehand.
13649                                     // This is a placeholder for a port of the transitions library.
13650                                     if (angular.isDefined(scope.tt_animation) && scope.tt_animation()) {
13651                                         transitionTimeout = $timeout(function() {
13652                                             $attElementDetach(tooltip[0]);
13653                                         }, 500);
13654                                     } else {
13655                                         $attElementDetach(tooltip[0]);
13656                                     }
13657                                 }
13658
13659                                 function setTooltipAriaLabel() {
13660                                     element.removeAttr('title');
13661                                     if(!isElementHovered){
13662                                         if (tooltipAriaLabelDefined) {
13663                                             element.attr('title', scope.tooltipAriaLabel);
13664                                         } else {
13665                                             element.attr('title', scope.tt_content);
13666                                         }
13667                                     }
13668                                 }
13669
13670                                 /**
13671                                  * Observe the relevant attributes.
13672                                  */
13673                                 attrs.$observe(type, function(val) {
13674                                     if (val) {
13675                                         scope.tt_content = val;
13676                                         setTooltipAriaLabel();
13677                                     } else {
13678                                         if (scope.tt_isOpen) {
13679                                             hide();
13680                                         }
13681                                     }
13682                                 });
13683
13684                                 attrs.$observe(prefix + 'Title', function(val) {
13685                                     scope.tt_title = val;
13686                                 });
13687
13688                                 attrs.$observe(prefix + 'Placement', function(val) {
13689                                     scope.tt_placement = angular.isDefined(val) ? val : options.placement;
13690                                 });
13691
13692                                 attrs.$observe(prefix + 'Style', function(val) {
13693                                     scope.tt_style = angular.isDefined(val) ? val : options.stylett;
13694                                 });
13695
13696                                 attrs.$observe(prefix + 'Animation', function(val) {
13697                                     scope.tt_animation = angular.isDefined(val) ? $parse(val) : function() {
13698                                         return options.animation;
13699                                     };
13700                                 });
13701
13702                                 attrs.$observe(prefix + 'PopupDelay', function(val) {
13703                                     var delay = parseInt(val, 10);
13704                                     scope.tt_popupDelay = !isNaN(delay) ? delay : options.popupDelay;
13705                                 });
13706
13707                                 attrs.$observe(prefix + 'Trigger', function(val) {
13708
13709                                     if (hasRegisteredTriggers) {
13710                                         element.unbind(triggers.show, showTooltipBind);
13711                                         element.unbind(triggers.hide, hideTooltipBind);
13712                                     }
13713
13714                                     triggers = getTriggers(val);
13715
13716                                     /* This fixes issue in which a click on input field with trigger as focus 
13717                                         causes focus to fire following click thus making tooltip flash. */
13718                                     if (triggers.show === 'focus') {
13719                                         element.bind('focus', showTooltipBind);
13720                                         element.bind('blur', hideTooltipBind);
13721                                         element.bind('click', function(e) {
13722                                             e.stopPropagation();
13723                                         });
13724                                     } else if (triggers.show === triggers.hide) {
13725                                         element.bind(triggers.show, toggleTooltipBind);
13726                                     } else {
13727                                         element.bind(triggers.show, showTooltipBind);
13728                                         element.bind(triggers.hide, hideTooltipBind);
13729                                     }
13730
13731                                     hasRegisteredTriggers = true;
13732                                 });
13733
13734                                 attrs.$observe(prefix + 'AppendToBody', function (val) {
13735                                     appendToBody = angular.isDefined(val) ? $parse(val)(scope) : appendToBody;
13736                                 });
13737
13738                                 attrs.$observe(prefix + 'Offset', function (val) {
13739                                     tooltipOffset = angular.isDefined(val) ? parseInt(val, 10) : 0;
13740                                 });
13741
13742                                 attrs.$observe(prefix + 'AriaLabel', function (val) {
13743                                     if (angular.isDefined(val)) {
13744                                         scope.tooltipAriaLabel = val;
13745                                         tooltipAriaLabelDefined = true;
13746                                     } else {
13747                                         tooltipAriaLabelDefined = false;
13748                                     }
13749                                     setTooltipAriaLabel();
13750                                 });
13751
13752                                 // if a tooltip is attached to <body> we need to remove it on
13753                                 // location change as its parent scope will probably not be destroyed
13754                                 // by the change.
13755                                 if (appendToBody) {
13756                                     scope.$on('$locationChangeSuccess', function() {
13757                                         if (scope.tt_isOpen) {
13758                                             hide();
13759                                         }
13760                                     });
13761                                 }
13762
13763                                 // Make sure tooltip is destroyed and removed.
13764                                 scope.$on('$destroy', function() {
13765                                     if (scope.tt_isOpen) {
13766                                         hide();
13767                                     } else {
13768                                         tooltip.remove();
13769                                     }
13770                                 });
13771                             }
13772                         };
13773                     };
13774                 }];
13775         }])
13776
13777         .directive('tooltipPopup', ['$document', '$documentBind', function($document, $documentBind) {
13778             return {
13779                 restrict: 'EA',
13780                 replace: true,
13781                 transclude: true,
13782                 scope: {content: '@', placement: '@', animation: '&', isOpen: '=', stylett: '@'},
13783                 templateUrl: 'app/scripts/ng_js_att_tpls/tooltip/tooltip-popup.html',
13784                 link: function(scope, elem) {
13785                     scope.$watch("isOpen", function() {
13786                         scope.isOpen;
13787                     });
13788                     elem.bind('click', function (e) {
13789                         e.stopPropagation();
13790                     });
13791                     var outsideClick = function() {
13792                         scope.$apply(function() {
13793                             scope.isOpen = false;
13794                         });
13795                     };
13796
13797                     $documentBind.event('click', 'isOpen', outsideClick, scope, true, 10);
13798                 }
13799             };
13800         }])
13801
13802         .directive('tooltip', ['$tooltip', function($tooltip) {
13803             return $tooltip('tooltip', 'tooltip', 'mouseenter');
13804         }])
13805
13806         .directive('tooltipCondition', [ '$timeout',function($timeout) {
13807                 return  {
13808                     restrict: 'EA',
13809                     replace: true,
13810                     scope:{
13811                         tooltipCondition:"@?"
13812                     },
13813                     template:'<p><span tooltip=\"{{tooltipCondition}}\" ng-if=\"showpop\">{{tooltipCondition}}</span><span id=\"innerElement\" ng-hide=\"showpop\">{{tooltipCondition}}</span></p>',
13814                     link: function(scope, elem, attr){
13815                         scope.showpop=false;
13816                         if(attr.height==='true'){
13817                             $timeout(function () {
13818                                var maxHeight=(elem[0].offsetHeight);
13819                                var elemHeight=elem.children(0)[0].offsetHeight;
13820                                if(elemHeight > maxHeight){
13821                                    scope.showpop=true;
13822                                }
13823                             });
13824                         }
13825                         else if(scope.tooltipCondition.length>=25){
13826                         scope.showpop=true;
13827                         }
13828                     }
13829                 };
13830         }]);
13831 angular.module('att.abs.popOvers', ['att.abs.tooltip', 'att.abs.utilities', 'ngSanitize'])
13832         .directive('popover', ['$tooltip', function($tooltip) {
13833                 return $tooltip('popover', 'popover', 'click');
13834             }])
13835         .directive('popoverPopup', ['$document', '$documentBind', '$timeout', 'events', 'DOMHelper', function($document, $documentBind, $timeout, events, DOMHelper) {
13836                 return {
13837                     restrict: 'EA',
13838                     replace: true,
13839                     transclude: true,
13840                     templateUrl: 'app/scripts/ng_js_att_tpls/popOvers/popOvers.html',
13841                     scope: {content: '@', placement: '@', animation: '&', isOpen: '=', stylett: '@'},
13842                     link: function(scope, elem, attr, ctrl) {
13843
13844                         scope.closeable = false;
13845                         try {
13846                             scope.closeable = scope.$parent.parentAttrs['closeable'] === '' ? true : false;
13847                         } catch (e) {}
13848
13849                         /* Before opening modal, find the focused element */
13850                         var launchingElement = undefined, 
13851                             firstTabableElement = undefined;
13852
13853                         var outsideClick = function(evt) {
13854                             scope.$apply(function() {
13855                                 scope.isOpen = false;
13856                             });
13857                         };
13858                         var escKeydown = function(evt) {
13859                             if (evt.which === 27 || evt.keyCode === 27) {
13860                                     console.log('ESC was pressed!');
13861                                     scope.$apply(function() {
13862                                         scope.isOpen = false;
13863                                 });
13864                             }
13865                         };
13866
13867                         $timeout(function() {
13868                             firstTabableElement = DOMHelper.firstTabableElement(elem);
13869                         }, 10, false);
13870                         
13871                         scope.$watch('isOpen', function(value) {
13872                             if (scope.isOpen) {
13873                                 launchingElement = document.activeElement;
13874                                 /* Focus on first tabbable element */
13875                                 if (angular.isDefined(firstTabableElement)) {
13876                                     try {
13877                                         firstTabableElement.focus();
13878                                     } catch(e) {}
13879                                 }
13880                             } else {
13881                                 if (angular.isDefined(launchingElement)) {
13882                                     try {
13883                                         launchingElement.focus();
13884                                     } catch (e) {} /* IE8 will throw exception */
13885                                 }
13886                             }
13887                         });
13888                         
13889                         scope.$watch("stylett", function(value) {
13890                             scope.popOverStyle = value;
13891                         });
13892
13893                         scope.$watch("placement", function(value) {
13894                             scope.popOverPlacement = value;
13895                         });
13896                         
13897                         scope.closeMe = function(){
13898                            scope.isOpen = false;
13899                         };
13900                         
13901                         elem.bind('click', function (e) {
13902                             events.stopPropagation(e);
13903                         });
13904                         
13905                         $documentBind.event('click', 'isOpen', outsideClick, scope, true, 10);
13906                         $documentBind.event('keydown', 'isOpen', escKeydown, scope, true, 10);
13907                     }
13908                 };
13909             }]);
13910
13911 angular.module('att.abs.profileCard', [])
13912             .constant('profileStatus',{
13913                 status:{
13914                     ACTIVE:{status:"Active",color:"green"},
13915                     DEACTIVATED:{status:"Deactivated",color:"red"},
13916                     LOCKED:{status:"Locked",color:"red"},
13917                     IDLE:{status:"Idle",color:"yellow"},
13918                     PENDING:{status:"Pending",color:"blue"}
13919                     },
13920                 role:"COMPANY ADMINISTRATOR"
13921                 })
13922             .directive('profileCard',['$http','$q','profileStatus', function($http,$q,profileStatus) {
13923                return {
13924                     restrict: 'EA',
13925                     replace:'true',
13926                     templateUrl:function(element, attrs){
13927                         if(!attrs.addUser){
13928                             return 'app/scripts/ng_js_att_tpls/profileCard/profileCard.html';
13929                         }
13930                         else{
13931                             return 'app/scripts/ng_js_att_tpls/profileCard/addUser.html';
13932                         }
13933                     },
13934                     scope:{
13935                         profile:'='
13936                     },
13937                     link: function(scope, elem, attr){
13938                         scope.image=true;
13939                         function isImage(src) {
13940                             var deferred = $q.defer();
13941                             var image = new Image();
13942                             image.onerror = function() {
13943                                 deferred.reject(false);
13944                             };
13945                             image.onload = function() {
13946                                 deferred.resolve(true);
13947                             };
13948                             if(src!==undefined && src.length>0 ){
13949                                 image.src = src;
13950                             }else{
13951                                  deferred.reject(false);
13952                             }
13953                             return deferred.promise;
13954                         }
13955                         if(!attr.addUser){
13956                         scope.image=false;
13957                         isImage(scope.profile.img).then(function(img) {
13958                             scope.image=img;
13959                         });
13960                         var splitName=(scope.profile.name).split(' ');
13961                         scope.initials='';
13962                         for(var i=0;i<splitName.length;i++){
13963                             scope.initials += splitName[i][0];
13964                         }
13965                         if(scope.profile.role.toUpperCase()===profileStatus.role){
13966                             scope.badge=true;
13967                         }
13968                         var profileState=profileStatus.status[scope.profile.state.toUpperCase()];
13969                         if(profileState) {
13970                             scope.profile.state=profileStatus.status[scope.profile.state.toUpperCase()].status;
13971                             scope.colorIcon=profileStatus.status[scope.profile.state.toUpperCase()].color;
13972                             if(scope.profile.state.toUpperCase()===profileStatus.status.PENDING.status.toUpperCase()||scope.profile.state.toUpperCase()===profileStatus.status.LOCKED.status.toUpperCase()){
13973                                     scope.profile.lastLogin=scope.profile.state;
13974                             }
13975                         }
13976                         var today=new Date().getTime();
13977                         var lastlogin=new Date(scope.profile.lastLogin).getTime();
13978                         var diff=(today-lastlogin)/(1000*60*60*24);
13979                         if(diff<=1){
13980                             scope.profile.lastLogin="Today";
13981                         }
13982                         else if(diff<=2){
13983                             scope.profile.lastLogin="Yesterday";
13984                         }
13985                     }
13986                 }
13987             };
13988         }]);
13989 angular.module('att.abs.progressBars', [])
13990
13991 .directive('attProgressBar', [function(){
13992     return {
13993         restrict: 'A',
13994         replace: true,
13995         templateUrl : 'app/scripts/ng_js_att_tpls/progressBars/progressBars.html'
13996     };
13997 }]);
13998 angular.module('att.abs.radio', [])
13999     .constant('attRadioConfig', {
14000         activeClass : "att-radio--on",
14001         disabledClass : "att-radio--disabled"
14002     })
14003 .directive('attRadio', ['$compile','attRadioConfig', function ($compile, attRadioConfig) {
14004     return {
14005         scope: {},
14006         restrict: 'A',
14007         require: 'ngModel',
14008         link: function (scope, element, attr, ctrl) {
14009             var ngCtrl = ctrl;
14010             scope.radioVal='';
14011             var parentDiv = angular.element('<div att-accessibility-click="13,32" ng-click="updateModel($event)" class="att-radio"></div>');
14012             element.attr("value",attr.attRadio);
14013             element.removeAttr("att-radio");
14014             element.removeAttr("title");
14015             element.attr("ng-model","radioVal");
14016             parentDiv.append(element.prop('outerHTML'));
14017             parentDiv.append('<div class="att-radio__indicator"></div>');
14018             parentDiv.attr("title", attr.title);
14019
14020             var elm = parentDiv.prop('outerHTML');
14021             elm = $compile(elm)(scope);
14022             element = element.replaceWith(elm);
14023             var radioElm = elm.find("input");
14024
14025             radioElm.on('focus', function() {                
14026                 elm.css("outline","thin dotted #333");
14027                 elm.css("outline","-webkit-focus-ring-color auto 5px");
14028             });
14029             radioElm.on('blur', function() {
14030                elm.css("outline","none");
14031             });
14032
14033             ngCtrl.$render = function () {
14034                 scope.radioVal = ngCtrl.$modelValue;
14035                 var selected = angular.equals(ngCtrl.$modelValue, attr.attRadio);                
14036                 elm.toggleClass(attRadioConfig.activeClass, selected);
14037             };
14038
14039             scope.updateModel = function () {
14040                radioElm[0].focus();
14041                 var isActive = elm.hasClass(attRadioConfig.activeClass);
14042
14043                 if (!isActive && !scope.disabled) {
14044                     ngCtrl.$setViewValue(isActive ? null : attr.attRadio);      
14045                     ngCtrl.$render();
14046                 }
14047             };
14048
14049             attr.$observe('disabled', function (val) {
14050                 scope.disabled = (val || val === "disabled" || val === "true");
14051                 if (scope.disabled){
14052                     elm.addClass(attRadioConfig.disabledClass);
14053                     elm.attr("tabindex", "-1");
14054                 }
14055             });
14056         }
14057     };
14058 }]);
14059 angular.module('att.abs.scrollbar', ['att.abs.position'])
14060
14061 .constant('attScrollbarConstant', {
14062     defaults: {
14063         // Vertical or horizontal scrollbar? ( x || y ).
14064         axis: 'y',
14065         // Whether navigation pane is required of not.
14066         navigation: false,
14067         // Enable or disable the mousewheel.
14068         wheel: true,
14069         // How many pixels must the mouswheel scroll at a time.
14070         wheelSpeed: 40,
14071         // Lock default scrolling window when there is no more content.
14072         wheelLock: true,
14073         //// Enable invert style scrolling
14074         scrollInvert: false,
14075         // Set the size of the scrollbar to auto or a fixed number.
14076         trackSize: false,
14077         // Set the size of the thumb to auto or a fixed number.
14078         thumbSize: false,
14079         // Set to false to hide the scrollbar if not being used
14080         alwaysVisible: true
14081     }
14082 })
14083
14084 .directive('attScrollbar', ['$window', '$timeout', '$parse', '$animate', 'attScrollbarConstant', '$position', function ($window, $timeout, $parse, $animate, attScrollbarConstant, $position) {
14085     return {
14086         restrict: 'A',
14087         scope: true,
14088         transclude: true,
14089         templateUrl: 'app/scripts/ng_js_att_tpls/scrollbar/scrollbar.html',
14090         controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {
14091             var defaults = {
14092                 axis: $attrs.attScrollbar || attScrollbarConstant.defaults.axis,
14093                 navigation: $attrs.navigation || attScrollbarConstant.defaults.navigation,
14094                 wheel: attScrollbarConstant.defaults.wheel,
14095                 wheelSpeed: attScrollbarConstant.defaults.wheelSpeed,
14096                 wheelLock: attScrollbarConstant.defaults.wheelLock,
14097                 scrollInvert: attScrollbarConstant.defaults.scrollInvert,
14098                 trackSize: attScrollbarConstant.defaults.trackSize,
14099                 thumbSize: attScrollbarConstant.defaults.thumbSize,
14100                 alwaysVisible: attScrollbarConstant.defaults.alwaysVisible
14101             };
14102             var options = $attrs.scrollbar;
14103             if (options) {
14104                 options = $parse(options)($scope);
14105             } else {
14106                 options = {};
14107             }
14108             this.options = angular.extend({}, defaults, options);
14109             this._defaults = defaults;
14110
14111             var self = this,
14112                 $body = angular.element(document.querySelectorAll('body')[0]),
14113                 $document = angular.element(document),
14114                 $viewport = angular.element($element[0].querySelectorAll('.scroll-viewport')[0]),
14115                 $overview = angular.element($element[0].querySelectorAll('.scroll-overview')[0]),
14116                 $scrollbar = angular.element($element[0].querySelectorAll('.scroll-bar')[0]),
14117                 $thumb = angular.element($element[0].querySelectorAll('.scroll-thumb')[0]),
14118                 mousePosition = 0,
14119                 isHorizontal = this.options.axis === 'x',
14120                 hasTouchEvents = false,
14121                 // Modern browsers support "wheel"
14122                 wheelEvent = ("onwheel" in document ? "wheel" :
14123                     // Webkit and IE support at least "mousewheel"
14124                     document.onmousewheel !== undefined ? "mousewheel" :
14125                     // let's assume that remaining browsers are older Firefox
14126                     "DOMMouseScroll"),
14127                 sizeLabel = isHorizontal ? 'width' : 'height',
14128                 sizeLabelCap = sizeLabel.charAt(0).toUpperCase() + sizeLabel.slice(1).toLowerCase(),
14129                 posiLabel = isHorizontal ? 'left' : 'top',
14130                 // moveEvent = document.createEvent('HTMLEvents'),
14131                 restoreVisibilityAfterWheel,
14132                 thumbscrolltouch = false,
14133                 documnetscrolltouch = false;
14134             if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
14135                 hasTouchEvents = true;
14136             }
14137
14138             //moveEvent.initEvent('move', true, true);
14139             this.contentPosition = 0;
14140             this.viewportSize = 0;
14141             this.contentSize = 0;
14142             this.contentRatio = 0;
14143             this.trackSize = 0;
14144             this.trackRatio = 0;
14145             this.thumbSize = 0;
14146             this.thumbPosition = 0;
14147
14148             this.initialize = function () {
14149                 if (!this.options.alwaysVisible) {
14150                     $scrollbar.css('opacity', 0);
14151                 }
14152                 self.update();
14153                 setEvents();
14154                 return self;
14155             };
14156
14157             this.setSizeData = function () {
14158                 this.viewportSize = $viewport.prop('offset' + sizeLabelCap) || 1;
14159                 this.contentSize = $overview.prop('scroll' + sizeLabelCap) || 1;
14160                 this.contentRatio = this.viewportSize / this.contentSize;
14161                 this.trackSize = this.options.trackSize || this.viewportSize;
14162                 this.thumbSize = Math.min(this.trackSize, Math.max(0, (this.options.thumbSize || (this.trackSize * this.contentRatio))));
14163                 this.trackRatio = this.options.thumbSize ? (this.contentSize - this.viewportSize) / (this.trackSize - this.thumbSize) : (this.contentSize / this.trackSize);
14164             };
14165
14166             this.update = function (scrollTo) {
14167                 self.setSizeData();
14168                 mousePosition = $scrollbar.prop('offsetTop');
14169
14170                 $scrollbar.toggleClass('disable', this.contentRatio >= 1 || isNaN(this.contentRatio));
14171
14172                 if (!this.options.alwaysVisible && this.contentRatio < 1 && this.viewportSize > 0) {
14173                     //flash the scrollbar when update happens
14174                     $animate.addClass($scrollbar, 'visible').then(function () {
14175                         $animate.removeClass($scrollbar, 'visible');
14176                         $scope.$digest();
14177                     });
14178                 }
14179
14180                 if (scrollTo !== null) {
14181                     if (scrollTo === 'bottom') {
14182                         this.contentPosition = this.contentSize - this.viewportSize;
14183                     } else {
14184                         this.contentPosition = parseInt(scrollTo, 10) || 0;
14185                     }
14186                 }
14187
14188                 ensureContentPosition();
14189                 $thumb.css(posiLabel, self.contentPosition / self.trackRatio + 'px');
14190                 $scrollbar.css(sizeLabel, self.trackSize + 'px');
14191                 $thumb.css(sizeLabel, self.thumbSize + 'px');
14192                 $overview.css(posiLabel, -self.contentPosition + 'px');
14193
14194                 return this;
14195             };
14196
14197             fireEvent = function (obj, evt) {
14198                 var fireOnThis = obj;
14199                 var evtObj;
14200                 if (document.createEvent) {
14201                     // alert("FF");
14202                     evtObj = document.createEvent('HTMLEvents');
14203                     evtObj.initEvent(evt, true, false);
14204                     fireOnThis.dispatchEvent(evtObj);
14205                 } else if (document.createEventObject) {
14206                     // alert("IE8");
14207                     evtObj = document.createEventObject();
14208                     fireOnThis.fireEvent('on' + evt, evtObj);
14209                 }
14210             };
14211
14212             function ensureContentPosition() {
14213                 // if scrollbar is on, ensure the bottom of the content does not go above the bottom of the viewport
14214                 if (self.contentRatio <= 1 && self.contentPosition > self.contentSize - self.viewportSize) {
14215                     self.contentPosition = self.contentSize - self.viewportSize;
14216                 }
14217                 // if scrollbar is off, ensure the top of the content does not go below the top of the viewport
14218                 else if (self.contentRatio > 1 && self.contentPosition > 0) {
14219                     self.contentPosition = 0;
14220                 }
14221
14222                 if (self.contentPosition <= 0) {
14223                     $scope.prevAvailable = false;
14224                 } else {
14225                     $scope.prevAvailable = true;
14226                 }
14227
14228                 if (self.contentPosition >= (self.contentSize - self.viewportSize)) {
14229                     $scope.nextAvailable = false;
14230                 } else {
14231                     $scope.nextAvailable = true;
14232                 }
14233             }
14234
14235             function setEvents() {
14236                 if (hasTouchEvents) {
14237                     $viewport.on('touchstart', touchstart);
14238                     $thumb.on('touchstart', touchstart);
14239                 } else {
14240                     $thumb.on('mousedown', start);
14241                     $scrollbar.on('mousedown', drag);
14242                 }
14243
14244                 angular.element($window).on('resize', resize);
14245
14246                 if (self.options.wheel) {
14247                     $element.on(wheelEvent, wheel);
14248                 }
14249             }
14250
14251             function resize() {
14252                 self.update();
14253             }
14254
14255             function touchstart(event) {
14256                 if (1 === event.touches.length) {
14257                     event.stopPropagation();
14258                     start(event.touches[0]);
14259                 }
14260             }
14261
14262             function start(event) {
14263                 $body.addClass('scroll-no-select');
14264                 $element.addClass('scroll-no-select');
14265
14266                 if (!self.options.alwaysVisible) {
14267                     $scrollbar.addClass('visible');
14268                 }
14269                 mousePosition = isHorizontal ? event.clientX : event.clientY;
14270                 self.thumbPosition = parseInt($thumb.css(posiLabel), 10) || 0;
14271
14272                 if (hasTouchEvents) {
14273                     documnetscrolltouch = false;
14274                     thumbscrolltouch = false;
14275                     $viewport.on('touchmove', touchdrag);
14276                     $viewport.on('touchend', end);
14277                     $thumb.on('touchmove', touchdragthumb);
14278                     $thumb.on('touchend', end);
14279                 } else {
14280                     $document.on('mousemove', drag);
14281                     $document.on('mouseup', end);
14282                     $thumb.on('mouseup', end);
14283                 }
14284             }
14285
14286             function wheel(event) {
14287                 if (self.contentRatio >= 1) {
14288                     return;
14289                 }
14290
14291                 if (!self.options.alwaysVisible) {
14292                     //cancel removing visibility if wheel event is triggered before the timeout
14293                     if (restoreVisibilityAfterWheel) {
14294                         $timeout.cancel(restoreVisibilityAfterWheel);
14295                     }
14296                     $scrollbar.addClass('visible');
14297
14298                     restoreVisibilityAfterWheel = $timeout(function () {
14299                         $scrollbar.removeClass('visible');
14300                     }, 100);
14301                 }
14302
14303                 var evntObj = (event && event.originalEvent) || event || $window.event,
14304                     deltaDir = self.options.axis.toUpperCase(),
14305                     delta = {
14306                         X: evntObj.deltaX || 0,
14307                         Y: evntObj.deltaY || 0
14308                     },
14309                     wheelSpeed = evntObj.deltaMode === 0 ? self.options.wheelSpeed : 1;
14310
14311                 if (self.options.scrollInvert) {
14312                     wheelSpeed *= -1;
14313                 }
14314
14315                 if (wheelEvent === 'mousewheel') {
14316                     delta.Y = -1 * evntObj.wheelDelta / 40;
14317                     if (evntObj.wheelDeltaX) {
14318                         delta.X = -1 * evntObj.wheelDeltaX / 40;
14319                     }
14320                 }
14321                 delta.X *= -1 / wheelSpeed;
14322                 delta.Y *= -1 / wheelSpeed;
14323
14324                 var wheelSpeedDelta = delta[deltaDir];
14325
14326                 self.contentPosition -= wheelSpeedDelta * self.options.wheelSpeed;
14327                 self.contentPosition = Math.min((self.contentSize - self.viewportSize), Math.max(0, self.contentPosition));
14328
14329                 fireEvent($element[0], 'move');
14330
14331                 ensureContentPosition();
14332                 $thumb.css(posiLabel, self.contentPosition / self.trackRatio + 'px');
14333                 $overview.css(posiLabel, -self.contentPosition + 'px');
14334
14335                 if (self.options.wheelLock || (self.contentPosition !== (self.contentSize - self.viewportSize) && self.contentPosition !== 0)) {
14336                     evntObj.preventDefault();
14337                 }
14338
14339                 $scope.$apply();
14340             }
14341
14342             function touchdrag(event) {
14343                 event.preventDefault();
14344                 documnetscrolltouch = true;
14345                 drag(event.touches[0]);
14346             }
14347
14348             function touchdragthumb(event) {
14349                 event.preventDefault();
14350                 thumbscrolltouch = true;
14351                 drag(event.touches[0]);
14352             }
14353
14354             function drag(event) {
14355                 if (self.contentRatio >= 1) {
14356                     return;
14357                 }
14358
14359                 var mousePositionNew = isHorizontal ? event.clientX : event.clientY,
14360                     thumbPositionDelta = mousePositionNew - mousePosition;
14361
14362                 if ((self.options.scrollInvert && !hasTouchEvents) ||
14363                     (hasTouchEvents && !self.options.scrollInvert)) {
14364                     thumbPositionDelta = mousePosition - mousePositionNew;
14365                 }
14366                 if (documnetscrolltouch && hasTouchEvents) {
14367                     thumbPositionDelta = mousePosition - mousePositionNew;
14368                 }
14369                 if (thumbscrolltouch && hasTouchEvents) {
14370                     thumbPositionDelta = mousePositionNew - mousePosition;
14371                 }
14372                 var thumbPositionNew = Math.min((self.trackSize - self.thumbSize), Math.max(0, self.thumbPosition + thumbPositionDelta));
14373                 self.contentPosition = thumbPositionNew * self.trackRatio;
14374
14375                 fireEvent($element[0], 'move');
14376
14377                 ensureContentPosition();
14378                 $thumb.css(posiLabel, thumbPositionNew + 'px');
14379                 $overview.css(posiLabel, -self.contentPosition + 'px');
14380
14381                 $scope.$apply();
14382             }
14383
14384             $scope.customScroll = function (direction) {
14385                 if (self.contentRatio >= 1) {
14386                     return;
14387                 }
14388
14389                 var customScrollDelta;
14390                 var viewportDimension = $position.position($viewport);
14391
14392                 if (isHorizontal) {
14393                     customScrollDelta = viewportDimension.width;
14394                 } else {
14395                     customScrollDelta = viewportDimension.height;
14396                 }
14397
14398                 if (direction) {
14399                     self.contentPosition += customScrollDelta;
14400                 } else {
14401                     self.contentPosition -= customScrollDelta;
14402                 }
14403                 self.contentPosition = Math.min((self.contentSize - self.viewportSize), Math.max(0, self.contentPosition));
14404
14405                 fireEvent($element[0], 'move');
14406
14407                 ensureContentPosition();
14408                 $thumb.css(posiLabel, self.contentPosition / self.trackRatio + 'px');
14409                 $overview.css(posiLabel, -self.contentPosition + 'px');
14410             };
14411
14412             function end() {
14413                 $body.removeClass('scroll-no-select');
14414                 $element.removeClass('scroll-no-select');
14415                 if (!self.options.alwaysVisible) {
14416                     $scrollbar.removeClass('visible');
14417                 }
14418                 $document.off('mousemove', drag);
14419                 $document.off('mouseup', end);
14420                 $thumb.off('mouseup', end);
14421                 $document.off('touchmove', touchdrag);
14422                 $document.off('ontouchend', end);
14423                 $thumb.off('touchmove', touchdragthumb);
14424                 $thumb.off('touchend', end);
14425             }
14426
14427             this.cleanup = function () {
14428                 $viewport.off('touchstart', touchstart);
14429                 $thumb.off('mousedown', start);
14430                 $scrollbar.off('mousedown', drag);
14431                 $thumb.off('touchmove', touchdragthumb);
14432                 $thumb.off('touchend', end);
14433                 angular.element($window).off('resize', resize);
14434                 $element.off(wheelEvent, wheel);
14435                 //ensure scrollbar isn't activated
14436                 self.options.alwaysVisible = true;
14437                 end();
14438             };
14439         }],
14440         link: function (scope, iElement, iAttrs, controller) {
14441             scope.navigation = controller.options.navigation;
14442             scope.viewportHeight = iAttrs.viewportHeight;
14443             scope.viewportWidth = iAttrs.viewportWidth;
14444             scope.scrollbarAxis = controller.options.axis;
14445             if (scope.scrollbarAxis === 'x') {
14446                 iElement.addClass('horizontal');
14447             } else if (scope.scrollbarAxis === 'y') {
14448                 iElement.addClass('vertical');
14449             }
14450
14451             var position = iElement.css('position');
14452             if (position !== 'relative' && position !== 'absolute') {
14453                 iElement.css('position', 'relative');
14454             }
14455
14456             scope.$watch(function () {
14457                 $timeout(refreshScrollbar, 100, false);
14458             });
14459
14460             var refreshScrollbar = function () {
14461                 var $overview = angular.element(iElement[0].querySelectorAll('.scroll-overview')[0]);
14462                 var newValue = $overview.prop('scrollHeight');
14463                 var oldValue = scope.oldValue;
14464                 if (newValue !== oldValue) {
14465                     scope.oldValue = newValue;
14466                     controller.update();
14467                 }
14468             };
14469
14470             controller.initialize();
14471             iElement.on('$destroy', function () {
14472                 controller.cleanup();
14473             });
14474         }
14475     };
14476 }]);
14477
14478 angular.module('att.abs.search', ['att.abs.utilities', 'att.abs.position', 'att.abs.utilities'])
14479 .directive('attSearch', ['$document', '$filter', '$isElement', '$documentBind', '$timeout', '$log', 'keymap', function($document, $filter, $isElement, $documentBind, $timeout, $log, keymap){
14480     return{
14481         restrict: 'A',
14482         scope:{cName: '=attSearch'},
14483         transclude: false,
14484         replace: false,
14485         require:'ngModel',
14486         templateUrl: 'app/scripts/ng_js_att_tpls/search/search.html',
14487         link: function(scope, element, attr, ctrl) {
14488             scope.selectedIndex = -1;
14489             scope.selectedOption = attr.placeholder;
14490             scope.isDisabled = false;
14491             scope.className = "select2-match";
14492             scope.showSearch = false;
14493             scope.showlist = false;
14494
14495             // This is used to jump to elements in list
14496             var search = '';
14497             // This is used to ensure searches only persist so many ms.
14498             var prevSearchDate = new Date();
14499             // This is used to shift focus back after closing dropdown
14500             var dropdownElement = undefined;
14501             // Used to ensure focus on dropdown elements
14502             var list = [];
14503             $timeout(function() {
14504                 list = element.find('li');
14505             }, 10);
14506
14507             $log.warn('attSearch is deprecated, please use attSelect instead. This component will be removed by version 2.7.')
14508
14509             if (attr.noFilter || attr.noFilter === 'true') {
14510                 scope.noFilter = true;
14511             } else {
14512                 scope.noFilter = false;
14513             }
14514             if (attr.placeholderAsOption === 'false') {
14515                 //scope.selectMsg = '';
14516                 scope.selectedOption = attr.placeholder;
14517             } else {
14518                 scope.selectMsg = attr.placeholder;
14519             }
14520             if (attr.startsWithFilter || attr.startsWithFilter === 'true') {
14521                 scope.startsWithFilter = true;
14522             }
14523             if (attr.showInputFilter === 'true') {
14524                 scope.showSearch = false;
14525                 $log.warn('showInputFilter functionality has been removed from the library.');
14526                 // This is deprecated
14527             }
14528             if (attr.disabled) {
14529                 scope.isDisabled = true;
14530             }
14531             dropdownElement = angular.element(element).children().eq(0).find('a')[0];
14532             var prevIndex = 0;
14533             var selectOptionFromSearch = function() {
14534                 if (!scope.noFilter) {
14535                     return;
14536                 }
14537
14538                 // Find next element that matches search criteria. 
14539                 // If no element is found, loop to beginning and search.
14540                 var criteria = search;
14541                 var i = 0;
14542                 for (i = prevIndex; i < scope.cName.length; i++) {
14543                     // Need to ensure we keep searching until all startsWith have passed before looping
14544                     if (scope.cName[i].title.startsWith(criteria) && i !== scope.selectedIndex) {
14545                         scope.selectOption(scope.cName[i], i, scope.showlist);
14546                         prevIndex = i;
14547                         search = '';
14548                         break;
14549                     }
14550                 }
14551                 if ((i >= scope.cName.length || !scope.cName[i+1].title.startsWith(criteria)) && prevIndex > 0) {
14552                     prevIndex = 0;
14553                 }
14554             };
14555             scope.showDropdown = function() {
14556                 if (!(attr.disabled)) {
14557                     scope.showlist = !scope.showlist;
14558                     scope.setSelectTop();
14559                 }
14560             };
14561             element.bind('keydown', function(e) {
14562                 if (keymap.isAllowedKey(e.keyCode) || keymap.isControl(e) || keymap.isFunctionKey(e)) {
14563                     e.preventDefault();
14564                     e.stopPropagation();
14565
14566                     switch (e.keyCode) {
14567                         case keymap.KEY.DOWN:
14568                             scope.selectNext();
14569                             break;
14570                         case keymap.KEY.UP:
14571                             scope.selectPrev();
14572                             search = '';
14573                             break;
14574                         case keymap.KEY.ENTER:
14575                             scope.selectCurrent();
14576                             search = '';
14577                             break;
14578                         case keymap.KEY.BACKSPACE:
14579                             scope.title = '';
14580                             search = '';
14581                             scope.$apply();
14582                             break;
14583                         case keymap.KEY.SPACE:
14584                             if (!scope.noFilter) {
14585                                 scope.title += ' ';
14586                             }
14587                             scope.$apply();
14588                             break;
14589                         case keymap.KEY.ESC:
14590                             if (scope.title === '' || scope.title === undefined) {
14591                                 scope.showlist = false;
14592                                 dropdownElement.focus();
14593                                 scope.$apply();
14594                             } else {
14595                                 scope.title = '';
14596                                 scope.$apply();
14597                             }
14598                             if (scope.noFilter) {
14599                                 search = '';
14600                                 dropdownElement.focus();
14601                                 scope.showlist = false;
14602                             }
14603                             break;
14604                         default:
14605                             break;
14606                     }
14607                 } else {
14608                     if (e.keyCode !== 9)
14609                     {
14610                         if (!scope.noFilter) {
14611                             scope.showlist = true;
14612                             scope.title = scope.title ? scope.title + String.fromCharCode(e.keyCode) : String.fromCharCode(e.keyCode);
14613                         } else {
14614                             var date = new Date();
14615                             var delta = Math.abs(prevSearchDate.getMilliseconds() - date.getMilliseconds());
14616                             prevSearchDate = date;
14617                             if (delta > 100) {
14618                                 search = '';
14619                             }
14620                             search = search ? search + String.fromCharCode(e.keyCode) : String.fromCharCode(e.keyCode);
14621                             if (search.length > 2) {
14622                                 search = search.substring(0, 2);
14623                             }
14624                             selectOptionFromSearch();
14625                         }
14626                         scope.$apply();
14627                     } else if (e.keyCode === 9) {
14628                         scope.showlist = false;
14629                         scope.title = '';
14630                         scope.$apply();
14631                     }
14632                 }
14633             });
14634             scope.selectOption = function(sTitle, sIndex, keepOpen) {
14635                 if (sIndex === -1 || sIndex === '-1') {
14636                     scope.selCategory = '';
14637                     scope.selectedIndex = -1;
14638                     ctrl.$setViewValue('');
14639                     if(attr.placeholderAsOption !== 'false')
14640                     {
14641                         scope.selectedOption = scope.selectMsg;
14642                     }
14643                 } else {
14644                     scope.selCategory = scope.cName[sIndex];
14645                     scope.selectedIndex = sIndex;
14646                     ctrl.$setViewValue(scope.selCategory);
14647                     scope.selectedOption = scope.selCategory.title;
14648                     if (angular.isDefined(list[sIndex])) {
14649                         list[sIndex].focus();
14650                     }
14651                 }
14652                 scope.title = '';
14653                 if (!keepOpen) {
14654                     scope.showlist = false;
14655                     dropdownElement.focus();
14656                 }
14657                 scope.$apply();
14658             };
14659             scope.selectCurrent = function() {
14660                 if (scope.showlist) {
14661                     scope.selectOption(scope.selectMsg, scope.selectedIndex, false);
14662                     scope.$apply();
14663                 } else {
14664                     scope.showlist = true;
14665                     scope.setSelectTop();
14666                     scope.$apply();
14667                 }
14668             };
14669             scope.hoverIn = function(cItem) {
14670                 scope.selectedIndex = cItem;
14671                 scope.focusme();
14672             };
14673             scope.setSelectTop = function() {
14674                 $timeout(function() {
14675                     if (scope.showlist && !scope.noFilter)
14676                     {
14677                         var containerUL = angular.element(element)[0].querySelector(".select2-results");
14678                         if(angular.element(containerUL.querySelector('.select2-result-current'))[0])
14679                         {
14680                             var selectedElemTopPos = angular.element(containerUL.querySelector('.select2-result-current'))[0].offsetTop;
14681                         }
14682                         angular.element(containerUL)[0].scrollTop = selectedElemTopPos;
14683                     }
14684                 });
14685             };
14686             scope.setCurrentTop = function() {
14687                 $timeout(function() {
14688                     if (scope.showlist) {
14689                         var containerUL = angular.element(element)[0].querySelector(".select2-results");
14690                         if(angular.element(containerUL.querySelector('.hovstyle'))[0])
14691                         {
14692                             var selectedElemTopPos = angular.element(containerUL.querySelector('.hovstyle'))[0].offsetTop;
14693                         }
14694                         if (selectedElemTopPos < (angular.element(containerUL)[0].scrollTop)) {
14695                             angular.element(containerUL)[0].scrollTop -= 30;
14696                         } else if ((selectedElemTopPos + 30) > (angular.element(containerUL)[0].clientHeight)) {
14697                             angular.element(containerUL)[0].scrollTop += 30;
14698                         }
14699
14700                     }
14701                 });
14702             };
14703             scope.selectNext = function() {
14704                 if ((scope.selectedIndex + 1) <= (scope.cName.length - 1)) {
14705                     scope.selectedIndex += 1;
14706                     if (!scope.showlist) {
14707                         scope.selectOption(scope.selectMsg, scope.selectedIndex, false);
14708                     }
14709                     scope.focusme();
14710                     scope.$apply();
14711                 }
14712                 scope.setCurrentTop();
14713             };
14714             scope.selectPrev = function() {
14715                 if ((scope.selectedIndex - 1) >= 0) {
14716                     scope.selectedIndex -= 1;
14717                     if (!scope.showlist) {
14718                         scope.selectOption(scope.selectMsg, scope.selectedIndex, false);
14719                     }
14720                     scope.focusme();
14721                     scope.$apply();
14722                 } else if (scope.selectedIndex - 1 < 0) {
14723                     // If placeholderAsOption is true or undefined (default), ensure we can select it on up key.
14724                     if (attr.placeholderAsOption === undefined || attr.placeholderAsOption === 'true') {
14725                         scope.selectedIndex = -1;
14726                     } else {
14727                         scope.selectedIndex = 0;
14728                     }
14729                     if (!scope.showlist) {
14730                         scope.selectOption(scope.selectMsg, scope.selectedIndex, false);
14731                     }
14732                     scope.focusme();
14733                     scope.$apply();
14734                 }
14735                 scope.setCurrentTop();
14736             };
14737             scope.updateSelection = function(sItem) {
14738                 scope.selectedOption = sItem.title;
14739                 scope.title = "";
14740             };
14741             scope.focusme = function() {
14742                 $timeout(function() {
14743                     var list = angular.element(element).find('ul').find('li');
14744                     var index = scope.selectedIndex + 2;
14745                     if (scope.noFilter) {
14746                         index = scope.selectedIndex;
14747                     }
14748                     if (angular.isDefined(list[index])) {
14749                         list[index].focus();
14750                     }
14751                 });
14752             };
14753             scope.$watch('selCategory', function(value) {
14754                 if (value) {
14755                     scope.updateSelection(value);
14756                 };
14757             });
14758             ctrl.$viewChangeListeners.push(function() {
14759                 scope.$eval(attr.ngChange);
14760             });
14761             ctrl.$render = function() {
14762                 scope.selCategory = ctrl.$viewValue;
14763             };
14764             var outsideClick = function(e) {
14765                 var isElement = $isElement(angular.element(e.target), element, $document);
14766                 if (!isElement) {
14767                     scope.showlist = false;
14768                     dropdownElement.focus();
14769                     scope.$apply();
14770                 }
14771             };
14772             $documentBind.click('showlist', outsideClick, scope);
14773         }
14774     };
14775 }]);
14776 angular.module('att.abs.select', ['att.abs.utilities', 'att.abs.position', 'att.abs.utilities'])
14777 .directive('attSelect', ["$document", "$filter", "$isElement", '$documentBind', '$timeout', 'keymap', '$log', function($document, $filter, $isElement, $documentBind, $timeout, keymap, $log) {
14778     return {
14779         restrict: 'A',
14780         scope: {
14781             cName: '=attSelect'
14782         },
14783         transclude: false,
14784         replace: false,
14785         require: 'ngModel',
14786         templateUrl: 'app/scripts/ng_js_att_tpls/select/select.html',
14787         link: function(scope, element, attr, ctrl) {
14788             scope.selectedIndex = -1;
14789             scope.selectedOption = attr.placeholder;
14790             scope.isDisabled = false;
14791             scope.className = "select2-match";
14792             scope.showSearch = false;
14793             scope.showlist = false;
14794
14795             // This is used to jump to elements in list
14796             var search = '';
14797             // This is used to ensure searches only persist so many ms.
14798             var prevSearchDate = new Date();
14799             // This is used to shift focus back after closing dropdown
14800             var dropdownElement = undefined;
14801             // Used to ensure focus on dropdown elements
14802             var list = [];
14803             $timeout(function() {
14804                 list = element.find('li');
14805             }, 10);
14806
14807             if (attr.noFilter || attr.noFilter === 'true') {
14808                 scope.noFilter = true;
14809             } else {
14810                 scope.noFilter = false;
14811             }
14812             if (attr.placeholderAsOption === 'false') {
14813                 scope.selectedOption = attr.placeholder;
14814             } else {
14815                 scope.selectMsg = attr.placeholder;
14816             }
14817             if (attr.startsWithFilter || attr.startsWithFilter === 'true') {
14818                 scope.startsWithFilter = true;
14819             }
14820             if (attr.showInputFilter === 'true') {
14821                 scope.showSearch = false;
14822                 /* This is deprecated */
14823                 $log.warn('showInputFilter functionality has been removed from the library.');   
14824             }
14825             if (attr.disabled) {
14826                 scope.isDisabled = true;
14827             }
14828             var getFilterType = function() {
14829                 if (scope.startsWithFilter) {
14830                     return 'startsWith';
14831                 } else {
14832                     return 'filter';
14833                 }
14834             };
14835             dropdownElement = angular.element(element).children().eq(0).find('span')[0];
14836             var prevIndex = 0;
14837             var selectOptionFromSearch = function() {
14838                 if (!scope.noFilter) {
14839                     return;
14840                 }
14841
14842                 // Find next element that matches search criteria.
14843                 // If no element is found, loop to beginning and search.
14844                 var criteria = search;
14845                 var i = 0;
14846                 for (i = prevIndex; i < scope.cName.length; i++) {
14847                     // Need to ensure we keep searching until all startsWith have passed before looping
14848                     if (scope.cName[i].title.startsWith(criteria) && i !== scope.selectedIndex) {
14849                         scope.selectOption(scope.cName[i], i, scope.showlist);
14850                         prevIndex = i;
14851                         search = '';
14852                         break;
14853                     }
14854                 }
14855                 if ((i >= scope.cName.length || !scope.cName[i+1].title.startsWith(criteria)) && prevIndex > 0) {
14856                     prevIndex = 0;
14857                 }
14858             };
14859             scope.showDropdown = function() {
14860                 if (!(attr.disabled)) {
14861                     scope.showlist = !scope.showlist;
14862                     scope.setSelectTop();
14863                     /* Ensure selected element is focused upon opening dropdown */
14864                     scope.focusme();
14865                 }
14866             };
14867             element.bind('keydown', function(e) {
14868                 if (keymap.isAllowedKey(e.keyCode) || keymap.isControl(e) || keymap.isFunctionKey(e)) {
14869                     e.preventDefault();
14870                     e.stopPropagation();
14871
14872                     switch (e.keyCode) {
14873                         case keymap.KEY.DOWN:
14874                             scope.selectNext();
14875                             break;
14876                         case keymap.KEY.UP:
14877                             scope.selectPrev();
14878                             search = '';
14879                             break;
14880                         case keymap.KEY.ENTER:
14881                             scope.selectCurrent();
14882                             search = '';
14883                             break;
14884                         case keymap.KEY.BACKSPACE:
14885                             scope.title = '';
14886                             search = '';
14887                             scope.$apply();
14888                             break;
14889                         case keymap.KEY.SPACE:
14890                             if (!scope.noFilter) {
14891                                 scope.title += ' ';
14892                             }
14893                             scope.$apply();
14894                             break;
14895                         case keymap.KEY.ESC:
14896                             if (scope.title === '' || scope.title === undefined) {
14897                                 scope.showlist = false;
14898                                 dropdownElement.focus();
14899                                 scope.$apply();
14900                             } else {
14901                                 scope.title = '';
14902                                 scope.$apply();
14903                             }
14904                             if (scope.noFilter) {
14905                                 search = '';
14906                                 dropdownElement.focus();
14907                                 scope.showlist = false;
14908                             }
14909                             break;
14910                         default:
14911                             break;
14912                     }
14913                 } else {
14914                     if (e.keyCode !== keymap.KEY.TAB)
14915                     {
14916                         if (!scope.noFilter) {
14917                             scope.showlist = true;
14918                             scope.title = scope.title ? scope.title + String.fromCharCode(e.keyCode) : String.fromCharCode(e.keyCode);
14919
14920                             /* Perform index correction */
14921                             if (scope.title != '') {
14922                                 var filteredArray = $filter(getFilterType())(scope.cName, scope.title);
14923
14924                                 for (var i = 0; i < filteredArray.length; i++) {
14925                                     for (var j = 0; j < scope.cName.length; j++) {
14926                                         if (!angular.isDefined(scope.cName[scope.selectedIndex])) {
14927                                             break;
14928                                         }
14929                                         if (filteredArray[i]['title'] === scope.cName[scope.selectedIndex]['title']) {
14930                                             scope.selectedIndex = i;
14931                                             scope.focusme();
14932                                             break;
14933                                         }
14934                                     }
14935                                 }
14936                             }
14937                         } else {
14938                             var date = new Date();
14939                             var delta = Math.abs(prevSearchDate.getMilliseconds() - date.getMilliseconds());
14940                             prevSearchDate = date;
14941                             if (delta > 100) {
14942                                 search = '';
14943                             }
14944                             search = search ? search + String.fromCharCode(e.keyCode) : String.fromCharCode(e.keyCode);
14945                             if (search.length > 2) {
14946                                 search = search.substring(0, 2);
14947                             }
14948                             selectOptionFromSearch();
14949                         }
14950                         scope.$apply();
14951                     } else if (e.keyCode === keymap.KEY.TAB) {
14952                         scope.showlist = false;
14953                         scope.title = '';
14954                         scope.$apply();
14955                     }
14956                 }
14957             });
14958             scope.selectOption = function(sTitle, sIndex, keepOpen) {
14959
14960                 if (sIndex === -1 || sIndex === '-1') {
14961                     scope.selCategory = '';
14962                     scope.selectedIndex = -1;
14963                     ctrl.$setViewValue('');
14964                     if(attr.placeholderAsOption !== 'false')
14965                     {
14966                         scope.selectedOption = scope.selectMsg;
14967                     }
14968                 }
14969                 else {
14970                     /* Apply filter here to remap the selected index and shift focus*/
14971                     if (scope.title != '') {
14972                         var filteredArray = $filter(getFilterType())(scope.cName, scope.title);
14973
14974                         if (angular.isDefined(filteredArray) && angular.isDefined(filteredArray[sIndex]))
14975                         {
14976                             for (var i = 0; i < scope.cName.length; i++) {
14977                                 if (filteredArray[sIndex]['title'] === scope.cName[i]['title']) {
14978                                     sIndex = i;
14979                                     break;
14980                                 }
14981                             }
14982                         }
14983                     }
14984                     scope.selCategory = scope.cName[sIndex];
14985                     scope.selectedIndex = sIndex;
14986                     ctrl.$setViewValue(scope.selCategory);
14987                     scope.selectedOption = scope.selCategory.title;
14988
14989                     $timeout(function(){
14990                         if (angular.isDefined(list[sIndex])) {
14991                             try{
14992                                 list[index].focus();
14993                             } catch (e) {} /* IE8 will throw exception if display:none or not in DOM */
14994                         }
14995                     });
14996                 }
14997                 scope.title = '';
14998                 if (!keepOpen) {
14999                     scope.showlist = false;
15000                     dropdownElement.focus();
15001                 }
15002             };
15003             scope.selectCurrent = function() {
15004                 if (scope.showlist) {
15005                     scope.selectOption(scope.selectMsg,scope.selectedIndex,false);
15006                 } else {
15007                     scope.showlist = true;
15008                     scope.setSelectTop();
15009                 }
15010                 scope.$apply();
15011             };
15012             scope.hoverIn = function(cItem) {
15013                 scope.selectedIndex = cItem;
15014                 scope.focusme();
15015             };
15016             scope.setSelectTop = function() {
15017                 $timeout(function() {
15018                     if (scope.showlist && !scope.noFilter)
15019                     {
15020                         var containerUL = angular.element(element)[0].querySelector(".select2-results");
15021                         if(angular.element(containerUL.querySelector('.select2-result-current'))[0])
15022                         {
15023                             var selectedElemTopPos = angular.element(containerUL.querySelector('.select2-result-current'))[0].offsetTop;
15024                         }
15025                         angular.element(containerUL)[0].scrollTop = selectedElemTopPos;
15026                     }
15027                 });
15028             };
15029             scope.setCurrentTop = function() {
15030                 $timeout(function() {
15031                     if (scope.showlist) {
15032                         var containerUL = angular.element(element)[0].querySelector(".select2-results");
15033                         if(angular.element(containerUL.querySelector('.hovstyle'))[0])
15034                         {
15035                             var selectedElemTopPos = angular.element(containerUL.querySelector('.hovstyle'))[0].offsetTop;
15036                         }
15037                         if (selectedElemTopPos < (angular.element(containerUL)[0].scrollTop)) {
15038                             angular.element(containerUL)[0].scrollTop -= 30;
15039                         } else if ((selectedElemTopPos + 30) > (angular.element(containerUL)[0].clientHeight)) {
15040                             angular.element(containerUL)[0].scrollTop += 30;
15041                         }
15042
15043                     }
15044                 });
15045             };
15046             scope.selectNext = function() {
15047                 var length = scope.cName.length;
15048                 
15049                 if ((scope.selectedIndex + 1) <= (scope.cName.length - 1)) {
15050                     scope.selectedIndex += 1;
15051                     var nextDisabled = scope.cName[scope.selectedIndex].disabled;
15052                     if (nextDisabled) {
15053                         scope.selectedIndex += 1;
15054                     }
15055                     if (!scope.showlist) {
15056                         scope.selectOption(scope.selectMsg, scope.selectedIndex,false);
15057                     }
15058                     scope.focusme();
15059                     scope.$apply();
15060                 }
15061                 scope.setCurrentTop();
15062             };
15063             scope.selectPrev = function() {
15064                 if ((scope.selectedIndex - 1) >= 0) {
15065                     scope.selectedIndex -= 1;
15066                     var prevDisabled = scope.cName[scope.selectedIndex].disabled;
15067                     if (prevDisabled) {
15068                         scope.selectedIndex -= 1;
15069                     }
15070                     if (!scope.showlist) {
15071                         scope.selectOption(scope.selectMsg, scope.selectedIndex,false);
15072                     }
15073                     scope.focusme();
15074                     scope.$apply();
15075                 } else if (scope.selectedIndex - 1 < 0) {
15076                     // If placeholderAsOption is true or undefined (default), ensure we can select it on up key.
15077                     if (attr.placeholderAsOption === undefined || attr.placeholderAsOption === 'true') {
15078                         if(attr.placeholder === undefined ){
15079                             scope.selectedIndex = 0;
15080                         }
15081                         else{
15082                             scope.selectedIndex = -1;
15083                         }
15084                     } else {
15085                         scope.selectedIndex = 0;
15086                     }
15087                     if (!scope.showlist) {
15088                         scope.selectOption(scope.selectMsg, scope.selectedIndex,false);
15089                     }
15090                     scope.focusme();
15091                     scope.$apply();
15092                 }
15093                 scope.setCurrentTop();
15094             };
15095             scope.updateSelection = function(sItem) {
15096                 scope.selectedOption = sItem.title;
15097                 scope.title = '';
15098
15099                 if (sItem.index < 0) {
15100                     scope.selectOption(scope.selectMsg, sItem.index, scope.showlist);
15101                 }
15102             };
15103             scope.focusme = function() {
15104                 $timeout(function() {
15105                     var list = angular.element(element).find('ul').find('li');
15106                     var index = scope.selectedIndex + 2;
15107                     if (scope.noFilter) {
15108                         index = scope.selectedIndex;
15109                     }
15110                     if (angular.isDefined(list[index])) {
15111                         try {
15112                             list[index].focus();
15113                         } catch (e) {} /* IE8 will throw exception if display:none or not in DOM */  
15114                     }
15115                 });
15116             };
15117             scope.$watch('selCategory', function(value) {
15118                 if (value) {
15119                     scope.updateSelection(value);
15120                 };
15121             });
15122             ctrl.$viewChangeListeners.push(function() {
15123                 scope.$eval(attr.ngChange);
15124             });
15125             ctrl.$render = function() {
15126                 scope.selCategory = ctrl.$viewValue;
15127             };
15128             var outsideClick = function(e) {
15129                 var isElement = $isElement(angular.element(e.target), element, $document);
15130                 if (!isElement) {
15131                     scope.showlist = false;
15132                     dropdownElement.focus();
15133                     scope.$apply();
15134                 }
15135             };
15136             $documentBind.click('showlist', outsideClick, scope);
15137         }
15138     };
15139 }])
15140 .directive('textDropdown', ['$document', '$isElement', '$documentBind', "keymap", function($document, $isElement, $documentBind, keymap) {
15141     return {
15142         restrict: 'EA',
15143         replace: true,
15144         scope: {
15145             actions: '=actions',
15146             defaultAction: '=defaultAction',
15147             onActionClicked: '=?'
15148         },
15149         templateUrl: 'app/scripts/ng_js_att_tpls/select/textDropdown.html',
15150         link: function(scope, element, attr) {
15151             scope.selectedIndex = 0;
15152             scope.selectedOption = attr.placeholder;
15153             scope.isDisabled = false;
15154             scope.isActionsShown = false;
15155             var dropdownElement = undefined;
15156             if (attr.disabled) {
15157                 scope.isDisabled = true;
15158             }
15159
15160             dropdownElement = element.find('div')[0];
15161
15162             // Set default Action
15163             if (!angular.isDefined(scope.defaultAction)) {
15164                 scope.currentAction = scope.actions[0];
15165                 scope.selectedIndex = 0;
15166             } else if (angular.isDefined(scope.defaultAction) || scope.defaultAction !== '') {
15167                 for (var act in scope.actions) {
15168                     if (scope.actions[act] === scope.defaultAction) {
15169                         scope.currentAction = scope.actions[act];
15170                         scope.selectedIndex = scope.actions.indexOf(act);
15171                         scope.isActionsShown = false;
15172                         break;
15173                     }
15174                 }
15175             } else {
15176                 scope.currentAction = scope.actions[0];
15177             }
15178             scope.toggle = function() {
15179                 scope.isActionsShown = !scope.isActionsShown;
15180             };
15181             scope.chooseAction = function($event, action, $index) {
15182                 if ($event != null) {
15183                     scope.currentAction = action;
15184                     scope.selectedIndex = $index;
15185                 } else {
15186                     scope.currentAction = scope.actions[scope.selectedIndex];
15187                 }
15188                 if (angular.isFunction(scope.onActionClicked)) {
15189                     scope.onActionClicked(scope.currentAction);
15190                 }
15191                 scope.toggle();
15192             };
15193             scope.isCurrentAction = function(action) {
15194                 return (action === scope.currentAction);
15195             };
15196             element.bind("keydown", function(e) {
15197                 if (keymap.isAllowedKey(e.keyCode) || keymap.isControl(e) || keymap.isFunctionKey(e)) {
15198                     e.preventDefault();
15199                     e.stopPropagation();
15200                     switch (e.keyCode) {
15201                         case keymap.KEY.DOWN:
15202                             scope.selectNext();
15203                             break;
15204                         case keymap.KEY.UP:
15205                             scope.selectPrev();
15206                             break;
15207                         case keymap.KEY.ENTER:
15208                             scope.selectCurrent();
15209                             break;
15210                         case keymap.KEY.ESC:
15211                             scope.isActionsShown = false;
15212                             dropdownElement.focus();
15213                             scope.$apply();
15214                             break;
15215                         default:
15216                             break;
15217                     }
15218                     scope.$apply();
15219                     return;
15220                 } else if (e.keyCode === keymap.KEY.TAB) {
15221                     scope.isActionsShown = false;
15222                     scope.$apply();
15223                 }
15224             });
15225             scope.selectCurrent = function() {
15226                 if (scope.selectedIndex < 0) {
15227                     scope.selectedIndex = 0;
15228                 }
15229                 if (!scope.isActionsShown) {
15230                     scope.toggle();
15231                 } else {
15232                     scope.chooseAction(null, scope.currentAction);
15233                 }
15234             };
15235             scope.selectNext = function() {
15236                 if (scope.isActionsShown) {
15237                     if ((scope.selectedIndex + 1) < scope.actions.length) {
15238                         scope.selectedIndex += 1;
15239                     } else {
15240                         scope.selectedIndex = (scope.actions.length - 1);
15241                     }
15242                     scope.$apply();
15243                 }
15244             };
15245             scope.selectPrev = function() {
15246                 if (scope.isActionsShown) {
15247                     if ((scope.selectedIndex - 1) >= 0) {
15248                         scope.selectedIndex -= 1;
15249                     } else if (scope.selectedIndex - 1 < 0) {
15250                         scope.selectedIndex = 0;
15251                     }
15252                     scope.$apply();
15253                 }
15254             };
15255             scope.hoverIn = function(cItem) {
15256                 scope.selectedIndex = cItem;
15257             };
15258             //end cato
15259             var outsideClick = function(e) {
15260                 var isElement = $isElement(angular.element(e.target), element, $document);
15261                 if (!isElement) {
15262                     scope.toggle();
15263                     scope.$apply();
15264                 }
15265             };
15266             $documentBind.click('isActionsShown', outsideClick, scope);
15267         }
15268     };
15269 }]);
15270 angular.module('att.abs.slider', ['att.abs.position'])
15271         .constant('sliderDefaultOptions', {
15272             width: 300,
15273             step: 1,
15274             precision: 0,
15275             disabledWidth: 116
15276         })
15277         .directive('attSlider', ['sliderDefaultOptions','$position','$document', function(sliderDefaultOptions,$position,$document)
15278             {
15279                 return {
15280                     restrict: 'EA',
15281                     replace: true,
15282                     transclude: true,
15283                     scope: {
15284                         floor: "=",
15285                         ceiling: "=",
15286                         step: "@",
15287                         precision: "@",
15288                         width: "@",
15289                         textDisplay: "=",
15290                         value: "=",
15291                         ngModelSingle: '=?',
15292                         ngModelLow: '=?',
15293                         ngModelHigh: '=?',
15294                         ngModelDisabled: '=?'
15295                     },
15296                     templateUrl: 'app/scripts/ng_js_att_tpls/slider/slider.html',
15297                     link: function(scope, elem, attr)
15298                     {
15299                         var minOffset, maxOffset, newOffset, newOffset1, newOffset2, offsetRange, valueRange, start_x = 0, disabledRange, disabled, evFlag = false, minValue, maxValue, range, refLow, refHigh, maxPtr, minPtr, singlePtr, getHandles;
15300                         scope.minPtrOffset = 0;
15301                         scope.maxPtrOffset = 0;
15302                         var disableWidth = sliderDefaultOptions.disabledWidth;
15303                         //Get handles
15304                         var obj = elem.children();
15305                         disabledRange = obj[0].children;
15306                         disabledRange = angular.element(disabledRange[0]);
15307                         getHandles = obj[1].children;
15308                         singlePtr = angular.element(getHandles[0]);
15309                         minPtr = angular.element(getHandles[1]);
15310                         maxPtr = angular.element(getHandles[2]);
15311                         disabled = ((attr.ngModelSingle == null) && (attr.ngModelLow == null) && (attr.ngModelHigh == null)) && (attr.ngModelDisabled != null);
15312                         range = (attr.ngModelSingle == null) && ((attr.ngModelLow != null) && (attr.ngModelHigh != null));
15313                         refLow = 'ngModelLow';
15314                         refHigh = 'ngModelHigh';
15315                         if (!range) {
15316                             minPtr.remove();
15317                             maxPtr.remove();
15318                         }
15319                         else {
15320                             singlePtr.remove();
15321                         }
15322                         if (!disabled) {
15323                             disabledRange.remove();
15324                         }
15325                         else {
15326                             scope.disabledStyle = {width: disableWidth + 'px', zIndex: 1};
15327                             scope.handleStyle = {left: disableWidth + 'px'};
15328                         }
15329                         minValue = parseFloat(scope.floor);
15330                         maxValue = parseFloat(scope.ceiling);
15331                         valueRange = maxValue - minValue;
15332                         minOffset = 0;
15333                         if (attr.width !== undefined) {
15334                             maxOffset = attr.width;
15335                         }
15336                         else {
15337                             if (elem[0].clientWidth !== 0) {
15338                                 maxOffset = elem[0].clientWidth;
15339                             }
15340                             else {
15341                                 maxOffset = sliderDefaultOptions.width;
15342                             }
15343                         }
15344                         offsetRange = maxOffset - minOffset;
15345                         //Key Down Event
15346                          scope.keyDown = function(ev){
15347                                if(ev.keyCode === 39){
15348                                 var elemLeft = $position.position(elem).left;
15349                                 if (newOffset){
15350                                     if(scope.ref === "ngModelLow"){
15351                                         newOffset1 = sliderDefaultOptions.step + newOffset1;
15352                                         newOffset = newOffset1;
15353                                     }
15354                                     else if(scope.ref === "ngModelHigh"){
15355                                         newOffset2 = sliderDefaultOptions.step + newOffset2;
15356                                         newOffset = newOffset2;
15357                                     }
15358                                     else{newOffset = sliderDefaultOptions.step + newOffset;}
15359                                 }
15360                                 else {
15361                                     if(range &&scope.ref === "ngModelLow"){
15362                                         return;
15363                                     }
15364                                     else {
15365                                         newOffset = sliderDefaultOptions.step + elemLeft;
15366                                         newOffset1 = newOffset2 = newOffset;
15367                                     }
15368                                 }
15369                                 }
15370                             else if(ev.keyCode === 37){
15371                                 var ptrLeft = $position.position(singlePtr).left;
15372                                 if(newOffset){
15373                                 if (!(newOffset<=0)){
15374                                     if(scope.ref === "ngModelLow"){
15375                                         newOffset1 = newOffset1 - sliderDefaultOptions.step;
15376                                         newOffset = newOffset1;
15377                                     }
15378                                     else if(scope.ref === "ngModelHigh"){
15379                                         newOffset2 = newOffset2 - sliderDefaultOptions.step;
15380                                         newOffset = newOffset2;
15381                                     }
15382                                     else {
15383                                         newOffset = newOffset - sliderDefaultOptions.step;
15384                                         newOffset1 = newOffset2 = newOffset;
15385                                     }
15386                                 }
15387                                 }
15388                                 else {
15389                                     newOffset = ptrLeft - sliderDefaultOptions.step;
15390                                 }
15391                                 }
15392                             if(newOffset>=0){
15393                                 scope.ptrOffset(newOffset);
15394                             }
15395                         };
15396                         //Mouse Down Event                         
15397                         scope.mouseDown = function(e, ref) {
15398                             scope.ref = ref;
15399                             evFlag = true;
15400                             if (!range){
15401                                 if (newOffset)
15402                                 {
15403                                     start_x = e.clientX - newOffset;
15404                                 }
15405                                 else {
15406                                     start_x = e.clientX;
15407                                 }
15408                             } else {
15409                                 if (scope.ref === refLow) {
15410                                     start_x = e.clientX - scope.minPtrOffset;
15411                                 }
15412                                 else {
15413                                     start_x = e.clientX - scope.maxPtrOffset;
15414                                 }
15415                             }
15416                             if (disabled) {
15417                                 scope.ref= 'ngModelDisabled';
15418                                 scope.disabledStyle = {width: disableWidth + 'px', zIndex: 1};
15419                             }
15420                         };
15421                         // Mouse Move Event
15422                         scope.moveElem = function(ev) {
15423                             if (evFlag) {
15424                                 var eventX;
15425                                 eventX = ev.clientX;
15426                                 newOffset = eventX - start_x;
15427                                 scope.ptrOffset(newOffset);
15428                             }
15429                         };
15430                         scope.focus=function(ev,ref){
15431                             console.log(ref);
15432                             scope.ref=ref;
15433                         }
15434                         // Mouse Up Event
15435                         scope.mouseUp = function(ev) {
15436                             evFlag = false;
15437                             minPtr.removeClass('dragging');
15438                             maxPtr.removeClass('dragging');
15439                             singlePtr.removeClass('dragging');
15440                             $document.off('mousemove');
15441                         };
15442                         // key Up Event
15443                         scope.keyUp = function(ev) {
15444                             evFlag = false;
15445                             minPtr.removeClass('dragging');
15446                             maxPtr.removeClass('dragging');
15447                             singlePtr.removeClass('dragging');
15448                             $document.off('mousemove');
15449                         };
15450                         //Function to calculate the current PositionValue
15451                         scope.calStep = function(value, precision, step, floor) {
15452                             var decimals, remainder, roundedValue, steppedValue;
15453                             if (floor === null) {
15454                                 floor = 0;
15455                             }
15456                             if (step === null) {
15457                                 step = 1 / Math.pow(10, precision);
15458                             }
15459                             remainder = (value - floor) % step;
15460                             steppedValue = remainder > (step / 2) ? value + step - remainder : value - remainder;
15461                             decimals = Math.pow(10, precision);
15462                             roundedValue = steppedValue * decimals / decimals;
15463                             return roundedValue.toFixed(precision);
15464                         };
15465                         //Function to calculate Offset Percent
15466                         scope.percentOffset = function(offset) {
15467                             return ((offset - minOffset) / offsetRange) * 100;
15468                         };
15469                         //Function to calculate Offset position
15470                         scope.ptrOffset = function(newOffset){
15471                             var newPercent, newValue;
15472                                 newOffset = Math.max(Math.min(newOffset, maxOffset), minOffset);
15473                                 newPercent = scope.percentOffset(newOffset);
15474                                 newValue = minValue + (valueRange * newPercent / 100.0);
15475                                 if (range) {
15476                                     var rangeSliderWidth;
15477                                     if (scope.ref === refLow) {
15478                                         scope.minHandleStyle = {left: newOffset + "px"};
15479                                         scope.minNewVal = newValue;
15480                                         scope.minPtrOffset = newOffset;
15481                                         minPtr.addClass('dragging');
15482                                         if (newValue > scope.maxNewVal) {
15483                                             scope.ref = refHigh;
15484                                             maxPtr[0].focus();
15485                                             scope.maxNewVal = newValue;
15486                                             scope.maxPtrOffset = newOffset;
15487                                             maxPtr.addClass('dragging');
15488                                             minPtr.removeClass('dragging');
15489                                             scope.maxHandleStyle = {left: newOffset + "px"};
15490                                         }
15491                                     }
15492                                     else {
15493                                         scope.maxHandleStyle = {left: newOffset + "px"};
15494                                         scope.maxNewVal = newValue;
15495                                         scope.maxPtrOffset = newOffset;
15496                                         maxPtr.addClass('dragging');
15497                                         if (newValue < scope.minNewVal) {
15498                                             scope.ref = refLow;
15499                                             minPtr[0].focus();
15500                                             scope.minVal = newValue;
15501                                             scope.minPtrOffset = newOffset;
15502                                             minPtr.addClass('dragging');
15503                                             maxPtr.removeClass('dragging');
15504                                             scope.minHandleStyle = {left: newOffset + "px"};
15505                                         }
15506                                     }
15507                                     rangeSliderWidth = parseInt(scope.maxPtrOffset) - parseInt(scope.minPtrOffset);
15508                                     scope.rangeStyle = {width: rangeSliderWidth + "px", left: scope.minPtrOffset + "px"};
15509                                 }
15510                                 else {
15511                                     if (disabled && newOffset > disableWidth) {
15512                                         scope.rangeStyle = {width: newOffset + "px", zIndex: 0};
15513                                     }
15514                                     else {
15515                                         singlePtr.addClass('dragging');
15516                                         scope.rangeStyle = {width: newOffset + "px"};
15517                                     }
15518                                     scope.handleStyle = {left: newOffset + "px"};
15519                                 }
15520                                 if ((scope.precision === undefined) || (scope.step === undefined)) {
15521                                     scope.precision = sliderDefaultOptions.precision;
15522                                     scope.step = sliderDefaultOptions.step;
15523                                 }
15524                                 newValue = scope.calStep(newValue, parseInt(scope.precision), parseFloat(scope.step), parseFloat(scope.floor));
15525                                 scope[scope.ref] = newValue;
15526                         };
15527                     }
15528                 };
15529             }
15530         ]).directive('attSliderMin',[function()
15531             {
15532              return{
15533                  require: '^attSlider',
15534                  restrict: 'EA',
15535                  replace: true,
15536                  transclude: true,
15537                  templateUrl: 'app/scripts/ng_js_att_tpls/slider/minContent.html'
15538                };
15539          }
15540     ]).directive('attSliderMax',[function()
15541             {
15542              return{
15543                  require: '^attSlider',
15544                  restrict: 'EA',
15545                  replace: true,
15546                  transclude: true,
15547                  templateUrl: 'app/scripts/ng_js_att_tpls/slider/maxContent.html'
15548              };
15549          }
15550     ]);
15551 angular.module('att.abs.splitButtonDropdown', ['att.abs.utilities','att.abs.position'])
15552     .directive('attButtonDropdown', ['$document', '$parse', '$documentBind', '$timeout','$isElement', function ($document, $parse, $documentBind, $timeout,$isElement) {
15553         return {
15554             restrict: 'EA',
15555             replace: true,
15556             transclude: true,            
15557             templateUrl: 'app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdown.html',
15558             scope: {
15559                 btnText: "@",
15560                 btnType: "@",
15561                 btnLink: "@",
15562                 btnClick: "&",
15563                 toggleTitle:"@",                
15564             },
15565             controller: ['$scope', '$element', function ($scope, $element) {
15566                     
15567                 this.cSelected = 0;    
15568                 this.closeAndFocusDropdown = function () {
15569                     if ($scope.isDropDownOpen) {
15570                         $scope.$apply(function () {
15571                         $scope.isDropDownOpen = false;
15572                         angular.element($element[0].querySelector('a.dropdown-toggle'))[0].focus();                        
15573                         });
15574                     }
15575                 };             
15576                 
15577                 this.focusNext = function () {                                            
15578                     this.cSelected = this.cSelected + 1 >= this.childScopes.length ?($scope.cycleSelection === true ? 0 : this.childScopes.length-1): this.cSelected +1;
15579                     this.childScopes[this.cSelected].sFlag = true;                    
15580                     this.resetFlag(this.cSelected);                    
15581                 }; 
15582                 
15583                 this.focusPrev = function () {                        
15584                     this.cSelected = this.cSelected -1 < 0 ? ($scope.cycleSelection === true ? this.childScopes.length-1 : 0) : this.cSelected - 1 ;
15585                     this.childScopes[this.cSelected].sFlag = true;                    
15586                     this.resetFlag(this.cSelected);                    
15587                 };                 
15588                                                 
15589                 this.childScopes = [];
15590                 this.registerScope = function(childScope)
15591                 {
15592                     this.childScopes.push(childScope);                    
15593                 };
15594                 
15595                 this.resetFlag = function(index){                                        
15596                     for(var i=0; i < this.childScopes.length; i++) 
15597                     {
15598                         if(i !== index)
15599                         {
15600                             this.childScopes[i].sFlag = false;
15601                         }
15602                     }
15603                 };
15604                 
15605             }],
15606             link: function (scope, element, attr) {                
15607                 scope.isSmall = attr.small === "" ? true : false;
15608                 scope.multiselect = attr.multiselect === ""? true : false;
15609                 scope.cycleSelection = attr.cycleSelection === "" ? true : false;
15610                 scope.isDropDownOpen = false;
15611                 scope.isActionDropdown = false;
15612                
15613                 if (!(scope.btnText)) {
15614                     scope.isActionDropdown = true;
15615                 }
15616
15617                 scope.clickFxn = function () {
15618                     if (typeof scope.btnClick === "function" && !scope.btnLink) {
15619                         scope.btnClick = $parse(scope.btnClick);
15620                         scope.btnClick();
15621                     }                    
15622                     if(scope.multiselect === true)
15623                     {
15624                         scope.isDropDownOpen = false;
15625                     }
15626                 };
15627
15628                 scope.toggleDropdown = function () {
15629                     if (!(scope.btnType === 'disabled')) {
15630                         scope.isDropDownOpen = !scope.isDropDownOpen;
15631                         if (scope.isDropDownOpen) {
15632                             $timeout(function () {
15633                                 angular.element(element[0].querySelector('li'))[0].focus();
15634                             });
15635                         }
15636                     }
15637                 };
15638
15639                 scope.btnTypeSelector = function (directiveValue, attrValue) {
15640                     if (directiveValue !== "") {
15641                         scope.btnTypeFinal = directiveValue;
15642                     } else {
15643                         scope.btnTypeFinal = attrValue;
15644                     }
15645                 };
15646
15647                 var outsideClick = function(e) {
15648                     var isElement = $isElement(angular.element(e.target), element.find('ul').eq(0), $document);
15649                     if (!isElement) {
15650                         scope.isDropDownOpen = false;
15651                         scope.$apply();
15652                     }
15653                 };
15654
15655                 $documentBind.click('isDropDownOpen', outsideClick, scope);
15656
15657                 attr.$observe('btnType', function (val) {
15658                     scope.btnType = val;
15659                 });
15660                 attr.$observe('attButtonDropdown', function (val) {
15661                     attr.attButtonDropdown = val;
15662                     scope.btnTypeSelector(attr.attButtonDropdown, scope.btnType);
15663                 });
15664             }
15665         };
15666
15667             }])
15668        
15669 .directive('attButtonDropdownItem', ['$location','keymap', function ($location,keymap) {
15670         return {
15671             restrict: 'EA',
15672             require: ['^attButtonDropdown','?ngModel'],
15673             replace: true,
15674             transclude: true,            
15675             templateUrl:'app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdownItem.html',                                                 scope: {
15676                 itemLink: "@"
15677             },
15678             link: function (scope, element, attr, ctrl) {
15679                 var rootLink = angular.element(element[0].querySelector('a'));
15680                 scope.sFlag = false;
15681                 ctrl[0].registerScope(scope);
15682                 var clickOnLink = function () {
15683                     if (scope.itemLinkFinal) {
15684                         $location.url(scope.itemLinkFinal);
15685                     }
15686                 };
15687                 
15688                 if(ctrl[1]){
15689                     scope.isSelected = ctrl[1].$viewValue;
15690                 }else{
15691                     scope.isSelected = false;
15692                 }                
15693                 
15694                 element.bind('keydown', function(e) {
15695                 if (keymap.isAllowedKey(e.keyCode) || keymap.isControl(e) || keymap.isFunctionKey(e)) {
15696                     e.preventDefault();
15697                     e.stopPropagation();
15698                     switch (e.keyCode) {
15699                         case keymap.KEY.DOWN: 
15700                             ctrl[0].focusNext();                             
15701                             break;
15702                         case keymap.KEY.UP:                            
15703                             ctrl[0].focusPrev();
15704                             break;
15705                         case keymap.KEY.ENTER:                                                        
15706                             scope.selectItem();
15707                             break;
15708                         case keymap.KEY.ESC:
15709                             ctrl[0].closeAndFocusDropdown();
15710                             break;
15711                         default:
15712                             break;
15713                     }
15714                     
15715                 }
15716                     scope.$apply();
15717                 }); 
15718                                  
15719                 scope.selectItem = function()
15720                 {
15721                     if(ctrl[1]){
15722                         scope.$evalAsync(function(){ctrl[1].$setViewValue(!ctrl[1].$viewValue)});
15723                     }
15724                 }; 
15725
15726             }
15727         };
15728     }]);
15729
15730 angular.module('att.abs.splitIconButton', ['att.abs.utilities'])
15731 .constant('iconStateConstants', {
15732     MIDDLE: 'middle',
15733     LEFT: 'left',
15734     RIGHT: 'right',
15735     NEXT_TO_DROPDOWN:'next-to-dropdown',
15736     LEFT_NEXT_TO_DROPDOWN:'left-next-to-dropdown',
15737     DIR_TYPE: {
15738         LEFT: 'left',
15739         RIGHT:  'right',
15740         BUTTON: 'button'
15741     },
15742     SPLIT_ICON_BTN_EVENT_EMITTER_KEY: 'splitIconButtonTap'
15743 })
15744 .directive('expandableLine', [function(){
15745     return {
15746         restrict: 'EA',
15747         replace: true,
15748         priority: 300,
15749         require: ['^attSplitIconButton', 'expandableLine'],
15750         controller: ['$scope', function($scope){
15751             $scope.isActive = false;
15752             this.setActiveState = function(isActive){
15753                 $scope.isActive = isActive;
15754             };
15755             this.isActive = $scope.isActive;
15756             this.dirType = $scope.dirType;
15757         }],
15758         template: '<div ng-class="{\'expand-line-container\': !isActive, \'expand-line-container-active\': isActive}"> <div ng-class="{\'hovered-line\':isActive, \'vertical-line\':!isActive}"> </div></div>',
15759         scope:{
15760             dirType: '@'
15761         },
15762         link: function(scope,element,attr,ctrls) {
15763             var attSplitIconButtonCtrl = ctrls[0];
15764             var expandableLineCtrl = ctrls[1];
15765             attSplitIconButtonCtrl.addSubCtrl(expandableLineCtrl);
15766         }
15767     };
15768 }])
15769 .controller('AttSplitIconCtrl', ['$scope', function($scope){
15770     this.setType = function(type){
15771         $scope.type = type;
15772     };  
15773     this.isDropdown = function(isDropdown){
15774          $scope.isDropdown = isDropdown;
15775     };
15776     this.dropDownClicked = function(){
15777         if($scope.dropDownClicked) {
15778             $scope.dropDownClicked();
15779         }
15780     };
15781     this.dirType = $scope.dirType;
15782 }])
15783 .directive('attSplitIcon', ['$document', '$timeout','iconStateConstants','$documentBind','events', 'keymap',
15784  function($document,$timeout,iconStateConstants,$documentBind, events, keymap){
15785     return {
15786         restrict: 'EA',
15787         replace: true,
15788         priority: 200,
15789         transclude: true,
15790         require: ['^attSplitIconButton','attSplitIcon'],
15791         templateUrl: 'app/scripts/ng_js_att_tpls/splitIconButton/splitIcon.html',
15792         scope:{
15793             icon: '@',
15794             iconTitle: '@title',
15795             hoverWatch: '=',
15796             dropDownWatch: '=',
15797             dirType: '@'
15798         },
15799         controller:'AttSplitIconCtrl',
15800         link: function(scope,element,attr,ctrls){
15801             var attSplitIconButtonCtrl = ctrls[0];
15802             var attSplitIconCtrl = ctrls[1];
15803             attSplitIconButtonCtrl.addSubCtrl(attSplitIconCtrl);
15804             scope.iconStateConstants = iconStateConstants;
15805             var currentIndex = 0;
15806             var isMyElement = false;
15807             var listElements;
15808             scope.isDropdown = false;
15809             scope.isDropdownOpen = false;
15810             var outsideClick = function(e) {
15811                 if(scope.isDropdown){
15812                     if (isMyElement) {
15813                         isMyElement = false;
15814                         scope.toggleDropdown();
15815                     } else{
15816                         scope.toggleDropdown(false);
15817                     }
15818                     scope.$apply();
15819                 }
15820             };
15821             if(attr.dropDownId && attr.dropDownId !== ''){
15822                 scope.dropDownId = attr.dropDownId;
15823                 scope.isDropdown = true;
15824             }
15825             scope.$on(iconStateConstants.SPLIT_ICON_BTN_EVENT_EMITTER_KEY, function(evnt, data){
15826                 if(typeof data === 'boolean' && data) {
15827                     scope.dropDownClicked();     
15828                     /*
15829                         Check if the dropdown is open and if we are selecting one
15830                         of the items, so that when pressing enter it will trigger it.
15831                     */
15832                     if(scope.isDropDownOpen) {
15833                         listElements[currentIndex].eq(0).find('a')[0].click();
15834                     }
15835                 } else {
15836                     var e = data;
15837                     //Only trigger the keyboard event if the icon button is a dropdown type
15838                     if(scope.isDropdown) {
15839                         triggerKeyboardEvents(e);   
15840                     }
15841                 }
15842                 function triggerKeyboardEvents(e) {
15843                     switch(e.which) {
15844                         case (keymap.KEY.TAB):
15845                             scope.toggleDropdown(false);
15846                             scope.$digest();
15847                             break;
15848                         case (keymap.KEY.ESC): 
15849                             outsideClick();
15850                             break;
15851                         case (keymap.KEY.ENTER):
15852                             if (scope.isDropDownOpen) {
15853                                 listElementsInit();
15854                             }
15855                             break;
15856                         case (keymap.KEY.UP):
15857                             e.preventDefault();
15858                             events.stopPropagation(e);
15859                             if(scope.isDropDownOpen) {
15860                                 scope.previousItemInDropdown();
15861                             }
15862                             break;
15863                         case (keymap.KEY.DOWN):
15864                             e.preventDefault();
15865                             events.stopPropagation(e);
15866                             //Dropdown is open and the user taps down again
15867                             if(scope.isDropDownOpen) {
15868                                 //Now we need to go through the rows in the dropdown
15869                                 scope.nextItemInDropdown();
15870                             } else {
15871                                 isMyElement = true;
15872                                 outsideClick();
15873                                 listElementsInit();
15874                             }
15875                             break;
15876                         default:
15877                             break;
15878                     }
15879                 }
15880                 function listElementsInit() {
15881                     if(listElements === undefined) {
15882                         listElements = [];
15883                         var liTemps = element.find('li');
15884                         for(var i = 0; i < liTemps.length; i++) {
15885                             listElements.push(liTemps.eq(i));
15886                         }
15887                         listElements[currentIndex].children().eq(0).addClass('selected-item');
15888                     }
15889                 }
15890             });
15891             scope.nextItemInDropdown = function(){
15892                 if(listElements && currentIndex < listElements.length - 1){
15893                     currentIndex++;
15894                     listElements[currentIndex - 1].children().eq(0).removeClass('selected-item');
15895                     listElements[currentIndex].children().eq(0).addClass('selected-item');
15896                 }
15897             };
15898             scope.previousItemInDropdown = function(){
15899                 if(currentIndex > 0) {
15900                     currentIndex--;
15901                     listElements[currentIndex].children().eq(0).addClass('selected-item');
15902
15903                     if(currentIndex + 1 < listElements.length)
15904                         listElements[currentIndex + 1].children().eq(0).removeClass('selected-item');
15905                 }
15906             };
15907             scope.$watch('isIconHovered', function(val) {
15908                 scope.hoverWatch = val;
15909             });
15910             scope.$watch('type', function(val) {
15911                 function toggleValues(isMiddle,isNextToDropDown,isRight,isLeft,isLeftNextDropdown){
15912                     scope['isMiddle']  = isMiddle;
15913                     scope['isNextToDropDown'] = isNextToDropDown;
15914                     scope['isRight']  = isRight;
15915                     scope['isLeft'] = isLeft;
15916                     scope['isLeftNextDropdown'] = isLeftNextDropdown;
15917                 };
15918                 switch(val) {
15919                     case (scope.iconStateConstants.MIDDLE):
15920                         toggleValues(true,false,false,true,false);
15921                         break;
15922                     case (scope.iconStateConstants.LEFT):
15923                         toggleValues(false,false,false,true,false);
15924                         break;
15925                     case (scope.iconStateConstants.RIGHT):
15926                         toggleValues(false,false,true,false,false);
15927                         break;
15928                     case (scope.iconStateConstants.NEXT_TO_DROPDOWN):
15929                         toggleValues(false,true,true,true,false);
15930                         break;
15931                     case (scope.iconStateConstants.LEFT_NEXT_TO_DROPDOWN):
15932                         toggleValues(false,false,false,true,true);
15933                         break;
15934                     default:
15935                         break;
15936                 }
15937             });
15938             scope.dropDownClicked = function() {
15939                 isMyElement = true;
15940             };
15941             scope.toggleDropdown = function(val) {
15942                 if(val !== undefined) {
15943                     scope.isDropDownOpen = val;
15944                 } else {
15945                     scope.isDropDownOpen = !scope.isDropDownOpen; 
15946                 }
15947                 scope.dropDownWatch = scope.isDropDownOpen;
15948             };
15949             $documentBind.click('isDropdown', outsideClick, scope);
15950         }
15951     };
15952 }])
15953 .controller('AttSplitIconButtonCtrl',['$scope', 'iconStateConstants',function($scope,iconStateConstants){
15954     this.subCtrls = [];
15955     $scope.isLeftLineShown=true;
15956     $scope.isRightLineShown=true;
15957     $scope.childrenScopes = [];
15958     var that = this;
15959
15960     function getDirIndex(dirType) {
15961         var index = -1;
15962         for(var c in that.subCtrls) {
15963             var ctrl = that.subCtrls[c];
15964             if(ctrl.dirType === dirType) {
15965                 index = c;
15966                 break;
15967             }
15968         }
15969         return index;
15970     }
15971     this.addSubCtrl =  function(sub) {
15972         this.subCtrls.push(sub);
15973     };
15974     this.isLeftLineShown = function(isShown) {
15975         if(isShown === undefined) {
15976             return $scope.isLeftLineShown;
15977         } else {
15978             $scope.isLeftLineShown = isShown;
15979         }
15980     };
15981     this.isRightLineShown = function(isShown) {
15982         if(isShown === undefined) {
15983             return $scope.isRightLineShown;
15984         } else {
15985             $scope.isRightLineShown = isShown;
15986         }
15987     };
15988     this.setLeftLineHover = function(isHovered) {
15989         var leftLineIndex = getDirIndex(iconStateConstants.DIR_TYPE.LEFT);
15990
15991         if($scope.isLeftLineShown && this.subCtrls[leftLineIndex] && this.subCtrls[leftLineIndex].setActiveState) {
15992             this.subCtrls[leftLineIndex].setActiveState(isHovered);
15993         }
15994     };
15995     this.setRightLineHover = function(isHovered) {
15996         var rightLineIndex = getDirIndex(iconStateConstants.DIR_TYPE.RIGHT);
15997         if($scope.isRightLineShown && this.subCtrls[rightLineIndex] && this.subCtrls[rightLineIndex].setActiveState){
15998             this.subCtrls[rightLineIndex].setActiveState(isHovered);
15999         }
16000     };
16001     this.toggleLines = function(isHovered, buttonGroupCtrl, buttonCtrl, isDropDownOpen) {  
16002         var subIconButtons = buttonGroupCtrl.subIconButtons;
16003         var subIconButtonsLength = subIconButtons.length;
16004         var leftLineIndex =  getDirIndex(iconStateConstants.DIR_TYPE.LEFT);
16005         var rightLineIndex =  getDirIndex(iconStateConstants.DIR_TYPE.RIGHT);
16006         function noVerticalLineToggle() {
16007             for(var i =0; i < subIconButtonsLength; i++) {
16008                 if(subIconButtons[i] === buttonCtrl) {
16009                     if(i + 1 <= subIconButtonsLength - 1 && subIconButtons[i+1].isLeftLineShown() 
16010                             && subIconButtons[i+1].subCtrls[leftLineIndex] 
16011                             && subIconButtons[i+1].subCtrls[leftLineIndex].setActiveState) {
16012                         subIconButtons[i+1].subCtrls[leftLineIndex].setActiveState(isHovered);
16013                     }
16014                     if(i - 1 >= 0 && subIconButtons[i-1].isRightLineShown() 
16015                             && subIconButtons[i-1].subCtrls[rightLineIndex] 
16016                             && subIconButtons[i-1].subCtrls[rightLineIndex].setActiveState) {
16017                         subIconButtons[i-1].subCtrls[rightLineIndex].setActiveState(isHovered);
16018                     }
16019                     break;
16020                 }
16021             }
16022         }   
16023         if(isDropDownOpen) {
16024             /*
16025               If the button is next to the dropdown button then just keep the 
16026               buttons left line or its left neighbors right line toggled on
16027               If the button is the dropdown button don't do anything
16028               else do things normally witht the button
16029             */
16030             /*if(subIconButtons[subIconButtonsLength-1] === buttonCtrl) {
16031
16032             }
16033             else */
16034             if(subIconButtons[subIconButtonsLength-2]==buttonCtrl) {
16035                 if(subIconButtons[subIconButtonsLength-2].isLeftLineShown()) {
16036                     subIconButtons[subIconButtonsLength-2].subCtrls[leftLineIndex].setActiveState(isHovered);
16037                 } else if(subIconButtonsLength  - 3 >= 0) {
16038                     if(subIconButtons[subIconButtonsLength-3].isRightLineShown()) {
16039                         subIconButtons[subIconButtonsLength-3].subCtrls[rightLineIndex].setActiveState(isHovered);
16040                     }
16041                 }
16042             } else {
16043                 noVerticalLineToggle();
16044
16045                 if($scope.isLeftLineShown) {
16046                     this.subCtrls[leftLineIndex].setActiveState(isHovered);
16047                 }
16048                 if($scope.isRightLineShown) {
16049                     this.subCtrls[rightLineIndex].setActiveState(isHovered);
16050                 }
16051             }
16052         } else { // End of if(isDropDownOpen)
16053             //Handle Special cases where they aren't showing any vertical lines
16054             //and the dropdown isn't down
16055             if(!$scope.isLeftLineShown && !$scope.isRightLineShown) {
16056                 noVerticalLineToggle();
16057             }   
16058             if($scope.isLeftLineShown && this.subCtrls[leftLineIndex].setActiveState) {
16059                 this.subCtrls[leftLineIndex].setActiveState(isHovered);
16060             }
16061             if($scope.isRightLineShown && this.subCtrls[rightLineIndex].setActiveState){
16062                 this.subCtrls[rightLineIndex].setActiveState(isHovered);
16063             }
16064         }
16065     };
16066     this.setButtonType = function(type){
16067         var buttonIndex = getDirIndex(iconStateConstants.DIR_TYPE.BUTTON);
16068         if(this.subCtrls[buttonIndex] && this.subCtrls[buttonIndex].setType) {
16069             this.subCtrls[buttonIndex].setType(type);
16070         }
16071     };
16072 }])
16073 .directive('attSplitIconButton', ['$document', 'iconStateConstants', 'keymap',
16074     function($document, iconStateConstants, keymap){
16075     return {
16076         restrict: 'EA',
16077         replace: true,
16078         priority: 100,
16079         transclude: true,
16080         require: ['^attSplitIconButtonGroup', 'attSplitIconButton'],
16081         controller: 'AttSplitIconButtonCtrl',
16082         templateUrl: 'app/scripts/ng_js_att_tpls/splitIconButton/splitIconButton.html',
16083         scope:{
16084             icon: '@',
16085             title: '@',
16086             dropDownId: '@'
16087         },
16088         link: function(scope,element,attr,ctrls) {
16089             if(!scope.title) {
16090                 scope.title = scope.icon;
16091             }
16092             var attSplitButtonGroupCtrl = ctrls[0];
16093             var attSplitIconButtonCtrl = ctrls[1];
16094             attSplitButtonGroupCtrl.addIconButton(attSplitIconButtonCtrl);
16095             element.bind('keydown', function(e){
16096                 //Check if the key is the up or down key
16097                 if(e.which === keymap.KEY.ESC ||
16098                     e.which === keymap.KEY.DOWN ||
16099                     e.which === keymap.KEY.ENTER ||
16100                     e.which === keymap.KEY.UP ||
16101                     e.which === keymap.KEY.TAB ) {
16102                     scope.clickHandler();
16103                     scope.$broadcast(iconStateConstants.SPLIT_ICON_BTN_EVENT_EMITTER_KEY, e);
16104                 }
16105             });
16106             scope.dropDownWatch = false;
16107             scope.iconStateConstants = iconStateConstants;
16108             scope.clickHandler = function() {
16109                 attSplitButtonGroupCtrl.hideLeftLineRightButton(attSplitIconButtonCtrl);
16110             };
16111             scope.$watch('isHovered', function(val){
16112                 if(val) {
16113                     attSplitIconButtonCtrl.toggleLines(val,attSplitButtonGroupCtrl,attSplitIconButtonCtrl,attSplitButtonGroupCtrl.isDropDownOpen);
16114                 } else{
16115                     attSplitIconButtonCtrl.toggleLines(val,attSplitButtonGroupCtrl,attSplitIconButtonCtrl,attSplitButtonGroupCtrl.isDropDownOpen);
16116                 }
16117             });
16118             scope.$watch('dropDownWatch', function(val) {
16119                 attSplitButtonGroupCtrl.isDropDownOpen = val;
16120                 attSplitButtonGroupCtrl.toggleDropdownState(val);
16121             });
16122         }
16123     }
16124 }])
16125 .controller('AttSplitIconButtonGroupCtrl',   ['$scope','iconStateConstants',function($scope,iconStateConstants){
16126     this.subIconButtons = [];
16127     this.addIconButton = function(iconButton){
16128        this.subIconButtons.push(iconButton);
16129     };
16130     this.isDropDownOpen = false;
16131     this.hideLeftLineRightButton = function(btn){
16132         var numButtons = this.subIconButtons.length;
16133         var buttonLeftOfRightMost = this.subIconButtons[numButtons - 2];
16134         var rightMostButton = this.subIconButtons[numButtons -1];
16135
16136         if (btn != buttonLeftOfRightMost && btn != rightMostButton ){
16137             rightMostButton.setLeftLineHover(false);
16138         }
16139     };
16140     this.toggleDropdownState = function(isDropDownOpen){
16141         var numButtons = this.subIconButtons.length;
16142         if(numButtons > 2) {
16143             if(isDropDownOpen) {
16144                 if(this.subIconButtons[numButtons - 2].isRightLineShown()) {
16145                     this.subIconButtons[numButtons - 2].setRightLineHover(true);
16146                 } else {
16147                     this.subIconButtons[numButtons - 1].setLeftLineHover(true);
16148                 }
16149                 this.subIconButtons[numButtons - 2].setButtonType(iconStateConstants.NEXT_TO_DROPDOWN);
16150             } else {
16151                 this.subIconButtons[numButtons - 1].setLeftLineHover(false);
16152                 this.subIconButtons[numButtons - 2].setButtonType(iconStateConstants.MIDDLE);
16153             }
16154         } else {
16155             if(isDropDownOpen) {
16156                 this.subIconButtons[0].setRightLineHover(true);
16157                 this.subIconButtons[0].setButtonType(iconStateConstants.LEFT_NEXT_TO_DROPDOWN);
16158             } else {
16159                 this.subIconButtons[0].setButtonType(iconStateConstants.LEFT);
16160             }
16161         }
16162     };
16163 }])
16164 .directive('attSplitIconButtonGroup', ['$document', '$timeout',  'iconStateConstants' ,function($document,$timeout,iconStateConstants){
16165     return {
16166         restrict: 'EA',
16167         replace: true,
16168         priority: 50,
16169         transclude: true,
16170         require: 'attSplitIconButtonGroup',
16171         controller: 'AttSplitIconButtonGroupCtrl',
16172         templateUrl: 'app/scripts/ng_js_att_tpls/splitIconButton/splitIconButtonGroup.html',
16173         scope:{},
16174         link: function(scope,element,attr,ctrls){
16175             $timeout(initialize,100);
16176             function initialize(){
16177                 var subIconButtonCtrls = ctrls.subIconButtons;
16178                 var leftMostButtonIndex = 0;
16179                 var rightMostButtonIndex =subIconButtonCtrls.length-1;
16180                 //left most button config
16181                 subIconButtonCtrls[leftMostButtonIndex].setButtonType(iconStateConstants.LEFT);
16182                 subIconButtonCtrls[leftMostButtonIndex].isLeftLineShown(false);
16183                 subIconButtonCtrls[leftMostButtonIndex].isRightLineShown(true);
16184                 //right most button config
16185                 subIconButtonCtrls[rightMostButtonIndex].setButtonType(iconStateConstants.RIGHT);
16186                 subIconButtonCtrls[rightMostButtonIndex].isRightLineShown(false);
16187                 subIconButtonCtrls[rightMostButtonIndex].isLeftLineShown(false);
16188                 //middle buttons config
16189                 if(rightMostButtonIndex >= 2) {
16190                     var index = 1;
16191                     while(index < rightMostButtonIndex) {
16192                         subIconButtonCtrls[index].setButtonType(iconStateConstants.MIDDLE);
16193                         subIconButtonCtrls[index].isRightLineShown(false);
16194                         subIconButtonCtrls[index].isLeftLineShown(false);
16195                         index++;
16196                     }
16197                     var skipIndex = 2;
16198                     while(skipIndex <= rightMostButtonIndex){
16199                         if(skipIndex == rightMostButtonIndex) {
16200                             subIconButtonCtrls[skipIndex].isLeftLineShown(true);
16201                         } else {
16202                             subIconButtonCtrls[skipIndex].isRightLineShown(true);
16203                             subIconButtonCtrls[skipIndex].isLeftLineShown(true); 
16204                         } 
16205                         skipIndex = skipIndex + 2;
16206                     }
16207                 }
16208                 //reposition the dropdown
16209                 var ulElem = element.find('ul');
16210                 if(ulElem.length > 0) {
16211                     var numButtons = rightMostButtonIndex+1;
16212                     if(numButtons > 2) {
16213                         var offset = (numButtons)*34-70+(numButtons/1.5) + 0.5;
16214                         var offSetStr = offset+'px';
16215                         angular.element(ulElem).css('left',offSetStr);
16216                         angular.element(ulElem).css('border-top-left-radius','0px');
16217                     } else {
16218                         angular.element(ulElem).css('left','0px');
16219                     }
16220                 }
16221             }
16222         }
16223     }
16224 }]);
16225
16226 angular.module('att.abs.stepSlider', ['att.abs.position'])
16227         .constant('sliderConstants', {
16228             /*
16229              The MIT License (MIT)
16230              Copyright (c) 2013 Julien Valéry
16231              */
16232             SLIDER: {
16233                 settings: {
16234                     from: 1,
16235                     to: 40,
16236                     step: 1,
16237                     smooth: true,
16238                     limits: true,
16239                     value: "3",
16240                     dimension: "",
16241                     vertical: false
16242                 },
16243                 className: "jslider",
16244                 selector: ".jslider-"
16245             },
16246             EVENTS: {
16247             },
16248             COLORS: {
16249                 GREEN: 'green',
16250                 BLUE_HIGHLIGHT: 'blue',
16251                 MAGENTA: 'magenta',
16252                 GOLD: 'gold',
16253                 PURPLE: 'purple',
16254                 DARK_BLUE: 'dark-blue',
16255                 REGULAR: 'regular',
16256                 WHITE: 'white'
16257             }
16258         })
16259         .factory('utils', function () {
16260             /*
16261              The MIT License (MIT)
16262              Copyright (c) 2013 Julien Valéry
16263              */
16264             return {
16265                 offset: function (elm) {
16266                     var rawDom = elm[0];
16267                     var _x = 0;
16268                     var _y = 0;
16269                     var body = document.documentElement || document.body;
16270                     var scrollX = window.pageXOffset || body.scrollLeft;
16271                     var scrollY = window.pageYOffset || body.scrollTop;
16272                     _x = rawDom.getBoundingClientRect().left + scrollX;
16273                     _y = rawDom.getBoundingClientRect().top + scrollY;
16274                     return {left: _x, top: _y};
16275                 },
16276                 roundUpToScale: function (mousePrc, scale, cutOffWidth, cutOffIndex) {
16277                     var lowerVal;
16278                     var higherVal;
16279                     var newMousePrc;
16280                     var middle;
16281
16282                     for (var index = 1; index < scale.length; index++) {
16283                         lowerVal = scale[index - 1];
16284                         higherVal = scale[index];
16285                         middle = ((higherVal - lowerVal) * .5) + lowerVal;
16286                         /*
16287                          Handles a situation where the user clicks close to the start point of
16288                          the slider but the pointer doesn't move
16289                          */
16290                         if ((lowerVal === 0 && mousePrc <= middle) || checkEquality(lowerVal, mousePrc)) {
16291                             newMousePrc = lowerVal;
16292                             break;
16293                         }
16294                         else if (lowerVal < mousePrc && (mousePrc < higherVal ||
16295                                 checkEquality(mousePrc, higherVal)))
16296                         {
16297                             newMousePrc = higherVal;
16298                             break;
16299                         }
16300                     }
16301                     //Check if the newMousePrc is <= the cuttOffPoint
16302                     if (cutOffWidth && newMousePrc < cutOffWidth) {
16303                         return scale[cutOffIndex];
16304                     }
16305                     else {
16306                         return newMousePrc;
16307                     }
16308                     /*
16309                      Checks to see if 2 points are so close that they are
16310                      basically equal.
16311                      */
16312                     function checkEquality(point1, point2) {
16313                         var precision = 0.1;
16314                         if (Math.abs(point2 - point1) <= precision) {
16315                             return true;
16316                         }
16317                         return false;
16318                     }
16319                 },
16320                 valueForDifferentScale: function (from, to, prc, prcToValueMapper) {
16321                     var decimalPrc = prc / 100;
16322                     if (decimalPrc === 0) {
16323                         return from;
16324                     }
16325                     return prcToValueMapper[prc];
16326                 },
16327                 /* converts the default value Kbps to Mbps or Gbps */
16328                 convertToMbpsGbps: function (unitValue, unitLabel, configDecimalPlaces) {
16329                     var defaultDecimalPlaces = 3; /* this is the default decimal places as per business requirements */
16330                     if (configDecimalPlaces) {
16331                         defaultDecimalPlaces = configDecimalPlaces;
16332                     }
16333
16334                     if ((unitValue > 1024 && unitValue < 1000000) && angular.equals(unitLabel, 'Kbps')) {
16335                         unitValue = truncator((unitValue/1000), defaultDecimalPlaces);
16336                         unitLabel = 'Mbps';
16337                     } else if ((unitValue > 1024 && unitValue < 1000000) && angular.equals(unitLabel, 'Mbps')){
16338                         unitValue = truncator((unitValue/1000), defaultDecimalPlaces);
16339                         unitLabel = 'Mbps';
16340                     } else if (unitValue <= 1024 && angular.equals(unitLabel, 'Mbps')) {
16341                         unitLabel = 'Kbps';
16342                     } else {
16343                         unitLabel = 'Kbps';
16344                     }
16345
16346                     if (unitValue >= 1000000 && angular.equals(unitLabel, 'Kbps')) {
16347                         unitValue = truncator((unitValue/1000000), defaultDecimalPlaces);
16348                         unitLabel = 'Gbps';
16349                     }
16350                     return {
16351                         unitValue: unitValue, 
16352                         unitLabel: unitLabel
16353                     };
16354                     
16355                     function truncator(numToTruncate, intDecimalPlaces) {    
16356                         var cnvrtdNum = Math.pow(10, intDecimalPlaces);
16357                         return ~~(numToTruncate * cnvrtdNum)/cnvrtdNum;
16358                     }
16359                 },
16360                 getConversionFactorValue: function (value, conversion, firstDimension) {
16361                     /*
16362                      Loop through the conversion array and keep checking the
16363                      startVal
16364                      */
16365                     if (value <= conversion[0].startVal) {
16366                         return{
16367                             scaledVal: value,
16368                             scaledDimension: firstDimension
16369                         };
16370                     }
16371                     var endIndex = 0;
16372                     for (var index in conversion) {
16373                         var c = conversion[index];
16374                         if (value > c.startVal) {
16375                             endIndex = index;
16376                         }
16377                     }
16378                     var scaleFactor = conversion[endIndex].scaleFactor;
16379                     var scaledVal = value / scaleFactor;
16380                     var scaledDimension = conversion[endIndex].dimension;
16381                     return {
16382                         scaledVal: scaledVal,
16383                         scaledDimension: scaledDimension
16384                     };
16385                 }
16386             };
16387         })
16388         .factory('sliderDraggable', ['utils', function (utils) {
16389                 /*
16390                  The MIT License (MIT)
16391                  Copyright (c) 2013 Julien Valéry
16392                  */
16393                 function Draggable() {
16394                     this._init.apply(this, arguments);
16395                 }
16396                 Draggable.prototype.oninit = function () {
16397                 };
16398                 Draggable.prototype.events = function () {
16399                 };
16400                 Draggable.prototype.onmousedown = function () {
16401                     this.ptr.css({position: "absolute"});
16402                 };
16403                 Draggable.prototype.onmousemove = function (evt, x, y) {
16404                     this.ptr.css({left: x, top: y});
16405                 };
16406                 Draggable.prototype.onmouseup = function () {
16407                 };
16408                 Draggable.prototype.isDefault = {
16409                     drag: false,
16410                     clicked: false,
16411                     toclick: true,
16412                     mouseup: false
16413                 };
16414                 Draggable.prototype._init = function () {
16415                     if (arguments.length > 0) {
16416                         this.ptr = arguments[0];
16417                         this.parent = arguments[2];
16418                         if (!this.ptr) {
16419                             return;
16420                         }
16421                         this.is = {};
16422                         angular.extend(this.is, this.isDefault);
16423                         var offset = utils.offset(this.ptr);
16424                         this.d = {
16425                             left: offset.left,
16426                             top: offset.top,
16427                             width: this.ptr[0].clientWidth,
16428                             height: this.ptr[0].clientHeight
16429                         };
16430                         this.oninit.apply(this, arguments);
16431                         this._events();
16432                     }
16433                 };
16434                 Draggable.prototype._getPageCoords = function (event) {
16435                     var value = {};
16436                     if (event.targetTouches && event.targetTouches[0]) {
16437                         value = {x: event.targetTouches[0].pageX, y: event.targetTouches[0].pageY};
16438                     } else {
16439                         value = {x: event.pageX, y: event.pageY};
16440                     }
16441                     return value;
16442                 };
16443                 Draggable.prototype._bindEvent = function (ptr, eventType, handler) {
16444                     if (this.supportTouches_) {
16445                         ptr[0].attachEvent(this.events_[ eventType ], handler);
16446                     }
16447                     else {
16448                         if (ptr.bind) {
16449                             ptr.bind(this.events_[ eventType ], handler);
16450                         }
16451                     }
16452                 };
16453                 Draggable.prototype._events = function () {
16454                     var self = this;
16455                     this.supportTouches_ = 'ontouchend' in document;
16456                     this.events_ = {
16457                         "click": this.supportTouches_ ? "touchstart" : "click",
16458                         "down": this.supportTouches_ ? "touchstart" : "mousedown",
16459                         "move": this.supportTouches_ ? "touchmove" : "mousemove",
16460                         "up": this.supportTouches_ ? "touchend" : "mouseup",
16461                         "mousedown": this.supportTouches_ ? "mousedown" : "mousedown"
16462                     };
16463                     var documentElt = angular.element(window.document);
16464                     this._bindEvent(documentElt, "move", function (event) {
16465                         if (self.is.drag) {
16466                             event.stopPropagation();
16467                             event.preventDefault();
16468                             if (!self.parent.disabled) {
16469                                 self._mousemove(event);
16470                             }
16471                         }
16472                     });
16473                     this._bindEvent(documentElt, "down", function (event) {
16474                         if (self.is.drag) {
16475                             event.stopPropagation();
16476                             event.preventDefault();
16477                         }
16478                     });
16479                     this._bindEvent(documentElt, "up", function (event) {
16480                         self._mouseup(event);
16481                     });
16482                     this._bindEvent(this.ptr, "down", function (event) {
16483                         self._mousedown(event);
16484                         return false;
16485                     });
16486                     this._bindEvent(this.ptr, "up", function (event) {
16487                         self._mouseup(event);
16488                     });
16489                     this.events();
16490                 };
16491                 Draggable.prototype._mousedown = function (evt) {
16492                     this.is.drag = true;
16493                     this.is.clicked = false;
16494                     this.is.mouseup = false;
16495                     var coords = this._getPageCoords(evt);
16496                     this.cx = coords.x - this.ptr[0].offsetLeft;
16497                     this.cy = coords.y - this.ptr[0].offsetTop;
16498                     angular.extend(this.d, {
16499                         left: this.ptr[0].offsetLeft,
16500                         top: this.ptr[0].offsetTop,
16501                         width: this.ptr[0].clientWidth,
16502                         height: this.ptr[0].clientHeight
16503                     });
16504                     if (this.outer && this.outer.get(0)) {
16505                         this.outer.css({height: Math.max(this.outer.height(), $(document.body).height()), overflow: "hidden"});
16506                     }
16507                     this.onmousedown(evt);
16508                 };
16509                 Draggable.prototype._mousemove = function (evt) {
16510                     if (this.uid === 0) {
16511                         return;
16512                     }
16513                     this.is.toclick = false;
16514                     var coords = this._getPageCoords(evt);
16515                     this.onmousemove(evt, coords.x - this.cx, coords.y - this.cy);
16516                 };
16517                 Draggable.prototype._mouseup = function (evt) {
16518                     if (this.is.drag) {
16519                         this.is.drag = false;
16520                         if (this.outer && this.outer.get(0)) {
16521                             if ($.browser.mozilla) {
16522                                 this.outer.css({overflow: "hidden"});
16523                             } else {
16524                                 this.outer.css({overflow: "visible"});
16525                             }
16526                             if ($.browser.msie && $.browser.version === '6.0') {
16527                                 this.outer.css({height: "100%"});
16528                             } else {
16529                                 this.outer.css({height: "auto"});
16530                             }
16531                         }
16532                         this.onmouseup(evt);
16533                     }
16534                 };
16535                 return Draggable;
16536             }])
16537         .factory('sliderPointer', ['sliderDraggable', 'utils', function (Draggable, utils) {
16538                 /*
16539                  The MIT License (MIT)
16540                  Copyright (c) 2013 Julien Valéry
16541                  */
16542                 function SliderPointer() {
16543                     Draggable.apply(this, arguments);
16544                 }
16545                 SliderPointer.prototype = new Draggable();
16546                 SliderPointer.prototype.oninit = function (ptr, id, _constructor) {
16547                     this.uid = id;
16548                     this.parent = _constructor;
16549                     this.value = {};
16550                     this.settings = angular.copy(_constructor.settings);
16551                 };
16552                 SliderPointer.prototype.onmousedown = function (evt) {
16553                     var off = utils.offset(this.parent.domNode);
16554                     var offset = {
16555                         left: off.left,
16556                         top: off.top,
16557                         width: this.parent.domNode[0].clientWidth,
16558                         height: this.parent.domNode[0].clientHeight
16559                     };
16560                     this._parent = {
16561                         offset: offset,
16562                         width: offset.width,
16563                         height: offset.height
16564                     };
16565                     this.ptr.addClass("jslider-pointer-hover");
16566                     this.setIndexOver();
16567                 };
16568                 SliderPointer.prototype.onmousemove = function (evt, x, y) {
16569                     var coords = this._getPageCoords(evt);
16570                     //val is the percent where the slider pointer is located
16571                     var val = this.calc(coords.x);
16572                     if (!this.parent.settings.smooth) {
16573                         val = utils.roundUpToScale(val,
16574                                 this.parent.settings.scale,
16575                                 this.parent.settings.cutOffWidth,
16576                                 this.parent.settings.cutOffIndex);
16577                     }
16578                     var cutOffWidth = this.parent.settings.cutOffWidth;
16579                     if (cutOffWidth && val < cutOffWidth) {
16580                         val = cutOffWidth;
16581                     }
16582                     this._set(val);
16583                 };
16584                 SliderPointer.prototype.onmouseup = function (evt) {
16585                     if (this.settings.callback && angular.isFunction(this.settings.callback)) {
16586                         var val = this.parent.getValue();
16587                         this.settings.callback.call(this.parent, val);
16588                     }
16589                     this.ptr.removeClass("jslider-pointer-hover");
16590                 };
16591                 SliderPointer.prototype.setIndexOver = function () {
16592                     this.parent.setPointersIndex(1);
16593                     this.index(2);
16594                 };
16595                 SliderPointer.prototype.index = function (i) {
16596                 };
16597                 SliderPointer.prototype.limits = function (x) {
16598                     return this.parent.limits(x, this);
16599                 };
16600                 SliderPointer.prototype.calc = function (coords) {
16601                     var diff = coords - this._parent.offset.left;
16602                     var val = this.limits((diff * 100) / this._parent.width);
16603                     return val;
16604                 };
16605                 SliderPointer.prototype.set = function (value, opt_origin) {
16606                     this.value.origin = this.parent.round(value);
16607                     this._set(this.parent.valueToPrc(value, this), opt_origin);
16608                 };
16609                 SliderPointer.prototype._set = function (prc, opt_origin) {
16610                     if (!opt_origin) {
16611                         this.value.origin = this.parent.prcToValue(prc);
16612                     }
16613                     this.value.prc = prc;
16614                     //Sets the location of the SliderPointer
16615                     this.ptr.css({left: prc + '%'});
16616                     this.parent.redraw(this);
16617                 };
16618                 return SliderPointer;
16619             }])
16620         .factory('slider', ['sliderPointer', 'sliderConstants', 'utils', function (SliderPointer, sliderConstants, utils) {
16621                 /*
16622                  The MIT License (MIT)
16623                  Copyright (c) 2013 Julien Valéry
16624                  */
16625                 var cutOffDom;
16626                 function Slider() {
16627                     return this.init.apply(this, arguments);
16628                 }
16629                 function changeCutOffWidth(width) {
16630                     cutOffDom.css('width', width);
16631                 }
16632                 ;
16633                 Slider.prototype.changeCutOffWidth = changeCutOffWidth;
16634                 Slider.prototype.init = function (inputNode, templateNode, settings) {
16635                     this.settings = sliderConstants.SLIDER.settings;
16636                     angular.extend(this.settings, angular.copy(settings));
16637                     this.inputNode = inputNode;
16638                     this.inputNode.addClass("ng-hide");
16639                     this.settings.interval = this.settings.to - this.settings.from;
16640                     if (this.settings.calculate && $.isFunction(this.settings.calculate)) {
16641                         this.nice = this.settings.calculate;
16642                     }
16643                     if (this.settings.onstatechange && $.isFunction(this.settings.onstatechange)) {
16644                         this.onstatechange = this.settings.onstatechange;
16645                     }
16646                     this.is = {init: false};
16647                     this.o = {};
16648                     this.create(templateNode);
16649                 };
16650                 Slider.prototype.create = function (templateNode) {
16651                     var $this = this;
16652                     this.domNode = templateNode;
16653                     var off = utils.offset(this.domNode);
16654                     var offset = {
16655                         left: off.left,
16656                         top: off.top,
16657                         width: this.domNode[0].clientWidth,
16658                         height: this.domNode[0].clientHeight
16659                     };
16660                     this.sizes = {domWidth: this.domNode[0].clientWidth, domOffset: offset};
16661                     angular.extend(this.o, {
16662                         pointers: {},
16663                         labels: {
16664                             0: {
16665                                 o: angular.element(this.domNode.find('div')[5])
16666                             },
16667                             1: {
16668                                 o: angular.element(this.domNode.find('div')[6])
16669                             }
16670                         },
16671                         limits: {
16672                             0: angular.element(this.domNode.find('div')[3]),
16673                             1: angular.element(this.domNode.find('div')[5])
16674                         }
16675                     });
16676                     angular.extend(this.o.labels[0], {
16677                         value: this.o.labels[0].o.find("span")
16678                     });
16679                     angular.extend(this.o.labels[1], {
16680                         value: this.o.labels[1].o.find("span")
16681                     });
16682                     if (!$this.settings.value.split(";")[1]) {
16683                         this.settings.single = true;
16684                     }
16685                     var domNodeDivs = this.domNode.find('div');
16686                     cutOffDom = angular.element(domNodeDivs[8]);
16687                     if (cutOffDom && cutOffDom.css) {
16688                         cutOffDom.css('width', '0%');
16689                     }
16690                     var pointers = [angular.element(domNodeDivs[1]), angular.element(domNodeDivs[2])];
16691                     angular.forEach(pointers, function (pointer, key) {
16692                         $this.settings = angular.copy($this.settings);
16693                         var value = $this.settings.value.split(';')[key];
16694                         if (value) {
16695                             $this.o.pointers[key] = new SliderPointer(pointer, key, $this);
16696                             var prev = $this.settings.value.split(';')[key - 1];
16697                             if (prev && parseInt(value, 10) < parseInt(prev, 10)) {
16698                                 value = prev;
16699                             }
16700                             var value1 = value < $this.settings.from ? $this.settings.from : value;
16701                             value1 = value > $this.settings.to ? $this.settings.to : value;
16702                             $this.o.pointers[key].set(value1, true);
16703                             if (key === 0) {
16704                                 $this.domNode.bind('mousedown', $this.clickHandler.apply($this));
16705                             }
16706                         }
16707                     });
16708                     this.o.value = angular.element(this.domNode.find("i")[2]);
16709                     this.is.init = true;
16710                     angular.forEach(this.o.pointers, function (pointer) {
16711                         $this.redraw(pointer);
16712                     });
16713                 };
16714                 Slider.prototype.clickHandler = function () {
16715                     var self = this;
16716                     return function (evt) {
16717                         if (self.disabled) {
16718                             return;
16719                         }
16720                         var className = evt.target.className;
16721                         var targetIdx = 0;
16722                         if (className.indexOf('jslider-pointer-to') > 0) {
16723                             targetIdx = 1;
16724                         }
16725                         var _off = utils.offset(self.domNode);
16726                         var offset = {
16727                             left: _off.left,
16728                             top: _off.top,
16729                             width: self.domNode[0].clientWidth,
16730                             height: self.domNode[0].clientHeight
16731                         };
16732                         targetIdx = 1;
16733                         var targetPtr = self.o.pointers[targetIdx];
16734                         targetPtr._parent = {offset: offset, width: offset.width, height: offset.height};
16735                         targetPtr._mousemove(evt);
16736                         targetPtr.onmouseup();
16737                         return false;
16738                     };
16739                 };
16740                 Slider.prototype.disable = function (bool) {
16741                     this.disabled = bool;
16742                 };
16743                 Slider.prototype.nice = function (value) {
16744                     return value;
16745                 };
16746                 Slider.prototype.onstatechange = function () {
16747                 };
16748                 Slider.prototype.limits = function (x, pointer) {
16749                     if (!this.settings.smooth) {
16750                         var step = this.settings.step * 100 / (this.settings.interval);
16751                         x = Math.round(x / step) * step;
16752                     }
16753                     var another = this.o.pointers[1 - pointer.uid];
16754                     if (another && pointer.uid && x < another.value.prc) {
16755                         x = another.value.prc;
16756                     }
16757                     if (another && !pointer.uid && x > another.value.prc) {
16758                         x = another.value.prc;
16759                     }
16760                     if (x < 0) {
16761                         x = 0;
16762                     }
16763                     if (x > 100) {
16764                         x = 100;
16765                     }
16766                     var val = Math.round(x * 10) / 10;
16767                     return val;
16768                 };
16769                 Slider.prototype.setPointersIndex = function (i) {
16770                     angular.forEach(this.getPointers(), function (pointer, i) {
16771                         pointer.index(i);
16772                     });
16773                 };
16774                 Slider.prototype.getPointers = function () {
16775                     return this.o.pointers;
16776                 };
16777                 Slider.prototype.onresize = function () {
16778                     var self = this;
16779                     this.sizes = {
16780                         domWidth: this.domNode[0].clientWidth,
16781                         domHeight: this.domNode[0].clientHeight,
16782                         domOffset: {
16783                             left: this.domNode[0].offsetLeft,
16784                             top: this.domNode[0].offsetTop,
16785                             width: this.domNode[0].clientWidth,
16786                             height: this.domNode[0].clientHeight
16787                         }
16788                     };
16789                     angular.forEach(this.o.pointers, function (ptr, key) {
16790                         self.redraw(ptr);
16791                     });
16792                 };
16793                 Slider.prototype.update = function () {
16794                     this.onresize();
16795                     this.drawScale();
16796                 };
16797                 Slider.prototype.drawScale = function () {
16798                 };
16799                 Slider.prototype.redraw = function (pointer) {
16800                     if (!this.settings.smooth) {
16801                         var newMousePrc = utils.roundUpToScale(pointer.value.prc,
16802                                 this.settings.scale,
16803                                 this.settings.cutOffWidth,
16804                                 this.settings.cutOffIndex);
16805                         pointer.value.origin = newMousePrc;
16806                         pointer.value.prc = newMousePrc;
16807                     }
16808
16809                     if (!this.is.init) {
16810                         return false;
16811                     }
16812                     this.setValue();
16813                     var width = this.o.pointers[1].value.prc;
16814                     var newPos = {left: '0%', width: width + '%'};
16815                     this.o.value.css(newPos);
16816                     var htmlValue = this.nice(pointer.value.origin);
16817                     var scaledDimension = this.settings.firstDimension;
16818                     if (this.settings.stepWithDifferentScale && !this.settings.smooth) {
16819                         htmlValue = utils.valueForDifferentScale(this.settings.from,
16820                                 this.settings.to, htmlValue, this.settings.prcToValueMapper);
16821                     }
16822                     //This is the base value before the conversion
16823                     if (this.settings.realtimeCallback && angular.isFunction(this.settings.realtimeCallback)
16824                             && this.settings.cutOffVal !== undefined && pointer.uid === 1) {
16825                         this.settings.realtimeCallback(htmlValue);
16826                     }
16827                     //Need to change this to the correct value for the scale
16828                     if (this.settings.conversion) {
16829                         var conversionObj = utils.getConversionFactorValue(parseInt(htmlValue),
16830                                 this.settings.conversion,
16831                                 this.settings.firstDimension);
16832                         htmlValue = conversionObj.scaledVal;
16833                         scaledDimension = conversionObj.scaledDimension;
16834                     }
16835
16836                     htmlValue = parseFloat(htmlValue);
16837                     var tooltipLabel = utils.convertToMbpsGbps(htmlValue, scaledDimension, this.settings.decimalPlaces);
16838
16839                     this.o.labels[pointer.uid].value.html(tooltipLabel.unitValue + ' ' + tooltipLabel.unitLabel);
16840                     //Top tooltip label
16841                     this.redrawLabels(pointer);
16842                 };
16843                 Slider.prototype.redrawLabels = function (pointer) {
16844                     function setPosition(label, sizes, prc) {
16845                         sizes.margin = -sizes.label / 2;
16846                         var domSize = self.sizes.domWidth;
16847                         var label_left = sizes.border + sizes.margin;
16848                         if (label_left < 0) {
16849                             sizes.margin -= label_left;
16850                         }
16851                         if (sizes.border + sizes.label / 2 > domSize) {
16852                             sizes.margin = 0;
16853                             sizes.right = true;
16854                         } else
16855                             sizes.right = false;
16856                         //Adjust the tooltip location
16857                         sizes.margin = -((label.o[0].clientWidth / 2) - label.o[0].clientWidth / 20);
16858                         label.o.css({left: prc + "%", marginLeft: sizes.margin, right: "auto"});
16859                         if (sizes.right)
16860                             label.o.css({left: "auto", right: 0});
16861                         return sizes;
16862                     }
16863                     var self = this;
16864                     var label = this.o.labels[pointer.uid];
16865                     var prc = pointer.value.prc;
16866                     var sizes = {
16867                         label: label.o[0].offsetWidth,
16868                         right: false,
16869                         border: (prc * domSize) / 100
16870                     };
16871                     var another_label = null;
16872                     var another = null;
16873                     if (!this.settings.single) {
16874                         another = this.o.pointers[1 - pointer.uid];
16875                         another_label = this.o.labels[another.uid];
16876                         switch (pointer.uid) {
16877                             case 0:
16878                                 if (sizes.border + sizes.label / 2 > another_label.o[0].offsetLeft - this.sizes.domOffset.left) {
16879                                     another_label.o.css({visibility: "hidden"});
16880                                     another_label.value.html(this.nice(another.value.origin));
16881                                     label.o.css({visibility: "hidden"});
16882                                     prc = (another.value.prc - prc) / 2 + prc;
16883                                     if (another.value.prc !== pointer.value.prc) {
16884                                         label.value.html(this.nice(pointer.value.origin) + "&nbsp;&ndash;&nbsp;" + this.nice(another.value.origin));
16885                                         sizes.label = label.o[0].clientWidth;
16886                                         sizes.border = (prc * domSize) / 100;
16887                                     }
16888                                 } else {
16889                                     another_label.o.css({visibility: "visible"});
16890                                 }
16891                                 break;
16892                             case 1:
16893                                 if (sizes.border - sizes.label / 2 < another_label.o[0].offsetLeft - this.sizes.domOffset.left + another_label.o[0].clientWidth) {
16894                                     another_label.o.css({visibility: "hidden"});
16895                                     another_label.value.html(this.nice(another.value.origin));
16896                                     label.o.css({visibility: "visible"});
16897                                     prc = (prc - another.value.prc) / 2 + another.value.prc;
16898                                     if (another.value.prc !== pointer.value.prc) {
16899                                         label.value.html(this.nice(another.value.origin) + "&nbsp;&ndash;&nbsp;" + this.nice(pointer.value.origin));
16900                                         sizes.label = label.o[0].clientWidth;
16901                                         sizes.border = (prc * domSize) / 100;
16902                                     }
16903                                 } else {
16904                                     another_label.o.css({visibility: "visible"});
16905                                 }
16906                                 break;
16907                         }
16908                     }
16909                     sizes = setPosition(label, sizes, prc);
16910                     var domSize = self.sizes.domWidth;
16911                     //This is the 0th pointer
16912                     if (another_label) {
16913                         sizes = {
16914                             label: another_label.o[0].clientWidth,
16915                             right: false,
16916                             border: (another.value.prc * this.sizes.domWidth) / 100
16917                         };
16918                         sizes = setPosition(another_label, sizes, another.value.prc);
16919                     }
16920                 };
16921                 Slider.prototype.redrawLimits = function () {
16922                     if (this.settings.limits) {
16923                         var limits = [true, true];
16924                         for (var key in this.o.pointers) {
16925                             if (!this.settings.single || key === 0) {
16926                                 var pointer = this.o.pointers[key];
16927                                 var label = this.o.labels[pointer.uid];
16928                                 var label_left = label.o[0].offsetLeft - this.sizes.domOffset.left;
16929                                 var limit = this.o.limits[0];
16930                                 if (label_left < limit[0].clientWidth)
16931                                     limits[0] = false;
16932                                 limit = this.o.limits[1];
16933                                 if (label_left + label.o[0].clientWidth > this.sizes.domWidth - limit[0].clientWidth)
16934                                     limits[1] = false;
16935                             }
16936                         }
16937                         for (var i = 0; i < limits.length; i++) {
16938                             if (limits[i]){
16939                                 angular.element(this.o.limits[i]).addClass("animate-show");}
16940                             else{
16941                                 angular.element(this.o.limits[i]).addClass("animate-hidde");}
16942                         }
16943                     }
16944                 };
16945                 Slider.prototype.setValue = function () {
16946                     var value = this.getValue();
16947                     this.inputNode.attr("value", value);
16948                     this.onstatechange.call(this, value, this.inputNode);
16949                 };
16950                 Slider.prototype.getValue = function () {
16951                     if (!this.is.init){
16952                         return false;}
16953                     var $this = this;
16954                     var value = "";
16955                     angular.forEach(this.o.pointers, function (pointer, key) {
16956                         if (pointer.value.prc !== undefined && !isNaN(pointer.value.prc)) {
16957                             var pointerPrc = pointer.value.prc;
16958                             var myValue = $this.prcToValue(pointerPrc);
16959                             if (!$this.settings.smooth) {
16960                                 var myValue = utils.valueForDifferentScale($this.settings.from,
16961                                         $this.settings.to,
16962                                         pointerPrc,
16963                                         $this.settings.prcToValueMapper);
16964                             }
16965                             value += (key > 0 ? ";" : "") + myValue;
16966                         }
16967                     });
16968                     return value;
16969                 };
16970                 Slider.prototype.getPrcValue = function () {
16971                     if (!this.is.init)
16972                         return false;
16973                     var value = "";
16974                     $.each(this.o.pointers, function (i) {
16975                         if (this.value.prc !== undefined && !isNaN(this.value.prc))
16976                             value += (i > 0 ? ";" : "") + this.value.prc;
16977                     });
16978                     return value;
16979                 };
16980                 Slider.prototype.prcToValue = function (prc) {
16981                     var value;
16982                     if (this.settings.heterogeneity && this.settings.heterogeneity.length > 0) {
16983                         var h = this.settings.heterogeneity;
16984                         var _start = 0;
16985                         var _from = this.settings.from;
16986                         for (var i = 0; i <= h.length; i++) {
16987                             var v;
16988                             if (h[i]){
16989                                 v = h[i].split("/");}
16990                             else{
16991                                 v = [100, this.settings.to];}
16992                             if (prc >= _start && prc <= v[0]) {
16993                                 value = _from + ((prc - _start) * (v[1] - _from)) / (v[0] - _start);
16994                             }
16995                             _start = v[0];
16996                             _from = v[1];
16997                         }
16998                     }
16999                     else {
17000                         value = this.settings.from + (prc * this.settings.interval) / 100;
17001                     }
17002                     var roundedValue = this.round(value);
17003                     return roundedValue;
17004                 };
17005                 Slider.prototype.valueToPrc = function (value, pointer) {
17006                     var prc;
17007                     if (this.settings.heterogeneity && this.settings.heterogeneity.length > 0) {
17008                         var h = this.settings.heterogeneity;
17009                         var _start = 0;
17010                         var _from = this.settings.from;
17011                         for (var i = 0; i <= h.length; i++) {
17012                             var v;
17013                             if (h[i])
17014                                 v = h[i].split("/");
17015                             else
17016                                 v = [100, this.settings.to];
17017                             if (value >= _from && value <= v[1]) {
17018                                 prc = pointer.limits(_start + (value - _from) * (v[0] - _start) / (v[1] - _from));
17019                             }
17020                             _start = v[0];
17021                             _from = v[1];
17022                         }
17023                     } else {
17024                         prc = pointer.limits((value - this.settings.from) * 100 / this.settings.interval);
17025                     }
17026                     return prc;
17027                 };
17028                 Slider.prototype.round = function (value) {
17029                     value = Math.round(value / this.settings.step) * this.settings.step;
17030                     if (this.settings.round){
17031                         value = Math.round(value * Math.pow(10, this.settings.round)) / Math.pow(10, this.settings.round);}
17032                     else{
17033                         value = Math.round(value);}
17034                     return value;
17035                 };
17036                 return Slider;
17037             }])
17038         .directive('attStepSlider', [
17039             '$compile', '$templateCache', '$timeout', '$window', 'slider', 'sliderConstants', 'utils',
17040             function (compile, templateCache, timeout, win, Slider, sliderConstants, utils) {
17041                 /*
17042                  The MIT License (MIT)
17043                  Copyright (c) 2013 Julien Valéry
17044                  */
17045                 var templateUrl = 'app/scripts/ng_js_att_tpls/stepSlider/attStepSlider.html';
17046                 return {
17047                     restrict: 'AE',
17048                     require: '?ngModel',
17049                     scope: {
17050                         options: '=',
17051                         cutOff: '='
17052                     },
17053                     priority: 1,
17054                     templateUrl: templateUrl,
17055                     link: function (scope, element, attrs, ngModel) {
17056                         if (!ngModel)
17057                             return;
17058                         scope.mainSliderClass = 'step-slider';
17059                         element.after(compile(templateCache.get(templateUrl))(scope, function (clonedElement, scope) {
17060                             scope.tmplElt = clonedElement;
17061                         }));
17062                         ngModel.$render = function () {
17063                             if (ngModel.$viewValue.split && ngModel.$viewValue.split(";").length === 1) {
17064                                 ngModel.$viewValue = '0;' + ngModel.$viewValue;
17065                             } else if (typeof (ngModel.$viewValue) === 'number') {
17066                                 ngModel.$viewValue = '0;' + ngModel.$viewValue;
17067                             }
17068                             if (!ngModel.$viewValue && ngModel.$viewValue !== 0) {
17069                                 return;
17070                             }
17071                             if (typeof (ngModel.$viewValue) === 'number') {
17072                                 ngModel.$viewValue = '' + ngModel.$viewValue;
17073                             }
17074                             if (scope.slider) {
17075                                 var firstPointer = '0';
17076                                 scope.slider.getPointers()[0].set(firstPointer, true);
17077                                 if (ngModel.$viewValue.split(";")[1]) {
17078                                     var value = ngModel.$viewValue.split(";")[1];
17079                                     if (value.length >= 4) {
17080                                         value = value.substring(0, 2);
17081                                     }
17082                                     if (!scope.options.realtime)
17083                                         scope.options.callback(parseFloat(ngModel.$viewValue.split(";")[1]));
17084                                     scope.slider.getPointers()[1].set(ngModel.$viewValue.split(";")[1], true);
17085                                 }
17086                             }
17087                         };
17088                         var init = function () {
17089                             scope.from = '' + scope.options.from;
17090                             scope.to = '' + scope.options.to;
17091                             if (scope.options.calculate && typeof scope.options.calculate === 'function') {
17092                                 scope.from = scope.options.calculate(scope.from);
17093                                 scope.to = scope.options.calculate(scope.to);
17094                             }
17095                             scope.showDividers = scope.options.showDividers;
17096                             scope.COLORS = sliderConstants.COLORS;
17097                             scope.sliderColor = scope.options.sliderColor;
17098                             if (!scope.sliderColor)
17099                                 scope.sliderColor = sliderConstants.COLORS.REGULAR;
17100                             var scaleArray = scope.options.scale;
17101                             /* Make a copy of the scaleArray before converting it to percentage for the bars */
17102                             var nonPercentScaleArray = [];
17103                             /* Define variable for displaying lower range values */
17104                             var scaledUpValueArray=[];
17105                             /* Create Mapper for the percentage to value */
17106                             var prcToValueMapper = {};
17107                             for (var i in scaleArray) {
17108                                 var s = scaleArray[i];
17109                                 nonPercentScaleArray.push(s);
17110                             }
17111                             function addScaleArrayStartAndEnd() {
17112                                 if (scaleArray[0] !== 0) {
17113                                     scaleArray.splice(0, 0, 0);
17114                                 }
17115                                 if (scaleArray[scaleArray.length - 1] !== 100) {
17116                                     scaleArray.splice(scaleArray.length, 0, 100);
17117                                 }
17118                             }
17119                             function convertScaleArrayToPercentage() {
17120                                 if (scaleArray[scaleArray.length - 1] !== scope.options.to) {
17121                                     scaleArray.splice(scaleArray.length, 0, scope.options.to);
17122                                 }
17123
17124                                 if(scope.options.displayScaledvalues){
17125                                     for(var i in scaleArray){
17126                                         scaledUpValueArray.push(Math.log2(scaleArray[i]));
17127                                     }
17128                                     var maxScaledUpValue=scaledUpValueArray[scaledUpValueArray.length-1];
17129                                 }
17130
17131                                 for (var i in scaleArray) {
17132                                     var prcValue;
17133                                     var fromValueCheck = (scaleArray[i] / scope.options.from);
17134                                     var toValueCheck = (scaleArray[i] / scope.options.to);
17135
17136                                     if (scope.options.displayScaledvalues){
17137                                         prcValue = (scaledUpValueArray[i] /maxScaledUpValue)*100;
17138                                     } else {
17139                                         prcValue = ((scaleArray[i] - scope.options.from) / (scope.options.to - scope.options.from)) * 100;
17140                                     }
17141
17142                                     var realValue = scaleArray[i];
17143
17144                                     if (toValueCheck === 1) {
17145                                         prcValue = 100;
17146                                     }
17147                                     else if (fromValueCheck === 1) {
17148                                         prcValue = 0;
17149                                     }
17150                                     scaleArray[i] = prcValue;
17151                                     prcToValueMapper['' + prcValue] = realValue;
17152                                 }
17153                             }
17154                             if ((scope.options.from !== 0 || scope.options.to !== 100)
17155                                     && scope.options.smooth) {
17156                                 /*
17157                                  scale array is in real values.
17158                                  */
17159                                 addScaleArrayStartAndEnd();
17160                                 scope.options.stepWithDifferentScale = true;
17161                             }
17162                             else if ((scope.options.from !== 0 || scope.options.to !== 100)
17163                                     && !scope.options.smooth) {
17164                                 /*
17165                                  Case for different from and to values other than 0 and 100
17166                                  so we have to do some different calculations
17167                                  */
17168                                 scope.options.stepWithDifferentScale = true;
17169                                 convertScaleArrayToPercentage();
17170                                 addScaleArrayStartAndEnd();
17171                             }
17172                             else {
17173                                 /*
17174                                  This is the normal case where the from and to values are 0 and
17175                                  100 respectively.        
17176                                  */
17177                                 //Check that the scale starts at 0 and 100
17178                                 convertScaleArrayToPercentage();
17179                                 addScaleArrayStartAndEnd();
17180                             }
17181                             var decimalPlaces = 0;
17182                             if (scope.options.decimalPlaces) {
17183                                 decimalPlaces = scope.options.decimalPlaces;
17184                             }
17185                             //Modify the endDimension based on whether converison was passed in
17186                             //Also change the toStr value to scale to the last factor
17187                             scope.endDimension = scope.options.dimension;
17188                             if (scope.options.conversion) {
17189                                 //Get the dimension of the last conversion
17190                                 var lastIndex = scope.options.conversion.length - 1;
17191                                 var lastDimension = scope.options.conversion[lastIndex].dimension;
17192                                 var lastScaleFactor = scope.options.conversion[lastIndex].scaleFactor;
17193                                 scope.endDimension = ' ' + lastDimension;
17194
17195                                 var toVal = (scope.to / lastScaleFactor).toFixed(decimalPlaces);
17196                                 scope.toStr = toVal;
17197                             } else {
17198                                 scope.toStr = scope.options.to;
17199                             }
17200
17201                             var tooltipLabel = utils.convertToMbpsGbps(scope.toStr, scope.endDimension, scope.options.decimalPlaces);
17202                             scope.toStr = tooltipLabel.unitValue;
17203                             scope.endDimension = ' ' + tooltipLabel.unitLabel;
17204
17205                             var OPTIONS = {
17206                                 from: scope.options.from,
17207                                 to: scope.options.to,
17208                                 step: scope.options.step,
17209                                 smooth: scope.options.smooth,
17210                                 limits: true,
17211                                 stepWithDifferentScale: scope.options.stepWithDifferentScale,
17212                                 round: scope.options.round || false,
17213                                 value: ngModel.$viewValue,
17214                                 scale: scope.options.scale,
17215                                 nonPercentScaleArray: nonPercentScaleArray,
17216                                 prcToValueMapper: prcToValueMapper,
17217                                 firstDimension: scope.options.dimension,
17218                                 decimalPlaces: decimalPlaces,
17219                                 conversion: scope.options.conversion,
17220                                 realtimeCallback: scope.options.callback
17221                             };
17222                             if (angular.isFunction(scope.options.realtime)) {
17223                                 OPTIONS.realtimeCallback = function (value) {
17224                                     ngModel.$setViewValue(value);
17225                                     scope.options.callback(value);
17226                                 };
17227                             }
17228                             else {
17229                                 OPTIONS.callback = forceApply;
17230                             }
17231                             OPTIONS.calculate = scope.options.calculate || undefined;
17232                             OPTIONS.onstatechange = scope.options.onstatechange || undefined;
17233                             timeout(function () {
17234                                 var scaleDiv = scope.tmplElt.find('div')[7];
17235                                 if (!OPTIONS.conversion) {
17236                                     scope.tmplElt.find('div').eq(6).find('span').eq(0).css('padding-left', '10px');
17237                                     scope.tmplElt.find('div').eq(6).find('span').eq(0).css('padding-right', '15px');
17238                                 }
17239                                 scope.slider = angular.element.slider(element, scope.tmplElt, OPTIONS);
17240                                 angular.element(scaleDiv).html(scope.generateScale());
17241                                 scope.drawScale(scaleDiv);
17242                                 initListener();
17243                                 scope.$watch('options.disable', function (val) {
17244                                     if (scope.slider) {
17245                                         scope.tmplElt.toggleClass('disabled', val);
17246                                         scope.slider.disable(val);
17247                                     }
17248                                 });
17249                                 scope.$watch('cutOff', function (cutOffVal) {
17250                                     if (cutOffVal && cutOffVal > 0) {
17251                                         var cutOffPrc = (cutOffVal - scope.slider.settings.from) / (scope.slider.settings.to -
17252                                                 scope.slider.settings.from);
17253                                         cutOffPrc = cutOffPrc * 100;
17254                                         scope.isCutOffSlider = true;
17255                                         scope.slider.settings.cutOffWidth = cutOffPrc;
17256                                         //cutOffVal is the actual value of the cutoff point
17257                                         scope.cutOffVal = cutOffVal;
17258                                         if (scope.options.conversion) {
17259                                             var convertedVal = utils.getConversionFactorValue(cutOffVal, scope.options.conversion, scope.options.dimension);
17260                                             convertedVal.scaledVal = parseFloat(convertedVal.scaledVal).toFixed(scope.options.decimalPlaces);
17261                                             scope.cutOffVal = convertedVal.scaledVal + ' ' + convertedVal.scaledDimension;
17262                                         }
17263                                         scope.slider.settings.cutOffVal = cutOffVal;
17264                                         //Calculate the cutOff percentage
17265                                         scope.slider.changeCutOffWidth(cutOffPrc + '%');
17266                                         var scale = scope.slider.settings.nonPercentScaleArray;
17267                                         //Calculate where the cutOff point in relation to the scale array
17268                                         for (var i in scale) {
17269                                             if (i >= 1) {
17270                                                 var lowerVal = scale[i - 1];
17271                                                 var higherVal = scale[i];
17272                                                 if (cutOffVal > lowerVal && cutOffVal <= higherVal) {
17273                                                     scope.slider.settings.cutOffIndex = i;
17274                                                 }
17275                                             }
17276                                         }
17277                                     } else {
17278                                         scope.slider.settings.cutOffVal = 0;
17279                                     }
17280                                 });
17281                             });
17282                         };
17283                         function initListener() {
17284                             angular.element(win).bind('resize', function (event) {
17285                                 scope.slider.onresize();
17286                             });
17287                         }
17288                         scope.generateScale = function () {
17289                             if (scope.options.scale && scope.options.scale.length > 0) {
17290                                 var str = "";
17291                                 var s = scope.options.scale;
17292                                 var position = 'left';
17293                                 for (var i = 0; i < s.length; i++) {
17294                                     if (i !== 0 && i !== s.length - 1) {
17295                                         var scaledPosition = ((s[i] - scope.from) / (scope.to - scope.from)) * 100;
17296                                         if (scope.options.stepWithDifferentScale && !scope.options.smooth) {
17297                                             scaledPosition = s[i];
17298                                         }
17299                                         str += '<span style="' + position + ': ' + scaledPosition + '%"></span>';
17300                                     }
17301                                 }
17302                                 return str;
17303                             } else
17304                                 return "";
17305                             return "";
17306                         };
17307                         scope.drawScale = function (scaleDiv) {
17308                             angular.forEach(angular.element(scaleDiv).find('ins'), function (scaleLabel, key) {
17309                                 scaleLabel.style.marginLeft = -scaleLabel.clientWidth / 2;
17310                             });
17311                         };
17312                         var forceApply = function (value) {
17313                             var val = value.split(";")[1];
17314                             scope.$apply(function () {
17315                                 ngModel.$setViewValue(parseInt(val));
17316                             });
17317                             if (scope.options.callback) {
17318                                 scope.options.callback(parseInt(val));
17319                             }
17320                         };
17321                         scope.$watch('options', function (value) {
17322                             init();
17323                         });
17324                         angular.element.slider = function (inputElement, element, settings) {
17325                             if (!element.data('jslider'))
17326                                 element.data('jslider', new Slider(inputElement, element, settings));
17327                             var sliderObj = element.data('jslider');
17328                             return sliderObj;
17329                         };
17330                     }
17331                 };
17332             }]);
17333 angular.module('att.abs.steptracker', ['att.abs.transition'])
17334         .directive('steptracker', ['$timeout', function ($timeout) {
17335                 return {
17336                     // This allows dev's clickHandler to cancel an operation
17337                     priority: 100,
17338                     scope: {
17339                         sdata: "=sdata",
17340                         cstep: "=currentStep",
17341                         clickHandler: '=?',
17342                         disableClick: '=?'
17343                     },
17344                     restrict: 'EA',
17345                     replace: true,
17346                     templateUrl: 'app/scripts/ng_js_att_tpls/steptracker/step-tracker.html',
17347                     link: function (scope, elem) {
17348                         if (scope.disableClick === undefined) {
17349                             scope.disableClick = false;
17350                         }
17351                         $timeout(function () {
17352                             if (scope.cstep < 1) {
17353                                 scope.cstep = 1;
17354                             }
17355                             else if (scope.cstep > scope.sdata.length) {
17356                                 scope.cstep = scope.sdata.length;
17357                             }
17358                             var divs = elem.find('div');
17359                             var slidertracks = [];
17360                             for (var i in divs) {
17361                                 if (divs.eq(i)[0]) {
17362                                     var el = divs.eq(i)[0].className;
17363                                     if (el.indexOf('track ng-scope') > -1) {
17364                                         slidertracks.push(divs.eq(i));
17365                                     }
17366                                 }
17367                             }
17368                             var currentPage,totalPage,currentTrack = updateCurrentTrack(scope.cstep);
17369                             function updateCurrentTrack(step) {
17370                                 // Always return the step-1 because array starts at 0
17371                                 return angular.element(slidertracks[step - 1]);
17372                             }
17373                             function updateTrackWidth() {
17374                                 if (scope.cstep > 0 && scope.cstep <= scope.sdata.length - 1 && currentPage > 0) {
17375                                     var newWidth = ((currentPage / totalPage) * 100) + "%";
17376                                     currentTrack = updateCurrentTrack(scope.cstep);
17377                                     currentTrack.css('width', newWidth);
17378                                 }
17379                             }
17380                             function updatePages() {
17381                                 if (scope.cstep <= scope.sdata.length) {
17382                                     currentPage = scope.sdata[scope.cstep - 1]['currentPage'];
17383                                     totalPage = scope.sdata[scope.cstep - 1]['totalPages'];
17384                                 }
17385                             }
17386                             // dynamically add width for steps, depending on the number of steps.
17387                             scope.set_width = function (indexval) {
17388                                 var setwidth = (100 / (scope.sdata.length - 1)) + "%";
17389                                 // skip last element and add width for all other element
17390                                 if ((scope.sdata.length - 1) > indexval) {
17391                                     return {'width': setwidth};
17392                                 }
17393                             };
17394                             scope.$watch('sdata', function () {
17395                                 updatePages();
17396                                 var prevStep = scope.cstep;
17397                                 // Before anything, ensure currentPage is never below 1
17398                                 if (currentPage < 1) {
17399                                     currentPage = 1;
17400                                     if (scope.cstep !== 1) {
17401                                         // Decrease step, current track width is 0%, new step width updates
17402                                         scope.cstep--;
17403                                         updatePages();
17404                                     }
17405                                 }
17406                                 // Move to next step, reset currentPage, totalPage, and ensure previous steps are completed
17407                                 if (currentPage > totalPage) {
17408                                     if (scope.cstep > scope.sdata.length - 1) {
17409                                         scope.cstep++;
17410                                         return;
17411                                     } else {
17412                                         currentPage = totalPage;
17413                                         updateTrackWidth();
17414                                         scope.cstep++;
17415                                         updatePages();
17416                                         updateTrackWidth();
17417                                     }
17418                                 }
17419                                 if (currentPage < 1 && prevStep === scope.cstep) {
17420                                     currentPage = 1;
17421                                     if (scope.cstep > 1) {
17422                                         scope.cstep--;
17423                                         scope.sdata[scope.cstep - 1]['currentPage'] = scope.sdata[scope.cstep - 1]['totalPages'];
17424                                         scope.sdata[scope.cstep]['currentPage'] = 1;
17425                                     }
17426                                 }
17427                                 updateTrackWidth();
17428                             }, true);
17429                             //add the active class for current step
17430                             scope.activestep = function (index) {
17431                                 return (index === scope.cstep - 1);
17432                             };
17433                             //add the done class for finished step
17434                             scope.donesteps = function (index) {
17435                                 return (index < scope.cstep - 1);
17436                             };
17437                             //add the last class for final step
17438                             scope.laststep = function (index) {
17439                                 return (index === scope.sdata.length - 1);
17440                             };
17441                             scope.isIncomplete = function (index) {
17442                                 if (index === scope.cstep - 1) {
17443                                     return false;
17444                                 }
17445                                 if (index >= 0 && index < scope.sdata.length - 1) {
17446                                     var step = scope.sdata[index];
17447                                     return (step['currentPage'] <= step['totalPages']);
17448                                 }
17449                             };
17450                             //click event
17451                             scope.stepclick = function ($event, steps) {
17452                                 // If we are decreasing steps, reset all currentPage counts to 1
17453                                 if (steps < scope.cstep) {
17454                                     for (var i = scope.cstep - 1; i > steps; i--) {
17455                                         scope.sdata[i]['currentPage'] = 1;
17456                                     }
17457                                     scope.sdata[steps]['currentPage']--;
17458                                 }
17459                                 if (angular.isFunction(scope.clickHandler)) {
17460                                     scope.clickHandler($event, steps);
17461                                 }
17462                                 scope.cstep = steps + 1;
17463                                 // In the case we decremented previously from this step, we need to reset currentpage to default
17464                                 if (scope.cstep <= scope.sdata.length && scope.sdata[scope.cstep]['currentPage'] < 1) {
17465                                     scope.sdata[scope.cstep]['currentPage'] = 1;
17466                                 }
17467                                 updatePages();
17468                                 updateTrackWidth();
17469                             };
17470                         }, 100);
17471                     }
17472                 };
17473             }
17474         ])
17475         .constant('timelineConstants', {
17476             STEP_TYPE: {
17477                 ALERT: 'alert',
17478                 COMPLETED: 'completed',
17479                 CANCELLED: 'cancelled'
17480             }
17481         })
17482         .controller('AttTimelineCtrl', ['$scope', '$timeout', function ($scope, $timeout) {
17483                 var timelineBarCtrls = [];
17484                 var timelineDotCtrls = [];
17485                 this.numSteps = 0;
17486                 this.isAlternate = function () {
17487                     return $scope.alternate;
17488                 };
17489                 this.addTimelineBarCtrls = function (t) {
17490                     timelineBarCtrls.push(t);
17491                 };
17492                 this.addTimelineDotCtrls = function (b) {
17493                     timelineDotCtrls.push(b);
17494                 };
17495                 $timeout(init, 200);
17496                 function init() {
17497                     function compare(a, b) {
17498                         if (a.order < b.order) {
17499                             return -1;
17500                         }
17501                         if (a.order > b.order) {
17502                             return 1;
17503                         }
17504                         return 0;
17505                     }
17506                     timelineDotCtrls.sort(compare);
17507                     timelineBarCtrls.sort(compare);
17508                     if ($scope.$parent.animate) {
17509                         animateSequence();
17510                     }
17511                     $scope.$watch('trigger', function (val) {
17512                         if (val) {
17513                             $scope.resetTimeline();
17514                         } else {
17515                             $scope.$parent.animate = false;
17516                         }
17517                     });
17518                 }
17519                 function animateSequence() {
17520                     var dotsDuration = .25;
17521                     var timelineBarProgressDuration = .25;
17522                     if (typeof $scope.barAnimateDuration === 'number') {
17523                         timelineBarProgressDuration = $scope.barAnimateDuration;
17524                     }
17525                     var start = createAnimation(0, timelineBarProgressDuration);
17526                     function setToInactiveStates() {
17527                         for (var i in timelineDotCtrls) {
17528                             var dotCtrl = timelineDotCtrls[i];
17529                             if (i % 2 === 0) {
17530                                 dotCtrl.unhoveredStateForBelow(.25);
17531                             } else {
17532                                 dotCtrl.unhoveredStateForAbove(.25);
17533                             }
17534                             if (dotCtrl.isStop()) {
17535                                 break;
17536                             }
17537                         }
17538                     }
17539                     function createAnimation(i, duration) {
17540                         if (i === 0) {
17541                             return function () {
17542                                 if (timelineDotCtrls[i + 1].isStop() && timelineDotCtrls[i + 1].isCancelled()) {
17543                                     timelineBarCtrls[i].isCancelled(true);
17544                                 }
17545                                 timelineBarCtrls[i].animate(createAnimation(i + 1, duration), duration);
17546                             };
17547                         } else if (i === timelineBarCtrls.length - 1) {
17548                             return function () {
17549                                 //Removes the bolded text from the start
17550                                 if (timelineDotCtrls[0].isCurrentStep()) {
17551                                     timelineDotCtrls[0].isCurrentStep(false);
17552                                 }
17553                                 if (timelineDotCtrls[i].isStop()) {
17554                                     timelineDotCtrls[i - 1].shrinkAnimate(dotsDuration);
17555                                     timelineDotCtrls[i].isCurrentStep(true);
17556                                 } else {
17557                                     timelineDotCtrls[i - 1].shrinkAnimate(dotsDuration);
17558                                     timelineBarCtrls[i].animate(createAnimation(i + 1, duration), duration);
17559                                 }
17560                                 timelineDotCtrls[i].expandedAnimate(dotsDuration);
17561                                 $timeout(function () {
17562                                     setToInactiveStates();
17563                                 }, 500);
17564                             };
17565                         }
17566                         //End Dot
17567                         else if (i === timelineBarCtrls.length) {
17568                             return function () {
17569                                 //Removes the bolded text from the start
17570                                 if (timelineDotCtrls[0].isCurrentStep()) {
17571                                     timelineDotCtrls[0].isCurrentStep(false);
17572                                 }
17573                                 timelineDotCtrls[i - 1].shrinkAnimate(dotsDuration);
17574                                 timelineDotCtrls[i].expandedAnimate(dotsDuration);
17575                                 timelineDotCtrls[i].isCurrentStep(true);
17576                                 $timeout(function () {
17577                                     setToInactiveStates();
17578                                 }, 500);
17579                             };
17580                         }
17581                         else {
17582                             return function () {
17583                                 //Removes the bolded text from the start
17584                                 if (timelineDotCtrls[0].isCurrentStep()) {
17585                                     timelineDotCtrls[0].isCurrentStep(false);
17586                                 }
17587                                 if (timelineDotCtrls[i].isStop()) {
17588                                     timelineDotCtrls[i - 1].shrinkAnimate(dotsDuration);
17589                                     timelineDotCtrls[i].expandedAnimate(dotsDuration);
17590                                     timelineDotCtrls[i].isCurrentStep(true);
17591                                     $timeout(function () {
17592                                         setToInactiveStates();
17593                                     }, 500);
17594                                 } else {
17595                                     if (timelineDotCtrls[i + 1].isStop() && timelineDotCtrls[i + 1].isCancelled()) {
17596                                         timelineBarCtrls[i].isCancelled(true);
17597                                     }
17598                                     timelineDotCtrls[i - 1].shrinkAnimate(dotsDuration);
17599                                     timelineBarCtrls[i].animate(createAnimation(i + 1, duration), duration);
17600                                     timelineDotCtrls[i].expandedAnimate(dotsDuration);
17601                                 }
17602                             };
17603                         }
17604                     }
17605                     start();
17606                 }
17607             }])
17608         .directive('attTimeline', ['$timeout', '$compile', function ($timeout, $compile) {
17609                 return {
17610                     restrict: 'EA',
17611                     replace: true,
17612                     scope: {
17613                         steps: '=',
17614                         trigger: '=',
17615                         alternate: '=',
17616                         barAnimateDuration: '='
17617                     },
17618                     templateUrl: 'app/scripts/ng_js_att_tpls/steptracker/timeline.html',
17619                     controller: 'AttTimelineCtrl',
17620                     link: function (scope, element, attrs, ctrl) {
17621                         var init = function () {
17622                             var steps = scope.steps;
17623                             var middleSteps = [];
17624                             for (var i = 1; i < steps.length; i++) {
17625                                 var aStep = steps[i];
17626                                 middleSteps.push(aStep);
17627                             }
17628                             scope.middleSteps = middleSteps;
17629                             //Used in calculating the width of the loading bars
17630                             ctrl.numSteps = steps.length - 1;
17631                         };
17632                         init();
17633                         //Recompile in case of scope changes
17634                         scope.resetTimeline = function () {
17635                             scope.animate = true;
17636                             $compile(element)(scope);
17637                         };
17638                     }
17639                 };
17640             }])
17641         .controller('TimelineBarCtrl', ['$scope', function ($scope) {
17642                 this.type = 'timelinebar';
17643                 this.order = parseInt($scope.order);
17644                 this.animate = function (callback, duration) {
17645                     $scope.loadingAnimation(callback, duration);
17646                 };
17647                 this.isCancelled = function (isCancelled) {
17648                     $scope.isCancelled = isCancelled;
17649                 };
17650             }])
17651         .directive('timelineBar', ['animation', '$progressBar', function (animation, $progressBar) {
17652                 return {
17653                     restrict: 'EA',
17654                     replace: true,
17655                     templateUrl: 'app/scripts/ng_js_att_tpls/steptracker/timelineBar.html',
17656                     scope: {
17657                         order: '@'
17658                     },
17659                     require: ['^attTimeline', 'timelineBar'],
17660                     controller: 'TimelineBarCtrl',
17661                     link: function (scope, element, attrs, ctrls) {
17662                         var attTimelineCtrl = ctrls[0];
17663                         var timelineBarCtrl = ctrls[1];
17664                         attTimelineCtrl.addTimelineBarCtrls(timelineBarCtrl);
17665                         scope.isCompleted = true;
17666                         var widthPerc = (100 / attTimelineCtrl.numSteps) - 3;
17667                         element.css('width', widthPerc + '%');
17668                         var elem = element.find('div').eq(0);
17669                         animation.set(elem, {opacity: 0.0});
17670                         var updateCallback = function (selfElement) {
17671                             animation.set(elem, {opacity: 1.0});
17672                             animation.set(elem, {
17673                                 scaleX: selfElement.progress(),
17674                                 transformOrigin: "left"
17675                             });
17676                         };
17677                         scope.loadingAnimation = $progressBar(updateCallback);
17678                     }
17679                 };
17680             }])
17681         .controller('TimelineDotCtrl', ['$scope', '$timeout', 'timelineConstants', function ($scope, $timeout, timelineConstants) {
17682                 this.type = 'dot';
17683                 this.order = parseInt($scope.order);
17684                 var self = this;
17685                 $timeout(function () {
17686                     if (self.order !== 0) {
17687                         if (self.order % 2 !== 0) {
17688                             $scope.initializeAboveForAnimation();
17689                         }
17690                         else {
17691                             $scope.initializeBelowForAnimation();
17692                         }
17693                     }
17694                 });
17695                 this.expandedAnimate = function (duration) {
17696                     $scope.setColor();
17697                     $scope.expandedAnimate(duration);
17698                     if (self.order !== 0 && !$scope.isStepsLessThanFive()) {
17699                         if (self.order % 2 !== 0) {
17700                             $scope.expandContentForAbove(duration);
17701                         } else {
17702                             $scope.expandContentForBelow(duration);
17703                         }
17704                     }
17705                 };
17706                 this.unhoveredStateForAbove = function (duration) {
17707                     $scope.unhoveredStateForAbove(duration);
17708                 };
17709                 this.unhoveredStateForBelow = function (duration) {
17710                     $scope.unhoveredStateForBelow(duration);
17711                 };
17712                 this.shrinkAnimate = function (duration) {
17713                     $scope.shrinkAnimate(duration);
17714                 };
17715                 this.setExpanded = function () {
17716                     $scope.setSize(3);
17717                 };
17718                 this.isStop = function () {
17719                     return $scope.isStop;
17720                 };
17721                 this.isCancelled = function () {
17722                     return ($scope.type === timelineConstants.STEP_TYPE.CANCELLED);
17723                 };
17724                 this.isAlert = function () {
17725                     return ($scope.type === timelineConstants.STEP_TYPE.ALERT);
17726                 };
17727                 //Sets the bolded text
17728                 this.isCurrentStep = function (isCurrentStep) {
17729                     if (isCurrentStep !== undefined) {
17730                         $scope.isCurrentStep = isCurrentStep;
17731                     }
17732                     return $scope.isCurrentStep;
17733                 };
17734             }])
17735         .directive('timelineDot', ['animation', 'timelineConstants',
17736             function (animation, timelineConstants) {
17737                 return {
17738                     restrict: 'EA',
17739                     replace: true,
17740                     scope: {
17741                         order: '@',
17742                         title: '@',
17743                         description: '@',
17744                         by: '@',
17745                         date: '@',
17746                         type: '@'
17747                     },
17748                     templateUrl: 'app/scripts/ng_js_att_tpls/steptracker/timelineDot.html',
17749                     require: ['^attTimeline', 'timelineDot'],
17750                     controller: 'TimelineDotCtrl',
17751                     link: function (scope, element, attrs, ctrls) {
17752                         var attTimelineCtrl = ctrls[0];
17753                         var timelineDotCtrl = ctrls[1];
17754                         attTimelineCtrl.addTimelineDotCtrls(timelineDotCtrl);
17755                         scope.numSteps = attTimelineCtrl.numSteps + 1;
17756                         scope.isCurrentStep = false;
17757                         scope.isCompleted = false;
17758                         scope.isStop = false;
17759                         if (scope.type === timelineConstants.STEP_TYPE.ALERT || scope.type === timelineConstants.STEP_TYPE.CANCELLED) {
17760                             scope.isStop = true;
17761                         }
17762                         scope.isInactive = true;
17763                         var divs = element.find('div');
17764                         var biggerCircleElem = divs.eq(0);
17765                         var expandableCircleElem = divs.eq(2);
17766                         var infoboxElem = divs.eq(3);
17767                         var titleElem = divs.eq(5);
17768                         var contentElem = divs.eq(6);
17769                         var dateElem = divs.eq(9);
17770                         function isEmptyStep() {
17771                             if (!scope.description && !scope.by && !scope.date) {
17772                                 return true;
17773                             }
17774                             return false;
17775                         }
17776                         scope.isStepsLessThanFive = function () {
17777                             if (scope.numSteps < 5) {
17778                                 return true;
17779                             }
17780                             return false;
17781                         };
17782                         scope.titleMouseover = function (num) {
17783                             if (!scope.isStepsLessThanFive() && !isEmptyStep()) {
17784                                 if (num === 1 && scope.order % 2 === 0) {
17785                                     scope.expandContentForBelow(.25);
17786                                 }
17787                                 if (num === 2 && scope.order % 2 !== 0) {
17788                                     scope.expandContentForAbove(.25);
17789                                 }
17790                             }
17791                         };
17792                         scope.titleMouseleave = function () {
17793                             if (scope.order % 2 === 0) {
17794                                 scope.unhoveredStateForBelow(.25);
17795                             }
17796                             else {
17797                                 scope.unhoveredStateForAbove(.25);
17798                             }
17799                         };
17800                         scope.initializeAboveForAnimation = function () {
17801                             if (!scope.isStepsLessThanFive() && attTimelineCtrl.isAlternate()) {
17802                                 animation.set(contentElem, {opacity: 0});
17803                                 animation.set(dateElem, {opacity: 0});
17804                                 if (!isEmptyStep()) {
17805                                     var yOffset = contentElem[0].offsetHeight + dateElem[0].offsetHeight;
17806                                     animation.set(titleElem, {'top': yOffset});
17807                                 }
17808                             }
17809                         };
17810                         scope.expandContentForAbove = function (duration) {
17811                             if (!scope.isStepsLessThanFive() && attTimelineCtrl.isAlternate()) {
17812                                 animation.to(titleElem, duration, {'top': 0});
17813                                 animation.to(contentElem, duration, {opacity: 1});
17814                                 animation.to(dateElem, duration, {opacity: 1});
17815                             }
17816                         };
17817                         scope.unhoveredStateForAbove = function (duration) {
17818                             if (!scope.isStepsLessThanFive() && attTimelineCtrl.isAlternate()) {
17819                                 animation.set(contentElem, {opacity: 0});
17820                                 animation.set(dateElem, {opacity: 1});
17821                                 var yOffset = contentElem[0].offsetHeight;
17822                                 animation.to(titleElem, duration, {'top': yOffset});
17823                             }
17824                         };
17825                         scope.initializeBelowForAnimation = function () {
17826                             if (!scope.isStepsLessThanFive() && attTimelineCtrl.isAlternate()) {
17827                                 animation.set(contentElem, {height: '0%', opacity: 0, top: '-20px'});
17828                                 animation.set(dateElem, {opacity: 0});
17829                             }
17830                         };
17831                         scope.expandContentForBelow = function (duration) {
17832                             if (!scope.isStepsLessThanFive() && attTimelineCtrl.isAlternate()) {
17833                                 animation.set(dateElem, {opacity: 1});
17834                                 animation.to(contentElem, duration, {height: 'auto', opacity: 1, top: '0px'});
17835                             }
17836                         };
17837                         scope.unhoveredStateForBelow = function (duration) {
17838                             if (!scope.isStepsLessThanFive() && attTimelineCtrl.isAlternate()) {
17839                                 animation.to(contentElem, duration, {height: '0%', opacity: 0, top: '-20px', position: 'relative'});
17840                                 animation.set(dateElem, {opacity: 1});
17841                             }
17842                         };
17843                         /*Default Initializaztion*/
17844                         //If the info box is above and the description and date and by are empty then we have do reset its position
17845                         if (isEmptyStep() && (scope.order % 2 !== 0 && attTimelineCtrl.isAlternate())) {
17846                             infoboxElem.css('top', '-47px');
17847                         }
17848                         //Check if the order is odd and set the appropiate above or below and other effects
17849                         if (scope.order % 2 === 0 || !attTimelineCtrl.isAlternate()) {
17850                             scope.isBelowInfoBoxShown = true;
17851                         }
17852                         else {
17853                             scope.isBelowInfoBoxShown = false;
17854                         }
17855                         //modify some css for steps less than 5 and not alternating
17856                         if (scope.isStepsLessThanFive() && !attTimelineCtrl.isAlternate()) {
17857                             animation.set(dateElem, {marginTop: 10});
17858                         }
17859                         //For IE 8 fix
17860                         animation.set(biggerCircleElem, {opacity: '.5'});
17861                         //shrink the expandableCircle to we can expand it later
17862                         animation.set(expandableCircleElem, {opacity: '0.0'});
17863                         animation.set(expandableCircleElem, {scale: .10});
17864                         if (scope.order === 0) {
17865                             animation.set(expandableCircleElem, {opacity: '1.0'});
17866                             animation.set(expandableCircleElem, {scale: 1});
17867                             animation.set(biggerCircleElem, {scale: 3});
17868                             scope.isCurrentStep = true;
17869                             scope.isInactive = false;
17870                             scope.isCompleted = true;
17871                         }
17872                         scope.setColor = function () {
17873                             scope.isInactive = false;
17874                             if (scope.type === timelineConstants.STEP_TYPE.CANCELLED) {
17875                                 scope.isCancelled = true;
17876                             }
17877                             else if (scope.type === timelineConstants.STEP_TYPE.ALERT) {
17878                                 scope.isAlert = true;
17879                             }
17880                             else {
17881                                 scope.isCompleted = true;
17882                             }
17883                             if (!scope.$phase) {
17884                                 scope.$apply();
17885                             }
17886                         };
17887                         scope.setSize = function (size) {
17888                             animation.set(biggerCircle, {scale: size});
17889                         };
17890                         scope.setExpandedCircle = function () {
17891                             animation.set(expandableCircleElem, {opacity: '1.0'});
17892                             animation.set(expandableCircleElem, {scale: 1});
17893                         };
17894                         scope.expandedAnimate = function (duration) {
17895                             animation.to(biggerCircleElem, duration, {scale: 3});
17896                             animation.set(expandableCircleElem, {opacity: '1.0'});
17897                             animation.to(expandableCircleElem, duration, {scale: 1});
17898                         };
17899                         scope.shrinkAnimate = function (duration) {
17900                             animation.to(biggerCircleElem, duration, {scale: 1});
17901                         };
17902                     }
17903                 };
17904             }]);
17905 angular.module('att.abs.table', ['att.abs.utilities'])
17906 .constant('tableConfig', {
17907     //true for descending & false for ascending
17908     defaultSortPattern: false,
17909     highlightSearchStringClass: 'tablesorter-search-highlight'
17910 })
17911
17912 .directive('attTable', ['$filter', function($filter) {
17913     return {
17914         restrict: 'EA',
17915         replace: true,
17916         transclude: true,
17917         scope: {
17918             tableData: "=",
17919             viewPerPage: "=",
17920             currentPage: "=",
17921             totalPage: "=",
17922             searchCategory: "=",
17923             searchString: "="
17924         },
17925         require: 'attTable',
17926         templateUrl: 'app/scripts/ng_js_att_tpls/table/attTable.html',
17927         controller: ['$scope', function($scope) {
17928             this.headers = [];
17929             this.currentSortIndex = null;
17930             this.setIndex = function(headerScope) {
17931                 this.headers.push(headerScope);
17932             };
17933             this.getIndex = function(headerName) {
17934                 for (var i = 0; i < this.headers.length; i++) {
17935                     if (this.headers[i].headerName === headerName) {
17936                         return this.headers[i].index;
17937                     }
17938                 }
17939                 return null;
17940             };
17941             this.sortData = function(columnIndex, reverse) {
17942                 $scope.$parent.columnIndex = columnIndex;
17943                 $scope.$parent.reverse = reverse;
17944                 this.currentSortIndex = columnIndex;
17945                 $scope.currentPage = 1;
17946                 this.resetSortPattern();
17947             };
17948             this.getSearchString = function() {
17949                 return $scope.searchString;
17950             };
17951             this.resetSortPattern = function() {
17952                 for(var i = 0; i < this.headers.length; i++) {
17953                     var currentScope = this.headers[i];
17954                     if(currentScope.index !== this.currentSortIndex) {
17955                         currentScope.resetSortPattern();
17956                     }
17957                 }
17958             };
17959         }],
17960         link: function(scope, elem, attr, ctrl) {
17961             scope.searchCriteria = {};
17962             scope.$watchCollection('tableData', function(value) {
17963                 if(value && !isNaN(value.length)) {
17964                     scope.totalRows = value.length;
17965                 }
17966             });
17967             scope.$watch('currentPage', function(val) {
17968                 scope.$parent.currentPage = val;
17969             });
17970             scope.$watch('viewPerPage', function(val) {
17971                 scope.$parent.viewPerPage = val;
17972             });
17973             scope.$watch(function() {
17974                 return scope.totalRows / scope.viewPerPage;
17975             }, function(value) {
17976                 if(!isNaN(value)) {
17977                     scope.totalPage = Math.ceil(value);
17978                     scope.currentPage = 1;
17979                 }
17980             });
17981             var searchValCheck = function(val){
17982                 if(angular.isDefined(val) && val !== null && val !== ""){
17983                     return true;
17984                 }
17985             };
17986             var setSearchCriteria = function(v1,v2){
17987                 if(searchValCheck(v1) && searchValCheck(v2)){
17988                     var index = ctrl.getIndex(v2);
17989                     scope.searchCriteria = {};
17990                     if (index !== null) {
17991                         scope.searchCriteria[index] = v1;
17992                     }
17993                 }else if(searchValCheck(v1) && (!angular.isDefined(v2) || v2 === null || v2 === "")){
17994                     scope.searchCriteria = {
17995                         $: v1
17996                     };
17997                 }else {
17998                     scope.searchCriteria = {};
17999                 }
18000             };
18001             scope.$watch('searchCategory', function(newVal,oldVal) {
18002                 if(newVal !== oldVal){
18003                     setSearchCriteria(scope.searchString,newVal);
18004                 }
18005             });
18006             scope.$watch('searchString', function (newVal,oldVal) {
18007                 if(newVal !== oldVal){
18008                     setSearchCriteria(newVal,scope.searchCategory);
18009                 }
18010             });
18011             scope.$watchCollection('searchCriteria', function(val) {
18012                 scope.$parent.searchCriteria = val;
18013                 scope.totalRows = scope.tableData && ($filter('filter')(scope.tableData, val, false)).length || 0;
18014                 scope.currentPage = 1;
18015             });
18016         }
18017     };
18018 }])
18019
18020 .directive('attTableRow', [function() {
18021     return {
18022         restrict: 'EA',
18023         compile: function (elem, attr) {
18024             if (attr.type === 'header') {
18025                 elem.find('tr').eq(0).addClass('tablesorter-headerRow');
18026             } else if (attr.type === 'body') {
18027                 var html = elem.children();
18028                 if(attr.rowRepeat){
18029                     if (attr.trackBy) {
18030                         html.attr('ng-repeat', attr.rowRepeat.concat(" | orderBy : columnIndex : reverse | filter : searchCriteria : false | attLimitTo : viewPerPage : viewPerPage*(currentPage-1) track by " + attr.trackBy));
18031                     } else {
18032                         html.attr('ng-repeat', attr.rowRepeat.concat(" | orderBy : columnIndex : reverse | filter : searchCriteria : false | attLimitTo : viewPerPage : viewPerPage*(currentPage-1) track by $index"));
18033                     }
18034                 }
18035                 html.attr('ng-class', "{'alt-row': $even,'normal-row': $odd}");
18036                 elem.append(html);
18037             }
18038         }
18039     };
18040 }])
18041
18042 .directive('attTableHeader', ['tableConfig', function(tableConfig) {
18043     return {
18044         restrict: 'EA',
18045         replace: true,
18046         transclude: true,
18047         scope: {
18048             sortable: '@',
18049             defaultSort: '@',
18050             index: '@key'
18051         },
18052         require: '^attTable',
18053         templateUrl: 'app/scripts/ng_js_att_tpls/table/attTableHeader.html',
18054         link: function(scope, elem, attr, ctrl) {
18055             var reverse = tableConfig.defaultSortPattern;
18056             scope.headerName = elem.text();
18057             scope.sortPattern = null;
18058             ctrl.setIndex(scope);
18059
18060             scope.$watch(function() {
18061                 return elem.text();
18062             }, function(value) {
18063                 scope.headerName = value;
18064             });
18065             scope.sort = function(sortType) {
18066                 if(typeof sortType === 'boolean') {
18067                     reverse = sortType;
18068                 }
18069                 ctrl.sortData(scope.index, reverse);
18070                 scope.sortPattern = reverse ? 'desc' : 'asc';
18071                 reverse = !reverse;
18072             };
18073             scope.$watch(function() {
18074                 return ctrl.currentSortIndex;
18075             }, function(value) {
18076                 if (value !== scope.index) {
18077                     scope.sortPattern = null;
18078                 }
18079             });
18080             if(scope.sortable !== 'false') {
18081                 if(scope.defaultSort === 'A' || scope.defaultSort === 'a') {
18082                     scope.sort(false);
18083                 } else if(scope.defaultSort === 'D' || scope.defaultSort === 'd') {
18084                     scope.sort(true);
18085                 }
18086             }
18087             scope.resetSortPattern = function() {
18088                 reverse = tableConfig.defaultSortPattern;
18089             };
18090         }
18091     };
18092 }])
18093
18094 .directive('attTableBody', ['$filter', '$timeout', 'tableConfig', function($filter, $timeout, tableConfig) {
18095     return {
18096         restrict: 'EA',
18097         require: '^attTable',
18098         replace: true,
18099         transclude: true,
18100         templateUrl: 'app/scripts/ng_js_att_tpls/table/attTableBody.html',
18101         link: function (scope, elem, attr, ctrl) {
18102             var highlightSearchStringClass = tableConfig.highlightSearchStringClass;
18103             var searchString = "";
18104             var wrapElement = function (elem) {
18105                 var text = elem.text();
18106                 elem.html($filter('highlight')(text, searchString, highlightSearchStringClass));
18107             };
18108             var traverse = function (elem) {
18109                 var innerHtml = elem.children();
18110                 if (innerHtml.length > 0) {
18111                     for (var i = 0; i < innerHtml.length; i++) {
18112                         traverse(innerHtml.eq(i));
18113                     }
18114                 } else {
18115                     wrapElement(elem);
18116                     return;
18117                 }
18118             };
18119             var clearWrap = function (elem) {
18120                 var elems = elem.find('*');
18121                 for (var i = 0; i < elems.length; i++) {
18122                     if (elems.eq(i).attr('class') && elems.eq(i).attr('class').indexOf(highlightSearchStringClass) !== -1) {
18123                         var text = elems.eq(i).text();
18124                         elems.eq(i).replaceWith(text);
18125                     }
18126                 }
18127             };
18128             $timeout(function () {
18129                 var actualHtml = elem.children();
18130                 scope.$watch(function () {
18131                     return ctrl.getSearchString();
18132                 }, function (val) {
18133                     searchString = val;
18134                     clearWrap(elem);
18135                     if (actualHtml.length > 0) {
18136                         traverse(elem);
18137                     } else {
18138                         wrapElement(elem);
18139                     }
18140                 });
18141             }, 50);
18142         }
18143     };
18144 }]);
18145
18146 angular.module('att.abs.tableMessages', ['att.abs.utilities'])
18147     .constant('messageConstants', {
18148             TABLE_MESSAGE_TYPES: {
18149                 noMatching: 1,
18150                 errorLoading: 2,
18151                 magnifySearch: 3,
18152                 isLoading: 4},
18153         USER_MESSAGE_TYPES: {
18154             success: 1,
18155             error: 0
18156             }
18157         })
18158         .directive('attTableMessage', ['messageConstants', function(messageConstants) {
18159                 return {
18160                     restrict: 'AE',
18161                     replace: true,
18162                     transclude: true,
18163                     scope: {
18164                         msgType: '=',
18165                         onRefreshClick: '&'
18166                     },
18167                     templateUrl: 'app/scripts/ng_js_att_tpls/tableMessages/attTableMessage.html',
18168                     link: function(scope) {
18169                         scope.messageConstants = messageConstants;
18170                         scope.refreshAction = function(evt) {
18171                             scope.onRefreshClick(evt);
18172                         };
18173                     }
18174                 };
18175         }]).directive('attUserMessage', ['messageConstants', '$timeout', 'DOMHelper', function(messageConstants, $timeout, DOMHelper) {
18176             return {
18177                 restrict: 'AE',
18178                 replace: true,
18179                 transclude: true,
18180                 scope: {
18181                     thetitle: '=',
18182                     type: '=',
18183                     message: '=',
18184                     trigger: '='
18185                 },
18186                 templateUrl: 'app/scripts/ng_js_att_tpls/tableMessages/attUserMessage.html',
18187                 link: function(scope, element) {
18188                     var prevActiveElement = undefined;
18189                     var firstElement = undefined;
18190                     scope.messageConstants = messageConstants;
18191
18192                     $timeout(function() {
18193                         firstElement = DOMHelper.firstTabableElement(element[0]);
18194                     }, 10);
18195
18196                     
18197                     scope.$watch('trigger', function() {
18198                         if (scope.trigger) {
18199                             prevActiveElement = document.activeElement;
18200                             if (angular.isDefined(firstElement)) {
18201                                 firstElement.focus();
18202                             }
18203                         } else {
18204                             if (angular.isDefined(prevActiveElement)) {
18205                                 prevActiveElement.focus();
18206                             }
18207                         }
18208                     })
18209
18210                     
18211                 }
18212             };
18213     }]);
18214 angular.module('att.abs.tabs', ['att.abs.utilities'])
18215     .directive('attTabs', function () {
18216         return{
18217             restrict: 'EA',
18218             transclude: false,
18219             replace: true,
18220             scope: {
18221                 tabs: "=title"
18222             },
18223             controller: ['$scope', function ($scope) {
18224                 this.getData = function () {
18225                     return $scope.tabs;
18226                 };
18227                 this.onClickTab = function (tab) {
18228                     $scope.currentTab = tab.url;
18229                     return $scope.currentTab;
18230                 };
18231                 this.isActiveTab = function (tab) {
18232                     return (tab === $scope.currentTab);
18233                 };
18234             }],
18235             link: function (scope) {
18236                 for (var i = 0; i < scope.tabs.length; i++) {
18237                     if ((scope.tabs[i].selected) && (scope.tabs[i].url)) {
18238                         scope.currentTab = scope.tabs[i].url;
18239                     }
18240                 }
18241             }
18242         };
18243     })
18244     .directive('floatingTabs', function () {
18245         return {
18246             require: '^attTabs',
18247             restrict: 'EA',
18248             transclude: false,
18249             replace: true,
18250             scope: {
18251                 size: "@"
18252             },
18253             templateUrl: 'app/scripts/ng_js_att_tpls/tabs/floatingTabs.html',
18254             link: function (scope, elem, attr, attTabsCtrl) {
18255                 scope.tabs = attTabsCtrl.getData();
18256                 scope.onClickTab = attTabsCtrl.onClickTab;
18257                 scope.isActiveTab = attTabsCtrl.isActiveTab;
18258             }
18259         };
18260     })
18261     .directive('simplifiedTabs', function () {
18262         return {
18263             require: '^attTabs',
18264             restrict: 'EA',
18265             transclude: false,
18266             replace: true,
18267             scope: {
18268                 ctab: "=ngModel"
18269             },
18270             templateUrl: 'app/scripts/ng_js_att_tpls/tabs/simplifiedTabs.html',
18271             link: function (scope, elem, attr, attTabsCtrl) {
18272                 scope.tabs = attTabsCtrl.getData();
18273                 scope.clickTab = function (tab) {
18274                     scope.ctab = tab.id;
18275                     return scope.ctab;
18276                 };
18277                 scope.isActive = function (tab) {
18278                     return (tab === scope.ctab);
18279                 };
18280             }
18281         };
18282     })
18283     .directive('genericTabs', ['$state',function ($state) {
18284         return {
18285             require: '^attTabs',
18286             restrict: 'EA',
18287             transclude: false,
18288             replace: true,
18289             scope: {
18290                 ctab: "=ngModel"
18291             },
18292             templateUrl: 'app/scripts/ng_js_att_tpls/tabs/genericTabs.html',
18293             link: function (scope, elem, attr, attTabsCtrl) {
18294                 scope.tabs = attTabsCtrl.getData();
18295                 scope.clickTab = function (tab) {
18296                     if (tab.state!=null) {
18297                         $state.go(tab.state);
18298                         return scope.ctab;
18299                     }
18300                     scope.ctab = tab.id;
18301                     return scope.ctab;
18302                 };
18303                 scope.isActive = function (tab) {
18304                     return (tab === scope.ctab);
18305                 };
18306             }
18307         };
18308     }])
18309     .directive('skipNavigation', function(){
18310         return{
18311             link: function(scope,elem,attr){
18312                 elem.bind('click', function(){
18313                     var skiptoBody = angular.element(elem.parent().parent().parent().parent())[0].querySelector('a.skiptoBody');
18314                     (angular.element(skiptoBody)).attr('tabindex',-1);
18315                     skiptoBody.focus();
18316                 });
18317
18318             }
18319         }
18320     })
18321     .directive('parentTab', [function () {
18322         return {
18323             restrict: 'EA',
18324             scope: {
18325                 menuItems: '=',
18326                 activeSubMenu: '=',
18327                 activeMenu: '='
18328             },
18329             controller: ['$scope', function ($scope) {
18330                 $scope.megaMenu = $scope.menuItems;
18331                 $scope.megaMenuTab;
18332                 $scope.megaMenuHoverTab;
18333                 this.setMenu = function () {
18334                     $scope.menuItems = $scope.megaMenu;
18335                     $scope.activeSubMenu.scroll=false;
18336                     for (var i = 0; i < $scope.menuItems.length; i++) {
18337                         if ($scope.menuItems[i].active) {
18338                             $scope.activeMenu = $scope.menuItems[i];
18339                         }
18340                     }
18341                     this.setSubMenuStatus(false);
18342                     $scope.$apply();
18343                 };
18344                 this.setActiveMenu = function () {
18345                     if (!($scope.megaMenuTab === undefined || $scope.megaMenuTab === null)) {
18346                         $scope.menuItems = [$scope.megaMenuTab];
18347                         $scope.megaMenuTab.scroll = true;
18348                         $scope.activeMenu = {};
18349                         $scope.activeSubMenu = $scope.megaMenuTab;
18350                         this.setSubMenuStatus(true);
18351                     }
18352                     else{
18353                         for(var i=0; i<$scope.menuItems.length; i++){
18354                             ($scope.menuItems[i].active = false);
18355                             if($scope.menuItems[i].subItems)
18356                                 for(var j=0; j<$scope.menuItems[i].subItems.length; j++){
18357                                     $scope.menuItems[i].subItems[j].active = false;
18358                                 };
18359                         };
18360                         $scope.menuItems=$scope.megaMenu;
18361                     }
18362                     $scope.$apply();
18363                 };
18364                 var checkSubMenuStatus = false;
18365                 this.setSubMenuStatus = function (value) {
18366                     checkSubMenuStatus = value;
18367                 };
18368                 this.getSubMenuStatus = function () {
18369                     return checkSubMenuStatus;
18370                 };
18371                 this.setActiveMenuTab = function (tab) {
18372                     $scope.megaMenuTab = tab;
18373                 };
18374                 this.setActiveMenuHoverTab = function (tab) {
18375                     $scope.megaMenuHoverTab = tab;
18376                 };
18377                 this.setActiveSubMenuTab = function () {
18378                     $scope.megaMenuTab = $scope.megaMenuHoverTab;
18379                 };
18380                 this.resetMenuTab = function () {
18381                     $scope.megaMenuTab = undefined;
18382                 };
18383                 this.clearSubMenu = function () {
18384                     /* Clears Sub-tems when focus shifts from Sub-menu to Mega menu*/
18385                     $scope.$evalAsync(function(){
18386                         $scope.megaMenuTab = undefined;
18387                         $scope.megaMenuHoverTab = undefined;
18388                     })
18389                 };
18390             }]
18391         };
18392     }])
18393     .directive('parentmenuTabs', [function () {
18394         return {
18395             restrict: 'EA',
18396             transclude: true,
18397             replace: true,
18398             scope: {
18399                 megaMenu: '@',
18400                 menuItems: '='
18401             },
18402             controller: ['$scope', function ($scope) {
18403                 this.getMenu = function () {
18404                     return $scope.menuItems;
18405                 };
18406                 this.setMenu = function (menuItem) {
18407                     $scope.menuItems = menuItem;
18408                 };
18409             }],
18410             templateUrl: 'app/scripts/ng_js_att_tpls/tabs/parentmenuTab.html'
18411         };
18412     }])
18413
18414     .directive('menuTabs', ["$window", "$document",'events','keymap', function (win, $document, events, keymap) {
18415         return {
18416             restrict: 'EA',
18417             transclude: true,
18418             replace: true,
18419             require: ['^?parentTab', '^?parentmenuTabs'],
18420             scope: {
18421                 activeMenu: "=",
18422                 menuItem: "=",
18423                 subMenu: "@",
18424                 subItemActive: "@",
18425                 tabName: "=?",
18426                 tabUrl: "=?"
18427             },
18428             templateUrl: function (element, attrs) {
18429                 if (attrs.megaMenu) {
18430                     return 'app/scripts/ng_js_att_tpls/tabs/menuTab.html';
18431                 }
18432                 else {
18433                     return 'app/scripts/ng_js_att_tpls/tabs/submenuTab.html';
18434                 }
18435             },
18436             link: function (scope, elem, attr, ctrl) {
18437                 var parentCtrl = ctrl[0];
18438                 var parentmenuCtrl = ctrl[1];
18439                 scope.clickInactive = true;
18440                 scope.showHoverChild = function (e) {
18441                     scope.clickInactive = false;
18442                     scope.hoverChild = ctrl[0].getSubMenuStatus();
18443                     if (e.type === "mouseover" && ctrl[0].getSubMenuStatus())
18444                     {
18445                         scope.showChildren(e);
18446                     }
18447                 };
18448                 scope.showChildren = function (e) {
18449                     scope.parentMenuItems = parentmenuCtrl.getMenu();
18450                     for (var i = 0; i < scope.parentMenuItems.length; i++) {
18451                         scope.parentMenuItems[i].active = false;
18452                         if (scope.parentMenuItems[i].subItems) {
18453                             for (var j = 0; j < scope.parentMenuItems[i].subItems.length; j++) {
18454                                 scope.parentMenuItems[i].subItems[j].active = false;
18455                             }
18456                         }
18457                         scope.clickInactive = true;
18458                     }
18459                     scope.menuItem.active = true;
18460                     scope.activeMenu = scope.menuItem;
18461                     e.stopPropagation();
18462                 };
18463                 scope.$watch("subItemActive", function (value) {
18464                     if (value === "true" && scope.subMenu === 'true') {
18465                         parentCtrl.setActiveMenuHoverTab(scope.menuItem);
18466                     }
18467                 });
18468                 scope.showMenuClick = function (e) {
18469                     parentCtrl.setActiveMenuTab(scope.menuItem);
18470                     e.stopPropagation();
18471                 };
18472                 scope.showSubMenuClick = function (e) {
18473                     parentCtrl.setActiveSubMenuTab();
18474                     e.stopPropagation();
18475                 };
18476                 scope.resetMenu = function (e) {
18477                     parentCtrl.resetMenuTab();
18478                     e.stopPropagation();
18479                 };
18480                 function debounce(method, delay) {
18481                     clearTimeout(method._tId);
18482                     method._tId = setTimeout(function () {
18483                         parentCtrl.setMenu();
18484                     }, delay);
18485                 }
18486                 function debounce1(method, delay) {
18487                     clearTimeout(method._tId);
18488                     method._tId = setTimeout(function () {
18489                         parentCtrl.setActiveMenu();
18490                     }, delay);
18491                 }
18492                 $document.bind('scroll', function () {
18493                     if (win.pageYOffset === 0) {
18494                         debounce(parentCtrl.setMenu, 100);
18495                     }
18496                     else if (win.pageYOffset > 1 && win.pageYOffset < 1500) {
18497                         debounce1(parentCtrl.setActiveMenu, 100);
18498                     }
18499                 });
18500                 elem.bind('keydown', function(evt){
18501                     if (!(evt.keyCode)){
18502                         evt.keyCode = evt.which;
18503                     }
18504                     if(evt.keyCode !== keymap.KEY.TAB){
18505                         events.preventDefault(evt);
18506                         events.stopPropagation(evt);
18507                     }
18508
18509                     switch (evt.keyCode) {
18510                         case keymap.KEY.ESC:
18511                             var skiptoBody;
18512                             if (!(elem.attr('mega-menu'))) {
18513                                 if (elem.attr("sub-menu") === "true") {
18514                                     /* condition true when user navigates through Sub-menu*/
18515
18516                                     skiptoBody = angular.element(elem.parent().parent().parent().parent().parent().parent().parent())[0].querySelector('a.skiptoBody');
18517                                     (angular.element(skiptoBody)).attr('tabindex',-1);
18518                                     skiptoBody.focus();
18519                                 }
18520                                 else if (elem.attr("sub-menu") === undefined) {
18521                                     skiptoBody = angular.element(elem.parent().parent().parent().parent().parent().parent().parent().parent().parent().parent())[0].querySelector('a.skiptoBody');
18522                                     (angular.element(skiptoBody)).attr('tabindex',-1);
18523                                     skiptoBody.focus();
18524                                 }
18525                             }
18526                             else
18527                             {
18528                                 if (elem.attr("menu-item") === "item") {
18529                                     /* Works when user on Mega menu*/
18530
18531                                     skiptoBody = angular.element(elem.parent().parent().parent().parent())[0].querySelector('a.skiptoBody');
18532                                     (angular.element(skiptoBody)).attr('tabindex',-1);
18533                                     skiptoBody.focus();
18534                                 }
18535                             }
18536                             break;
18537                         case keymap.KEY.RIGHT:
18538                             if (!(elem.attr('mega-menu'))) {
18539                                  var el = angular.element(elem)[0];
18540                                 if (elem.attr("sub-menu") === "true") {
18541                                     /* condition true when user navigates through Sub-menu*/
18542                                     if(el.nextElementSibling === null){ break;}
18543                                     if(el.nextElementSibling){
18544                                         el.nextElementSibling.querySelector("a").focus();
18545                                     }
18546                                     else{
18547                                         do{
18548                                             if (el && el.nextSibling){
18549                                                 el = el.nextSibling;
18550                                             }
18551                                             else{
18552                                                 break;
18553                                             }
18554                                         } while (el && el.tagName !== 'LI');
18555                                         if(el){
18556                                             if (el.querySelector("a") == null){}
18557                                             else{
18558                                             el.querySelector("a").focus();}
18559                                         }
18560                                         events.preventDefault(evt);
18561                                         events.stopPropagation(evt);
18562                                     }
18563                                 }
18564                                 else if (elem.attr("sub-menu") === undefined) {
18565                                     if(el.nextElementSibling === null) break;
18566                                     if(el.nextElementSibling){
18567                                         el.nextElementSibling.querySelector("a").focus();
18568                                     }
18569                                     else{
18570                                         do{
18571                                             if (el && el.nextSibling){
18572                                                 el = el.nextSibling;
18573                                             }
18574                                             else{
18575                                                 break;
18576                                             }
18577                                         } while (el && el.tagName !== 'LI');
18578                                         if(el){
18579                                             if (el.querySelector("a") == null){}
18580                                             else{
18581                                             el.querySelector("a").focus();}
18582                                         }
18583
18584                                     }
18585                                 }
18586                             }
18587                             else
18588                             {
18589                                 if (elem.attr("menu-item") === "item") {
18590                                     /* When user navigates through on Mega menu*/
18591
18592                                     var el = angular.element(elem)[0];
18593
18594                                         if(el.nextElementSibling){
18595                                             if(el.nextElementSibling.querySelector("span") == null){
18596                                             }
18597                                             else {
18598                                                 el.nextElementSibling.querySelector("span").focus();
18599                                             }
18600                                     }
18601                                     else{
18602                                         do{
18603                                             if (el && el.nextSibling){
18604                                                 el = el.nextSibling;
18605                                             }
18606                                             else{
18607                                                 break;
18608                                             }
18609                                         } while (el && el.tagName !== 'LI');
18610                                         if(el){
18611                                             if(el.querySelector("span") === null){}
18612                                             else {
18613                                                 el.querySelector("span").focus();
18614                                             }
18615                                         }
18616                                         events.preventDefault(evt);
18617                                         events.stopPropagation(evt);
18618                                     }
18619                                 }
18620                             }
18621                             break;
18622                         case keymap.KEY.DOWN:
18623
18624
18625                             if (elem.attr('mega-menu')) {
18626                                 /* When user navigates from top menu to Sub-menu*/
18627                                 angular.element(elem)[0].querySelectorAll(".megamenu__items")[0].querySelector("a").focus();
18628                             }
18629                             else if(elem.attr("sub-menu") === undefined) {
18630                             /*When user navigates within Sub Items*/
18631                                 var el = document.activeElement;
18632                                 if(el.nextElementSibling === null) break;
18633                                  if(el.nextElementSibling) {
18634                                     el.nextElementSibling.focus();
18635                                 }else{
18636                                      do {
18637                                          if (el && el.nextSibling){
18638                                              el = el.nextSibling;
18639                                          }
18640                                          else{
18641                                              break;
18642                                          }
18643                                      } while (el && el.tagName !== 'A');
18644                                      if(el.attributes !== null){                                        
18645                                          el.focus();
18646                                      }
18647                                      events.stopPropagation(evt);
18648                                  }
18649
18650                             }
18651                             else if (elem.attr("sub-menu")=== "true" ) {
18652                                 /* condition true when user navigates from sub menu to  Sub Item*/
18653                                 var childItems = angular.element(elem)[0].querySelector("span").querySelector('a');
18654                                 if(childItems === null) break;
18655                                 childItems.focus();
18656                             }
18657                             break;
18658
18659                         case keymap.KEY.LEFT:
18660
18661                             if (!(elem.attr('mega-menu'))) {
18662                                 var el = angular.element(elem)[0];
18663                                 if (elem.attr("sub-menu") === "true") {
18664                                     /* condition true when user navigates through Sub-menu*/
18665                                     if(el.previousElementSibling === null) break;
18666                                     if(el.previousElementSibling){
18667                                         el.previousElementSibling.querySelector("a").focus();
18668                                     }
18669                                     else{
18670                                         do{
18671                                             if (el && el.previousSibling){
18672                                                 el = el.previousSibling;
18673                                             }
18674                                             else{
18675                                                 break;
18676                                             }
18677                                         } while (el && el.tagName !== 'LI');
18678                                         if(el){
18679                                             if (el.querySelector("a") == null){}
18680                                             else{
18681                                             el.querySelector("a").focus();}
18682                                         }
18683                                         events.preventDefault(evt);
18684                                         events.stopPropagation(evt);
18685                                     }
18686
18687                                     /*el.previousElementSibling.querySelector("span").focus();
18688                                     events.stopPropagation(evt);
18689                                     break;*/
18690                                 }
18691                                 else if (elem.attr("sub-menu") === undefined) {
18692                                     if(el.previousElementSibling === null) break;
18693                                     if(el.previousElementSibling){
18694                                         el.previousElementSibling.querySelector("a").focus();
18695                                     }
18696                                     else{
18697                                         do{
18698                                             if (el && el.previousSibling){
18699                                                 el = el.previousSibling;
18700                                             }
18701                                             else{
18702                                                 break;
18703                                             }
18704                                         } while (el && el.tagName !== 'LI');
18705                                         if(el){
18706                                             if (el.querySelector("a") == null){}
18707                                             else{
18708                                             el.querySelector("a").focus();}
18709                                         }
18710                                     }
18711                                 }
18712                             }
18713                             else
18714                             {
18715                                 if (elem.attr("menu-item") === "item") {
18716                                     /* Works when user on Mega menu*/
18717
18718                                     var el = angular.element(elem)[0];
18719                                         if(el.previousElementSibling){
18720
18721                                             if(el.previousElementSibling.querySelector("span") === null){
18722                                             }
18723                                             else {
18724                                                 el.previousElementSibling.querySelector("span").focus();
18725                                             }
18726                                       
18727                                     }
18728                                     else{
18729                                         do{
18730                                             if (el && el.previousSibling){
18731                                                 el = el.previousSibling;
18732                                             }
18733                                             else{
18734                                                 break;
18735                                             }
18736                                         } while (el && el.tagName !== 'LI');
18737                                         if(el){
18738                                             if (el.querySelector("span") === null) {
18739                                             }
18740                                             else {
18741                                             el.querySelector("span").focus();
18742                                             }
18743                                         }
18744                                         events.preventDefault(evt);
18745                                         events.stopPropagation(evt);
18746                                     }
18747                                 }
18748                             }
18749                             break;
18750                         case keymap.KEY.UP:
18751
18752                             if (elem.attr("sub-menu") === "true") {
18753                                 var el = document.activeElement;
18754                                 var parent_menu = angular.element(elem.parent().parent().parent().parent())[0].querySelector("span");
18755                                 parent_menu.focus();
18756                                 parentCtrl.clearSubMenu();
18757                                 scope.menuItem.active = false;
18758                                 break;
18759                             }
18760                             else if(elem.attr("sub-menu") === undefined) {
18761                                 /* condition true when user navigates within Sub Items*/
18762                                 var el = document.activeElement;
18763                                 var parent_menu = angular.element(elem.parent().parent().parent().parent())[0].querySelector("a");                                
18764                                 if(document.activeElement === angular.element(el).parent().parent()[0].querySelectorAll('a')[0]){
18765                                     parent_menu.focus();
18766                                     break;
18767                                 };
18768
18769                                 if(el.previousElementSibling) {
18770                                     var prev_a =  el.previousElementSibling;
18771                                     (el.previousElementSibling != null)? el.previousElementSibling.focus(): parent_menu.focus();
18772                                 }else{
18773                                     do{
18774                                         if (el && el.previousSibling){
18775                                             el = el.previousSibling;
18776                                         }
18777                                         else{
18778                                             break;
18779                                         }
18780                                     } while (el && el.tagName !== 'A');
18781                                     if(el && (el.nodeType !== 3)){
18782                                         el.focus();
18783                                     }
18784                                     events.preventDefault(evt);
18785                                     events.stopPropagation(evt);
18786                                 }
18787
18788                                 break;
18789                             }
18790                         default:
18791                             break;
18792                     }
18793                 });
18794             }
18795         };
18796     }]);
18797
18798 angular.module('att.abs.tagBadges', [])
18799         .directive('tagBadges', ['$parse', '$timeout', function($parse, $timeout) {
18800                 return {
18801                     restrict: 'EA',
18802                     replace: false,
18803                     transclude: true,
18804                     templateUrl: 'app/scripts/ng_js_att_tpls/tagBadges/tagBadges.html',
18805                     scope: {
18806                         styleType: "@",
18807                         onClose: "&"
18808                     },
18809                     link: function(scope, elem, attr) {
18810                         scope.isSmall = false;
18811                         scope.isIcon = false;
18812                         scope.isColor = false;
18813                         scope.display = true;
18814                         scope.isClosable = false;
18815                         scope.isHighlight = false;
18816                         scope.customColor = false;
18817
18818                         if (attr.small === "") {
18819                             scope.isSmall = true;
18820                         }
18821                         if (scope.styleType === "icon") {
18822                             scope.isIcon = true;
18823                         }
18824                         else if (scope.styleType === "color") {
18825                             scope.isColor = true;
18826                             if(attr.color !== undefined && attr.color !== "") {
18827                                 scope.customColor = true;
18828                                 attr.$observe("color", function(val) {
18829                                     scope.border_type_borderColor = val;
18830                                     scope.background_type_backgroundColor = val;
18831                                     scope.background_type_borderColor = val;
18832                                 });
18833                             }
18834                         }
18835                         scope.activeHighlight = function(state){
18836                             if(scope.customColor){
18837                                 if(state){
18838                                     scope.isHighlight = true;
18839                                 }
18840                                 else{
18841                                     scope.isHighlight = false;
18842                                 }
18843                             }
18844                         };
18845                         if (attr.closable === "") {
18846                             scope.isClosable = true;
18847                             scope.closeMe = function() {
18848                                 scope.display = false;
18849                                 $timeout(function(){
18850                                     elem.attr("tabindex", "0");
18851                                     elem[0].focus();
18852                                     elem.bind('blur', function(){
18853                                         elem.remove();
18854                                     });
18855                                 });
18856                                 if(attr['onClose']){
18857                                     scope.onClose = $parse(scope.onClose);
18858                                     scope.onClose();
18859                                 }
18860                             };
18861                         }
18862                     }
18863                 };
18864             }]);
18865 angular.module('att.abs.textOverflow', [])
18866         .constant('textDefaultOptions', {
18867             width: '50%'
18868         })
18869 .directive('attTextOverflow', ['textDefaultOptions','$compile',function(textDefaultOptions,$compile)
18870 {
18871     return {
18872         restrict: 'A',
18873         link: function(scope, elem, attrs)
18874         {
18875             var tooltipText = elem.text();
18876             elem.addClass('text-ellipsis');
18877             attrs.$observe('attTextOverflow', function(val){
18878                 if(val){
18879                     elem.css({"width":val});
18880                 }
18881                 else{
18882                     elem.css({"width":textDefaultOptions.width});
18883                 }
18884             });
18885             if(!(elem.attr('tooltip'))){
18886                 elem.attr("tooltip", tooltipText);
18887                 elem.attr("tooltip-placement", 'above');
18888                 var newElem =  angular.element(elem);
18889                 $compile(newElem)(scope);
18890             }
18891         }
18892     };
18893 }]);
18894
18895 angular.module('att.abs.toggle', ['angular-gestures', 'att.abs.position'])
18896         .directive('attToggleTemplate', ['$compile', '$log', '$position', function ($compile, $log, $position)
18897             {
18898                 return{
18899                     restrict: 'A',
18900                     require: 'ngModel',
18901                     transclude: true,
18902                     scope: {
18903                         modelVal: "=ngModel"
18904                     },
18905                     templateUrl: 'app/scripts/ng_js_att_tpls/toggle/demoToggle.html',
18906                     link: function (scope, element, attr) {
18907                         scope.initialDragPosition = 0;
18908                         var dragStatus = 0;
18909                         var switchMovementPath = ($position.offset(element.children().eq(1).children().eq(0)).width - 1);
18910                         var updateModelVal = function () {
18911                             if (scope.attrValue === attr.ngTrueValue || scope.attrValue)
18912                             {
18913                                 scope.modelVal = false;
18914                             }
18915                             else
18916                             {
18917                                 scope.modelVal = true;
18918                             }
18919                         };
18920                         scope.updateModel = function (env) {
18921                             {
18922                                 if (dragStatus !== 1) {
18923                                     updateModelVal();
18924                                     dragStatus = 0;
18925                                 }
18926                             }
18927                             env.preventDefault();
18928                         };
18929                         scope.drag = function (e) {
18930                             dragStatus = 1;
18931                             if (e.type === 'dragstart') {
18932                                 scope.initialDragPosition = $position.position(element.children().eq(1)).left;
18933                                 element.children().eq(1).addClass('dragging');
18934                             } else if (e.type === 'drag') {
18935                                 var left = Math.min(0, Math.max(scope.initialDragPosition + e.gesture.deltaX, -switchMovementPath));
18936                                 element.children().eq(1).css({
18937                                     left: left + 'px'
18938                                 });
18939                             } else if (e.type === 'dragend') {
18940                                 var isOn = $position.position(element.children().eq(1)).left > (switchMovementPath * -1) / 2;
18941                                 element.children().eq(1).removeClass('dragging');
18942                                 TweenMax.to(element.children().eq(1), .1, {left: isOn ? 0 : (switchMovementPath * -1), ease: Power4.easeOut,
18943                                     onComplete: function () {
18944                                         element.children().eq(1).css({left: ''});
18945                                     }});
18946                                 if (isOn || (!isOn && e.gesture.direction === "left")) {
18947                                     updateModelVal();
18948                                 }
18949                                 dragStatus = 0;
18950                             }
18951
18952                             return false;
18953                         };
18954
18955                         scope.directiveValue = attr.attToggleTemplate;
18956                         scope.on = attr.trueValue;
18957                         scope.off = attr.falseValue;
18958                         var switchMovementPathPixels = ((switchMovementPath) * -1) + 'px';
18959                         scope.$watch('modelVal', function (newVal) {
18960                             scope.attrValue = newVal;
18961                             if (newVal === attr.ngTrueValue || newVal) {
18962                                 element.children().eq(1).css({
18963                                     left: '0px'
18964                                 });
18965                                 element.addClass('att-checkbox--on');
18966                                 var elem = element.find('div').find('div').eq(1);
18967                                 elem.attr("aria-checked", true);
18968                                 dragStatus = 0;
18969                             } else {
18970                                 element.children().eq(1).css({
18971                                     left: switchMovementPathPixels
18972                                 });
18973                                 element.removeClass('att-checkbox--on');
18974                                  var elem = element.find('div').find('div').eq(1);
18975                                 elem.attr("aria-checked", false);
18976                                 dragStatus = 0;
18977                             }
18978                             element.children().eq(1).css({
18979                                 left: ''
18980                             });
18981                         });
18982                     }
18983                 };
18984             }
18985         ])
18986
18987         .directive('attToggleMain', ['$compile', function ($compile)
18988             {
18989                 return{
18990                     restrict: 'A',
18991                     require: 'ngModel',
18992                     transclude: true,
18993                     replace: true,
18994                     scope: {
18995                         modelValue: "=ngModel",
18996                         trueValue: "=ngTrueValue",
18997                         falseValue: "=ngFalseValue"
18998                     },
18999                     link: function (scope, element, attr) {
19000                         var html = "";
19001                         var attrVal = "";
19002                         element.removeAttr('att-toggle-main');
19003                         scope.on = attr.ngTrueValue;
19004                         scope.off = attr.ngFalseValue;
19005                         scope.largeValue = attr.attToggleMain;
19006                         if (angular.isDefined(attr.ngTrueValue)) {
19007                             html += ' true-value="{{on}}" false-value="{{off}}"';
19008                         }
19009                         if (scope.largeValue !== undefined)
19010                         {
19011                             attrVal += ' ="{{largeValue}}"';
19012                         }
19013
19014                         element.css({display: 'none'});
19015                         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>');
19016                         elm = $compile(elm)(scope);
19017                         element.replaceWith(elm);
19018                     }
19019                 };
19020             }]);
19021 angular.module('att.abs.treeview', [])
19022         .directive('treeView', function() {
19023             return{
19024                 restrict: 'A',
19025                 link: function(scope, elem) {
19026                     var el = elem.children('ul li');
19027                     var list = TweenMax.from(el, .2, {display: 'none', paused: true, reversed: true});
19028                     elem.attr("tabindex","0");
19029                     function toggleBranch() {
19030                         if (list.reversed())
19031                         {
19032                             list.play();
19033                         } else
19034                         {
19035                             list.reverse();
19036                         }
19037                     };
19038                     function toggleTree(e) {
19039                         e.stopPropagation();
19040                         if (angular.element(e.target).attr("tree-view") !== undefined)
19041                         {
19042                             if (elem.hasClass('minus'))
19043                             {
19044                                 elem.removeClass('minus');
19045                             }
19046                             else
19047                             {
19048                                 elem.addClass('minus');
19049                             }
19050                             toggleBranch();
19051                         }
19052                     }
19053                     elem.on('click', function(e) {
19054                         toggleTree(e);
19055                     });
19056                     elem.on('keypress', function (e) {
19057                         var activeCode = e.keyCode ? e.keyCode : e.charCode;
19058                         var keyCode = [13,32];
19059                         if (keyCode.length > 0 && ((activeCode && keyCode.indexOf(activeCode) > -1))) {
19060                             toggleTree(e);
19061                             e.preventDefault();
19062                         }
19063                     });
19064                 }
19065             };
19066         });
19067
19068 angular.module('att.abs.typeAhead', ['att.abs.tagBadges'])
19069
19070         .directive('focusMe',['$timeout', '$parse', function($timeout, $parse) {
19071             return {
19072                 link: function(scope, element, attrs) {
19073                     var model = $parse(attrs.focusMe);
19074                     scope.$watch(model, function(value) {
19075                         if (value) {
19076                             $timeout(function() {
19077                                 element[0].focus();
19078                                 scope.inputActive=true;
19079                             });
19080                         }
19081                     });
19082                     element.bind('blur', function() {
19083                          model.assign(scope, false);
19084                          scope.inputActive=false;
19085                          scope.$digest();
19086                      });
19087                 }
19088             };
19089         }])
19090
19091         .directive('typeAhead', ['$timeout','$log', function($timeout,$log) {
19092                 return {
19093                     restrict: 'EA',
19094                     templateUrl: 'app/scripts/ng_js_att_tpls/typeAhead/typeAhead.html',
19095                     replace: true,
19096                     scope: {
19097                         items: '=',
19098                         title: '@?',
19099                         titleName: '@',
19100                         subtitle: '@',
19101                         model: '=',
19102                         emailIdList:'=',
19103                         emailMessage:'='
19104                     },
19105                     link: function(scope, elem) {
19106                         if(!angular.isDefined(scope.titleName) && angular.isDefined(scope.title)){
19107                              $timeout(function(){
19108                             scope.titleName = scope.title;
19109                             $log.warn("title attribute is deprecated and title-name attribute is used instead as it is conflicting with html title attribute");
19110                              });
19111                         }
19112                         scope.lineItems = [];
19113                         scope.filteredListLength = -1;
19114                         scope.filteredList = [];
19115                         scope.setFocus = function() {
19116                         scope.clickFocus = true;
19117                         };
19118                         scope.setFocus();
19119                         scope.handleSelection = function(selectedItem,emailItem) {
19120                             scope.lineItems.push(selectedItem);
19121                             scope.emailIdList.push(emailItem);
19122                             scope.model = "";
19123                             scope.current = 0;
19124                             scope.selected = true;
19125                             scope.clickFocus = true;
19126                         };
19127                         scope.theMethodToBeCalled = function(index) {
19128                             var tempArr = scope.lineItems.slice();
19129                             scope.emailIdList.splice(index, 1);
19130                             tempArr.splice(index, 1);
19131                             $timeout(function() {
19132                                 scope.lineItems = [];
19133                                 scope.$apply();
19134                                 scope.lineItems = scope.lineItems.concat(tempArr);
19135                             });
19136                         };
19137
19138                         scope.current = 0;
19139                         scope.selected = true;
19140
19141                         scope.isCurrent = function(index, itemName,itemEmail,dropdownLength) {
19142                             if (scope.current === index) {
19143                                 scope.itemName = itemName;
19144                                 scope.itemEmail = itemEmail;
19145                             }
19146                             scope.dropdownLength=dropdownLength;
19147                             return scope.current === index;
19148                         };
19149
19150                         scope.setCurrent = function(index) {
19151                             scope.current = index;
19152                         };
19153
19154                         scope.selectionIndex = function(evt) {
19155                             if (evt.keyCode === 38 && scope.current > 0) {
19156                                evt.preventDefault();
19157                                 scope.current = scope.current - 1;
19158                                 scope.isCurrent(scope.current);
19159                             } else if (evt.keyCode === 9) {
19160                                 scope.selected = true;
19161                             } else if (evt.keyCode === 13 && scope.dropdownLength!==scope.items.length) {
19162                                 scope.handleSelection(scope.itemName,scope.itemEmail);
19163                             } else if ((evt.keyCode === 8 && scope.model.length === 0) || evt.keyCode === 46) {
19164                                 scope.theMethodToBeCalled(scope.lineItems.length - 1);
19165                             } else if (evt.keyCode === 40 && scope.current < scope.dropdownLength-1) {
19166                                 evt.preventDefault();
19167                                 scope.current = scope.current + 1;
19168                                 scope.isCurrent(scope.current);
19169                             }
19170                             elem[0].querySelector('.list-scrollable').scrollTop = (scope.current - 1) * 35;
19171                         };
19172                     }
19173                 };
19174             }]);
19175 angular.module('att.abs.verticalSteptracker', ['ngSanitize'])
19176     .directive('verticalSteptracker', [ function(){
19177         return {
19178             restrict: 'EA',
19179             transclude: true,
19180             replace: false,
19181             scope: {},
19182             template: '<div class="vertical-nav"><ul ng-transclude arial-label="step list" role="presentation" class="tickets-list-height"></ul></div>',
19183             link: function () {}
19184         };
19185     }])
19186     .directive('verticalSteptrackerStep',[ function(){
19187         return {
19188             restrict: 'EA',
19189             transclude: true,
19190             replace: false,
19191             scope: {
19192                 type: "=type",
19193                 id: "=id"
19194             },
19195             templateUrl: 'app/scripts/ng_js_att_tpls/verticalSteptracker/vertical-step-tracker.html',
19196             link: function(){}
19197          };
19198     }])
19199     .directive('attAbsLink',[ function(){
19200         return{
19201             restrict: 'EA',
19202             transclude: true,
19203             replace: false,
19204             template: '<span ng-transclude class="view-log"></span>'
19205         };
19206     }]);
19207 angular.module('att.abs.videoControls', [])
19208         .config(['$compileProvider' , function ($compileProvider) {
19209                 $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|javascript):/);
19210             }])
19211         .directive('videoControls', [function() {
19212                 return {
19213                     restrict: 'EA',
19214                     replace: true,
19215                     transclude: true,
19216                     templateUrl: 'app/scripts/ng_js_att_tpls/videoControls/videoControls.html'
19217                 };
19218             }])
19219         .directive('photoControls', [function() {
19220                 return {
19221                     restrict: 'EA',
19222                     replace: true,
19223                     transclude: true,
19224                     templateUrl: 'app/scripts/ng_js_att_tpls/videoControls/photoControls.html',
19225                     scope: {
19226                         prevLink: "@",
19227                         nextLink: "@"
19228                     },
19229                     link: function(scope, elem, attr) {
19230                         if(!attr['prevLink']){
19231                             scope.prevLink = 'javascript:void(0)';
19232                         }
19233                         if(!attr['nextLink']){
19234                             scope.nextLink = 'javascript:void(0)';
19235                         }
19236                         scope.links = {
19237                             prevLink : scope.prevLink,
19238                             nextLink : scope.nextLink
19239                         };
19240                     }
19241                 };
19242             }]);
19243 angular.module("app/scripts/ng_js_att_tpls/accordion/accordion.html", []).run(["$templateCache", function($templateCache) {
19244   $templateCache.put("app/scripts/ng_js_att_tpls/accordion/accordion.html",
19245     "<div class=\"att-accordion__group tabpanel\" ng-class=\"{'att-accordion__group att-accordion__group--open':isOpen,'att-accordion__group':!isOpen }\">\n" +
19246     "    <a  ng-show=\"showicon\" \n" +
19247     "        class=\"toggle-header att-accordion__heading att-accordion__toggle noafter\" \n" +
19248     "        aria-selected=\"{{focused}}\" \n" +
19249     "        aria-controls=\"panel{{index}}\" \n" +
19250     "        aria-expanded=\"{{isOpen}}\" \n" +
19251     "        ng-class=\"{focus: focused, selected: focused}\"         \n" +
19252     "        role=\"tab\" \n" +
19253     "        ng-click=\"toggle()\" \n" +
19254     "        accordion-transclude=\"heading\" \n" +
19255     "        style=\"cursor:pointer; text-decoration:none\">\n" +
19256     "        <span>{{heading}}</span>\n" +
19257     "        <i ng-class=\"{'icon-chevron-down':!isOpen,'icon-chevron-up':isOpen }\" class=\"pull-right\"></i>\n" +
19258     "    </a>\n" +
19259     "    <div ng-show=\"!showicon\" \n" +
19260     "         ng-class=\"{focus: focused, selected: focused}\" \n" +
19261     "         style=\"text-decoration:none\" \n" +
19262     "         accordion-transclude=\"heading\"          \n" +
19263     "         role=\"tab\"  \n" +
19264     "         aria-expanded=\"{{isOpen}}\"\n" +
19265     "         aria-selected=\"{{focused}}\" \n" +
19266     "         aria-controls=\"panel{{index}}\" \n" +
19267     "         class=\"toggle-header att-accordion__heading att-accordion__toggle noafter\">\n" +
19268     "        <span>{{heading}}</span>\n" +
19269     "    </div>    \n" +
19270     "    <div aria-label=\"{{heading}}\" \n" +
19271     "         aria-hidden=\"{{!isOpen}}\" \n" +
19272     "         role=\"tabpanel\" \n" +
19273     "         collapse=\"!isOpen\" \n" +
19274     "         class=\"att-accordion__body\" \n" +
19275     "         id=\"panel{{index}}\" \n" +
19276     "         ng-transclude>\n" +
19277     "    </div>\n" +
19278     "    <div class=\"att-accordion__bottom--border\"></div>    \n" +
19279     "</div> ");
19280 }]);
19281
19282 angular.module("app/scripts/ng_js_att_tpls/accordion/accordion_alt.html", []).run(["$templateCache", function($templateCache) {
19283   $templateCache.put("app/scripts/ng_js_att_tpls/accordion/accordion_alt.html",
19284     "<div class=\"att-accordion__group tabpanel\" ng-class=\"{'att-accordion__group att-accordion__group--open':isOpen,'att-accordion__group':!isOpen }\">\n" +
19285     "    <a class=\"toggle-header att-accordion__heading att-accordion__toggle\" \n" +
19286     "       aria-selected=\"{{focused}}\" \n" +
19287     "       aria-controls=\"panel{{index}}\" \n" +
19288     "       ng-class=\"{focus: focused, selected: focused}\" \n" +
19289     "       aria-expanded=\"{{isOpen}}\" \n" +
19290     "       role=\"tab\" \n" +
19291     "       ng-click=\"toggle()\" \n" +
19292     "       accordion-transclude=\"heading\">        \n" +
19293     "    </a>\n" +
19294     "    <span>{{heading}}</span>\n" +
19295     "    <div aria-label=\"{{heading}}\" \n" +
19296     "         aria-hidden=\"{{!isOpen}}\" \n" +
19297     "         role=\"tabpanel\" \n" +
19298     "         collapse=\"!isOpen\" \n" +
19299     "         class=\"att-accordion__body\" \n" +
19300     "         id=\"panel{{index}}\" \n" +
19301     "         ng-transclude>\n" +
19302     "    </div>\n" +
19303     "</div> ");
19304 }]);
19305
19306 angular.module("app/scripts/ng_js_att_tpls/accordion/attAccord.html", []).run(["$templateCache", function($templateCache) {
19307   $templateCache.put("app/scripts/ng_js_att_tpls/accordion/attAccord.html",
19308     "<div ng-transclude></div>");
19309 }]);
19310
19311 angular.module("app/scripts/ng_js_att_tpls/accordion/attAccordBody.html", []).run(["$templateCache", function($templateCache) {
19312   $templateCache.put("app/scripts/ng_js_att_tpls/accordion/attAccordBody.html",
19313     "<div ng-transclude></div>");
19314 }]);
19315
19316 angular.module("app/scripts/ng_js_att_tpls/accordion/attAccordHeader.html", []).run(["$templateCache", function($templateCache) {
19317   $templateCache.put("app/scripts/ng_js_att_tpls/accordion/attAccordHeader.html",
19318     "<div ng-click=\"clickFunc()\">\n" +
19319     "   <div ng-transclude>\n" +
19320     "           <i class=\"icon-chevron-down\"></i>\n" +
19321     "   </div>\n" +
19322     "</div>");
19323 }]);
19324
19325 angular.module("app/scripts/ng_js_att_tpls/alert/alert.html", []).run(["$templateCache", function($templateCache) {
19326   $templateCache.put("app/scripts/ng_js_att_tpls/alert/alert.html",
19327     "<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" +
19328     "    <div class=\"container\">\n" +
19329     "        <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" +
19330     "        <span ng-transclude> </span>\n" +
19331     "    </div>\n" +
19332     "</div>");
19333 }]);
19334
19335 angular.module("app/scripts/ng_js_att_tpls/boardStrip/attAddBoard.html", []).run(["$templateCache", function($templateCache) {
19336   $templateCache.put("app/scripts/ng_js_att_tpls/boardStrip/attAddBoard.html",
19337     "<div tabindex=\"0\" att-accessibility-click=\"13,32\" ng-click=\"addBoard()\" aria-label=\"Add Board\" class=\"boardstrip-item--add\">\n" +
19338     "    <i aria-hidden=\"true\" class=\"icon-add centered\"></i>\n" +
19339     "    <br/>\n" +
19340     "    <div class=\"centered\">Add board</div>\n" +
19341     "</div>");
19342 }]);
19343
19344 angular.module("app/scripts/ng_js_att_tpls/boardStrip/attBoard.html", []).run(["$templateCache", function($templateCache) {
19345   $templateCache.put("app/scripts/ng_js_att_tpls/boardStrip/attBoard.html",
19346     "<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" +
19347     "    <div ng-transclude></div>\n" +
19348     "    <div class=\"board-caret\" ng-if=\"getCurrentIndex()===boardIndex\">\n" +
19349     "        <div class=\"board-caret-indicator\"></div>\n" +
19350     "        <div class=\"board-caret-arrow-up\"></div>\n" +
19351     "    </div>\n" +
19352     "</li>");
19353 }]);
19354
19355 angular.module("app/scripts/ng_js_att_tpls/boardStrip/attBoardStrip.html", []).run(["$templateCache", function($templateCache) {
19356   $templateCache.put("app/scripts/ng_js_att_tpls/boardStrip/attBoardStrip.html",
19357     "<div class=\"att-boardstrip\">\n" +
19358     "   <div class=\"boardstrip-reel\">\n" +
19359     "           <div class=\"prev-items\" ng-if=\"isPrevBoard()\">\n" +
19360     "                   <i tabindex=\"0\" aria-label=\"Scroll Boardstrip Left\" att-accessibility-click=\"13,32\" ng-click=\"prevBoard()\" class=\"arrow icon-arrow-left-circle\"></i>\n" +
19361     "           </div>\n" +
19362     "           <div att-add-board on-add-board=\"onAddBoard()\"></div>\n" +
19363     "           <div class=\"board-viewport\"><ul role=\"presentation\" class=\"boardstrip-container\" ng-transclude></ul></div>\n" +
19364     "           <div class=\"next-items\" ng-if=\"isNextBoard()\">\n" +
19365     "                   <i tabindex=\"0\" aria-label=\"Scroll Boardstrip Right\" att-accessibility-click=\"13,32\" ng-click=\"nextBoard()\" class=\"arrow icon-arrow-right-circle\"></i>\n" +
19366     "           </div>\n" +
19367     "   </div>\n" +
19368     "</div>");
19369 }]);
19370
19371 angular.module("app/scripts/ng_js_att_tpls/buttons/buttonDropdown.html", []).run(["$templateCache", function($templateCache) {
19372   $templateCache.put("app/scripts/ng_js_att_tpls/buttons/buttonDropdown.html",
19373     "<div class=\"att-btn-dropdown\">\n" +
19374     "    <div class=\"buttons-dropdown--small btn-group\" ng-class=\"{'open': isOpen}\" att-accessibility-click=\"13,32\" ng-click=\"toggle()\">\n" +
19375     "        \n" +
19376     "        <button role=\"menu\" class=\"button button--secondary button--small buttons-dropdown__drop dropdown-toggle\" ng-if=\"type==='dots'\" alt=\"Click for Options\" >\n" +
19377     "            \n" +
19378     "            <div class=\"circle\"></div>\n" +
19379     "            <div class=\"circle\"></div>\n" +
19380     "            <div class=\"circle\"></div>\n" +
19381     "        </button>\n" +
19382     "        <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" +
19383     "        \n" +
19384     "\n" +
19385     "        <ul ng-class=\"{'dropdown-menu dots-dropdwn': type==='dots', 'dropdown-menu actions-dropdwn': type === 'actions'}\" ng-transclude></ul>\n" +
19386     "    </div>\n" +
19387     "    \n" +
19388     "</div>\n" +
19389     "");
19390 }]);
19391
19392 angular.module("app/scripts/ng_js_att_tpls/colorselector/colorselector.html", []).run(["$templateCache", function($templateCache) {
19393   $templateCache.put("app/scripts/ng_js_att_tpls/colorselector/colorselector.html",
19394     "<div class=\"att-radio att-color-selector__item\"  \n" +
19395     "     ng-class=\"{'att-radio--on': (iconColor === selected)}\">\n" +
19396     "    <div class=\"att-radio__indicator\" tabindex=\"0\" att-accessibility-click=\"32,13\" ng-click=\"selectedcolor(iconColor)\" \n" +
19397     "         ng-style=\"applycolor\" ng-transclude></div>\n" +
19398     "</div>");
19399 }]);
19400
19401 angular.module("app/scripts/ng_js_att_tpls/datepicker/dateFilter.html", []).run(["$templateCache", function($templateCache) {
19402   $templateCache.put("app/scripts/ng_js_att_tpls/datepicker/dateFilter.html",
19403     "<div class=\"calendar\" ng-class=\"{'monthpicker':mode === 1}\">\n" +
19404     "    <div class=\"select2-container\" ng-class=\"{'select2-container-active select2-dropdown-open': showDropdownList}\" style=\"width: 100%; z-index:0\">\n" +
19405     "        <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" +
19406     "            <span class=\"select2-chosen\" ng-show=\"!showCalendar\">{{selectedOption}}</span>\n" +
19407     "            <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" +
19408     "            <abbr class=\"select2-search-choice-close\"></abbr>\n" +
19409     "            <span ng-class=\"{'select2-arrow': mode !== 1, 'calendar-icon': mode === 1}\"><b></b></span>\n" +
19410     "        </a>\n" +
19411     "        <a id=\"select2-chosen\" class=\"select2-choice\" href=\"javascript:void(0)\" ng-show=\"showCalendar\">\n" +
19412     "            <span class=\"select2-chosen\" ng-show=\"!showCalendar\">{{selectedOption}}</span>\n" +
19413     "            <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" +
19414     "            <abbr class=\"select2-search-choice-close\"></abbr>\n" +
19415     "            <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" +
19416     "        </a>\n" +
19417     "    </div>\n" +
19418     "    <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" +
19419     "        <div  id=\"dateFilterList\" att-scrollbar ><ul class=\"select2-results options\" ng-transclude></ul></div>\n" +
19420     "           <ul class=\"select2-results sttings\" style=\"margin-top:0px\">\n" +
19421     "                   <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" +
19422     "                <div class=\"select2-result-label\" ng-if=\"mode !== 1\">Custom Single Date...</div>\n" +
19423     "                           <div class=\"select2-result-label\" ng-if=\"mode === 1\">Custom single month...</div>\n" +
19424     "            </li>\n" +
19425     "            <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" +
19426     "                <div class=\"select2-result-label\" ng-if=\"mode !== 1\">Custom Range...</div>\n" +
19427     "                           <div class=\"select2-result-label\" ng-if=\"mode === 1\">Custom month range...</div>\n" +
19428     "            </li>\n" +
19429     "            <li class=\"select2-result select2-highlighted btnContainer\" ng-style=\"{display: (showCalendar && 'block') || 'none'}\">\n" +
19430     "                <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" +
19431     "                <button tabindex=\"0\" att-button=\"\" btn-type=\"secondary\" size=\"small\" att-accessibility-click=\"13,32\" ng-click=\"cancel()\">Cancel</button>\n" +
19432     "                <div>\n" +
19433     "                    <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" +
19434     "                    <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" +
19435     "                </div>\n" +
19436     "            </li>\n" +
19437     "           </ul>\n" +
19438     "    </div>\n" +
19439     "    <div class=\"datepicker-wrapper show-right\" ng-style=\"{display: (showCalendar && 'block') || 'none'}\">\n" +
19440     "        <span datepicker ng-blur=\"resetFocus($event)\" att-element-focus=\"focusSingleDateCalendar\" ng-show=\"checkCurrentSelection('Custom Single Date')\"></span>\n" +
19441     "        <span datepicker ng-blur=\"resetFocus($event)\" att-element-focus=\"focusRangeCalendar\" ng-show=\"checkCurrentSelection('Custom Range')\"></span>\n" +
19442     "    </div>\n" +
19443     "</div>\n" +
19444     "");
19445 }]);
19446
19447 angular.module("app/scripts/ng_js_att_tpls/datepicker/dateFilterList.html", []).run(["$templateCache", function($templateCache) {
19448   $templateCache.put("app/scripts/ng_js_att_tpls/datepicker/dateFilterList.html",
19449     "<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" +
19450     "                <div class=\"select2-result-label\" ng-class=\"{'disabled':disabled}\" ng-transclude></div>\n" +
19451     "</li>");
19452 }]);
19453
19454 angular.module("app/scripts/ng_js_att_tpls/datepicker/datepicker.html", []).run(["$templateCache", function($templateCache) {
19455   $templateCache.put("app/scripts/ng_js_att_tpls/datepicker/datepicker.html",
19456     "<div id=\"datepicker\" class=\"datepicker\" ng-class=\"{'monthpicker': mode === 1}\" aria-hidden=\"false\" role=\"dialog\" tabindex=\"-1\" aria-labelledby=\"datepicker\">\n" +
19457     "    <div class=\"datepicker-days\" style=\"display: block;\">\n" +
19458     "        <table class=\"table-condensed\">\n" +
19459     "            <thead>\n" +
19460     "                <tr>\n" +
19461     "                    <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" +
19462     "                    <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" +
19463     "            <div class=\"icons-list\" data-size=\"medium\"><i class=\"icon-arrow-left-circle\" ng-class=\"{'disabled': disablePrev}\" alt=\"Left Arrow\"></i>\n" +
19464     "            </div><span class=\"hidden-spoken\">Previous Month</span>\n" +
19465     "            </th>\n" +
19466     "            <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" +
19467     "            <div class=\"icons-list\" data-size=\"medium\"><i class=\"icon-arrow-right-circle\" ng-class=\"{'disabled': disableNext}\" alt=\"Right Arrow\"></i>\n" +
19468     "            </div><span class=\"hidden-spoken\">Next Month</span>\n" +
19469     "            </th>\n" +
19470     "            </tr>\n" +
19471     "            <tr ng-if=\"labels.length > 0\">\n" +
19472     "                <th tabindex=\"-1\" class=\"dow weekday\" ng-repeat=\"label in labels\"><span>{{label.pre}}</span></th>\n" +
19473     "            </tr>\n" +
19474     "            </thead>\n" +
19475     "            <tbody>\n" +
19476     "                <tr>\n" +
19477     "                    <td id=\"datepickerBody\" att-scrollbar colspan=\"{{currentRows[0].length}}\" style=\"padding: 0px;\" headers=\"\">\n" +
19478     "                        <table ng-class=\"{'table-condensed': mode === 0, 'monthtable-condensed': mode === 1}\" style=\"padding: 0px;\">\n" +
19479     "                            <thead class=\"hidden-spoken\">\n" +
19480     "                                <tr ng-show=\"labels.length > 0\">\n" +
19481     "                                    <th id=\"{{label.post}}\" tabindex=\"-1\" class=\"dow weekday\" ng-repeat=\"label in labels\"></th>\n" +
19482     "                                </tr>\n" +
19483     "                            </thead>\n" +
19484     "                            <tbody>\n" +
19485     "                                <tr ng-repeat=\"row in currentRows\">\n" +
19486     "                                    <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" +
19487     "                                </tr>\n" +
19488     "                                <tr ng-if=\"mode === 1\" class=\"divider\"><td colspan=\"{{nextRows[0].length}}\"><hr></td></tr>\n" +
19489     "                                <tr>\n" +
19490     "                                    <th id=\"month\" tabindex=\"0\" class=\"datepicker-switch internal\" colspan=\"{{nextRows[0].length}}\" style=\"text-align:left\">{{nextTitle}}</th>\n" +
19491     "                                </tr>\n" +
19492     "                                <tr ng-repeat=\"row in nextRows\">\n" +
19493     "                                    <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" +
19494     "                                </tr>\n" +
19495     "                            </tbody>\n" +
19496     "                        </table>\n" +
19497     "                    </td>\n" +
19498     "                </tr>\n" +
19499     "            </tbody>\n" +
19500     "        </table>\n" +
19501     "    </div>\n" +
19502     "</div>\n" +
19503     "");
19504 }]);
19505
19506 angular.module("app/scripts/ng_js_att_tpls/datepicker/datepickerPopup.html", []).run(["$templateCache", function($templateCache) {
19507   $templateCache.put("app/scripts/ng_js_att_tpls/datepicker/datepickerPopup.html",
19508     "<div class=\"calendar\">\n" +
19509     "    <div class=\"box\" ng-class=\"{'active': isOpen}\">\n" +
19510     "        <span ng-transclude></span>\n" +
19511     "        <i class=\"calendar-icon\" tabindex=\"0\" att-accessibility-click=\"13,32\" ng-click=\"toggle()\" alt=\"Calendar Icon\"></i>\n" +
19512     "    </div>\n" +
19513     "    <div class=\"datepicker-wrapper datepicker-wrapper-display-none\" ng-style=\"{display: (isOpen && 'block') || 'none'}\" aria-hidden=\"false\" role=\"dialog\" tabindex=\"-1\">\n" +
19514     "        <span datepicker></span>\n" +
19515     "    </div>\n" +
19516     "</div>\n" +
19517     "");
19518 }]);
19519
19520 angular.module("app/scripts/ng_js_att_tpls/dividerLines/dividerLines.html", []).run(["$templateCache", function($templateCache) {
19521   $templateCache.put("app/scripts/ng_js_att_tpls/dividerLines/dividerLines.html",
19522     "<div class=\"divider-container\" ng-class=\"{'divider-container-light': lightContainer}\">\n" +
19523     "    <hr ng-class=\"{'divider-light': lightContainer}\">\n" +
19524     "</div>\n" +
19525     "\n" +
19526     "");
19527 }]);
19528
19529 angular.module("app/scripts/ng_js_att_tpls/dragdrop/fileUpload.html", []).run(["$templateCache", function($templateCache) {
19530   $templateCache.put("app/scripts/ng_js_att_tpls/dragdrop/fileUpload.html",
19531     "<label class=\"fileContainer\"><span ng-transclude></span><input type=\"file\" att-file-change></label>");
19532 }]);
19533
19534 angular.module("app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlert.html", []).run(["$templateCache", function($templateCache) {
19535   $templateCache.put("app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlert.html",
19536     "<div class=\"form-field\" ng-class=\"{'error': errorMessage, 'warning': warningMessage}\">\n" +
19537     "    <label class=\"form-field__label\" ng-class=\"{'form-field__label--show': showLabel, 'form-field__label--hide': hideLabel}\"></label>\n" +
19538     "    <div class=\"form-field-input-container\" ng-transclude></div>\n" +
19539     "</div>");
19540 }]);
19541
19542 angular.module("app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlertPrv.html", []).run(["$templateCache", function($templateCache) {
19543   $templateCache.put("app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlertPrv.html",
19544     "<div class=\"form-field\" ng-class=\"{'error':hideErrorMsg}\">\n" +
19545     "    <div class=\"form-field-input-container\" ng-transclude></div>\n" +
19546     "   <div class=\"form-field__message error\" type=\"error\" ng-show=\"hideErrorMsg\" >\n" +
19547     "           <i class=\"icon-info-alert\"></i>{{errorMessage}}\n" +
19548     "   </div>\n" +
19549     "</div>\n" +
19550     "");
19551 }]);
19552
19553 angular.module("app/scripts/ng_js_att_tpls/formField/creditCardImage.html", []).run(["$templateCache", function($templateCache) {
19554   $templateCache.put("app/scripts/ng_js_att_tpls/formField/creditCardImage.html",
19555     "<span class=\"css-sprite pull-right\">\n" +
19556     "<span class=\"hidden-spoken\">We accept</span>\n" +
19557     "<ul class=\"{{newValCCI}}\">\n" +
19558     "        <li class=\"css-sprite-mc\"><span class=\"hidden-spoken\">MasterCard</span></li>\n" +
19559     "        <li class=\"css-sprite-visa\"><span class=\"hidden-spoken\">Visa</span></li>\n" +
19560     "        <li class=\"css-sprite-amex\"><span class=\"hidden-spoken\">American Express</span></li>\n" +
19561     "        <li class=\"css-sprite-discover\"><span class=\"hidden-spoken\">Discover</span></li>                                                                                                               \n" +
19562     "</ul>\n" +
19563     "</span>\n" +
19564     "<label for=\"ccForm.card\" class=\"pull-left\">Card number</label>");
19565 }]);
19566
19567 angular.module("app/scripts/ng_js_att_tpls/formField/cvcSecurityImg.html", []).run(["$templateCache", function($templateCache) {
19568   $templateCache.put("app/scripts/ng_js_att_tpls/formField/cvcSecurityImg.html",
19569     "<div>\n" +
19570     "<button type=\"button\" class=\"btn btn-alt btn-tooltip\" style=\"padding-top:16px\" title=\"Help\"><i class=\"hidden-spoken\">Help</i></button>\n" +
19571     "<div class=\"helpertext\" role=\"tooltip\">\n" +
19572     "<div class=\"popover-title\"></div>\n" +
19573     "<div class=\"popover-content\">\n" +
19574     "    <p class=\"text-legal cvc-cc\">\n" +
19575     "        <img ng-src=\"images/{{newValI}}.png\" alt=\"{{newValIAlt}}\">\n" +
19576     "    </p>\n" +
19577     "</div>\n" +
19578     "</div>\n" +
19579     "</div>\n" +
19580     "");
19581 }]);
19582
19583 angular.module("app/scripts/ng_js_att_tpls/hourpicker/hourpicker.html", []).run(["$templateCache", function($templateCache) {
19584   $templateCache.put("app/scripts/ng_js_att_tpls/hourpicker/hourpicker.html",
19585     "<div class=\"hourpicker\">\n" +
19586     "    <div class=\"dropdown-width\">\n" +
19587     "        <div ng-model=\"showlist\" class=\"select2-container topDropDownWidth\" ng-class=\"{'select2-dropdown-open select2-container-active': showlist}\" >\n" +
19588     "            <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" +
19589     "                <span class=\"select2-chosen\">{{selectedOption}}</span>\n" +
19590     "                <span class=\"select2-arrow\"><b></b></span>\n" +
19591     "            </a>\n" +
19592     "        </div>             \n" +
19593     "        <div class=\"select2-display-none select2-with-searchbox select2-drop-active show-search resultTopWidth\" ng-show=\"showlist\">       \n" +
19594     "        <ul class=\"select2-results resultTopMargin\" >                       \n" +
19595     "            <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" +
19596     "        </ul>\n" +
19597     "        </div>\n" +
19598     "    </div>\n" +
19599     "    <div ng-show=\"showDaysSelector\" class=\"customdays-width\">\n" +
19600     "        <div att-divider-lines class=\"divider-margin-f\"></div>  \n" +
19601     "        <div class=\"col-md-3 fromto-margin\">\n" +
19602     "            <div>From</div> <br>\n" +
19603     "            <div>To</div>\n" +
19604     "        </div>\n" +
19605     "        <div ng-repeat=\"day in days\">\n" +
19606     "            <div class=\"col-md-3 col-md-days\">\n" +
19607     "                <div  class=\"col-md-1 daysselect-margin\">\n" +
19608     "                    <input type=\"checkbox\" ng-model=\"daysList[day]\" title=\"Day selection {{$index}}\" att-checkbox ng-change=\"addSelectedValue(day)\">    \n" +
19609     "                </div>\n" +
19610     "                <span>{{day}}</span><br>\n" +
19611     "                \n" +
19612     "                <div class=\"dropDownMarginBottom\">\n" +
19613     "                    <div class=\"select2-container topDropDownWidth\" ng-class=\"{'select2-dropdown-open select2-container-active': FrtimeListDay[day]}\" >\n" +
19614     "                        <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" +
19615     "                            <span class=\"select2-chosen dropDownMarginRight\" >{{selectedFromOption[day]}} <i ng-if=\"daysList[day]\" ng-class=\"FrtimeListDay[day] ? 'icon-dropdown-up' : 'icon-dropdown-down'\"></i></span>\n" +
19616     "                        </a>\n" +
19617     "                    </div>             \n" +
19618     "                    \n" +
19619     "                    <div class=\"select2-display-none select2-with-searchbox select2-drop-active show-search resultFromDropDown\"  ng-show=\"FrtimeListDay[day]\">       \n" +
19620     "                    <ul class=\"select2-results resultTopMargin\" >                       \n" +
19621     "                        <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" +
19622     "                    </ul>\n" +
19623     "                    </div>\n" +
19624     "                </div>\n" +
19625     "                \n" +
19626     "                <div class=\"dropDownMarginBottom\">\n" +
19627     "                    <div class=\"select2-container topDropDownWidth\" ng-class=\"{'select2-dropdown-open select2-container-active': TotimeListDay[day]}\" >\n" +
19628     "                        <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" +
19629     "                            <span class=\"select2-chosen dropDownMarginRight\">{{selectedToOption[day]}} <i ng-if=\"daysList[day]\" ng-class=\"TotimeListDay[day] ? 'icon-dropdown-up' : 'icon-dropdown-down'\" ></i></span>\n" +
19630     "                        </a>\n" +
19631     "                    </div>\n" +
19632     "                    \n" +
19633     "                    <div class=\"select2-display-none select2-with-searchbox select2-drop-active show-search resultToDropDown\" ng-show=\"TotimeListDay[day]\">       \n" +
19634     "                    <ul class=\"select2-results resultTopMargin\" >                       \n" +
19635     "                        <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" +
19636     "                    </ul>\n" +
19637     "                    </div>\n" +
19638     "                </div>\n" +
19639     "            </div>  \n" +
19640     "        </div>    \n" +
19641     "        <div att-divider-lines class=\"divider-margin-s\"></div>\n" +
19642     "    </div>\n" +
19643     "    <div ng-transclude></div>\n" +
19644     "</div>");
19645 }]);
19646
19647 angular.module("app/scripts/ng_js_att_tpls/links/readMore.html", []).run(["$templateCache", function($templateCache) {
19648   $templateCache.put("app/scripts/ng_js_att_tpls/links/readMore.html",
19649     "<div>\n" +
19650     "    <div ng-bind-html=\"textToDisplay\" ng-class=\"{'att--readMore': readFlag, 'att--readLess': !readFlag}\" ng-style=\"readLinkStyle\"></div>\n" +
19651     "    <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" +
19652     "    </span>\n" +
19653     "</div>\n" +
19654     "<span class=\"att--readless__link\" ng-show=\"readLessLink\">\n" +
19655     "    <a href=\"javascript:void(0);\" ng-click=\"readLess()\" att-accessbility-click=\"32,13\">Read Less</a>\n" +
19656     "</span>");
19657 }]);
19658
19659 angular.module("app/scripts/ng_js_att_tpls/loading/loading.html", []).run(["$templateCache", function($templateCache) {
19660   $templateCache.put("app/scripts/ng_js_att_tpls/loading/loading.html",
19661     "<div data-progress=\"{{progressStatus}}\" class=\"{{colorClass}}\" ng-class=\"{'att-loading-count':icon == 'count','loading--small':icon == 'small','loading': icon != 'count'}\" alt=\"Loading\">\n" +
19662     "   <div class=\"att-loading-circle\" ng-if=\"icon == 'count'\">\n" +
19663     "           <div class=\"att-loading-circle__mask att-loading-circle__full\">\n" +
19664     "                   <div class=\"att-loading-circle__fill\"></div>\n" +
19665     "           </div>\n" +
19666     "           <div class=\"att-loading-circle__mask att-loading-circle__half\">\n" +
19667     "                   <div class=\"att-loading-circle__fill\"></div>\n" +
19668     "                   <div class=\"att-loading-circle__fill att-loading-circle__fix\"></div>\n" +
19669     "           </div>\n" +
19670     "   </div>\n" +
19671     "   <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" +
19672     "</div>\n" +
19673     "\n" +
19674     "");
19675 }]);
19676
19677 angular.module("app/scripts/ng_js_att_tpls/modal/backdrop.html", []).run(["$templateCache", function($templateCache) {
19678   $templateCache.put("app/scripts/ng_js_att_tpls/modal/backdrop.html",
19679     "<div class=\"overlayed\" ng-class=\"{show: animate}\" \n" +
19680     "     ng-style=\"{'z-index': 2000 + index*10,'overflow':'scroll'}\">         \n" +
19681     "</div>");
19682 }]);
19683
19684 angular.module("app/scripts/ng_js_att_tpls/modal/tabbedItem.html", []).run(["$templateCache", function($templateCache) {
19685   $templateCache.put("app/scripts/ng_js_att_tpls/modal/tabbedItem.html",
19686     "<div>\n" +
19687     "    <ul class=\"tabs_overlay\">\n" +
19688     "        <li ng-repeat=\"item in items\" class=\"tabs_overlay__item two__item\" ng-class=\"{'active':isActiveTab($index)}\" ng-click=\"clickTab($index)\">\n" +
19689     "            <i class=\"{{item.iconClass}}\"></i>\n" +
19690     "            {{item.title}} ({{item.number}})\n" +
19691     "            <a class=\"viewLink\" att-link>Show</a>\n" +
19692     "        </li>\n" +
19693     "    </ul>\n" +
19694     "</div>");
19695 }]);
19696
19697 angular.module("app/scripts/ng_js_att_tpls/modal/tabbedOverlayItem.html", []).run(["$templateCache", function($templateCache) {
19698   $templateCache.put("app/scripts/ng_js_att_tpls/modal/tabbedOverlayItem.html",
19699     "<div>\n" +
19700     "    <ul class=\"tabs_overlay\">\n" +
19701     "        <li ng-repeat=\"item in items\" class=\"tabs_overlay__item two__item\" ng-class=\"{'active':isActiveTab($index)}\" ng-click=\"clickTab($index)\">\n" +
19702     "            <i class=\"{{item.iconClass}}\"></i>\n" +
19703     "            {{item.title}} ({{item.number}})\n" +
19704     "            <a class=\"viewLink\" att-link>Show</a>\n" +
19705     "        </li>\n" +
19706     "    </ul>\n" +
19707     "</div>");
19708 }]);
19709
19710 angular.module("app/scripts/ng_js_att_tpls/modal/window.html", []).run(["$templateCache", function($templateCache) {
19711   $templateCache.put("app/scripts/ng_js_att_tpls/modal/window.html",
19712     "<div tabindex=\"-1\" role=\"dialog\" att-element-focus=\"focusModalFlag\" class=\"modals {{ windowClass }}\" ng-class=\"{show: animate}\" \n" +
19713     "     ng-style=\"{'z-index': 2010 + index*10}\"  ng-click=\"close($event)\" ng-transclude>         \n" +
19714     "</div>\n" +
19715     "");
19716 }]);
19717
19718 angular.module("app/scripts/ng_js_att_tpls/pagination/pagination.html", []).run(["$templateCache", function($templateCache) {
19719   $templateCache.put("app/scripts/ng_js_att_tpls/pagination/pagination.html",
19720     "<div class=\"pager\">\n" +
19721     "    <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" +
19722     "    <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" +
19723     "    <span class=\"pager__item\" ng-if=\"totalPages > 7 && currentPage > 3\">...</span>\n" +
19724     "    <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" +
19725     "    <span class=\"pager__item\" ng-if=\"totalPages > 7 && currentPage < totalPages - 2 && showInput !== true\">...</span>\n" +
19726     "    <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" +
19727     "    <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" +
19728     "    <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" +
19729     "</div>");
19730 }]);
19731
19732 angular.module("app/scripts/ng_js_att_tpls/paneSelector/innerPane.html", []).run(["$templateCache", function($templateCache) {
19733   $templateCache.put("app/scripts/ng_js_att_tpls/paneSelector/innerPane.html",
19734     "<div class='inner-pane' ng-transclude></div>");
19735 }]);
19736
19737 angular.module("app/scripts/ng_js_att_tpls/paneSelector/paneGroup.html", []).run(["$templateCache", function($templateCache) {
19738   $templateCache.put("app/scripts/ng_js_att_tpls/paneSelector/paneGroup.html",
19739     "<div class='pane-group' ng-transclude></div>");
19740 }]);
19741
19742 angular.module("app/scripts/ng_js_att_tpls/paneSelector/sidePane.html", []).run(["$templateCache", function($templateCache) {
19743   $templateCache.put("app/scripts/ng_js_att_tpls/paneSelector/sidePane.html",
19744     "<div class='side-pane' ng-transclude></div>");
19745 }]);
19746
19747 angular.module("app/scripts/ng_js_att_tpls/tooltip/tooltip-popup.html", []).run(["$templateCache", function($templateCache) {
19748   $templateCache.put("app/scripts/ng_js_att_tpls/tooltip/tooltip-popup.html",
19749     "<div class=\"att-tooltip \" \n" +
19750     "     ng-class=\"{ 'att-tooltip--on': isOpen, \n" +
19751     "                'att-tooltip--dark att-tooltip--dark--hover':stylett=='dark', \n" +
19752     "                'att-tooltip--light att-tooltip--light--hover':stylett=='light',\n" +
19753     "                'att-tooltip--left':placement=='left', \n" +
19754     "                'att-tooltip--above':placement=='above', \n" +
19755     "                'att-tooltip--right':placement=='right', \n" +
19756     "                'att-tooltip--below':placement=='below'}\" \n" +
19757     "    ng-bind-html=\"content | unsafe\" ></div>");
19758 }]);
19759
19760 angular.module("app/scripts/ng_js_att_tpls/popOvers/popOvers.html", []).run(["$templateCache", function($templateCache) {
19761   $templateCache.put("app/scripts/ng_js_att_tpls/popOvers/popOvers.html",
19762     "<div class=\"att-popover popover-demo\" ng-style=\"{backgroundColor:popOverStyle}\"\n" +
19763     "     ng-class=\"{'att-tooltip--dark':popOverStyle==='grey',\n" +
19764     "                'att-pop-over--left':popOverPlacement==='left', \n" +
19765     "                'att-pop-over--bell':popOverPlacement==='bell', \n" +
19766     "                'att-pop-over--above':popOverPlacement==='above', \n" +
19767     "                'att-pop-over--right':popOverPlacement==='right'}\" \n" +
19768     "    style='position: absolute; max-width: 490px;'>\n" +
19769     "    <div class=\"pop-over-caret\"\n" +
19770     "         ng-class=\"{'pop-over-caret-border--left':popOverPlacement==='left', \n" +
19771     "                'pop-over-caret-border--above':popOverPlacement==='above', \n" +
19772     "                'pop-over-caret-border--right':popOverPlacement==='right', \n" +
19773     "                'pop-over-caret-border--below':popOverPlacement==='below'}\">\n" +
19774     "    </div>\n" +
19775     "    <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" +
19776     "         ng-class=\"{'pop-over-caret--left':popOverPlacement==='left', \n" +
19777     "                'pop-over-caret--above':popOverPlacement==='above', \n" +
19778     "                'pop-over-caret--right':popOverPlacement==='right', \n" +
19779     "                'pop-over-caret--below':popOverPlacement==='below'}\"></div>\n" +
19780     "    \n" +
19781     "    <div class=\"att-popover-content\">\n" +
19782     "   <a ng-if=\"closeable\" href=\"javascript:void(0)\" class=\"icon-close att-popover__close\" ng-click=\"closeMe();$event.preventDefault()\"></a>\n" +
19783     "        <div class=\"popover-packages__container\" ng-include=\"content\"></div>\n" +
19784     "    </div>\n" +
19785     "</div>");
19786 }]);
19787
19788 angular.module("app/scripts/ng_js_att_tpls/profileCard/addUser.html", []).run(["$templateCache", function($templateCache) {
19789   $templateCache.put("app/scripts/ng_js_att_tpls/profileCard/addUser.html",
19790     "<div  class=\"col-md-9 profile-card add-user\">\n" +
19791     "    <div class=\"atcenter\">\n" +
19792     "        <div><i class=\"icon-add\"></i></div>\n" +
19793     "        <span>add User</span>\n" +
19794     "    </div>\n" +
19795     "</div>");
19796 }]);
19797
19798 angular.module("app/scripts/ng_js_att_tpls/profileCard/profileCard.html", []).run(["$templateCache", function($templateCache) {
19799   $templateCache.put("app/scripts/ng_js_att_tpls/profileCard/profileCard.html",
19800     "<div class=\"col-md-9 profile-card\">\n" +
19801     "    <div class=\"top-block\">\n" +
19802     "       <div class=\"profile-image\">\n" +
19803     "            <img ng-if=\"image\" profile-name=\"{{profile.name}}\" ng-src=\"{{profile.img}}\" alt=\"{{profile.name}}\">\n" +
19804     "            <span ng-hide=\"image\" class=\"default-img\">{{initials}}</span>\n" +
19805     "            <p class=\"name\" tooltip-condition=\"{{profile.name}}\" height=\"true\"></p>\n" +
19806     "            <p class=\"status\">\n" +
19807     "                <span class=\"status-icon\" ng-class=\"{'icon-green':colorIcon==='green','icon-red':colorIcon==='red','icon-blue':colorIcon==='blue','icon-yellow':colorIcon==='yellow'}\">   \n" +
19808     "                </span>\n" +
19809     "                <span>{{profile.state}}<span ng-if=\"badge\" class=\"status-badge\">Admin</span></span>\n" +
19810     "            </p>\n" +
19811     "        </div>\n" +
19812     "    </div>\n" +
19813     "    <div class=\"bottom-block\">\n" +
19814     "         <div class=\"profile-details\">\n" +
19815     "            <label>Username</label>\n" +
19816     "            <p att-text-overflow=\"92%\" tooltip-condition=\"{{profile.userName}}\">{{profile.userName}}</p>\n" +
19817     "            <label>Email</label>\n" +
19818     "            <p att-text-overflow=\"92%\" tooltip-condition=\"{{profile.email}}\">{{profile.email}}</p>\n" +
19819     "            <label>Role</label>\n" +
19820     "            <p att-text-overflow=\"92%\" tooltip-condition=\"{{profile.role}}\">{{profile.role}}</p>\n" +
19821     "            <label>Last Login</label>\n" +
19822     "            <p att-text-overflow=\"92%\" tooltip-condition=\"{{profile.lastLogin}}\">{{profile.lastLogin}}</p>\n" +
19823     "         </div>\n" +
19824     "    </div>\n" +
19825     "</div>");
19826 }]);
19827
19828 angular.module("app/scripts/ng_js_att_tpls/progressBars/progressBars.html", []).run(["$templateCache", function($templateCache) {
19829   $templateCache.put("app/scripts/ng_js_att_tpls/progressBars/progressBars.html",
19830     "<div class=\"att-progress\">\n" +
19831     "    <div class=\"att-progress-value\">&nbsp;</div>\n" +
19832     "</div>");
19833 }]);
19834
19835 angular.module("app/scripts/ng_js_att_tpls/scrollbar/scrollbar.html", []).run(["$templateCache", function($templateCache) {
19836   $templateCache.put("app/scripts/ng_js_att_tpls/scrollbar/scrollbar.html",
19837     "<div class=\"scroll-bar\" style=\"position: absolute\">\n" +
19838     "    <div class=\"scroll-thumb\" style=\"position: absolute; overflow: hidden\"></div>\n" +
19839     "</div>\n" +
19840     "<div class=\"prev icons-list\" data-size=\"medium\" ng-show=\"navigation && prevAvailable\" ng-style=\"{height: scrollbarAxis === 'x' && position.height + 'px'}\">\n" +
19841     "    <a href=\"javascript:void(0);\" ng-click=\"customScroll(false)\" aria-label=\"Scroll\" aria-hidden=\"true\">\n" +
19842     "        <i ng-class=\"{'icon-chevron-up': (scrollbarAxis === 'y'), 'icon-chevron-left': (scrollbarAxis === 'x')}\"></i>\n" +
19843     "    </a>\n" +
19844     "</div>\n" +
19845     "<div class=\"scroll-viewport\" ng-style=\"{height: (scrollbarAxis === 'x' && position.height + 'px') || viewportHeight, width: viewportWidth}\" style=\"position: relative; overflow: hidden\">\n" +
19846     "    <div class=\"scroll-overview\" style=\"position: absolute; display: table; width: 100%\" att-position=\"position\" ng-transclude></div>\n" +
19847     "</div>\n" +
19848     "<div class='next icons-list' data-size=\"medium\" ng-show=\"navigation && nextAvailable\" ng-style=\"{height: scrollbarAxis === 'x' && position.height + 'px'}\">\n" +
19849     "    <a href=\"javascript:void(0);\" ng-click=\"customScroll(true)\" aria-label=\"Scroll\" aria-hidden=\"true\">\n" +
19850     "        <i ng-class=\"{'icon-chevron-down': (scrollbarAxis === 'y'), 'icon-chevron-right': (scrollbarAxis === 'x')}\"></i>\n" +
19851     "    </a>\n" +
19852     "</div>\n" +
19853     "");
19854 }]);
19855
19856 angular.module("app/scripts/ng_js_att_tpls/search/search.html", []).run(["$templateCache", function($templateCache) {
19857   $templateCache.put("app/scripts/ng_js_att_tpls/search/search.html",
19858     "<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" +
19859     "    <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" +
19860     "        <span class=\"select2-chosen needsclick\" aria-hidden = \"true\">{{selectedOption}}</span>\n" +
19861     "        <abbr class=\"select2-search-choice-close needsclick\"></abbr>\n" +
19862     "        <span class=\"select2-arrow needsclick\" role=\"presentation\">\n" +
19863     "            <b role=\"presentation\" class=\"needsclick\"></b>\n" +
19864     "        </span>\n" +
19865     "    </a>    \n" +
19866     "    <input class=\"select2-focusser select2-offscreen\"            \n" +
19867     "           tabindex=\"-1\" \n" +
19868     "           type=\"text\" \n" +
19869     "           aria-hidden=\"true\" \n" +
19870     "           title=\"hidden\"           \n" +
19871     "           aria-haspopup=\"true\"           \n" +
19872     "           role=\"button\">    \n" +
19873     "</div>\n" +
19874     "\n" +
19875     "<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" +
19876     "    <div class=\"select2-search\">\n" +
19877     "        <label ng-if=\"!noFilter\" class=\"select2-offscreen\" aria-label=\"Inline Search Field\" aria-hidden=\"true\">Inline Search Field</label>\n" +
19878     "        <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" +
19879     "    </div>\n" +
19880     "    <ul id=\"inList\" class=\"select2-results\" role=\"listbox\">\n" +
19881     "        <li ng-show=\"filteredName.length === 0\" class=\"select2-no-results\" tabindex=\"-1\">No matches found</li>\n" +
19882     "        <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" +
19883     "            <div ng-if=\"startsWithFilter\" class=\"select2-result-label\" ng-bind-html=\"selectMsg | unsafe\" role=\"option\">\n" +
19884     "                <span class=\"select2-match\"></span>\n" +
19885     "            </div>\n" +
19886     "            <div ng-if=\"!startsWithFilter\" class=\"select2-result-label\" ng-bind-html=\"selectMsg | highlight:title:className | unsafe\" role=\"option\">\n" +
19887     "                <span class=\"select2-match\"></span>\n" +
19888     "            </div>\n" +
19889     "        </li>\n" +
19890     "\n" +
19891     "        <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" +
19892     "            <div class=\"select2-result-label\" ng-bind-html=\"item.title | unsafe\" role=\"option\">\n" +
19893     "                <span class=\"select2-match\"></span>\n" +
19894     "            </div>\n" +
19895     "        </li>\n" +
19896     "\n" +
19897     "        <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" +
19898     "            <div class=\"select2-result-label\" ng-bind-html=\"item.title | highlight:title:className | unsafe\" role=\"option\">\n" +
19899     "                <span class=\"select2-match\"></span>\n" +
19900     "            </div>\n" +
19901     "        </li>\n" +
19902     "    </ul>\n" +
19903     "</div>");
19904 }]);
19905
19906 angular.module("app/scripts/ng_js_att_tpls/select/select.html", []).run(["$templateCache", function($templateCache) {
19907   $templateCache.put("app/scripts/ng_js_att_tpls/select/select.html",
19908     "<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" +
19909     "    <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=\"{{selectedOption}} selected\" ng-focus=\"isact=true;\" ng-blur=\"isact=false;\">\n" +
19910     "        <span class=\"select2-chosen needsclick\" aria-hidden=\"true\">{{selectedOption}}</span>\n" +
19911     "        <abbr class=\"select2-search-choice-close needsclick\"></abbr>\n" +
19912     "        <span class=\"select2-arrow needsclick\" role=\"presentation\">\n" +
19913     "            <b role=\"presentation\" class=\"needsclick\"></b>\n" +
19914     "        </span>\n" +
19915     "    </span>    \n" +
19916     "    <input class=\"select2-focusser select2-offscreen\"            \n" +
19917     "           tabindex=\"-1\" \n" +
19918     "           type=\"text\" \n" +
19919     "           aria-hidden=\"true\" \n" +
19920     "           title=\"hidden\"           \n" +
19921     "           aria-haspopup=\"true\"           \n" +
19922     "           role=\"button\">    \n" +
19923     "</div>\n" +
19924     "\n" +
19925     "<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" +
19926     "    <div class=\"select2-search\">\n" +
19927     "        <label ng-if=\"!noFilter\" class=\"select2-offscreen\" aria-label=\"Inline Search Field\" aria-hidden=\"true\">Inline Search Field</label>\n" +
19928     "        <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" +
19929     "    </div>\n" +
19930     "    <ul id=\"inList\" class=\"select2-results\" role=\"listbox\">\n" +
19931     "        <li ng-if=\"!noFilter\" ng-show=\"filteredName.length === 0\" class=\"select2-no-results\" tabindex=\"-1\">No matches found</li>\n" +
19932     "        <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" +
19933     "            <div ng-if=\"startsWithFilter\" class=\"select2-result-label\" ng-bind-html=\"selectMsg | unsafe\" role=\"option\">\n" +
19934     "                <span class=\"select2-match\"></span>\n" +
19935     "            </div>\n" +
19936     "            <div ng-if=\"!startsWithFilter\" class=\"select2-result-label\" ng-bind-html=\"selectMsg | highlight:title:className | unsafe\" role=\"option\">\n" +
19937     "                <span class=\"select2-match\"></span>\n" +
19938     "            </div>\n" +
19939     "        </li>\n" +
19940     "\n" +
19941     "        <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" +
19942     "            <div class=\"select2-result-label\" ng-bind-html=\"item.title | unsafe\" role=\"option\">\n" +
19943     "                <span class=\"select2-match\"></span>\n" +
19944     "            </div>\n" +
19945     "        </li>\n" +
19946     "\n" +
19947     "        <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" +
19948     "            <div class=\"select2-result-label\" ng-bind-html=\"item.title | highlight:title:className | unsafe\" role=\"option\">\n" +
19949     "                <span class=\"select2-match\"></span>\n" +
19950     "            </div>\n" +
19951     "        </li>\n" +
19952     "    </ul>\n" +
19953     "</div>");
19954 }]);
19955
19956 angular.module("app/scripts/ng_js_att_tpls/select/textDropdown.html", []).run(["$templateCache", function($templateCache) {
19957   $templateCache.put("app/scripts/ng_js_att_tpls/select/textDropdown.html",
19958     "<div tabindex=\"0\" class=\"text-dropdown\">\n" +
19959     "   <div class=\"dropdown\" ng-class=\"{'not-visible': isActionsShown}\" ng-click=\"toggle()\">\n" +
19960     "           <span class=\"action--selected\" ng-bind=\"currentAction\"></span>\n" +
19961     "           <i ng-class=\"isActionsShown ? 'icon-dropdown-up' : 'icon-dropdown-down'\"></i>\n" +
19962     "   </div>\n" +
19963     "   <ul ng-class=\"isActionsShown ? 'actionsOpened' : 'actionsClosed'\" ng-show=\"isActionsShown\">\n" +
19964     "           <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" +
19965     "   </ul>\n" +
19966     "</div>");
19967 }]);
19968
19969 angular.module("app/scripts/ng_js_att_tpls/slider/maxContent.html", []).run(["$templateCache", function($templateCache) {
19970   $templateCache.put("app/scripts/ng_js_att_tpls/slider/maxContent.html",
19971     "<div class=\"att-slider__label att-slider__label--max att-slider__label--below\" ng-transclude></div>");
19972 }]);
19973
19974 angular.module("app/scripts/ng_js_att_tpls/slider/minContent.html", []).run(["$templateCache", function($templateCache) {
19975   $templateCache.put("app/scripts/ng_js_att_tpls/slider/minContent.html",
19976     "<div class=\"att-slider__label att-slider__label--min att-slider__label--below\" ng-transclude></div>");
19977 }]);
19978
19979 angular.module("app/scripts/ng_js_att_tpls/slider/slider.html", []).run(["$templateCache", function($templateCache) {
19980   $templateCache.put("app/scripts/ng_js_att_tpls/slider/slider.html",
19981     "<div class=\"att-slider\" ng-mousemove=\"moveElem($event)\" ng-mouseup=\"mouseUp($event)\">\n" +
19982     "    <div class=\"att-slider__track\">\n" +
19983     "        <div class=\"att-slider__range att-slider__range--disabled\" ng-style=\"disabledStyle\"></div>\n" +
19984     "        <div class=\"att-slider__range\" ng-style=\"rangeStyle\"></div>\n" +
19985     "    </div>\n" +
19986     "    <div class=\"att-slider__handles-container\">\n" +
19987     "       <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" +
19988     "       <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" +
19989     "       <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" +
19990     "    </div>\n" +
19991     "    <div ng-transclude></div>\n" +
19992     "</div>");
19993 }]);
19994
19995 angular.module("app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdown.html", []).run(["$templateCache", function($templateCache) {
19996   $templateCache.put("app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdown.html",
19997     "<div class=\" btn-group\" \n" +
19998     "     ng-class=\"{'buttons-dropdown--large':!isSmall, \n" +
19999     "                 'buttons-dropdown--small':isSmall, \n" +
20000     "                 'action-dropdown':(isActionDropdown), \n" +
20001     "                 'open':isDropDownOpen}\">\n" +
20002     "    <a tabindex=\"0\" href=\"javascript:void(0)\" class=\"button btn buttons-dropdown__split\" \n" +
20003     "       ng-class=\"{'button--primary':(btnType==undefined || btnType=='primary'), \n" +
20004     "                   'button--secondary':btnType=='secondary', \n" +
20005     "                   'button--disabled':btnType=='disabled', \n" +
20006     "                   'button--small':isSmall}\" \n" +
20007     "       ng-if=\"!isActionDropdown\"\n" +
20008     "       ng-click=\"btnType==='disabled'?undefined:clickFxn()\" att-accessibility-click=\"13,32\">{{btnText}}</a>\n" +
20009     "    <a tabindex=\"0\" href=\"javascript:void(0)\" role=\"button\" aria-label=\"Toggle Dropdown\" aria-haspopup=\"true\" class=\"button buttons-dropdown__drop dropdown-toggle\" \n" +
20010     "       ng-class=\"{'button--primary':(btnType==undefined || btnType=='primary'), \n" +
20011     "               'button--secondary':btnType=='secondary', \n" +
20012     "               'button--disabled':btnType=='disabled', \n" +
20013     "               'button--small':isSmall}\" ng-click=\"toggleDropdown()\" att-accessibility-click=\"13,32\">{{toggleTitle}} </a>\n" +
20014     "    <ul class=\"dropdown-menu\" ng-class=\"{'align-right':multiselect ===true}\" aria-expanded=\"{{isDropDownOpen}}\" ng-click=\"hideDropdown()\" role=\"menu\" ng-transclude></ul>\n" +
20015     "</div>  ");
20016 }]);
20017
20018 angular.module("app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdownItem.html", []).run(["$templateCache", function($templateCache) {
20019   $templateCache.put("app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdownItem.html",
20020     "<li role=\"menuitem\" att-element-focus=\"sFlag\" tabindex=\"0\" ng-transclude></li>");
20021 }]);
20022
20023 angular.module("app/scripts/ng_js_att_tpls/splitIconButton/splitIcon.html", []).run(["$templateCache", function($templateCache) {
20024   $templateCache.put("app/scripts/ng_js_att_tpls/splitIconButton/splitIcon.html",
20025     "<div class='split-icon-button-container'>\n" +
20026     "\n" +
20027     "   <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" +
20028     "           <a class='{{icon}}' title='{{iconTitle}}' tabindex=\"0\"></a>\n" +
20029     "           <i ng-if=\"isRight && !isMiddle && !isLeftNextDropdown && !isNextToDropDown\" \n" +
20030     "                   ng-class=\"isDropDownOpen ? 'icon-dropdown-up' : 'icon-dropdown-down'\"> </i>\n" +
20031     "   </div> \n" +
20032     "\n" +
20033     "    <ul ng-if='isDropdown' class='dropdown-menu {{dropDownId}}' ng-show='\n" +
20034     "    isDropDownOpen' ng-click='toggleDropdown(false)' role=\"presentation\" ng-transclude>\n" +
20035     "    </ul>\n" +
20036     "\n" +
20037     "</div>");
20038 }]);
20039
20040 angular.module("app/scripts/ng_js_att_tpls/splitIconButton/splitIconButton.html", []).run(["$templateCache", function($templateCache) {
20041   $templateCache.put("app/scripts/ng_js_att_tpls/splitIconButton/splitIconButton.html",
20042     "<div>\n" +
20043     "   <div ng-if='isLeftLineShown' dir-type='{{iconStateConstants.DIR_TYPE.LEFT}}' expandable-line></div>\n" +
20044     "   <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" +
20045     "           <div ng-transclude>\n" +
20046     "           </div>\n" +
20047     "   </div>\n" +
20048     "   <div ng-if='isRightLineShown' dir-type='{{iconStateConstants.DIR_TYPE.RIGHT}}' expandable-line></div>\n" +
20049     "</div>");
20050 }]);
20051
20052 angular.module("app/scripts/ng_js_att_tpls/splitIconButton/splitIconButtonGroup.html", []).run(["$templateCache", function($templateCache) {
20053   $templateCache.put("app/scripts/ng_js_att_tpls/splitIconButton/splitIconButtonGroup.html",
20054     "<div ng-transclude>\n" +
20055     "</div>");
20056 }]);
20057
20058 angular.module("app/scripts/ng_js_att_tpls/stepSlider/attStepSlider.html", []).run(["$templateCache", function($templateCache) {
20059   $templateCache.put("app/scripts/ng_js_att_tpls/stepSlider/attStepSlider.html",
20060     "<span ng-class=\"mainSliderClass\">\n" +
20061     "    <table>\n" +
20062     "        <tr>\n" +
20063     "            <td>\n" +
20064     "                <div class=\"jslider-bg\">\n" +
20065     "                    <i class=\"l\"></i>\n" +
20066     "                    <i class=\"r\"></i>\n" +
20067     "                    <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" +
20068     "                </div>\n" +
20069     "                <div class=\"jslider-pointer\" id=\"left-pointer\"></div>\n" +
20070     "                <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" +
20071     "                <div class=\"jslider-label\"><span ng-bind=\"from\"></span><span ng-bind=\"options.dimension\"></span></div>\n" +
20072     "                <div class=\"jslider-label jslider-label-to\"><span ng-bind=\"toStr\"></span><span ng-bind=\"endDimension\"></span></div>\n" +
20073     "                <div class=\"jslider-value\" id=\"jslider-value-left\"><span></span>{{options.dimension}}</div>\n" +
20074     "                <div class=\"jslider-value jslider-value-to\"><span></span>{{toolTipDimension}}</div>\n" +
20075     "                <div class=\"jslider-scale\" ng-class=\"{'show-dividers': showDividers, 'cutoff-slider-dividers':isCutOffSlider}\">\n" +
20076     "                </div>\n" +
20077     "                <div class=\"jslider-cutoff\">\n" +
20078     "                    <div class=\"jslider-label jslider-label-cutoff\">\n" +
20079     "                        <span ng-bind=\"cutOffVal\"></span>\n" +
20080     "                    </div>\n" +
20081     "                </div>\n" +
20082     "            </td>\n" +
20083     "        </tr>\n" +
20084     "    </table>\n" +
20085     "</span>\n" +
20086     "");
20087 }]);
20088
20089 angular.module("app/scripts/ng_js_att_tpls/steptracker/step-tracker.html", []).run(["$templateCache", function($templateCache) {
20090   $templateCache.put("app/scripts/ng_js_att_tpls/steptracker/step-tracker.html",
20091     "<div class=\"steptracker1\">\n" +
20092     "    <div class=\"steptracker-bg\">\n" +
20093     "        <div tabindex=\"0\" ng-click=\"stepclick($event, $index);\" att-accessibility-click=\"13,23\" class=\"steptracker-track size-onethird\" ng-repeat=\"step in sdata\"\n" +
20094     "             ng-style=\"set_width($index)\"\n" +
20095     "             ng-class=\"{'last':laststep($index),'done':donesteps($index),'active':activestep($index), 'incomplete': isIncomplete($index), 'disabled': disableClick}\">\n" +
20096     "            <div class=\"circle\">{{($index) + 1}}<span>{{step.title}}</span></div>\n" +
20097     "            <div ng-if=\"!laststep($index)\" class=\"track\"></div>\n" +
20098     "        </div>\n" +
20099     "    </div>\n" +
20100     "</div>");
20101 }]);
20102
20103 angular.module("app/scripts/ng_js_att_tpls/steptracker/step.html", []).run(["$templateCache", function($templateCache) {
20104   $templateCache.put("app/scripts/ng_js_att_tpls/steptracker/step.html",
20105     "<div class=\"steptracker1\">\n" +
20106     "    <div class=\"steptracker-bg\">\n" +
20107     "        <div class=\"steptracker-track size-onethird\" \n" +
20108     "             ng-class=\"{'last':laststep($index),'done':donesteps($index),'active':activestep($index)}\">\n" +
20109     "            <div class=\"circle\" tabindex=\"0\" \n" +
20110     "                 ng-click=\"stepclick($event, $index);\" \n" +
20111     "                 att-accessibility-click=\"13,23\">{{($index) + 1}}<span>{{step.title}}</span></div>\n" +
20112     "            <div ng-if=\"!laststep($index)\" class=\"track\"></div>\n" +
20113     "        </div>\n" +
20114     "    </div>\n" +
20115     "</div>\n" +
20116     "");
20117 }]);
20118
20119 angular.module("app/scripts/ng_js_att_tpls/steptracker/timeline.html", []).run(["$templateCache", function($templateCache) {
20120   $templateCache.put("app/scripts/ng_js_att_tpls/steptracker/timeline.html",
20121     "<div class='att-timeline'>\n" +
20122     "   <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" +
20123     "\n" +
20124     "   <div ng-repeat=\"m in middleSteps track by $index\">\n" +
20125     "           <div timeline-bar order='{{$index}}'></div>\n" +
20126     "           <div timeline-dot order='{{$index + 1}}' title='{{m.title}}' description='{{m.description}}' by='{{m.by}}' date='{{m.date}}' type='{{m.type}}'>\n" +
20127     "           </div>\n" +
20128     "   </div>\n" +
20129     "\n" +
20130     "</div>");
20131 }]);
20132
20133 angular.module("app/scripts/ng_js_att_tpls/steptracker/timelineBar.html", []).run(["$templateCache", function($templateCache) {
20134   $templateCache.put("app/scripts/ng_js_att_tpls/steptracker/timelineBar.html",
20135     "<div class='timeline-bar'>\n" +
20136     "   <div class='progress-bar' ng-class=\"{'completed-color':isCompleted,'cancelled-color':isCancelled,'alert-color':isAlert}\">\n" +
20137     "   </div>\n" +
20138     "   <hr></hr>\n" +
20139     "</div>");
20140 }]);
20141
20142 angular.module("app/scripts/ng_js_att_tpls/steptracker/timelineDot.html", []).run(["$templateCache", function($templateCache) {
20143   $templateCache.put("app/scripts/ng_js_att_tpls/steptracker/timelineDot.html",
20144     "<div class='timeline-dot'>\n" +
20145     "\n" +
20146     "   <div class='bigger-circle' ng-class=\"{'completed-color':isCompleted,'cancelled-color':isCancelled,'alert-color':isAlert}\">\n" +
20147     "   </div>\n" +
20148     "\n" +
20149     "   <div class='inactive-circle'>\n" +
20150     "   </div>\n" +
20151     "\n" +
20152     "   <div class='expandable-circle' ng-class=\"{'completed-color':isCompleted,'cancelled-color':isCancelled,'alert-color':isAlert}\">\n" +
20153     "   </div>\n" +
20154     "\n" +
20155     "   <div ng-class=\"{'below-info-box':isBelowInfoBoxShown, 'above-info-box': !isBelowInfoBoxShown}\" tabindex=\"0\">\n" +
20156     "           \n" +
20157     "           <div ng-if='isBelowInfoBoxShown' class='vertical-line'>\n" +
20158     "           </div>\n" +
20159     "\n" +
20160     "           <div class='info-container' ng-init='isContentShown=false'>\n" +
20161     "                   <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" +
20162     "                   <div class='content'>\n" +
20163     "                           <div class='description' ng-bind='description'></div>\n" +
20164     "                           <div class='submitter' ng-bind='by'></div>\n" +
20165     "                   </div>\n" +
20166     "                   <div class='date' ng-mouseover='titleMouseover(2)' ng-mouseleave='titleMouseleave()' ng-bind='date'></div>\n" +
20167     "           </div>\n" +
20168     "\n" +
20169     "           <div ng-if='!isBelowInfoBoxShown' class='vertical-line'>\n" +
20170     "           </div>\n" +
20171     "   </div>\n" +
20172     "\n" +
20173     "</div>");
20174 }]);
20175
20176 angular.module("app/scripts/ng_js_att_tpls/table/attTable.html", []).run(["$templateCache", function($templateCache) {
20177   $templateCache.put("app/scripts/ng_js_att_tpls/table/attTable.html",
20178     "<table class=\"tablesorter tablesorter-default\" ng-transclude></table>\n" +
20179     "");
20180 }]);
20181
20182 angular.module("app/scripts/ng_js_att_tpls/table/attTableBody.html", []).run(["$templateCache", function($templateCache) {
20183   $templateCache.put("app/scripts/ng_js_att_tpls/table/attTableBody.html",
20184     "<td ng-transclude></td>\n" +
20185     "");
20186 }]);
20187
20188 angular.module("app/scripts/ng_js_att_tpls/table/attTableHeader.html", []).run(["$templateCache", function($templateCache) {
20189   $templateCache.put("app/scripts/ng_js_att_tpls/table/attTableHeader.html",
20190     "<th role=\"button\" aria-label=\"column header {{headerName}} {{sortable !== 'false' && '' || 'sortable'}} {{sortPattern !== 'null' && '' || sortPattern}}\" tabindex=\"{{sortable !== 'false' && '0' || '-1'}}\" class=\"tablesorter-header\" ng-class=\"{'tablesorter-headerAsc': sortPattern === 'asc', 'tablesorter-headerDesc': sortPattern === 'desc', '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>");
20191 }]);
20192
20193 angular.module("app/scripts/ng_js_att_tpls/tableMessages/attTableMessage.html", []).run(["$templateCache", function($templateCache) {
20194   $templateCache.put("app/scripts/ng_js_att_tpls/tableMessages/attTableMessage.html",
20195     "<div class=\"att-table-message\">\n" +
20196     "   <div class=\"message\" ng-if=\"msgType==messageConstants.TABLE_MESSAGE_TYPES.noMatching\">\n" +
20197     "      <div class=\"img-magnify-glass\"></div> \n" +
20198     "      <div>\n" +
20199     "         <div ng-transclude></div>\n" +
20200     "      </div>\n" +
20201     "   </div>\n" +
20202     "   <div class=\"message\" ng-if=\"msgType==messageConstants.TABLE_MESSAGE_TYPES.errorLoading\">\n" +
20203     "      <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" +
20204     "      <div>Oops!</div>\n" +
20205     "      <div>The information could not load at this time.</div>\n" +
20206     "      <div>Please <a href=\"javascript:void(0)\" ng-click=\"refreshAction($event)\">refresh the page</a>\n" +
20207     "      </div>\n" +
20208     "   </div>\n" +
20209     "   <div class=\"message\" ng-if=\"msgType==messageConstants.TABLE_MESSAGE_TYPES.magnifySearch\">\n" +
20210     "      <div class=\"img-magnify-glass\"></div>\n" +
20211     "      <div>\n" +
20212     "         <p class=\"title\" tabindex=\"0\">Please input values to <br/> begin your search.</p>\n" +
20213     "      </div>\n" +
20214     "   </div>\n" +
20215     "   <div class=\"message loading-message\" ng-if=\"msgType==messageConstants.TABLE_MESSAGE_TYPES.isLoading\">\n" +
20216     "      <div class=\"img-loading-dots\"></div>\n" +
20217     "      <div ng-transclude></div>\n" +
20218     "   </div>\n" +
20219     "</div>");
20220 }]);
20221
20222 angular.module("app/scripts/ng_js_att_tpls/tableMessages/attUserMessage.html", []).run(["$templateCache", function($templateCache) {
20223   $templateCache.put("app/scripts/ng_js_att_tpls/tableMessages/attUserMessage.html",
20224     "<div class=\"att-user-message\">\n" +
20225     "  <div ng-class=\"type==messageConstants.USER_MESSAGE_TYPES.error && trigger ? 'message-wrapper-error' : 'hidden'\">\n" +
20226     "      <div class=\"message-icon-error\"> <i class=\"icon-info-alert\"></i> </div>\n" +
20227     "\n" +
20228     "      <div class=\"message-body-wrapper\">\n" +
20229     "        <div class=\"message-title-error\" ng-if=\"thetitle && thetitle.length > 0\"> <span ng-bind=\"thetitle\" tabindex=\"0\" aria-label=\"{{thetitle}}\"></span> </div>\n" +
20230     "        <div class=\"message-msg\" ng-bind=\"message\" ng-if=\"message && message.length > 0\" tabindex=\"0\"></div>\n" +
20231     "        <div class=\"message-bottom\">\n" +
20232     "           <div ng-transclude></div>\n" +
20233     "        </div>\n" +
20234     "      </div>\n" +
20235     "\n" +
20236     "   </div>\n" +
20237     "  <div ng-class=\"type==messageConstants.USER_MESSAGE_TYPES.success && trigger ? 'message-wrapper-success' : 'hidden'\">\n" +
20238     "      <div class=\"message-icon-success\"> <i class=\"icon-included-checkmark\"></i></div>\n" +
20239     "\n" +
20240     "      <div class=\"message-body-wrapper\">\n" +
20241     "        <div class=\"message-title-success\" ng-if=\"thetitle && thetitle.length > 0\" >\n" +
20242     "          <span ng-bind=\"thetitle\" tabindex=\"0\" aria-label=\"{{thetitle}}\"></span>\n" +
20243     "        </div>\n" +
20244     "        <div class=\"message-msg\" ng-bind=\"message\" ng-if=\"message && message.length > 0\" tabindex=\"0\"></div>\n" +
20245     "        <div class=\"message-bottom\">\n" +
20246     "           <div ng-transclude></div>\n" +
20247     "        </div>\n" +
20248     "      </div>\n" +
20249     "\n" +
20250     "   </div>\n" +
20251     "</div>\n" +
20252     "");
20253 }]);
20254
20255 angular.module("app/scripts/ng_js_att_tpls/tabs/floatingTabs.html", []).run(["$templateCache", function($templateCache) {
20256   $templateCache.put("app/scripts/ng_js_att_tpls/tabs/floatingTabs.html",
20257     "<ul ng-class=\"{'tabsbid': size === 'large', 'tabsbid--small': size === 'small'}\">\n" +
20258     " <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" +
20259     "        <a class=\"tabsbid__item-link\" href=\"{{tab.url}}\" tabindex=\"0\" att-accessibility-click=\"32,13\">{{tab.title}}</a>\n" +
20260     "  </li>\n" +
20261     "</ul>");
20262 }]);
20263
20264 angular.module("app/scripts/ng_js_att_tpls/tabs/genericTabs.html", []).run(["$templateCache", function($templateCache) {
20265   $templateCache.put("app/scripts/ng_js_att_tpls/tabs/genericTabs.html",
20266     "<ul ng-class=\"{'tabsbid': size === 'large', 'tabsbid--small': size === 'small'}\">\n" +
20267     "    <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" +
20268     "           <a class=\"tabsbid__item-link\" href=\"{{tab.url}}\" tabindex=\"0\" att-accessibility-click=\"32,13\">{{tab.title}}</a>\n" +
20269     "    </li>\n" +
20270     "</ul>\n" +
20271     "");
20272 }]);
20273
20274 angular.module("app/scripts/ng_js_att_tpls/tabs/menuTab.html", []).run(["$templateCache", function($templateCache) {
20275   $templateCache.put("app/scripts/ng_js_att_tpls/tabs/menuTab.html",
20276     "<li class=\"megamenu__item\" ng-mouseover=\"showHoverChild($event)\" ng-class=\"{'tabs__item--active': menuItem.active==true && !hoverChild==true}\">\n" +
20277     "    <span role=\"menuitem\" att-accessibility-click=\"13,32\" tabindex=\"0\" ng-click=\"showChildren($event);!clickInactive||resetMenu($event)\">{{tabName}}</span>\n" +
20278     "    <div ng-transclude></div>\n" +
20279     "</li>\n" +
20280     "");
20281 }]);
20282
20283 angular.module("app/scripts/ng_js_att_tpls/tabs/parentmenuTab.html", []).run(["$templateCache", function($templateCache) {
20284   $templateCache.put("app/scripts/ng_js_att_tpls/tabs/parentmenuTab.html",
20285     "<div ng-class=\"{'megamenu-tabs': megaMenu,'submenu-tabs': !megaMenu}\">\n" +
20286     "    <ul class=\"megamenu__items\" role=\"presentation\" ng-transclude>\n" +
20287     "    </ul>\n" +
20288     "</div>");
20289 }]);
20290
20291 angular.module("app/scripts/ng_js_att_tpls/tabs/simplifiedTabs.html", []).run(["$templateCache", function($templateCache) {
20292   $templateCache.put("app/scripts/ng_js_att_tpls/tabs/simplifiedTabs.html",
20293     "<div class=\"simplified-tabs\">\n" +
20294     "<ul class=\"simplified-tabs__items\" role=\"tablist\">\n" +
20295     "    <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" +
20296     "    <li class=\"tabs__pointer\"></li>\n" +
20297     "</ul>\n" +
20298     "</div>");
20299 }]);
20300
20301 angular.module("app/scripts/ng_js_att_tpls/tabs/submenuTab.html", []).run(["$templateCache", function($templateCache) {
20302   $templateCache.put("app/scripts/ng_js_att_tpls/tabs/submenuTab.html",
20303     "<li class=\"tabsbid__item megamenu__item\" ng-class=\"{'subMenuHover': menuItem.active==true}\">\n" +
20304     "<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" +
20305     "<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" +
20306     "<span ng-transclude></span>\n" +
20307     "</li>\n" +
20308     "");
20309 }]);
20310
20311 angular.module("app/scripts/ng_js_att_tpls/tagBadges/tagBadges.html", []).run(["$templateCache", function($templateCache) {
20312   $templateCache.put("app/scripts/ng_js_att_tpls/tagBadges/tagBadges.html",
20313     "<div class=\"tags__item\" \n" +
20314     "     ng-class=\"{'tags__item--small':isSmall, \n" +
20315     "                 'tags__item--color':isColor, \n" +
20316     "                 'tags__item--cloud':!isClosable && !isColor,'active':applyActiveClass}\"\n" +
20317     "     ng-if=\"display\" \n" +
20318     "     ng-style=\"{borderColor: border_type_borderColor, background: isHighlight?'#bbb':undefined, color: isHighlight?'#444':undefined }\"\n" +
20319     "     ng-mousedown=\"activeHighlight(true)\" role=\"presentation\" ng-mouseup=\"activeHighlight(false)\">\n" +
20320     "    <i class=\"icon-filter tags__item--icon\" ng-if=\"isIcon\">&nbsp;</i>\n" +
20321     "    <i class=\"tags__item--color-icon\" ng-if=\"isColor\" ng-style=\"{backgroundColor: background_type_backgroundColor, borderColor: background_type_borderColor}\"></i>\n" +
20322     "    <span class=\"tags__item--title\" role=\"presentation\"  tabindex=0 aria-label=\"tag\" ng-mousedown=\"activeHighlight(true)\" ng-mouseup=\"activeHighlight(false)\" ng-transclude></span>\n" +
20323     "    <a href=\"javascript:void(0)\" title=\"Dismiss Link\" class=\"tags__item--action\" ng-click=\"closeMe();$event.preventDefault()\" ng-if=\"isClosable\"\n" +
20324     "       ng-style=\"{color: (isHighlight && '#444') || '#888' , borderLeft: (isHighlight && '1px solid #444')|| '1px solid #888' }\">\n" +
20325     "        <i class=\"icon-erase\">&nbsp;</i>\n" +
20326     "    </a>\n" +
20327     "</div>");
20328 }]);
20329
20330 angular.module("app/scripts/ng_js_att_tpls/toggle/demoToggle.html", []).run(["$templateCache", function($templateCache) {
20331   $templateCache.put("app/scripts/ng_js_att_tpls/toggle/demoToggle.html",
20332     "<span ng-transclude></span>\n" +
20333     "<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" +
20334     "    <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" +
20335     "    <div class=\"att-switch-thumb\" tabindex=\"0\" title=\"Toggle switch\" role=\"checkbox\"  ng-class=\"{'large' : directiveValue == 'large'}\"></div>\n" +
20336     "    <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" +
20337     "</div>\n" +
20338     "");
20339 }]);
20340
20341 angular.module("app/scripts/ng_js_att_tpls/typeAhead/typeAhead.html", []).run(["$templateCache", function($templateCache) {
20342   $templateCache.put("app/scripts/ng_js_att_tpls/typeAhead/typeAhead.html",
20343     "<div class=\"typeahead mainContainerOuter\">\n" +
20344     "    <span class=\"message\">To</span>\n" +
20345     "    <div class='maincontainer' ng-click=\"setFocus()\" ng-focus=\"inputActive=true\" ng-class =\"{'typeahed_active':inputActive || (lineItems.length && inputActive)}\">\n" +
20346     "        <span tag-badges closable ng-repeat =\"lineItem in lineItems track by $index\" on-close=\"theMethodToBeCalled($index)\" >{{lineItem}}</span>\n" +
20347     "        <input type=\"text\"  focus-me=\"clickFocus\" ng-focus=\"inputActive=true\" ng-model=\"model\" ng-keydown=\"selected = false; selectionIndex($event)\"/><br/> \n" +
20348     "    </div>\n" +
20349     "    <div ng-hide=\"!model.length || selected\">\n" +
20350     "        <div class=\"filtercontainer list-scrollable\" ng-show=\"( items | filter:model).length\">\n" +
20351     "            <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" +
20352     "                <span class=\"title\" >{{item[titleName]}}</span>\n" +
20353     "                <span class=\"subtitle\">{{item[subtitle]}}</span>\n" +
20354     "            </div>  \n" +
20355     "        </div>\n" +
20356     "    </div>\n" +
20357     "   \n" +
20358     "    <div class=\"textAreaEmailContentDiv\">\n" +
20359     "        <span class=\"message\">Message</span>\n" +
20360     "        <textarea rows=\"4\" cols=\"50\" role=\"textarea\" class=\"textAreaEmailContent\" ng-model=\"emailMessage\">To send \n" +
20361     " a text, picture, or video message1 to an AT&T wireless device from your email:my message.</textarea>\n" +
20362     "        \n" +
20363     "    </div>\n" +
20364     "    \n" +
20365     "</div>\n" +
20366     "");
20367 }]);
20368
20369 angular.module("app/scripts/ng_js_att_tpls/verticalSteptracker/vertical-step-tracker.html", []).run(["$templateCache", function($templateCache) {
20370   $templateCache.put("app/scripts/ng_js_att_tpls/verticalSteptracker/vertical-step-tracker.html",
20371     "<li>\n" +
20372     "    <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" +
20373     "    <span ng-transclude></span>\n" +
20374     "</li>\n" +
20375     "        \n" +
20376     "");
20377 }]);
20378
20379 angular.module("app/scripts/ng_js_att_tpls/videoControls/photoControls.html", []).run(["$templateCache", function($templateCache) {
20380   $templateCache.put("app/scripts/ng_js_att_tpls/videoControls/photoControls.html",
20381     "<div>\n" +
20382     "    <a title=\"{{links.prevLink}}\" aria-label=\"Previous Link\"  ng-href=\"{{links.prevLink}}\"><i alt=\"previous\" class=\"icon-arrow-left\">&nbsp;</i></a>\n" +
20383     "    <span ng-transclude></span>\n" +
20384     "    <a title=\"{{links.nextLink}}\" aria-label=\"Next Link\"  ng-href=\"{{links.nextLink}}\"><i alt=\"next\" class=\"icon-arrow-right\">&nbsp;</i></a>\n" +
20385     "</div>");
20386 }]);
20387
20388 angular.module("app/scripts/ng_js_att_tpls/videoControls/videoControls.html", []).run(["$templateCache", function($templateCache) {
20389   $templateCache.put("app/scripts/ng_js_att_tpls/videoControls/videoControls.html",
20390     "<div class=\"video-player\">\n" +
20391     "    <div class=\"video-player__control video-player__play-button\">\n" +
20392     "        <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" +
20393     "    </div>\n" +
20394     "    <div class=\"video-player__control video-player__track\">\n" +
20395     "\n" +
20396     "        <div class=\"video-player__track--inner\">\n" +
20397     "            <div class=\"video-player__track--loaded\" style=\"width: 75%\"></div>\n" +
20398     "            <div class=\"video-player__track--played\" style=\"width: 40%\">\n" +
20399     "                <div class=\"att-tooltip att-tooltip--on att-tooltip--dark att-tooltip--above video-player__track-tooltip\" ng-transclude></div>\n" +
20400     "                <div class=\"video-player__track-handle\"></div>\n" +
20401     "            </div>\n" +
20402     "        </div>\n" +
20403     "    </div>\n" +
20404     "    <a class=\"video-player__time\" ng-transclude></a>\n" +
20405     "    <div class=\"video-player__control video-player__volume_icon\">\n" +
20406     "        <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" +
20407     "    </div>\n" +
20408     "    <ul class=\"video-player__control video-player__volume\">\n" +
20409     "        <li class=\"video-player__volume-bar video-player__volume-bar--full\">&nbsp;</li>\n" +
20410     "        <li class=\"video-player__volume-bar video-player__volume-bar--full\">&nbsp;</li>\n" +
20411     "        <li class=\"video-player__volume-bar\">&nbsp;</li>\n" +
20412     "        <li class=\"video-player__volume-bar\">&nbsp;</li>\n" +
20413     "        <li class=\"video-player__volume-bar\">&nbsp;</li>\n" +
20414     "    </ul>\n" +
20415     "    <div class=\"video-player__control video-player__toggle-fullscreen-button\">\n" +
20416     "        <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" +
20417     "    </div>\n" +
20418     "</div>");
20419 }]);
20420
20421 return {}
20422 })(angular, window);