nexus site path corrected
[portal.git] / ecomp-portal-BE / war / static / ebz / angular_js / att-abs-tpls-1.2.51.js
1 angular.module("att.abs", ["att.abs.tpls", "att.abs.position","att.abs.transition","att.abs.accordion","att.abs.alert","att.abs.breadCrumbs","att.abs.utilities","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.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.tabs","att.abs.tagBadges","att.abs.textOverflow","att.abs.toggle","att.abs.tooltip","att.abs.treeview","att.abs.typeAhead","att.abs.userMessages","att.abs.verticalSteptracker","att.abs.videoControls"]);
2 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/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/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/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/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/search/search_2.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/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/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/tooltip/tooltip-popup.html","app/scripts/ng_js_att_tpls/typeAhead/typeAhead.html","app/scripts/ng_js_att_tpls/userMessages/attTableMessage.html","app/scripts/ng_js_att_tpls/userMessages/attUserMessage.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"]);
3 angular.module('att.abs.position', [])
4
5 .factory('$position', ['$document', '$window', function ($document, $window) {
6     function getStyle(el, cssprop) {
7         if (el.currentStyle) { //IE
8             return el.currentStyle[cssprop];
9         } else if ($window.getComputedStyle) {
10             return $window.getComputedStyle(el)[cssprop];
11         }
12         // finally try and get inline style
13         return el.style[cssprop];
14     }
15
16     /**
17      * Checks if a given element is statically positioned
18      * @param element - raw DOM element
19      */
20     function isStaticPositioned(element) {
21         return (getStyle(element, "position") || 'static') === 'static';
22     }
23
24     /**
25      * returns the closest, non-statically positioned parentOffset of a given element
26      * @param element
27      */
28     var parentOffsetEl = function (element) {
29         var docDomEl = $document[0];
30         var offsetParent = element.offsetParent || docDomEl;
31         while (offsetParent && offsetParent !== docDomEl && isStaticPositioned(offsetParent)) {
32             offsetParent = offsetParent.offsetParent;
33         }
34         return offsetParent || docDomEl;
35     };
36
37     return {
38         /**
39          * Provides read-only equivalent of jQuery's position function:
40          * http://api.jquery.com/position/
41          */
42         position: function (element) {
43             var elBCR = this.offset(element);
44             var offsetParentBCR = {
45                 top: 0,
46                 left: 0
47             };
48             var offsetParentEl = parentOffsetEl(element[0]);
49             if (offsetParentEl !== $document[0]) {
50                 offsetParentBCR = this.offset(angular.element(offsetParentEl));
51                 offsetParentBCR.top += offsetParentEl.clientTop - offsetParentEl.scrollTop;
52                 offsetParentBCR.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft;
53             }
54
55             return {
56                 width: element.prop('offsetWidth'),
57                 height: element.prop('offsetHeight'),
58                 top: elBCR.top - offsetParentBCR.top,
59                 left: elBCR.left - offsetParentBCR.left
60             };
61         },
62
63         /**
64          * Provides read-only equivalent of jQuery's offset function:
65          * http://api.jquery.com/offset/
66          */
67         offset: function (element) {
68             var boundingClientRect = element[0].getBoundingClientRect();
69             return {
70                 width: element.prop('offsetWidth'),
71                 height: element.prop('offsetHeight'),
72                 top: boundingClientRect.top + ($window.pageYOffset || $document[0].body.scrollTop || $document[0].documentElement.scrollTop),
73                 left: boundingClientRect.left + ($window.pageXOffset || $document[0].body.scrollLeft || $document[0].documentElement.scrollLeft)
74             };
75         }
76     };
77 }])
78
79 .factory('$isElement', [function () {
80     var isElement = function (currentElem, targetElem, alternateElem) {
81         if (currentElem[0] === targetElem[0]) {
82             return true;
83         } else if (currentElem[0] === alternateElem[0]) {
84             return false;
85         } else {
86             return isElement((currentElem.parent()[0] && currentElem.parent()) || targetElem, targetElem, alternateElem);
87         }
88     };
89
90     return isElement;
91 }]);
92
93 /*!
94  * VERSION: 1.7.3
95  * DATE: 2014-01-14
96  * UPDATES AND DOCS AT: http://www.greensock.com
97  *
98  * @license Copyright (c) 2008-2014, GreenSock. All rights reserved.
99  * This work is subject to the terms at http://www.greensock.com/terms_of_use.html or for
100  * Club GreenSock members, the software agreement that was issued with your membership.
101  * 
102  * @author: Jack Doyle, jack@greensock.com
103  **/
104 (window._gsQueue || (window._gsQueue = [])).push( function() {
105
106         "use strict";
107
108         var _doc = document.documentElement,
109                 _window = window,
110                 _max = function(element, axis) {
111                         var dim = (axis === "x") ? "Width" : "Height",
112                                 scroll = "scroll" + dim,
113                                 client = "client" + dim,
114                                 body = document.body;
115                         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];
116                 },
117
118                 ScrollToPlugin = window._gsDefine.plugin({
119                         propName: "scrollTo",
120                         API: 2,
121                         version:"1.7.3",
122
123                         //called when the tween renders for the first time. This is where initial values should be recorded and any setup routines should run.
124                         init: function(target, value, tween) {
125                                 this._wdw = (target === _window);
126                                 this._target = target;
127                                 this._tween = tween;
128                                 if (typeof(value) !== "object") {
129                                         value = {y:value}; //if we don't receive an object as the parameter, assume the user intends "y".
130                                 }
131                                 this._autoKill = (value.autoKill !== false);
132                                 this.x = this.xPrev = this.getX();
133                                 this.y = this.yPrev = this.getY();
134                                 if (value.x != null) {
135                                         this._addTween(this, "x", this.x, (value.x === "max") ? _max(target, "x") : value.x, "scrollTo_x", true);
136                                         this._overwriteProps.push("scrollTo_x");
137                                 } else {
138                                         this.skipX = true;
139                                 }
140                                 if (value.y != null) {
141                                         this._addTween(this, "y", this.y, (value.y === "max") ? _max(target, "y") : value.y, "scrollTo_y", true);
142                                         this._overwriteProps.push("scrollTo_y");
143                                 } else {
144                                         this.skipY = true;
145                                 }
146                                 return true;
147                         },
148
149                         //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.)
150                         set: function(v) {
151                                 this._super.setRatio.call(this, v);
152
153                                 var x = (this._wdw || !this.skipX) ? this.getX() : this.xPrev,
154                                         y = (this._wdw || !this.skipY) ? this.getY() : this.yPrev,
155                                         yDif = y - this.yPrev,
156                                         xDif = x - this.xPrev;
157
158                                 if (this._autoKill) {
159                                         //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.
160                                         if (!this.skipX && (xDif > 7 || xDif < -7) && x < _max(this._target, "x")) {
161                                                 this.skipX = true; //if the user scrolls separately, we should stop tweening!
162                                         }
163                                         if (!this.skipY && (yDif > 7 || yDif < -7) && y < _max(this._target, "y")) {
164                                                 this.skipY = true; //if the user scrolls separately, we should stop tweening!
165                                         }
166                                         if (this.skipX && this.skipY) {
167                                                 this._tween.kill();
168                                         }
169                                 }
170                                 if (this._wdw) {
171                                         _window.scrollTo((!this.skipX) ? this.x : x, (!this.skipY) ? this.y : y);
172                                 } else {
173                                         if (!this.skipY) {
174                                                 this._target.scrollTop = this.y;
175                                         }
176                                         if (!this.skipX) {
177                                                 this._target.scrollLeft = this.x;
178                                         }
179                                 }
180                                 this.xPrev = this.x;
181                                 this.yPrev = this.y;
182                         }
183
184                 }),
185                 p = ScrollToPlugin.prototype;
186
187         ScrollToPlugin.max = _max;
188
189         p.getX = function() {
190                 return (!this._wdw) ? this._target.scrollLeft : (_window.pageXOffset != null) ? _window.pageXOffset : (_doc.scrollLeft != null) ? _doc.scrollLeft : document.body.scrollLeft;
191         };
192
193         p.getY = function() {
194                 return (!this._wdw) ? this._target.scrollTop : (_window.pageYOffset != null) ? _window.pageYOffset : (_doc.scrollTop != null) ? _doc.scrollTop : document.body.scrollTop;
195         };
196
197         p._kill = function(lookup) {
198                 if (lookup.scrollTo_x) {
199                         this.skipX = true;
200                 }
201                 if (lookup.scrollTo_y) {
202                         this.skipY = true;
203                 }
204                 return this._super._kill.call(this, lookup);
205         };
206
207 }); if (window._gsDefine) { window._gsQueue.pop()(); }
208 /*!
209  * VERSION: 1.12.1
210  * DATE: 2014-06-26
211  * UPDATES AND DOCS AT: http://www.greensock.com
212  * 
213  * Includes all of the following: TweenLite, TweenMax, TimelineLite, TimelineMax, EasePack, CSSPlugin, RoundPropsPlugin, BezierPlugin, AttrPlugin, DirectionalRotationPlugin
214  *
215  * @license Copyright (c) 2008-2014, GreenSock. All rights reserved.
216  * This work is subject to the terms at http://www.greensock.com/terms_of_use.html or for
217  * Club GreenSock members, the software agreement that was issued with your membership.
218  * 
219  * @author: Jack Doyle, jack@greensock.com
220  **/
221
222 (window._gsQueue || (window._gsQueue = [])).push( function() {
223
224         "use strict";
225
226         window._gsDefine("TweenMax", ["core.Animation","core.SimpleTimeline","TweenLite"], function(Animation, SimpleTimeline, TweenLite) {
227
228                 var _slice = [].slice,
229                         TweenMax = function(target, duration, vars) {
230                                 TweenLite.call(this, target, duration, vars);
231                                 this._cycle = 0;
232                                 this._yoyo = (this.vars.yoyo === true);
233                                 this._repeat = this.vars.repeat || 0;
234                                 this._repeatDelay = this.vars.repeatDelay || 0;
235                                 this._dirty = true; //ensures that if there is any repeat, the totalDuration will get recalculated to accurately report it.
236                                 this.render = TweenMax.prototype.render; //speed optimization (avoid prototype lookup on this "hot" method)
237                         },
238                         _tinyNum = 0.0000000001,
239                         TweenLiteInternals = TweenLite._internals,
240                         _isSelector = TweenLiteInternals.isSelector,
241                         _isArray = TweenLiteInternals.isArray,
242                         p = TweenMax.prototype = TweenLite.to({}, 0.1, {}),
243                         _blankArray = [];
244
245                 TweenMax.version = "1.12.1";
246                 p.constructor = TweenMax;
247                 p.kill()._gc = false;
248                 TweenMax.killTweensOf = TweenMax.killDelayedCallsTo = TweenLite.killTweensOf;
249                 TweenMax.getTweensOf = TweenLite.getTweensOf;
250                 TweenMax.lagSmoothing = TweenLite.lagSmoothing;
251                 TweenMax.ticker = TweenLite.ticker;
252                 TweenMax.render = TweenLite.render;
253
254                 p.invalidate = function() {
255                         this._yoyo = (this.vars.yoyo === true);
256                         this._repeat = this.vars.repeat || 0;
257                         this._repeatDelay = this.vars.repeatDelay || 0;
258                         this._uncache(true);
259                         return TweenLite.prototype.invalidate.call(this);
260                 };
261                 
262                 p.updateTo = function(vars, resetDuration) {
263                         var curRatio = this.ratio, p;
264                         if (resetDuration && this._startTime < this._timeline._time) {
265                                 this._startTime = this._timeline._time;
266                                 this._uncache(false);
267                                 if (this._gc) {
268                                         this._enabled(true, false);
269                                 } else {
270                                         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.
271                                 }
272                         }
273                         for (p in vars) {
274                                 this.vars[p] = vars[p];
275                         }
276                         if (this._initted) {
277                                 if (resetDuration) {
278                                         this._initted = false;
279                                 } else {
280                                         if (this._gc) {
281                                                 this._enabled(true, false);
282                                         }
283                                         if (this._notifyPluginsOfEnabled && this._firstPT) {
284                                                 TweenLite._onPluginEvent("_onDisable", this); //in case a plugin like MotionBlur must perform some cleanup tasks
285                                         }
286                                         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. 
287                                                 var prevTime = this._time;
288                                                 this.render(0, true, false);
289                                                 this._initted = false;
290                                                 this.render(prevTime, true, false);
291                                         } else if (this._time > 0) {
292                                                 this._initted = false;
293                                                 this._init();
294                                                 var inv = 1 / (1 - curRatio),
295                                                         pt = this._firstPT, endValue;
296                                                 while (pt) {
297                                                         endValue = pt.s + pt.c; 
298                                                         pt.c *= inv;
299                                                         pt.s = endValue - pt.c;
300                                                         pt = pt._next;
301                                                 }
302                                         }
303                                 }
304                         }
305                         return this;
306                 };
307                                 
308                 p.render = function(time, suppressEvents, force) {
309                         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.
310                                 this.invalidate();
311                         }
312                         var totalDur = (!this._dirty) ? this._totalDuration : this.totalDuration(),
313                                 prevTime = this._time,
314                                 prevTotalTime = this._totalTime, 
315                                 prevCycle = this._cycle,
316                                 duration = this._duration,
317                                 prevRawPrevTime = this._rawPrevTime,
318                                 isComplete, callback, pt, cycleDuration, r, type, pow, rawPrevTime, i;
319                         if (time >= totalDur) {
320                                 this._totalTime = totalDur;
321                                 this._cycle = this._repeat;
322                                 if (this._yoyo && (this._cycle & 1) !== 0) {
323                                         this._time = 0;
324                                         this.ratio = this._ease._calcEnd ? this._ease.getRatio(0) : 0;
325                                 } else {
326                                         this._time = duration;
327                                         this.ratio = this._ease._calcEnd ? this._ease.getRatio(1) : 1;
328                                 }
329                                 if (!this._reversed) {
330                                         isComplete = true;
331                                         callback = "onComplete";
332                                 }
333                                 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.
334                                         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.
335                                                 time = 0;
336                                         }
337                                         if (time === 0 || prevRawPrevTime < 0 || prevRawPrevTime === _tinyNum) if (prevRawPrevTime !== time) {
338                                                 force = true;
339                                                 if (prevRawPrevTime > _tinyNum) {
340                                                         callback = "onReverseComplete";
341                                                 }
342                                         }
343                                         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.
344                                 }
345                                 
346                         } else if (time < 0.0000001) { //to work around occasional floating point math artifacts, round super small values to 0.
347                                 this._totalTime = this._time = this._cycle = 0;
348                                 this.ratio = this._ease._calcEnd ? this._ease.getRatio(0) : 0;
349                                 if (prevTotalTime !== 0 || (duration === 0 && prevRawPrevTime > 0 && prevRawPrevTime !== _tinyNum)) {
350                                         callback = "onReverseComplete";
351                                         isComplete = this._reversed;
352                                 }
353                                 if (time < 0) {
354                                         this._active = false;
355                                         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.
356                                                 if (prevRawPrevTime >= 0) {
357                                                         force = true;
358                                                 }
359                                                 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.
360                                         }
361                                 } 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.
362                                         force = true;
363                                 }
364                         } else {
365                                 this._totalTime = this._time = time;
366                                 
367                                 if (this._repeat !== 0) {
368                                         cycleDuration = duration + this._repeatDelay;
369                                         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!)
370                                         if (this._cycle !== 0) if (this._cycle === this._totalTime / cycleDuration) {
371                                                 this._cycle--; //otherwise when rendered exactly at the end time, it will act as though it is repeating (at the beginning)
372                                         }
373                                         this._time = this._totalTime - (this._cycle * cycleDuration);
374                                         if (this._yoyo) if ((this._cycle & 1) !== 0) {
375                                                 this._time = duration - this._time;
376                                         }
377                                         if (this._time > duration) {
378                                                 this._time = duration;
379                                         } else if (this._time < 0) {
380                                                 this._time = 0;
381                                         }
382                                 }
383
384                                 if (this._easeType) {
385                                         r = this._time / duration;
386                                         type = this._easeType;
387                                         pow = this._easePower;
388                                         if (type === 1 || (type === 3 && r >= 0.5)) {
389                                                 r = 1 - r;
390                                         }
391                                         if (type === 3) {
392                                                 r *= 2;
393                                         }
394                                         if (pow === 1) {
395                                                 r *= r;
396                                         } else if (pow === 2) {
397                                                 r *= r * r;
398                                         } else if (pow === 3) {
399                                                 r *= r * r * r;
400                                         } else if (pow === 4) {
401                                                 r *= r * r * r * r;
402                                         }
403
404                                         if (type === 1) {
405                                                 this.ratio = 1 - r;
406                                         } else if (type === 2) {
407                                                 this.ratio = r;
408                                         } else if (this._time / duration < 0.5) {
409                                                 this.ratio = r / 2;
410                                         } else {
411                                                 this.ratio = 1 - (r / 2);
412                                         }
413
414                                 } else {
415                                         this.ratio = this._ease.getRatio(this._time / duration);
416                                 }
417                                 
418                         }
419                                 
420                         if (prevTime === this._time && !force && prevCycle === this._cycle) {
421                                 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.
422                                         this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray);
423                                 }
424                                 return;
425                         } else if (!this._initted) {
426                                 this._init();
427                                 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.
428                                         return;
429                                 } 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.
430                                         this._time = prevTime;
431                                         this._totalTime = prevTotalTime;
432                                         this._rawPrevTime = prevRawPrevTime;
433                                         this._cycle = prevCycle;
434                                         TweenLiteInternals.lazyTweens.push(this);
435                                         this._lazy = time;
436                                         return;
437                                 }
438                                 //_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.
439                                 if (this._time && !isComplete) {
440                                         this.ratio = this._ease.getRatio(this._time / duration);
441                                 } else if (isComplete && this._ease._calcEnd) {
442                                         this.ratio = this._ease.getRatio((this._time === 0) ? 0 : 1);
443                                 }
444                         }
445                         if (this._lazy !== false) {
446                                 this._lazy = false;
447                         }
448
449                         if (!this._active) if (!this._paused && this._time !== prevTime && time >= 0) {
450                                 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.
451                         }
452                         if (prevTotalTime === 0) {
453                                 if (this._initted === 2 && time > 0) {
454                                         //this.invalidate();
455                                         this._init(); //will just apply overwriting since _initted of (2) means it was a from() tween that had immediateRender:true
456                                 }
457                                 if (this._startAt) {
458                                         if (time >= 0) {
459                                                 this._startAt.render(time, suppressEvents, force);
460                                         } else if (!callback) {
461                                                 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.
462                                         }
463                                 }
464                                 if (this.vars.onStart) if (this._totalTime !== 0 || duration === 0) if (!suppressEvents) {
465                                         this.vars.onStart.apply(this.vars.onStartScope || this, this.vars.onStartParams || _blankArray);
466                                 }
467                         }
468                         
469                         pt = this._firstPT;
470                         while (pt) {
471                                 if (pt.f) {
472                                         pt.t[pt.p](pt.c * this.ratio + pt.s);
473                                 } else {
474                                         pt.t[pt.p] = pt.c * this.ratio + pt.s;
475                                 }
476                                 pt = pt._next;
477                         }
478                         
479                         if (this._onUpdate) {
480                                 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.
481                                         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.
482                                 }
483                                 if (!suppressEvents) if (this._totalTime !== prevTotalTime || isComplete) {
484                                         this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray);
485                                 }
486                         }
487                         if (this._cycle !== prevCycle) if (!suppressEvents) if (!this._gc) if (this.vars.onRepeat) {
488                                 this.vars.onRepeat.apply(this.vars.onRepeatScope || this, this.vars.onRepeatParams || _blankArray);
489                         }
490                         if (callback) if (!this._gc) { //check gc because there's a chance that kill() could be called in an onUpdate
491                                 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.
492                                         this._startAt.render(time, suppressEvents, force);
493                                 }
494                                 if (isComplete) {
495                                         if (this._timeline.autoRemoveChildren) {
496                                                 this._enabled(false, false);
497                                         }
498                                         this._active = false;
499                                 }
500                                 if (!suppressEvents && this.vars[callback]) {
501                                         this.vars[callback].apply(this.vars[callback + "Scope"] || this, this.vars[callback + "Params"] || _blankArray);
502                                 }
503                                 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.
504                                         this._rawPrevTime = 0;
505                                 }
506                         }
507                 };
508                 
509 //---- STATIC FUNCTIONS -----------------------------------------------------------------------------------------------------------
510                 
511                 TweenMax.to = function(target, duration, vars) {
512                         return new TweenMax(target, duration, vars);
513                 };
514                 
515                 TweenMax.from = function(target, duration, vars) {
516                         vars.runBackwards = true;
517                         vars.immediateRender = (vars.immediateRender != false);
518                         return new TweenMax(target, duration, vars);
519                 };
520                 
521                 TweenMax.fromTo = function(target, duration, fromVars, toVars) {
522                         toVars.startAt = fromVars;
523                         toVars.immediateRender = (toVars.immediateRender != false && fromVars.immediateRender != false);
524                         return new TweenMax(target, duration, toVars);
525                 };
526                 
527                 TweenMax.staggerTo = TweenMax.allTo = function(targets, duration, vars, stagger, onCompleteAll, onCompleteAllParams, onCompleteAllScope) {
528                         stagger = stagger || 0;
529                         var delay = vars.delay || 0,
530                                 a = [],
531                                 finalComplete = function() {
532                                         if (vars.onComplete) {
533                                                 vars.onComplete.apply(vars.onCompleteScope || this, arguments);
534                                         }
535                                         onCompleteAll.apply(onCompleteAllScope || this, onCompleteAllParams || _blankArray);
536                                 },
537                                 l, copy, i, p;
538                         if (!_isArray(targets)) {
539                                 if (typeof(targets) === "string") {
540                                         targets = TweenLite.selector(targets) || targets;
541                                 }
542                                 if (_isSelector(targets)) {
543                                         targets = _slice.call(targets, 0);
544                                 }
545                         }
546                         l = targets.length;
547                         for (i = 0; i < l; i++) {
548                                 copy = {};
549                                 for (p in vars) {
550                                         copy[p] = vars[p];
551                                 }
552                                 copy.delay = delay;
553                                 if (i === l - 1 && onCompleteAll) {
554                                         copy.onComplete = finalComplete;
555                                 }
556                                 a[i] = new TweenMax(targets[i], duration, copy);
557                                 delay += stagger;
558                         }
559                         return a;
560                 };
561                 
562                 TweenMax.staggerFrom = TweenMax.allFrom = function(targets, duration, vars, stagger, onCompleteAll, onCompleteAllParams, onCompleteAllScope) {
563                         vars.runBackwards = true;
564                         vars.immediateRender = (vars.immediateRender != false);
565                         return TweenMax.staggerTo(targets, duration, vars, stagger, onCompleteAll, onCompleteAllParams, onCompleteAllScope);
566                 };
567                 
568                 TweenMax.staggerFromTo = TweenMax.allFromTo = function(targets, duration, fromVars, toVars, stagger, onCompleteAll, onCompleteAllParams, onCompleteAllScope) {
569                         toVars.startAt = fromVars;
570                         toVars.immediateRender = (toVars.immediateRender != false && fromVars.immediateRender != false);
571                         return TweenMax.staggerTo(targets, duration, toVars, stagger, onCompleteAll, onCompleteAllParams, onCompleteAllScope);
572                 };
573                                 
574                 TweenMax.delayedCall = function(delay, callback, params, scope, useFrames) {
575                         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});
576                 };
577                 
578                 TweenMax.set = function(target, vars) {
579                         return new TweenMax(target, 0, vars);
580                 };
581                 
582                 TweenMax.isTweening = function(target) {
583                         return (TweenLite.getTweensOf(target, true).length > 0);
584                 };
585                 
586                 var _getChildrenOf = function(timeline, includeTimelines) {
587                                 var a = [],
588                                         cnt = 0,
589                                         tween = timeline._first;
590                                 while (tween) {
591                                         if (tween instanceof TweenLite) {
592                                                 a[cnt++] = tween;
593                                         } else {
594                                                 if (includeTimelines) {
595                                                         a[cnt++] = tween;
596                                                 }
597                                                 a = a.concat(_getChildrenOf(tween, includeTimelines));
598                                                 cnt = a.length;
599                                         }
600                                         tween = tween._next;
601                                 }
602                                 return a;
603                         }, 
604                         getAllTweens = TweenMax.getAllTweens = function(includeTimelines) {
605                                 return _getChildrenOf(Animation._rootTimeline, includeTimelines).concat( _getChildrenOf(Animation._rootFramesTimeline, includeTimelines) );
606                         };
607                 
608                 TweenMax.killAll = function(complete, tweens, delayedCalls, timelines) {
609                         if (tweens == null) {
610                                 tweens = true;
611                         }
612                         if (delayedCalls == null) {
613                                 delayedCalls = true;
614                         }
615                         var a = getAllTweens((timelines != false)),
616                                 l = a.length,
617                                 allTrue = (tweens && delayedCalls && timelines),
618                                 isDC, tween, i;
619                         for (i = 0; i < l; i++) {
620                                 tween = a[i];
621                                 if (allTrue || (tween instanceof SimpleTimeline) || ((isDC = (tween.target === tween.vars.onComplete)) && delayedCalls) || (tweens && !isDC)) {
622                                         if (complete) {
623                                                 tween.totalTime(tween._reversed ? 0 : tween.totalDuration());
624                                         } else {
625                                                 tween._enabled(false, false);
626                                         }
627                                 }
628                         }
629                 };
630                 
631                 TweenMax.killChildTweensOf = function(parent, complete) {
632                         if (parent == null) {
633                                 return;
634                         }
635                         var tl = TweenLiteInternals.tweenLookup,
636                                 a, curParent, p, i, l;
637                         if (typeof(parent) === "string") {
638                                 parent = TweenLite.selector(parent) || parent;
639                         }
640                         if (_isSelector(parent)) {
641                                 parent = _slice.call(parent, 0);
642                         }
643                         if (_isArray(parent)) {
644                                 i = parent.length;
645                                 while (--i > -1) {
646                                         TweenMax.killChildTweensOf(parent[i], complete);
647                                 }
648                                 return;
649                         }
650                         a = [];
651                         for (p in tl) {
652                                 curParent = tl[p].target.parentNode;
653                                 while (curParent) {
654                                         if (curParent === parent) {
655                                                 a = a.concat(tl[p].tweens);
656                                         }
657                                         curParent = curParent.parentNode;
658                                 }
659                         }
660                         l = a.length;
661                         for (i = 0; i < l; i++) {
662                                 if (complete) {
663                                         a[i].totalTime(a[i].totalDuration());
664                                 }
665                                 a[i]._enabled(false, false);
666                         }
667                 };
668
669                 var _changePause = function(pause, tweens, delayedCalls, timelines) {
670                         tweens = (tweens !== false);
671                         delayedCalls = (delayedCalls !== false);
672                         timelines = (timelines !== false);
673                         var a = getAllTweens(timelines),
674                                 allTrue = (tweens && delayedCalls && timelines),
675                                 i = a.length,
676                                 isDC, tween;
677                         while (--i > -1) {
678                                 tween = a[i];
679                                 if (allTrue || (tween instanceof SimpleTimeline) || ((isDC = (tween.target === tween.vars.onComplete)) && delayedCalls) || (tweens && !isDC)) {
680                                         tween.paused(pause);
681                                 }
682                         }
683                 };
684                 
685                 TweenMax.pauseAll = function(tweens, delayedCalls, timelines) {
686                         _changePause(true, tweens, delayedCalls, timelines);
687                 };
688                 
689                 TweenMax.resumeAll = function(tweens, delayedCalls, timelines) {
690                         _changePause(false, tweens, delayedCalls, timelines);
691                 };
692
693                 TweenMax.globalTimeScale = function(value) {
694                         var tl = Animation._rootTimeline,
695                                 t = TweenLite.ticker.time;
696                         if (!arguments.length) {
697                                 return tl._timeScale;
698                         }
699                         value = value || _tinyNum; //can't allow zero because it'll throw the math off
700                         tl._startTime = t - ((t - tl._startTime) * tl._timeScale / value);
701                         tl = Animation._rootFramesTimeline;
702                         t = TweenLite.ticker.frame;
703                         tl._startTime = t - ((t - tl._startTime) * tl._timeScale / value);
704                         tl._timeScale = Animation._rootTimeline._timeScale = value;
705                         return value;
706                 };
707                 
708         
709 //---- GETTERS / SETTERS ----------------------------------------------------------------------------------------------------------
710                 
711                 p.progress = function(value) {
712                         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);
713                 };
714                 
715                 p.totalProgress = function(value) {
716                         return (!arguments.length) ? this._totalTime / this.totalDuration() : this.totalTime( this.totalDuration() * value, false);
717                 };
718                 
719                 p.time = function(value, suppressEvents) {
720                         if (!arguments.length) {
721                                 return this._time;
722                         }
723                         if (this._dirty) {
724                                 this.totalDuration();
725                         }
726                         if (value > this._duration) {
727                                 value = this._duration;
728                         }
729                         if (this._yoyo && (this._cycle & 1) !== 0) {
730                                 value = (this._duration - value) + (this._cycle * (this._duration + this._repeatDelay));
731                         } else if (this._repeat !== 0) {
732                                 value += this._cycle * (this._duration + this._repeatDelay);
733                         }
734                         return this.totalTime(value, suppressEvents);
735                 };
736
737                 p.duration = function(value) {
738                         if (!arguments.length) {
739                                 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.
740                         }
741                         return Animation.prototype.duration.call(this, value);
742                 };
743
744                 p.totalDuration = function(value) {
745                         if (!arguments.length) {
746                                 if (this._dirty) {
747                                         //instead of Infinity, we use 999999999999 so that we can accommodate reverses
748                                         this._totalDuration = (this._repeat === -1) ? 999999999999 : this._duration * (this._repeat + 1) + (this._repeatDelay * this._repeat);
749                                         this._dirty = false;
750                                 }
751                                 return this._totalDuration;
752                         }
753                         return (this._repeat === -1) ? this : this.duration( (value - (this._repeat * this._repeatDelay)) / (this._repeat + 1) );
754                 };
755                 
756                 p.repeat = function(value) {
757                         if (!arguments.length) {
758                                 return this._repeat;
759                         }
760                         this._repeat = value;
761                         return this._uncache(true);
762                 };
763                 
764                 p.repeatDelay = function(value) {
765                         if (!arguments.length) {
766                                 return this._repeatDelay;
767                         }
768                         this._repeatDelay = value;
769                         return this._uncache(true);
770                 };
771                 
772                 p.yoyo = function(value) {
773                         if (!arguments.length) {
774                                 return this._yoyo;
775                         }
776                         this._yoyo = value;
777                         return this;
778                 };
779                 
780                 
781                 return TweenMax;
782                 
783         }, true);
784
785
786
787
788
789
790
791
792 /*
793  * ----------------------------------------------------------------
794  * TimelineLite
795  * ----------------------------------------------------------------
796  */
797         window._gsDefine("TimelineLite", ["core.Animation","core.SimpleTimeline","TweenLite"], function(Animation, SimpleTimeline, TweenLite) {
798
799                 var TimelineLite = function(vars) {
800                                 SimpleTimeline.call(this, vars);
801                                 this._labels = {};
802                                 this.autoRemoveChildren = (this.vars.autoRemoveChildren === true);
803                                 this.smoothChildTiming = (this.vars.smoothChildTiming === true);
804                                 this._sortChildren = true;
805                                 this._onUpdate = this.vars.onUpdate;
806                                 var v = this.vars,
807                                         val, p;
808                                 for (p in v) {
809                                         val = v[p];
810                                         if (_isArray(val)) if (val.join("").indexOf("{self}") !== -1) {
811                                                 v[p] = this._swapSelfInParams(val);
812                                         }
813                                 }
814                                 if (_isArray(v.tweens)) {
815                                         this.add(v.tweens, 0, v.align, v.stagger);
816                                 }
817                         },
818                         _tinyNum = 0.0000000001,
819                         _isSelector = TweenLite._internals.isSelector,
820                         _isArray = TweenLite._internals.isArray,
821                         _blankArray = [],
822                         _globals = window._gsDefine.globals,
823                         _copy = function(vars) {
824                                 var copy = {}, p;
825                                 for (p in vars) {
826                                         copy[p] = vars[p];
827                                 }
828                                 return copy;
829                         },
830                         _pauseCallback = function(tween, callback, params, scope) {
831                                 tween._timeline.pause(tween._startTime);
832                                 if (callback) {
833                                         callback.apply(scope || tween._timeline, params || _blankArray);
834                                 }
835                         },
836                         _slice = _blankArray.slice,
837                         p = TimelineLite.prototype = new SimpleTimeline();
838
839                 TimelineLite.version = "1.12.1";
840                 p.constructor = TimelineLite;
841                 p.kill()._gc = false;
842
843                 p.to = function(target, duration, vars, position) {
844                         var Engine = (vars.repeat && _globals.TweenMax) || TweenLite;
845                         return duration ? this.add( new Engine(target, duration, vars), position) : this.set(target, vars, position);
846                 };
847
848                 p.from = function(target, duration, vars, position) {
849                         return this.add( ((vars.repeat && _globals.TweenMax) || TweenLite).from(target, duration, vars), position);
850                 };
851
852                 p.fromTo = function(target, duration, fromVars, toVars, position) {
853                         var Engine = (toVars.repeat && _globals.TweenMax) || TweenLite;
854                         return duration ? this.add( Engine.fromTo(target, duration, fromVars, toVars), position) : this.set(target, toVars, position);
855                 };
856
857                 p.staggerTo = function(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope) {
858                         var tl = new TimelineLite({onComplete:onCompleteAll, onCompleteParams:onCompleteAllParams, onCompleteScope:onCompleteAllScope, smoothChildTiming:this.smoothChildTiming}),
859                                 i;
860                         if (typeof(targets) === "string") {
861                                 targets = TweenLite.selector(targets) || targets;
862                         }
863                         if (_isSelector(targets)) { //senses if the targets object is a selector. If it is, we should translate it into an array.
864                                 targets = _slice.call(targets, 0);
865                         }
866                         stagger = stagger || 0;
867                         for (i = 0; i < targets.length; i++) {
868                                 if (vars.startAt) {
869                                         vars.startAt = _copy(vars.startAt);
870                                 }
871                                 tl.to(targets[i], duration, _copy(vars), i * stagger);
872                         }
873                         return this.add(tl, position);
874                 };
875
876                 p.staggerFrom = function(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope) {
877                         vars.immediateRender = (vars.immediateRender != false);
878                         vars.runBackwards = true;
879                         return this.staggerTo(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope);
880                 };
881
882                 p.staggerFromTo = function(targets, duration, fromVars, toVars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope) {
883                         toVars.startAt = fromVars;
884                         toVars.immediateRender = (toVars.immediateRender != false && fromVars.immediateRender != false);
885                         return this.staggerTo(targets, duration, toVars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope);
886                 };
887
888                 p.call = function(callback, params, scope, position) {
889                         return this.add( TweenLite.delayedCall(0, callback, params, scope), position);
890                 };
891
892                 p.set = function(target, vars, position) {
893                         position = this._parseTimeOrLabel(position, 0, true);
894                         if (vars.immediateRender == null) {
895                                 vars.immediateRender = (position === this._time && !this._paused);
896                         }
897                         return this.add( new TweenLite(target, 0, vars), position);
898                 };
899
900                 TimelineLite.exportRoot = function(vars, ignoreDelayedCalls) {
901                         vars = vars || {};
902                         if (vars.smoothChildTiming == null) {
903                                 vars.smoothChildTiming = true;
904                         }
905                         var tl = new TimelineLite(vars),
906                                 root = tl._timeline,
907                                 tween, next;
908                         if (ignoreDelayedCalls == null) {
909                                 ignoreDelayedCalls = true;
910                         }
911                         root._remove(tl, true);
912                         tl._startTime = 0;
913                         tl._rawPrevTime = tl._time = tl._totalTime = root._time;
914                         tween = root._first;
915                         while (tween) {
916                                 next = tween._next;
917                                 if (!ignoreDelayedCalls || !(tween instanceof TweenLite && tween.target === tween.vars.onComplete)) {
918                                         tl.add(tween, tween._startTime - tween._delay);
919                                 }
920                                 tween = next;
921                         }
922                         root.add(tl, 0);
923                         return tl;
924                 };
925
926                 p.add = function(value, position, align, stagger) {
927                         var curTime, l, i, child, tl, beforeRawTime;
928                         if (typeof(position) !== "number") {
929                                 position = this._parseTimeOrLabel(position, 0, true, value);
930                         }
931                         if (!(value instanceof Animation)) {
932                                 if ((value instanceof Array) || (value && value.push && _isArray(value))) {
933                                         align = align || "normal";
934                                         stagger = stagger || 0;
935                                         curTime = position;
936                                         l = value.length;
937                                         for (i = 0; i < l; i++) {
938                                                 if (_isArray(child = value[i])) {
939                                                         child = new TimelineLite({tweens:child});
940                                                 }
941                                                 this.add(child, curTime);
942                                                 if (typeof(child) !== "string" && typeof(child) !== "function") {
943                                                         if (align === "sequence") {
944                                                                 curTime = child._startTime + (child.totalDuration() / child._timeScale);
945                                                         } else if (align === "start") {
946                                                                 child._startTime -= child.delay();
947                                                         }
948                                                 }
949                                                 curTime += stagger;
950                                         }
951                                         return this._uncache(true);
952                                 } else if (typeof(value) === "string") {
953                                         return this.addLabel(value, position);
954                                 } else if (typeof(value) === "function") {
955                                         value = TweenLite.delayedCall(0, value);
956                                 } else {
957                                         throw("Cannot add " + value + " into the timeline; it is not a tween, timeline, function, or string.");
958                                 }
959                         }
960
961                         SimpleTimeline.prototype.add.call(this, value, position);
962
963                         //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.
964                         if (this._gc || this._time === this._duration) if (!this._paused) if (this._duration < this.duration()) {
965                                 //in case any of the ancestors had completed but should now be enabled...
966                                 tl = this;
967                                 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.
968                                 while (tl._timeline) {
969                                         if (beforeRawTime && tl._timeline.smoothChildTiming) {
970                                                 tl.totalTime(tl._totalTime, true); //moves the timeline (shifts its startTime) if necessary, and also enables it.
971                                         } else if (tl._gc) {
972                                                 tl._enabled(true, false);
973                                         }
974                                         tl = tl._timeline;
975                                 }
976                         }
977
978                         return this;
979                 };
980
981                 p.remove = function(value) {
982                         if (value instanceof Animation) {
983                                 return this._remove(value, false);
984                         } else if (value instanceof Array || (value && value.push && _isArray(value))) {
985                                 var i = value.length;
986                                 while (--i > -1) {
987                                         this.remove(value[i]);
988                                 }
989                                 return this;
990                         } else if (typeof(value) === "string") {
991                                 return this.removeLabel(value);
992                         }
993                         return this.kill(null, value);
994                 };
995
996                 p._remove = function(tween, skipDisable) {
997                         SimpleTimeline.prototype._remove.call(this, tween, skipDisable);
998                         var last = this._last;
999                         if (!last) {
1000                                 this._time = this._totalTime = this._duration = this._totalDuration = 0;
1001                         } else if (this._time > last._startTime + last._totalDuration / last._timeScale) {
1002                                 this._time = this.duration();
1003                                 this._totalTime = this._totalDuration;
1004                         }
1005                         return this;
1006                 };
1007
1008                 p.append = function(value, offsetOrLabel) {
1009                         return this.add(value, this._parseTimeOrLabel(null, offsetOrLabel, true, value));
1010                 };
1011
1012                 p.insert = p.insertMultiple = function(value, position, align, stagger) {
1013                         return this.add(value, position || 0, align, stagger);
1014                 };
1015
1016                 p.appendMultiple = function(tweens, offsetOrLabel, align, stagger) {
1017                         return this.add(tweens, this._parseTimeOrLabel(null, offsetOrLabel, true, tweens), align, stagger);
1018                 };
1019
1020                 p.addLabel = function(label, position) {
1021                         this._labels[label] = this._parseTimeOrLabel(position);
1022                         return this;
1023                 };
1024
1025                 p.addPause = function(position, callback, params, scope) {
1026                         return this.call(_pauseCallback, ["{self}", callback, params, scope], this, position);
1027                 };
1028
1029                 p.removeLabel = function(label) {
1030                         delete this._labels[label];
1031                         return this;
1032                 };
1033
1034                 p.getLabelTime = function(label) {
1035                         return (this._labels[label] != null) ? this._labels[label] : -1;
1036                 };
1037
1038                 p._parseTimeOrLabel = function(timeOrLabel, offsetOrLabel, appendIfAbsent, ignore) {
1039                         var i;
1040                         //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().
1041                         if (ignore instanceof Animation && ignore.timeline === this) {
1042                                 this.remove(ignore);
1043                         } else if (ignore && ((ignore instanceof Array) || (ignore.push && _isArray(ignore)))) {
1044                                 i = ignore.length;
1045                                 while (--i > -1) {
1046                                         if (ignore[i] instanceof Animation && ignore[i].timeline === this) {
1047                                                 this.remove(ignore[i]);
1048                                         }
1049                                 }
1050                         }
1051                         if (typeof(offsetOrLabel) === "string") {
1052                                 return this._parseTimeOrLabel(offsetOrLabel, (appendIfAbsent && typeof(timeOrLabel) === "number" && this._labels[offsetOrLabel] == null) ? timeOrLabel - this.duration() : 0, appendIfAbsent);
1053                         }
1054                         offsetOrLabel = offsetOrLabel || 0;
1055                         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).
1056                                 i = timeOrLabel.indexOf("=");
1057                                 if (i === -1) {
1058                                         if (this._labels[timeOrLabel] == null) {
1059                                                 return appendIfAbsent ? (this._labels[timeOrLabel] = this.duration() + offsetOrLabel) : offsetOrLabel;
1060                                         }
1061                                         return this._labels[timeOrLabel] + offsetOrLabel;
1062                                 }
1063                                 offsetOrLabel = parseInt(timeOrLabel.charAt(i-1) + "1", 10) * Number(timeOrLabel.substr(i+1));
1064                                 timeOrLabel = (i > 1) ? this._parseTimeOrLabel(timeOrLabel.substr(0, i-1), 0, appendIfAbsent) : this.duration();
1065                         } else if (timeOrLabel == null) {
1066                                 timeOrLabel = this.duration();
1067                         }
1068                         return Number(timeOrLabel) + offsetOrLabel;
1069                 };
1070
1071                 p.seek = function(position, suppressEvents) {
1072                         return this.totalTime((typeof(position) === "number") ? position : this._parseTimeOrLabel(position), (suppressEvents !== false));
1073                 };
1074
1075                 p.stop = function() {
1076                         return this.paused(true);
1077                 };
1078
1079                 p.gotoAndPlay = function(position, suppressEvents) {
1080                         return this.play(position, suppressEvents);
1081                 };
1082
1083                 p.gotoAndStop = function(position, suppressEvents) {
1084                         return this.pause(position, suppressEvents);
1085                 };
1086
1087                 p.render = function(time, suppressEvents, force) {
1088                         if (this._gc) {
1089                                 this._enabled(true, false);
1090                         }
1091                         var totalDur = (!this._dirty) ? this._totalDuration : this.totalDuration(),
1092                                 prevTime = this._time,
1093                                 prevStart = this._startTime,
1094                                 prevTimeScale = this._timeScale,
1095                                 prevPaused = this._paused,
1096                                 tween, isComplete, next, callback, internalForce;
1097                         if (time >= totalDur) {
1098                                 this._totalTime = this._time = totalDur;
1099                                 if (!this._reversed) if (!this._hasPausedChild()) {
1100                                         isComplete = true;
1101                                         callback = "onComplete";
1102                                         if (this._duration === 0) if (time === 0 || this._rawPrevTime < 0 || this._rawPrevTime === _tinyNum) if (this._rawPrevTime !== time && this._first) {
1103                                                 internalForce = true;
1104                                                 if (this._rawPrevTime > _tinyNum) {
1105                                                         callback = "onReverseComplete";
1106                                                 }
1107                                         }
1108                                 }
1109                                 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.
1110                                 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.
1111
1112                         } else if (time < 0.0000001) { //to work around occasional floating point math artifacts, round super small values to 0.
1113                                 this._totalTime = this._time = 0;
1114                                 if (prevTime !== 0 || (this._duration === 0 && this._rawPrevTime !== _tinyNum && (this._rawPrevTime > 0 || (time < 0 && this._rawPrevTime >= 0)))) {
1115                                         callback = "onReverseComplete";
1116                                         isComplete = this._reversed;
1117                                 }
1118                                 if (time < 0) {
1119                                         this._active = false;
1120                                         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.
1121                                                 internalForce = true;
1122                                         }
1123                                         this._rawPrevTime = time;
1124                                 } else {
1125                                         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.
1126
1127                                         time = 0; //to avoid occasional floating point rounding errors (could cause problems especially with zero-duration tweens at the very beginning of the timeline)
1128                                         if (!this._initted) {
1129                                                 internalForce = true;
1130                                         }
1131                                 }
1132
1133                         } else {
1134                                 this._totalTime = this._time = this._rawPrevTime = time;
1135                         }
1136                         if ((this._time === prevTime || !this._first) && !force && !internalForce) {
1137                                 return;
1138                         } else if (!this._initted) {
1139                                 this._initted = true;
1140                         }
1141
1142                         if (!this._active) if (!this._paused && this._time !== prevTime && time > 0) {
1143                                 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.
1144                         }
1145
1146                         if (prevTime === 0) if (this.vars.onStart) if (this._time !== 0) if (!suppressEvents) {
1147                                 this.vars.onStart.apply(this.vars.onStartScope || this, this.vars.onStartParams || _blankArray);
1148                         }
1149
1150                         if (this._time >= prevTime) {
1151                                 tween = this._first;
1152                                 while (tween) {
1153                                         next = tween._next; //record it here because the value could change after rendering...
1154                                         if (this._paused && !prevPaused) { //in case a tween pauses the timeline when rendering
1155                                                 break;
1156                                         } else if (tween._active || (tween._startTime <= this._time && !tween._paused && !tween._gc)) {
1157                                                 if (!tween._reversed) {
1158                                                         tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force);
1159                                                 } else {
1160                                                         tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force);
1161                                                 }
1162                                         }
1163                                         tween = next;
1164                                 }
1165                         } else {
1166                                 tween = this._last;
1167                                 while (tween) {
1168                                         next = tween._prev; //record it here because the value could change after rendering...
1169                                         if (this._paused && !prevPaused) { //in case a tween pauses the timeline when rendering
1170                                                 break;
1171                                         } else if (tween._active || (tween._startTime <= prevTime && !tween._paused && !tween._gc)) {
1172                                                 if (!tween._reversed) {
1173                                                         tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force);
1174                                                 } else {
1175                                                         tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force);
1176                                                 }
1177                                         }
1178                                         tween = next;
1179                                 }
1180                         }
1181
1182                         if (this._onUpdate) if (!suppressEvents) {
1183                                 this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray);
1184                         }
1185
1186                         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
1187                                 if (isComplete) {
1188                                         if (this._timeline.autoRemoveChildren) {
1189                                                 this._enabled(false, false);
1190                                         }
1191                                         this._active = false;
1192                                 }
1193                                 if (!suppressEvents && this.vars[callback]) {
1194                                         this.vars[callback].apply(this.vars[callback + "Scope"] || this, this.vars[callback + "Params"] || _blankArray);
1195                                 }
1196                         }
1197                 };
1198
1199                 p._hasPausedChild = function() {
1200                         var tween = this._first;
1201                         while (tween) {
1202                                 if (tween._paused || ((tween instanceof TimelineLite) && tween._hasPausedChild())) {
1203                                         return true;
1204                                 }
1205                                 tween = tween._next;
1206                         }
1207                         return false;
1208                 };
1209
1210                 p.getChildren = function(nested, tweens, timelines, ignoreBeforeTime) {
1211                         ignoreBeforeTime = ignoreBeforeTime || -9999999999;
1212                         var a = [],
1213                                 tween = this._first,
1214                                 cnt = 0;
1215                         while (tween) {
1216                                 if (tween._startTime < ignoreBeforeTime) {
1217                                         //do nothing
1218                                 } else if (tween instanceof TweenLite) {
1219                                         if (tweens !== false) {
1220                                                 a[cnt++] = tween;
1221                                         }
1222                                 } else {
1223                                         if (timelines !== false) {
1224                                                 a[cnt++] = tween;
1225                                         }
1226                                         if (nested !== false) {
1227                                                 a = a.concat(tween.getChildren(true, tweens, timelines));
1228                                                 cnt = a.length;
1229                                         }
1230                                 }
1231                                 tween = tween._next;
1232                         }
1233                         return a;
1234                 };
1235
1236                 p.getTweensOf = function(target, nested) {
1237                         var disabled = this._gc,
1238                                 a = [],
1239                                 cnt = 0,
1240                                 tweens, i;
1241                         if (disabled) {
1242                                 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.
1243                         }
1244                         tweens = TweenLite.getTweensOf(target);
1245                         i = tweens.length;
1246                         while (--i > -1) {
1247                                 if (tweens[i].timeline === this || (nested && this._contains(tweens[i]))) {
1248                                         a[cnt++] = tweens[i];
1249                                 }
1250                         }
1251                         if (disabled) {
1252                                 this._enabled(false, true);
1253                         }
1254                         return a;
1255                 };
1256
1257                 p._contains = function(tween) {
1258                         var tl = tween.timeline;
1259                         while (tl) {
1260                                 if (tl === this) {
1261                                         return true;
1262                                 }
1263                                 tl = tl.timeline;
1264                         }
1265                         return false;
1266                 };
1267
1268                 p.shiftChildren = function(amount, adjustLabels, ignoreBeforeTime) {
1269                         ignoreBeforeTime = ignoreBeforeTime || 0;
1270                         var tween = this._first,
1271                                 labels = this._labels,
1272                                 p;
1273                         while (tween) {
1274                                 if (tween._startTime >= ignoreBeforeTime) {
1275                                         tween._startTime += amount;
1276                                 }
1277                                 tween = tween._next;
1278                         }
1279                         if (adjustLabels) {
1280                                 for (p in labels) {
1281                                         if (labels[p] >= ignoreBeforeTime) {
1282                                                 labels[p] += amount;
1283                                         }
1284                                 }
1285                         }
1286                         return this._uncache(true);
1287                 };
1288
1289                 p._kill = function(vars, target) {
1290                         if (!vars && !target) {
1291                                 return this._enabled(false, false);
1292                         }
1293                         var tweens = (!target) ? this.getChildren(true, true, false) : this.getTweensOf(target),
1294                                 i = tweens.length,
1295                                 changed = false;
1296                         while (--i > -1) {
1297                                 if (tweens[i]._kill(vars, target)) {
1298                                         changed = true;
1299                                 }
1300                         }
1301                         return changed;
1302                 };
1303
1304                 p.clear = function(labels) {
1305                         var tweens = this.getChildren(false, true, true),
1306                                 i = tweens.length;
1307                         this._time = this._totalTime = 0;
1308                         while (--i > -1) {
1309                                 tweens[i]._enabled(false, false);
1310                         }
1311                         if (labels !== false) {
1312                                 this._labels = {};
1313                         }
1314                         return this._uncache(true);
1315                 };
1316
1317                 p.invalidate = function() {
1318                         var tween = this._first;
1319                         while (tween) {
1320                                 tween.invalidate();
1321                                 tween = tween._next;
1322                         }
1323                         return this;
1324                 };
1325
1326                 p._enabled = function(enabled, ignoreTimeline) {
1327                         if (enabled === this._gc) {
1328                                 var tween = this._first;
1329                                 while (tween) {
1330                                         tween._enabled(enabled, true);
1331                                         tween = tween._next;
1332                                 }
1333                         }
1334                         return SimpleTimeline.prototype._enabled.call(this, enabled, ignoreTimeline);
1335                 };
1336
1337                 p.duration = function(value) {
1338                         if (!arguments.length) {
1339                                 if (this._dirty) {
1340                                         this.totalDuration(); //just triggers recalculation
1341                                 }
1342                                 return this._duration;
1343                         }
1344                         if (this.duration() !== 0 && value !== 0) {
1345                                 this.timeScale(this._duration / value);
1346                         }
1347                         return this;
1348                 };
1349
1350                 p.totalDuration = function(value) {
1351                         if (!arguments.length) {
1352                                 if (this._dirty) {
1353                                         var max = 0,
1354                                                 tween = this._last,
1355                                                 prevStart = 999999999999,
1356                                                 prev, end;
1357                                         while (tween) {
1358                                                 prev = tween._prev; //record it here in case the tween changes position in the sequence...
1359                                                 if (tween._dirty) {
1360                                                         tween.totalDuration(); //could change the tween._startTime, so make sure the tween's cache is clean before analyzing it.
1361                                                 }
1362                                                 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
1363                                                         this.add(tween, tween._startTime - tween._delay);
1364                                                 } else {
1365                                                         prevStart = tween._startTime;
1366                                                 }
1367                                                 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.
1368                                                         max -= tween._startTime;
1369                                                         if (this._timeline.smoothChildTiming) {
1370                                                                 this._startTime += tween._startTime / this._timeScale;
1371                                                         }
1372                                                         this.shiftChildren(-tween._startTime, false, -9999999999);
1373                                                         prevStart = 0;
1374                                                 }
1375                                                 end = tween._startTime + (tween._totalDuration / tween._timeScale);
1376                                                 if (end > max) {
1377                                                         max = end;
1378                                                 }
1379                                                 tween = prev;
1380                                         }
1381                                         this._duration = this._totalDuration = max;
1382                                         this._dirty = false;
1383                                 }
1384                                 return this._totalDuration;
1385                         }
1386                         if (this.totalDuration() !== 0) if (value !== 0) {
1387                                 this.timeScale(this._totalDuration / value);
1388                         }
1389                         return this;
1390                 };
1391
1392                 p.usesFrames = function() {
1393                         var tl = this._timeline;
1394                         while (tl._timeline) {
1395                                 tl = tl._timeline;
1396                         }
1397                         return (tl === Animation._rootFramesTimeline);
1398                 };
1399
1400                 p.rawTime = function() {
1401                         return this._paused ? this._totalTime : (this._timeline.rawTime() - this._startTime) * this._timeScale;
1402                 };
1403
1404                 return TimelineLite;
1405
1406         }, true);
1407         
1408
1409
1410
1411
1412
1413
1414
1415         
1416         
1417         
1418         
1419         
1420 /*
1421  * ----------------------------------------------------------------
1422  * TimelineMax
1423  * ----------------------------------------------------------------
1424  */
1425         window._gsDefine("TimelineMax", ["TimelineLite","TweenLite","easing.Ease"], function(TimelineLite, TweenLite, Ease) {
1426
1427                 var TimelineMax = function(vars) {
1428                                 TimelineLite.call(this, vars);
1429                                 this._repeat = this.vars.repeat || 0;
1430                                 this._repeatDelay = this.vars.repeatDelay || 0;
1431                                 this._cycle = 0;
1432                                 this._yoyo = (this.vars.yoyo === true);
1433                                 this._dirty = true;
1434                         },
1435                         _tinyNum = 0.0000000001,
1436                         _blankArray = [],
1437                         _easeNone = new Ease(null, null, 1, 0),
1438                         p = TimelineMax.prototype = new TimelineLite();
1439
1440                 p.constructor = TimelineMax;
1441                 p.kill()._gc = false;
1442                 TimelineMax.version = "1.12.1";
1443
1444                 p.invalidate = function() {
1445                         this._yoyo = (this.vars.yoyo === true);
1446                         this._repeat = this.vars.repeat || 0;
1447                         this._repeatDelay = this.vars.repeatDelay || 0;
1448                         this._uncache(true);
1449                         return TimelineLite.prototype.invalidate.call(this);
1450                 };
1451
1452                 p.addCallback = function(callback, position, params, scope) {
1453                         return this.add( TweenLite.delayedCall(0, callback, params, scope), position);
1454                 };
1455
1456                 p.removeCallback = function(callback, position) {
1457                         if (callback) {
1458                                 if (position == null) {
1459                                         this._kill(null, callback);
1460                                 } else {
1461                                         var a = this.getTweensOf(callback, false),
1462                                                 i = a.length,
1463                                                 time = this._parseTimeOrLabel(position);
1464                                         while (--i > -1) {
1465                                                 if (a[i]._startTime === time) {
1466                                                         a[i]._enabled(false, false);
1467                                                 }
1468                                         }
1469                                 }
1470                         }
1471                         return this;
1472                 };
1473
1474                 p.tweenTo = function(position, vars) {
1475                         vars = vars || {};
1476                         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.
1477                                 duration, p, t;
1478                         for (p in vars) {
1479                                 copy[p] = vars[p];
1480                         }
1481                         copy.time = this._parseTimeOrLabel(position);
1482                         duration = (Math.abs(Number(copy.time) - this._time) / this._timeScale) || 0.001;
1483                         t = new TweenLite(this, duration, copy);
1484                         copy.onStart = function() {
1485                                 t.target.paused(true);
1486                                 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.
1487                                         t.duration( Math.abs( t.vars.time - t.target.time()) / t.target._timeScale );
1488                                 }
1489                                 if (vars.onStart) { //in case the user had an onStart in the vars - we don't want to overwrite it.
1490                                         vars.onStart.apply(vars.onStartScope || t, vars.onStartParams || _blankArray);
1491                                 }
1492                         };
1493                         return t;
1494                 };
1495
1496                 p.tweenFromTo = function(fromPosition, toPosition, vars) {
1497                         vars = vars || {};
1498                         fromPosition = this._parseTimeOrLabel(fromPosition);
1499                         vars.startAt = {onComplete:this.seek, onCompleteParams:[fromPosition], onCompleteScope:this};
1500                         vars.immediateRender = (vars.immediateRender !== false);
1501                         var t = this.tweenTo(toPosition, vars);
1502                         return t.duration((Math.abs( t.vars.time - fromPosition) / this._timeScale) || 0.001);
1503                 };
1504
1505                 p.render = function(time, suppressEvents, force) {
1506                         if (this._gc) {
1507                                 this._enabled(true, false);
1508                         }
1509                         var totalDur = (!this._dirty) ? this._totalDuration : this.totalDuration(),
1510                                 dur = this._duration,
1511                                 prevTime = this._time,
1512                                 prevTotalTime = this._totalTime,
1513                                 prevStart = this._startTime,
1514                                 prevTimeScale = this._timeScale,
1515                                 prevRawPrevTime = this._rawPrevTime,
1516                                 prevPaused = this._paused,
1517                                 prevCycle = this._cycle,
1518                                 tween, isComplete, next, callback, internalForce, cycleDuration;
1519                         if (time >= totalDur) {
1520                                 if (!this._locked) {
1521                                         this._totalTime = totalDur;
1522                                         this._cycle = this._repeat;
1523                                 }
1524                                 if (!this._reversed) if (!this._hasPausedChild()) {
1525                                         isComplete = true;
1526                                         callback = "onComplete";
1527                                         if (this._duration === 0) if (time === 0 || prevRawPrevTime < 0 || prevRawPrevTime === _tinyNum) if (prevRawPrevTime !== time && this._first) {
1528                                                 internalForce = true;
1529                                                 if (prevRawPrevTime > _tinyNum) {
1530                                                         callback = "onReverseComplete";
1531                                                 }
1532                                         }
1533                                 }
1534                                 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.
1535                                 if (this._yoyo && (this._cycle & 1) !== 0) {
1536                                         this._time = time = 0;
1537                                 } else {
1538                                         this._time = dur;
1539                                         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.
1540                                 }
1541
1542                         } else if (time < 0.0000001) { //to work around occasional floating point math artifacts, round super small values to 0.
1543                                 if (!this._locked) {
1544                                         this._totalTime = this._cycle = 0;
1545                                 }
1546                                 this._time = 0;
1547                                 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)
1548                                         callback = "onReverseComplete";
1549                                         isComplete = this._reversed;
1550                                 }
1551                                 if (time < 0) {
1552                                         this._active = false;
1553                                         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.
1554                                                 internalForce = true;
1555                                         }
1556                                         this._rawPrevTime = time;
1557                                 } else {
1558                                         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.
1559                                         time = 0; //to avoid occasional floating point rounding errors (could cause problems especially with zero-duration tweens at the very beginning of the timeline)
1560                                         if (!this._initted) {
1561                                                 internalForce = true;
1562                                         }
1563                                 }
1564
1565                         } else {
1566                                 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.
1567                                         internalForce = true;
1568                                 }
1569                                 this._time = this._rawPrevTime = time;
1570                                 if (!this._locked) {
1571                                         this._totalTime = time;
1572                                         if (this._repeat !== 0) {
1573                                                 cycleDuration = dur + this._repeatDelay;
1574                                                 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!)
1575                                                 if (this._cycle !== 0) if (this._cycle === this._totalTime / cycleDuration) {
1576                                                         this._cycle--; //otherwise when rendered exactly at the end time, it will act as though it is repeating (at the beginning)
1577                                                 }
1578                                                 this._time = this._totalTime - (this._cycle * cycleDuration);
1579                                                 if (this._yoyo) if ((this._cycle & 1) !== 0) {
1580                                                         this._time = dur - this._time;
1581                                                 }
1582                                                 if (this._time > dur) {
1583                                                         this._time = dur;
1584                                                         time = dur + 0.0001; //to avoid occasional floating point rounding error
1585                                                 } else if (this._time < 0) {
1586                                                         this._time = time = 0;
1587                                                 } else {
1588                                                         time = this._time;
1589                                                 }
1590                                         }
1591                                 }
1592                         }
1593
1594                         if (this._cycle !== prevCycle) if (!this._locked) {
1595                                 /*
1596                                 make sure children at the end/beginning of the timeline are rendered properly. If, for example,
1597                                 a 3-second long timeline rendered at 2.9 seconds previously, and now renders at 3.2 seconds (which
1598                                 would get transated to 2.8 seconds if the timeline yoyos or 0.2 seconds if it just repeats), there
1599                                 could be a callback or a short tween that's at 2.95 or 3 seconds in which wouldn't render. So
1600                                 we need to push the timeline to the end (and/or beginning depending on its yoyo value). Also we must
1601                                 ensure that zero-duration tweens at the very beginning or end of the TimelineMax work.
1602                                 */
1603                                 var backwards = (this._yoyo && (prevCycle & 1) !== 0),
1604                                         wrap = (backwards === (this._yoyo && (this._cycle & 1) !== 0)),
1605                                         recTotalTime = this._totalTime,
1606                                         recCycle = this._cycle,
1607                                         recRawPrevTime = this._rawPrevTime,
1608                                         recTime = this._time;
1609
1610                                 this._totalTime = prevCycle * dur;
1611                                 if (this._cycle < prevCycle) {
1612                                         backwards = !backwards;
1613                                 } else {
1614                                         this._totalTime += dur;
1615                                 }
1616                                 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.
1617
1618                                 this._rawPrevTime = (dur === 0) ? prevRawPrevTime - 0.0001 : prevRawPrevTime;
1619                                 this._cycle = prevCycle;
1620                                 this._locked = true; //prevents changes to totalTime and skips repeat/yoyo behavior when we recursively call render()
1621                                 prevTime = (backwards) ? 0 : dur;
1622                                 this.render(prevTime, suppressEvents, (dur === 0));
1623                                 if (!suppressEvents) if (!this._gc) {
1624                                         if (this.vars.onRepeat) {
1625                                                 this.vars.onRepeat.apply(this.vars.onRepeatScope || this, this.vars.onRepeatParams || _blankArray);
1626                                         }
1627                                 }
1628                                 if (wrap) {
1629                                         prevTime = (backwards) ? dur + 0.0001 : -0.0001;
1630                                         this.render(prevTime, true, false);
1631                                 }
1632                                 this._locked = false;
1633                                 if (this._paused && !prevPaused) { //if the render() triggered callback that paused this timeline, we should abort (very rare, but possible)
1634                                         return;
1635                                 }
1636                                 this._time = recTime;
1637                                 this._totalTime = recTotalTime;
1638                                 this._cycle = recCycle;
1639                                 this._rawPrevTime = recRawPrevTime;
1640                         }
1641
1642                         if ((this._time === prevTime || !this._first) && !force && !internalForce) {
1643                                 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.
1644                                         this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray);
1645                                 }
1646                                 return;
1647                         } else if (!this._initted) {
1648                                 this._initted = true;
1649                         }
1650
1651                         if (!this._active) if (!this._paused && this._totalTime !== prevTotalTime && time > 0) {
1652                                 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.
1653                         }
1654
1655                         if (prevTotalTime === 0) if (this.vars.onStart) if (this._totalTime !== 0) if (!suppressEvents) {
1656                                 this.vars.onStart.apply(this.vars.onStartScope || this, this.vars.onStartParams || _blankArray);
1657                         }
1658
1659                         if (this._time >= prevTime) {
1660                                 tween = this._first;
1661                                 while (tween) {
1662                                         next = tween._next; //record it here because the value could change after rendering...
1663                                         if (this._paused && !prevPaused) { //in case a tween pauses the timeline when rendering
1664                                                 break;
1665                                         } else if (tween._active || (tween._startTime <= this._time && !tween._paused && !tween._gc)) {
1666                                                 if (!tween._reversed) {
1667                                                         tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force);
1668                                                 } else {
1669                                                         tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force);
1670                                                 }
1671
1672                                         }
1673                                         tween = next;
1674                                 }
1675                         } else {
1676                                 tween = this._last;
1677                                 while (tween) {
1678                                         next = tween._prev; //record it here because the value could change after rendering...
1679                                         if (this._paused && !prevPaused) { //in case a tween pauses the timeline when rendering
1680                                                 break;
1681                                         } else if (tween._active || (tween._startTime <= prevTime && !tween._paused && !tween._gc)) {
1682                                                 if (!tween._reversed) {
1683                                                         tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force);
1684                                                 } else {
1685                                                         tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force);
1686                                                 }
1687                                         }
1688                                         tween = next;
1689                                 }
1690                         }
1691
1692                         if (this._onUpdate) if (!suppressEvents) {
1693                                 this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray);
1694                         }
1695                         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
1696                                 if (isComplete) {
1697                                         if (this._timeline.autoRemoveChildren) {
1698                                                 this._enabled(false, false);
1699                                         }
1700                                         this._active = false;
1701                                 }
1702                                 if (!suppressEvents && this.vars[callback]) {
1703                                         this.vars[callback].apply(this.vars[callback + "Scope"] || this, this.vars[callback + "Params"] || _blankArray);
1704                                 }
1705                         }
1706                 };
1707
1708                 p.getActive = function(nested, tweens, timelines) {
1709                         if (nested == null) {
1710                                 nested = true;
1711                         }
1712                         if (tweens == null) {
1713                                 tweens = true;
1714                         }
1715                         if (timelines == null) {
1716                                 timelines = false;
1717                         }
1718                         var a = [],
1719                                 all = this.getChildren(nested, tweens, timelines),
1720                                 cnt = 0,
1721                                 l = all.length,
1722                                 i, tween;
1723                         for (i = 0; i < l; i++) {
1724                                 tween = all[i];
1725                                 if (tween.isActive()) {
1726                                         a[cnt++] = tween;
1727                                 }
1728                         }
1729                         return a;
1730                 };
1731
1732
1733                 p.getLabelAfter = function(time) {
1734                         if (!time) if (time !== 0) { //faster than isNan()
1735                                 time = this._time;
1736                         }
1737                         var labels = this.getLabelsArray(),
1738                                 l = labels.length,
1739                                 i;
1740                         for (i = 0; i < l; i++) {
1741                                 if (labels[i].time > time) {
1742                                         return labels[i].name;
1743                                 }
1744                         }
1745                         return null;
1746                 };
1747
1748                 p.getLabelBefore = function(time) {
1749                         if (time == null) {
1750                                 time = this._time;
1751                         }
1752                         var labels = this.getLabelsArray(),
1753                                 i = labels.length;
1754                         while (--i > -1) {
1755                                 if (labels[i].time < time) {
1756                                         return labels[i].name;
1757                                 }
1758                         }
1759                         return null;
1760                 };
1761
1762                 p.getLabelsArray = function() {
1763                         var a = [],
1764                                 cnt = 0,
1765                                 p;
1766                         for (p in this._labels) {
1767                                 a[cnt++] = {time:this._labels[p], name:p};
1768                         }
1769                         a.sort(function(a,b) {
1770                                 return a.time - b.time;
1771                         });
1772                         return a;
1773                 };
1774
1775
1776 //---- GETTERS / SETTERS -------------------------------------------------------------------------------------------------------
1777
1778                 p.progress = function(value) {
1779                         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);
1780                 };
1781
1782                 p.totalProgress = function(value) {
1783                         return (!arguments.length) ? this._totalTime / this.totalDuration() : this.totalTime( this.totalDuration() * value, false);
1784                 };
1785
1786                 p.totalDuration = function(value) {
1787                         if (!arguments.length) {
1788                                 if (this._dirty) {
1789                                         TimelineLite.prototype.totalDuration.call(this); //just forces refresh
1790                                         //Instead of Infinity, we use 999999999999 so that we can accommodate reverses.
1791                                         this._totalDuration = (this._repeat === -1) ? 999999999999 : this._duration * (this._repeat + 1) + (this._repeatDelay * this._repeat);
1792                                 }
1793                                 return this._totalDuration;
1794                         }
1795                         return (this._repeat === -1) ? this : this.duration( (value - (this._repeat * this._repeatDelay)) / (this._repeat + 1) );
1796                 };
1797
1798                 p.time = function(value, suppressEvents) {
1799                         if (!arguments.length) {
1800                                 return this._time;
1801                         }
1802                         if (this._dirty) {
1803                                 this.totalDuration();
1804                         }
1805                         if (value > this._duration) {
1806                                 value = this._duration;
1807                         }
1808                         if (this._yoyo && (this._cycle & 1) !== 0) {
1809                                 value = (this._duration - value) + (this._cycle * (this._duration + this._repeatDelay));
1810                         } else if (this._repeat !== 0) {
1811                                 value += this._cycle * (this._duration + this._repeatDelay);
1812                         }
1813                         return this.totalTime(value, suppressEvents);
1814                 };
1815
1816                 p.repeat = function(value) {
1817                         if (!arguments.length) {
1818                                 return this._repeat;
1819                         }
1820                         this._repeat = value;
1821                         return this._uncache(true);
1822                 };
1823
1824                 p.repeatDelay = function(value) {
1825                         if (!arguments.length) {
1826                                 return this._repeatDelay;
1827                         }
1828                         this._repeatDelay = value;
1829                         return this._uncache(true);
1830                 };
1831
1832                 p.yoyo = function(value) {
1833                         if (!arguments.length) {
1834                                 return this._yoyo;
1835                         }
1836                         this._yoyo = value;
1837                         return this;
1838                 };
1839
1840                 p.currentLabel = function(value) {
1841                         if (!arguments.length) {
1842                                 return this.getLabelBefore(this._time + 0.00000001);
1843                         }
1844                         return this.seek(value, true);
1845                 };
1846
1847                 return TimelineMax;
1848
1849         }, true);
1850         
1851
1852
1853
1854
1855         
1856         
1857         
1858         
1859         
1860         
1861         
1862 /*
1863  * ----------------------------------------------------------------
1864  * BezierPlugin
1865  * ----------------------------------------------------------------
1866  */
1867         (function() {
1868
1869                 var _RAD2DEG = 180 / Math.PI,
1870                         _r1 = [],
1871                         _r2 = [],
1872                         _r3 = [],
1873                         _corProps = {},
1874                         Segment = function(a, b, c, d) {
1875                                 this.a = a;
1876                                 this.b = b;
1877                                 this.c = c;
1878                                 this.d = d;
1879                                 this.da = d - a;
1880                                 this.ca = c - a;
1881                                 this.ba = b - a;
1882                         },
1883                         _correlate = ",x,y,z,left,top,right,bottom,marginTop,marginLeft,marginRight,marginBottom,paddingLeft,paddingTop,paddingRight,paddingBottom,backgroundPosition,backgroundPosition_y,",
1884                         cubicToQuadratic = function(a, b, c, d) {
1885                                 var q1 = {a:a},
1886                                         q2 = {},
1887                                         q3 = {},
1888                                         q4 = {c:d},
1889                                         mab = (a + b) / 2,
1890                                         mbc = (b + c) / 2,
1891                                         mcd = (c + d) / 2,
1892                                         mabc = (mab + mbc) / 2,
1893                                         mbcd = (mbc + mcd) / 2,
1894                                         m8 = (mbcd - mabc) / 8;
1895                                 q1.b = mab + (a - mab) / 4;
1896                                 q2.b = mabc + m8;
1897                                 q1.c = q2.a = (q1.b + q2.b) / 2;
1898                                 q2.c = q3.a = (mabc + mbcd) / 2;
1899                                 q3.b = mbcd - m8;
1900                                 q4.b = mcd + (d - mcd) / 4;
1901                                 q3.c = q4.a = (q3.b + q4.b) / 2;
1902                                 return [q1, q2, q3, q4];
1903                         },
1904                         _calculateControlPoints = function(a, curviness, quad, basic, correlate) {
1905                                 var l = a.length - 1,
1906                                         ii = 0,
1907                                         cp1 = a[0].a,
1908                                         i, p1, p2, p3, seg, m1, m2, mm, cp2, qb, r1, r2, tl;
1909                                 for (i = 0; i < l; i++) {
1910                                         seg = a[ii];
1911                                         p1 = seg.a;
1912                                         p2 = seg.d;
1913                                         p3 = a[ii+1].d;
1914
1915                                         if (correlate) {
1916                                                 r1 = _r1[i];
1917                                                 r2 = _r2[i];
1918                                                 tl = ((r2 + r1) * curviness * 0.25) / (basic ? 0.5 : _r3[i] || 0.5);
1919                                                 m1 = p2 - (p2 - p1) * (basic ? curviness * 0.5 : (r1 !== 0 ? tl / r1 : 0));
1920                                                 m2 = p2 + (p3 - p2) * (basic ? curviness * 0.5 : (r2 !== 0 ? tl / r2 : 0));
1921                                                 mm = p2 - (m1 + (((m2 - m1) * ((r1 * 3 / (r1 + r2)) + 0.5) / 4) || 0));
1922                                         } else {
1923                                                 m1 = p2 - (p2 - p1) * curviness * 0.5;
1924                                                 m2 = p2 + (p3 - p2) * curviness * 0.5;
1925                                                 mm = p2 - (m1 + m2) / 2;
1926                                         }
1927                                         m1 += mm;
1928                                         m2 += mm;
1929
1930                                         seg.c = cp2 = m1;
1931                                         if (i !== 0) {
1932                                                 seg.b = cp1;
1933                                         } else {
1934                                                 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.
1935                                         }
1936
1937                                         seg.da = p2 - p1;
1938                                         seg.ca = cp2 - p1;
1939                                         seg.ba = cp1 - p1;
1940
1941                                         if (quad) {
1942                                                 qb = cubicToQuadratic(p1, cp1, cp2, p2);
1943                                                 a.splice(ii, 1, qb[0], qb[1], qb[2], qb[3]);
1944                                                 ii += 4;
1945                                         } else {
1946                                                 ii++;
1947                                         }
1948
1949                                         cp1 = m2;
1950                                 }
1951                                 seg = a[ii];
1952                                 seg.b = cp1;
1953                                 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.
1954                                 seg.da = seg.d - seg.a;
1955                                 seg.ca = seg.c - seg.a;
1956                                 seg.ba = cp1 - seg.a;
1957                                 if (quad) {
1958                                         qb = cubicToQuadratic(seg.a, cp1, seg.c, seg.d);
1959                                         a.splice(ii, 1, qb[0], qb[1], qb[2], qb[3]);
1960                                 }
1961                         },
1962                         _parseAnchors = function(values, p, correlate, prepend) {
1963                                 var a = [],
1964                                         l, i, p1, p2, p3, tmp;
1965                                 if (prepend) {
1966                                         values = [prepend].concat(values);
1967                                         i = values.length;
1968                                         while (--i > -1) {
1969                                                 if (typeof( (tmp = values[i][p]) ) === "string") if (tmp.charAt(1) === "=") {
1970                                                         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
1971                                                 }
1972                                         }
1973                                 }
1974                                 l = values.length - 2;
1975                                 if (l < 0) {
1976                                         a[0] = new Segment(values[0][p], 0, 0, values[(l < -1) ? 0 : 1][p]);
1977                                         return a;
1978                                 }
1979                                 for (i = 0; i < l; i++) {
1980                                         p1 = values[i][p];
1981                                         p2 = values[i+1][p];
1982                                         a[i] = new Segment(p1, 0, 0, p2);
1983                                         if (correlate) {
1984                                                 p3 = values[i+2][p];
1985                                                 _r1[i] = (_r1[i] || 0) + (p2 - p1) * (p2 - p1);
1986                                                 _r2[i] = (_r2[i] || 0) + (p3 - p2) * (p3 - p2);
1987                                         }
1988                                 }
1989                                 a[i] = new Segment(values[i][p], 0, 0, values[i+1][p]);
1990                                 return a;
1991                         },
1992                         bezierThrough = function(values, curviness, quadratic, basic, correlate, prepend) {
1993                                 var obj = {},
1994                                         props = [],
1995                                         first = prepend || values[0],
1996                                         i, p, a, j, r, l, seamless, last;
1997                                 correlate = (typeof(correlate) === "string") ? ","+correlate+"," : _correlate;
1998                                 if (curviness == null) {
1999                                         curviness = 1;
2000                                 }
2001                                 for (p in values[0]) {
2002                                         props.push(p);
2003                                 }
2004                                 //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)
2005                                 if (values.length > 1) {
2006                                         last = values[values.length - 1];
2007                                         seamless = true;
2008                                         i = props.length;
2009                                         while (--i > -1) {
2010                                                 p = props[i];
2011                                                 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
2012                                                         seamless = false;
2013                                                         break;
2014                                                 }
2015                                         }
2016                                         if (seamless) {
2017                                                 values = values.concat(); //duplicate the array to avoid contaminating the original which the user may be reusing for other tweens
2018                                                 if (prepend) {
2019                                                         values.unshift(prepend);
2020                                                 }
2021                                                 values.push(values[1]);
2022                                                 prepend = values[values.length - 3];
2023                                         }
2024                                 }
2025                                 _r1.length = _r2.length = _r3.length = 0;
2026                                 i = props.length;
2027                                 while (--i > -1) {
2028                                         p = props[i];
2029                                         _corProps[p] = (correlate.indexOf(","+p+",") !== -1);
2030                                         obj[p] = _parseAnchors(values, p, _corProps[p], prepend);
2031                                 }
2032                                 i = _r1.length;
2033                                 while (--i > -1) {
2034                                         _r1[i] = Math.sqrt(_r1[i]);
2035                                         _r2[i] = Math.sqrt(_r2[i]);
2036                                 }
2037                                 if (!basic) {
2038                                         i = props.length;
2039                                         while (--i > -1) {
2040                                                 if (_corProps[p]) {
2041                                                         a = obj[props[i]];
2042                                                         l = a.length - 1;
2043                                                         for (j = 0; j < l; j++) {
2044                                                                 r = a[j+1].da / _r2[j] + a[j].da / _r1[j];
2045                                                                 _r3[j] = (_r3[j] || 0) + r * r;
2046                                                         }
2047                                                 }
2048                                         }
2049                                         i = _r3.length;
2050                                         while (--i > -1) {
2051                                                 _r3[i] = Math.sqrt(_r3[i]);
2052                                         }
2053                                 }
2054                                 i = props.length;
2055                                 j = quadratic ? 4 : 1;
2056                                 while (--i > -1) {
2057                                         p = props[i];
2058                                         a = obj[p];
2059                                         _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
2060                                         if (seamless) {
2061                                                 a.splice(0, j);
2062                                                 a.splice(a.length - j, j);
2063                                         }
2064                                 }
2065                                 return obj;
2066                         },
2067                         _parseBezierData = function(values, type, prepend) {
2068                                 type = type || "soft";
2069                                 var obj = {},
2070                                         inc = (type === "cubic") ? 3 : 2,
2071                                         soft = (type === "soft"),
2072                                         props = [],
2073                                         a, b, c, d, cur, i, j, l, p, cnt, tmp;
2074                                 if (soft && prepend) {
2075                                         values = [prepend].concat(values);
2076                                 }
2077                                 if (values == null || values.length < inc + 1) { throw "invalid Bezier data"; }
2078                                 for (p in values[0]) {
2079                                         props.push(p);
2080                                 }
2081                                 i = props.length;
2082                                 while (--i > -1) {
2083                                         p = props[i];
2084                                         obj[p] = cur = [];
2085                                         cnt = 0;
2086                                         l = values.length;
2087                                         for (j = 0; j < l; j++) {
2088                                                 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);
2089                                                 if (soft) if (j > 1) if (j < l - 1) {
2090                                                         cur[cnt++] = (a + cur[cnt-2]) / 2;
2091                                                 }
2092                                                 cur[cnt++] = a;
2093                                         }
2094                                         l = cnt - inc + 1;
2095                                         cnt = 0;
2096                                         for (j = 0; j < l; j += inc) {
2097                                                 a = cur[j];
2098                                                 b = cur[j+1];
2099                                                 c = cur[j+2];
2100                                                 d = (inc === 2) ? 0 : cur[j+3];
2101                                                 cur[cnt++] = tmp = (inc === 3) ? new Segment(a, b, c, d) : new Segment(a, (2 * b + a) / 3, (2 * b + c) / 3, c);
2102                                         }
2103                                         cur.length = cnt;
2104                                 }
2105                                 return obj;
2106                         },
2107                         _addCubicLengths = function(a, steps, resolution) {
2108                                 var inc = 1 / resolution,
2109                                         j = a.length,
2110                                         d, d1, s, da, ca, ba, p, i, inv, bez, index;
2111                                 while (--j > -1) {
2112                                         bez = a[j];
2113                                         s = bez.a;
2114                                         da = bez.d - s;
2115                                         ca = bez.c - s;
2116                                         ba = bez.b - s;
2117                                         d = d1 = 0;
2118                                         for (i = 1; i <= resolution; i++) {
2119                                                 p = inc * i;
2120                                                 inv = 1 - p;
2121                                                 d = d1 - (d1 = (p * p * da + 3 * inv * (p * ca + inv * ba)) * p);
2122                                                 index = j * resolution + i - 1;
2123                                                 steps[index] = (steps[index] || 0) + d * d;
2124                                         }
2125                                 }
2126                         },
2127                         _parseLengthData = function(obj, resolution) {
2128                                 resolution = resolution >> 0 || 6;
2129                                 var a = [],
2130                                         lengths = [],
2131                                         d = 0,
2132                                         total = 0,
2133                                         threshold = resolution - 1,
2134                                         segments = [],
2135                                         curLS = [], //current length segments array
2136                                         p, i, l, index;
2137                                 for (p in obj) {
2138                                         _addCubicLengths(obj[p], a, resolution);
2139                                 }
2140                                 l = a.length;
2141                                 for (i = 0; i < l; i++) {
2142                                         d += Math.sqrt(a[i]);
2143                                         index = i % resolution;
2144                                         curLS[index] = d;
2145                                         if (index === threshold) {
2146                                                 total += d;
2147                                                 index = (i / resolution) >> 0;
2148                                                 segments[index] = curLS;
2149                                                 lengths[index] = total;
2150                                                 d = 0;
2151                                                 curLS = [];
2152                                         }
2153                                 }
2154                                 return {length:total, lengths:lengths, segments:segments};
2155                         },
2156
2157
2158
2159                         BezierPlugin = window._gsDefine.plugin({
2160                                         propName: "bezier",
2161                                         priority: -1,
2162                                         version: "1.3.2",
2163                                         API: 2,
2164                                         global:true,
2165
2166                                         //gets called when the tween renders for the first time. This is where initial values should be recorded and any setup routines should run.
2167                                         init: function(target, vars, tween) {
2168                                                 this._target = target;
2169                                                 if (vars instanceof Array) {
2170                                                         vars = {values:vars};
2171                                                 }
2172                                                 this._func = {};
2173                                                 this._round = {};
2174                                                 this._props = [];
2175                                                 this._timeRes = (vars.timeResolution == null) ? 6 : parseInt(vars.timeResolution, 10);
2176                                                 var values = vars.values || [],
2177                                                         first = {},
2178                                                         second = values[0],
2179                                                         autoRotate = vars.autoRotate || tween.vars.orientToBezier,
2180                                                         p, isFunc, i, j, prepend;
2181
2182                                                 this._autoRotate = autoRotate ? (autoRotate instanceof Array) ? autoRotate : [["x","y","rotation",((autoRotate === true) ? 0 : Number(autoRotate) || 0)]] : null;
2183                                                 for (p in second) {
2184                                                         this._props.push(p);
2185                                                 }
2186
2187                                                 i = this._props.length;
2188                                                 while (--i > -1) {
2189                                                         p = this._props[i];
2190
2191                                                         this._overwriteProps.push(p);
2192                                                         isFunc = this._func[p] = (typeof(target[p]) === "function");
2193                                                         first[p] = (!isFunc) ? parseFloat(target[p]) : target[ ((p.indexOf("set") || typeof(target["get" + p.substr(3)]) !== "function") ? p : "get" + p.substr(3)) ]();
2194                                                         if (!prepend) if (first[p] !== values[0][p]) {
2195                                                                 prepend = first;
2196                                                         }
2197                                                 }
2198                                                 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);
2199                                                 this._segCount = this._beziers[p].length;
2200
2201                                                 if (this._timeRes) {
2202                                                         var ld = _parseLengthData(this._beziers, this._timeRes);
2203                                                         this._length = ld.length;
2204                                                         this._lengths = ld.lengths;
2205                                                         this._segments = ld.segments;
2206                                                         this._l1 = this._li = this._s1 = this._si = 0;
2207                                                         this._l2 = this._lengths[0];
2208                                                         this._curSeg = this._segments[0];
2209                                                         this._s2 = this._curSeg[0];
2210                                                         this._prec = 1 / this._curSeg.length;
2211                                                 }
2212
2213                                                 if ((autoRotate = this._autoRotate)) {
2214                                                         this._initialRotations = [];
2215                                                         if (!(autoRotate[0] instanceof Array)) {
2216                                                                 this._autoRotate = autoRotate = [autoRotate];
2217                                                         }
2218                                                         i = autoRotate.length;
2219                                                         while (--i > -1) {
2220                                                                 for (j = 0; j < 3; j++) {
2221                                                                         p = autoRotate[i][j];
2222                                                                         this._func[p] = (typeof(target[p]) === "function") ? target[ ((p.indexOf("set") || typeof(target["get" + p.substr(3)]) !== "function") ? p : "get" + p.substr(3)) ] : false;
2223                                                                 }
2224                                                                 p = autoRotate[i][2];
2225                                                                 this._initialRotations[i] = this._func[p] ? this._func[p].call(this._target) : this._target[p];
2226                                                         }
2227                                                 }
2228                                                 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.
2229                                                 return true;
2230                                         },
2231
2232                                         //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.)
2233                                         set: function(v) {
2234                                                 var segments = this._segCount,
2235                                                         func = this._func,
2236                                                         target = this._target,
2237                                                         notStart = (v !== this._startRatio),
2238                                                         curIndex, inv, i, p, b, t, val, l, lengths, curSeg;
2239                                                 if (!this._timeRes) {
2240                                                         curIndex = (v < 0) ? 0 : (v >= 1) ? segments - 1 : (segments * v) >> 0;
2241                                                         t = (v - (curIndex * (1 / segments))) * segments;
2242                                                 } else {
2243                                                         lengths = this._lengths;
2244                                                         curSeg = this._curSeg;
2245                                                         v *= this._length;
2246                                                         i = this._li;
2247                                                         //find the appropriate segment (if the currently cached one isn't correct)
2248                                                         if (v > this._l2 && i < segments - 1) {
2249                                                                 l = segments - 1;
2250                                                                 while (i < l && (this._l2 = lengths[++i]) <= v) {       }
2251                                                                 this._l1 = lengths[i-1];
2252                                                                 this._li = i;
2253                                                                 this._curSeg = curSeg = this._segments[i];
2254                                                                 this._s2 = curSeg[(this._s1 = this._si = 0)];
2255                                                         } else if (v < this._l1 && i > 0) {
2256                                                                 while (i > 0 && (this._l1 = lengths[--i]) >= v) { }
2257                                                                 if (i === 0 && v < this._l1) {
2258                                                                         this._l1 = 0;
2259                                                                 } else {
2260                                                                         i++;
2261                                                                 }
2262                                                                 this._l2 = lengths[i];
2263                                                                 this._li = i;
2264                                                                 this._curSeg = curSeg = this._segments[i];
2265                                                                 this._s1 = curSeg[(this._si = curSeg.length - 1) - 1] || 0;
2266                                                                 this._s2 = curSeg[this._si];
2267                                                         }
2268                                                         curIndex = i;
2269                                                         //now find the appropriate sub-segment (we split it into the number of pieces that was defined by "precision" and measured each one)
2270                                                         v -= this._l1;
2271                                                         i = this._si;
2272                                                         if (v > this._s2 && i < curSeg.length - 1) {
2273                                                                 l = curSeg.length - 1;
2274                                                                 while (i < l && (this._s2 = curSeg[++i]) <= v) {        }
2275                                                                 this._s1 = curSeg[i-1];
2276                                                                 this._si = i;
2277                                                         } else if (v < this._s1 && i > 0) {
2278                                                                 while (i > 0 && (this._s1 = curSeg[--i]) >= v) {        }
2279                                                                 if (i === 0 && v < this._s1) {
2280                                                                         this._s1 = 0;
2281                                                                 } else {
2282                                                                         i++;
2283                                                                 }
2284                                                                 this._s2 = curSeg[i];
2285                                                                 this._si = i;
2286                                                         }
2287                                                         t = (i + (v - this._s1) / (this._s2 - this._s1)) * this._prec;
2288                                                 }
2289                                                 inv = 1 - t;
2290
2291                                                 i = this._props.length;
2292                                                 while (--i > -1) {
2293                                                         p = this._props[i];
2294                                                         b = this._beziers[p][curIndex];
2295                                                         val = (t * t * b.da + 3 * inv * (t * b.ca + inv * b.ba)) * t + b.a;
2296                                                         if (this._round[p]) {
2297                                                                 val = Math.round(val);
2298                                                         }
2299                                                         if (func[p]) {
2300                                                                 target[p](val);
2301                                                         } else {
2302                                                                 target[p] = val;
2303                                                         }
2304                                                 }
2305
2306                                                 if (this._autoRotate) {
2307                                                         var ar = this._autoRotate,
2308                                                                 b2, x1, y1, x2, y2, add, conv;
2309                                                         i = ar.length;
2310                                                         while (--i > -1) {
2311                                                                 p = ar[i][2];
2312                                                                 add = ar[i][3] || 0;
2313                                                                 conv = (ar[i][4] === true) ? 1 : _RAD2DEG;
2314                                                                 b = this._beziers[ar[i][0]];
2315                                                                 b2 = this._beziers[ar[i][1]];
2316
2317                                                                 if (b && b2) { //in case one of the properties got overwritten.
2318                                                                         b = b[curIndex];
2319                                                                         b2 = b2[curIndex];
2320
2321                                                                         x1 = b.a + (b.b - b.a) * t;
2322                                                                         x2 = b.b + (b.c - b.b) * t;
2323                                                                         x1 += (x2 - x1) * t;
2324                                                                         x2 += ((b.c + (b.d - b.c) * t) - x2) * t;
2325
2326                                                                         y1 = b2.a + (b2.b - b2.a) * t;
2327                                                                         y2 = b2.b + (b2.c - b2.b) * t;
2328                                                                         y1 += (y2 - y1) * t;
2329                                                                         y2 += ((b2.c + (b2.d - b2.c) * t) - y2) * t;
2330
2331                                                                         val = notStart ? Math.atan2(y2 - y1, x2 - x1) * conv + add : this._initialRotations[i];
2332
2333                                                                         if (func[p]) {
2334                                                                                 target[p](val);
2335                                                                         } else {
2336                                                                                 target[p] = val;
2337                                                                         }
2338                                                                 }
2339                                                         }
2340                                                 }
2341                                         }
2342                         }),
2343                         p = BezierPlugin.prototype;
2344
2345
2346                 BezierPlugin.bezierThrough = bezierThrough;
2347                 BezierPlugin.cubicToQuadratic = cubicToQuadratic;
2348                 BezierPlugin._autoCSS = true; //indicates that this plugin can be inserted into the "css" object using the autoCSS feature of TweenLite
2349                 BezierPlugin.quadraticToCubic = function(a, b, c) {
2350                         return new Segment(a, (2 * b + a) / 3, (2 * b + c) / 3, c);
2351                 };
2352
2353                 BezierPlugin._cssRegister = function() {
2354                         var CSSPlugin = window._gsDefine.globals.CSSPlugin;
2355                         if (!CSSPlugin) {
2356                                 return;
2357                         }
2358                         var _internals = CSSPlugin._internals,
2359                                 _parseToProxy = _internals._parseToProxy,
2360                                 _setPluginRatio = _internals._setPluginRatio,
2361                                 CSSPropTween = _internals.CSSPropTween;
2362                         _internals._registerComplexSpecialProp("bezier", {parser:function(t, e, prop, cssp, pt, plugin) {
2363                                 if (e instanceof Array) {
2364                                         e = {values:e};
2365                                 }
2366                                 plugin = new BezierPlugin();
2367                                 var values = e.values,
2368                                         l = values.length - 1,
2369                                         pluginValues = [],
2370                                         v = {},
2371                                         i, p, data;
2372                                 if (l < 0) {
2373                                         return pt;
2374                                 }
2375                                 for (i = 0; i <= l; i++) {
2376                                         data = _parseToProxy(t, values[i], cssp, pt, plugin, (l !== i));
2377                                         pluginValues[i] = data.end;
2378                                 }
2379                                 for (p in e) {
2380                                         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.
2381                                 }
2382                                 v.values = pluginValues;
2383                                 pt = new CSSPropTween(t, "bezier", 0, 0, data.pt, 2);
2384                                 pt.data = data;
2385                                 pt.plugin = plugin;
2386                                 pt.setRatio = _setPluginRatio;
2387                                 if (v.autoRotate === 0) {
2388                                         v.autoRotate = true;
2389                                 }
2390                                 if (v.autoRotate && !(v.autoRotate instanceof Array)) {
2391                                         i = (v.autoRotate === true) ? 0 : Number(v.autoRotate);
2392                                         v.autoRotate = (data.end.left != null) ? [["left","top","rotation",i,false]] : (data.end.x != null) ? [["x","y","rotation",i,false]] : false;
2393                                 }
2394                                 if (v.autoRotate) {
2395                                         if (!cssp._transform) {
2396                                                 cssp._enableTransforms(false);
2397                                         }
2398                                         data.autoRotate = cssp._target._gsTransform;
2399                                 }
2400                                 plugin._onInitTween(data.proxy, v, cssp._tween);
2401                                 return pt;
2402                         }});
2403                 };
2404
2405                 p._roundProps = function(lookup, value) {
2406                         var op = this._overwriteProps,
2407                                 i = op.length;
2408                         while (--i > -1) {
2409                                 if (lookup[op[i]] || lookup.bezier || lookup.bezierThrough) {
2410                                         this._round[op[i]] = value;
2411                                 }
2412                         }
2413                 };
2414
2415                 p._kill = function(lookup) {
2416                         var a = this._props,
2417                                 p, i;
2418                         for (p in this._beziers) {
2419                                 if (p in lookup) {
2420                                         delete this._beziers[p];
2421                                         delete this._func[p];
2422                                         i = a.length;
2423                                         while (--i > -1) {
2424                                                 if (a[i] === p) {
2425                                                         a.splice(i, 1);
2426                                                 }
2427                                         }
2428                                 }
2429                         }
2430                         return this._super._kill.call(this, lookup);
2431                 };
2432
2433         }());
2434
2435
2436
2437
2438
2439
2440         
2441         
2442         
2443         
2444         
2445         
2446         
2447         
2448 /*
2449  * ----------------------------------------------------------------
2450  * CSSPlugin
2451  * ----------------------------------------------------------------
2452  */
2453         window._gsDefine("plugins.CSSPlugin", ["plugins.TweenPlugin","TweenLite"], function(TweenPlugin, TweenLite) {
2454
2455                 /** @constructor **/
2456                 var CSSPlugin = function() {
2457                                 TweenPlugin.call(this, "css");
2458                                 this._overwriteProps.length = 0;
2459                                 this.setRatio = CSSPlugin.prototype.setRatio; //speed optimization (avoid prototype lookup on this "hot" method)
2460                         },
2461                         _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.
2462                         _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
2463                         _cs, //computed style (we store this in a shared variable to conserve memory and make minification tighter
2464                         _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.
2465                         _specialProps = {},
2466                         p = CSSPlugin.prototype = new TweenPlugin("css");
2467
2468                 p.constructor = CSSPlugin;
2469                 CSSPlugin.version = "1.12.1";
2470                 CSSPlugin.API = 2;
2471                 CSSPlugin.defaultTransformPerspective = 0;
2472                 CSSPlugin.defaultSkewType = "compensated";
2473                 p = "px"; //we'll reuse the "p" variable to keep file size down
2474                 CSSPlugin.suffixMap = {top:p, right:p, bottom:p, left:p, width:p, height:p, fontSize:p, padding:p, margin:p, perspective:p, lineHeight:""};
2475
2476
2477                 var _numExp = /(?:\d|\-\d|\.\d|\-\.\d)+/g,
2478                         _relNumExp = /(?:\d|\-\d|\.\d|\-\.\d|\+=\d|\-=\d|\+=.\d|\-=\.\d)+/g,
2479                         _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)"
2480                         _NaNExp = /[^\d\-\.]/g,
2481                         _suffixExp = /(?:\d|\-|\+|=|#|\.)*/g,
2482                         _opacityExp = /opacity *= *([^)]*)/i,
2483                         _opacityValExp = /opacity:([^;]*)/i,
2484                         _alphaFilterExp = /alpha\(opacity *=.+?\)/i,
2485                         _rgbhslExp = /^(rgb|hsl)/,
2486                         _capsExp = /([A-Z])/g,
2487                         _camelExp = /-([a-z])/gi,
2488                         _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)
2489                         _camelFunc = function(s, g) { return g.toUpperCase(); },
2490                         _horizExp = /(?:Left|Right|Width)/i,
2491                         _ieGetMatrixExp = /(M11|M12|M21|M22)=[\d\-\.e]+/gi,
2492                         _ieSetMatrixExp = /progid\:DXImageTransform\.Microsoft\.Matrix\(.+?\)/i,
2493                         _commasOutsideParenExp = /,(?=[^\)]*(?:\(|$))/gi, //finds any commas that are not within parenthesis
2494                         _DEG2RAD = Math.PI / 180,
2495                         _RAD2DEG = 180 / Math.PI,
2496                         _forcePT = {},
2497                         _doc = document,
2498                         _tempDiv = _doc.createElement("div"),
2499                         _tempImg = _doc.createElement("img"),
2500                         _internals = CSSPlugin._internals = {_specialProps:_specialProps}, //provides a hook to a few internal methods that we need to access from inside other plugins
2501                         _agent = navigator.userAgent,
2502                         _autoRound,
2503                         _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).
2504
2505                         _isSafari,
2506                         _isFirefox, //Firefox has a bug that causes 3D transformed elements to randomly disappear unless a repaint is forced after each update on each element.
2507                         _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!)
2508                         _ieVers,
2509                         _supportsOpacity = (function() { //we set _isSafari, _ieVers, _isFirefox, and _supportsOpacity all in one function here to reduce file size slightly, especially in the minified version.
2510                                 var i = _agent.indexOf("Android"),
2511                                         d = _doc.createElement("div"), a;
2512
2513                                 _isSafari = (_agent.indexOf("Safari") !== -1 && _agent.indexOf("Chrome") === -1 && (i === -1 || Number(_agent.substr(i+8, 1)) > 3));
2514                                 _isSafariLT6 = (_isSafari && (Number(_agent.substr(_agent.indexOf("Version/")+8, 1)) < 6));
2515                                 _isFirefox = (_agent.indexOf("Firefox") !== -1);
2516
2517                                 if ((/MSIE ([0-9]{1,}[\.0-9]{0,})/).exec(_agent)) {
2518                                         _ieVers = parseFloat( RegExp.$1 );
2519                                 }
2520
2521                                 d.innerHTML = "<a style='top:1px;opacity:.55;'>a</a>";
2522                                 a = d.getElementsByTagName("a")[0];
2523                                 return a ? /^0.55/.test(a.style.opacity) : false;
2524                         }()),
2525                         _getIEOpacity = function(v) {
2526                                 return (_opacityExp.test( ((typeof(v) === "string") ? v : (v.currentStyle ? v.currentStyle.filter : v.style.filter) || "") ) ? ( parseFloat( RegExp.$1 ) / 100 ) : 1);
2527                         },
2528                         _log = function(s) {//for logging messages, but in a way that won't throw errors in old versions of IE.
2529                                 if (window.console) {
2530                                         //console.log(s);
2531                                 }
2532                         },
2533                         _prefixCSS = "", //the non-camelCase vendor prefix like "-o-", "-moz-", "-ms-", or "-webkit-"
2534                         _prefix = "", //camelCase vendor prefix like "O", "ms", "Webkit", or "Moz".
2535
2536                         // @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)
2537                         _checkPropPrefix = function(p, e) {
2538                                 e = e || _tempDiv;
2539                                 var s = e.style,
2540                                         a, i;
2541                                 if (s[p] !== undefined) {
2542                                         return p;
2543                                 }
2544                                 p = p.charAt(0).toUpperCase() + p.substr(1);
2545                                 a = ["O","Moz","ms","Ms","Webkit"];
2546                                 i = 5;
2547                                 while (--i > -1 && s[a[i]+p] === undefined) { }
2548                                 if (i >= 0) {
2549                                         _prefix = (i === 3) ? "ms" : a[i];
2550                                         _prefixCSS = "-" + _prefix.toLowerCase() + "-";
2551                                         return _prefix + p;
2552                                 }
2553                                 return null;
2554                         },
2555
2556                         _getComputedStyle = _doc.defaultView ? _doc.defaultView.getComputedStyle : function() {},
2557
2558                         /**
2559                          * @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:
2560                          * var currentLeft = CSSPlugin.getStyle( document.getElementById("myElement"), "left");
2561                          *
2562                          * @param {!Object} t Target element whose style property you want to query
2563                          * @param {!string} p Property name (like "left" or "top" or "marginTop", etc.)
2564                          * @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.
2565                          * @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.
2566                          * @param {string=} dflt Default value that should be returned in the place of null, "none", "auto" or "auto auto".
2567                          * @return {?string} The current property value
2568                          */
2569                         _getStyle = CSSPlugin.getStyle = function(t, p, cs, calc, dflt) {
2570                                 var rv;
2571                                 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.
2572                                         return _getIEOpacity(t);
2573                                 }
2574                                 if (!calc && t.style[p]) {
2575                                         rv = t.style[p];
2576                                 } else if ((cs = cs || _getComputedStyle(t))) {
2577                                         rv = cs[p] || cs.getPropertyValue(p) || cs.getPropertyValue(p.replace(_capsExp, "-$1").toLowerCase());
2578                                 } else if (t.currentStyle) {
2579                                         rv = t.currentStyle[p];
2580                                 }
2581                                 return (dflt != null && (!rv || rv === "none" || rv === "auto" || rv === "auto auto")) ? dflt : rv;
2582                         },
2583
2584                         /**
2585                          * @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.
2586                          * @param {!Object} t Target element
2587                          * @param {!string} p Property name (like "left", "top", "marginLeft", etc.)
2588                          * @param {!number} v Value
2589                          * @param {string=} sfx Suffix (like "px" or "%" or "em")
2590                          * @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.
2591                          * @return {number} value in pixels
2592                          */
2593                         _convertToPixels = _internals.convertToPixels = function(t, p, v, sfx, recurse) {
2594                                 if (sfx === "px" || !sfx) { return v; }
2595                                 if (sfx === "auto" || !v) { return 0; }
2596                                 var horiz = _horizExp.test(p),
2597                                         node = t,
2598                                         style = _tempDiv.style,
2599                                         neg = (v < 0),
2600                                         pix, cache, time;
2601                                 if (neg) {
2602                                         v = -v;
2603                                 }
2604                                 if (sfx === "%" && p.indexOf("border") !== -1) {
2605                                         pix = (v / 100) * (horiz ? t.clientWidth : t.clientHeight);
2606                                 } else {
2607                                         style.cssText = "border:0 solid red;position:" + _getStyle(t, "position") + ";line-height:0;";
2608                                         if (sfx === "%" || !node.appendChild) {
2609                                                 node = t.parentNode || _doc.body;
2610                                                 cache = node._gsCache;
2611                                                 time = TweenLite.ticker.frame;
2612                                                 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)
2613                                                         return cache.width * v / 100;
2614                                                 }
2615                                                 style[(horiz ? "width" : "height")] = v + sfx;
2616                                         } else {
2617                                                 style[(horiz ? "borderLeftWidth" : "borderTopWidth")] = v + sfx;
2618                                         }
2619                                         node.appendChild(_tempDiv);
2620                                         pix = parseFloat(_tempDiv[(horiz ? "offsetWidth" : "offsetHeight")]);
2621                                         node.removeChild(_tempDiv);
2622                                         if (horiz && sfx === "%" && CSSPlugin.cacheWidths !== false) {
2623                                                 cache = node._gsCache = node._gsCache || {};
2624                                                 cache.time = time;
2625                                                 cache.width = pix / v * 100;
2626                                         }
2627                                         if (pix === 0 && !recurse) {
2628                                                 pix = _convertToPixels(t, p, v, sfx, true);
2629                                         }
2630                                 }
2631                                 return neg ? -pix : pix;
2632                         },
2633                         _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
2634                                 if (_getStyle(t, "position", cs) !== "absolute") { return 0; }
2635                                 var dim = ((p === "left") ? "Left" : "Top"),
2636                                         v = _getStyle(t, "margin" + dim, cs);
2637                                 return t["offset" + dim] - (_convertToPixels(t, p, parseFloat(v), v.replace(_suffixExp, "")) || 0);
2638                         },
2639
2640                         // @private returns at object containing ALL of the style properties in camelCase and their associated values.
2641                         _getAllStyles = function(t, cs) {
2642                                 var s = {},
2643                                         i, tr;
2644                                 if ((cs = cs || _getComputedStyle(t, null))) {
2645                                         if ((i = cs.length)) {
2646                                                 while (--i > -1) {
2647                                                         s[cs[i].replace(_camelExp, _camelFunc)] = cs.getPropertyValue(cs[i]);
2648                                                 }
2649                                         } else { //Opera behaves differently - cs.length is always 0, so we must do a for...in loop.
2650                                                 for (i in cs) {
2651                                                         s[i] = cs[i];
2652                                                 }
2653                                         }
2654                                 } else if ((cs = t.currentStyle || t.style)) {
2655                                         for (i in cs) {
2656                                                 if (typeof(i) === "string" && s[i] === undefined) {
2657                                                         s[i.replace(_camelExp, _camelFunc)] = cs[i];
2658                                                 }
2659                                         }
2660                                 }
2661                                 if (!_supportsOpacity) {
2662                                         s.opacity = _getIEOpacity(t);
2663                                 }
2664                                 tr = _getTransform(t, cs, false);
2665                                 s.rotation = tr.rotation;
2666                                 s.skewX = tr.skewX;
2667                                 s.scaleX = tr.scaleX;
2668                                 s.scaleY = tr.scaleY;
2669                                 s.x = tr.x;
2670                                 s.y = tr.y;
2671                                 if (_supports3D) {
2672                                         s.z = tr.z;
2673                                         s.rotationX = tr.rotationX;
2674                                         s.rotationY = tr.rotationY;
2675                                         s.scaleZ = tr.scaleZ;
2676                                 }
2677                                 if (s.filters) {
2678                                         delete s.filters;
2679                                 }
2680                                 return s;
2681                         },
2682
2683                         // @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.
2684                         _cssDif = function(t, s1, s2, vars, forceLookup) {
2685                                 var difs = {},
2686                                         style = t.style,
2687                                         val, p, mpt;
2688                                 for (p in s2) {
2689                                         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") {
2690                                                 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.
2691                                                 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.
2692                                                         mpt = new MiniPropTween(style, p, style[p], mpt);
2693                                                 }
2694                                         }
2695                                 }
2696                                 if (vars) {
2697                                         for (p in vars) { //copy properties (except className)
2698                                                 if (p !== "className") {
2699                                                         difs[p] = vars[p];
2700                                                 }
2701                                         }
2702                                 }
2703                                 return {difs:difs, firstMPT:mpt};
2704                         },
2705                         _dimensions = {width:["Left","Right"], height:["Top","Bottom"]},
2706                         _margins = ["marginLeft","marginRight","marginTop","marginBottom"],
2707
2708                         /**
2709                          * @private Gets the width or height of an element
2710                          * @param {!Object} t Target element
2711                          * @param {!string} p Property name ("width" or "height")
2712                          * @param {Object=} cs Computed style object (if one exists). Just a speed optimization.
2713                          * @return {number} Dimension (in pixels)
2714                          */
2715                         _getDimension = function(t, p, cs) {
2716                                 var v = parseFloat((p === "width") ? t.offsetWidth : t.offsetHeight),
2717                                         a = _dimensions[p],
2718                                         i = a.length;
2719                                 cs = cs || _getComputedStyle(t, null);
2720                                 while (--i > -1) {
2721                                         v -= parseFloat( _getStyle(t, "padding" + a[i], cs, true) ) || 0;
2722                                         v -= parseFloat( _getStyle(t, "border" + a[i] + "Width", cs, true) ) || 0;
2723                                 }
2724                                 return v;
2725                         },
2726
2727                         // @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)
2728                         _parsePosition = function(v, recObj) {
2729                                 if (v == null || v === "" || v === "auto" || v === "auto auto") { //note: Firefox uses "auto auto" as default whereas Chrome uses "auto".
2730                                         v = "0 0";
2731                                 }
2732                                 var a = v.split(" "),
2733                                         x = (v.indexOf("left") !== -1) ? "0%" : (v.indexOf("right") !== -1) ? "100%" : a[0],
2734                                         y = (v.indexOf("top") !== -1) ? "0%" : (v.indexOf("bottom") !== -1) ? "100%" : a[1];
2735                                 if (y == null) {
2736                                         y = "0";
2737                                 } else if (y === "center") {
2738                                         y = "50%";
2739                                 }
2740                                 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.
2741                                         x = "50%";
2742                                 }
2743                                 if (recObj) {
2744                                         recObj.oxp = (x.indexOf("%") !== -1);
2745                                         recObj.oyp = (y.indexOf("%") !== -1);
2746                                         recObj.oxr = (x.charAt(1) === "=");
2747                                         recObj.oyr = (y.charAt(1) === "=");
2748                                         recObj.ox = parseFloat(x.replace(_NaNExp, ""));
2749                                         recObj.oy = parseFloat(y.replace(_NaNExp, ""));
2750                                 }
2751                                 return x + " " + y + ((a.length > 2) ? " " + a[2] : "");
2752                         },
2753
2754                         /**
2755                          * @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!)
2756                          * @param {(number|string)} e End value which is typically a string, but could be a number
2757                          * @param {(number|string)} b Beginning value which is typically a string but could be a number
2758                          * @return {number} Amount of change between the beginning and ending values (relative values that have a "+=" or "-=" are recognized)
2759                          */
2760                         _parseChange = function(e, b) {
2761                                 return (typeof(e) === "string" && e.charAt(1) === "=") ? parseInt(e.charAt(0) + "1", 10) * parseFloat(e.substr(2)) : parseFloat(e) - parseFloat(b);
2762                         },
2763
2764                         /**
2765                          * @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.
2766                          * @param {Object} v Value to be parsed
2767                          * @param {!number} d Default value (which is also used for relative calculations if "+=" or "-=" is found in the first parameter)
2768                          * @return {number} Parsed value
2769                          */
2770                         _parseVal = function(v, d) {
2771                                 return (v == null) ? d : (typeof(v) === "string" && v.charAt(1) === "=") ? parseInt(v.charAt(0) + "1", 10) * Number(v.substr(2)) + d : parseFloat(v);
2772                         },
2773
2774                         /**
2775                          * @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.
2776                          * @param {Object} v Value to be parsed
2777                          * @param {!number} d Default value (which is also used for relative calculations if "+=" or "-=" is found in the first parameter)
2778                          * @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"
2779                          * @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.
2780                          * @return {number} parsed angle in radians
2781                          */
2782                         _parseAngle = function(v, d, p, directionalEnd) {
2783                                 var min = 0.000001,
2784                                         cap, split, dif, result;
2785                                 if (v == null) {
2786                                         result = d;
2787                                 } else if (typeof(v) === "number") {
2788                                         result = v;
2789                                 } else {
2790                                         cap = 360;
2791                                         split = v.split("_");
2792                                         dif = Number(split[0].replace(_NaNExp, "")) * ((v.indexOf("rad") === -1) ? 1 : _RAD2DEG) - ((v.charAt(1) === "=") ? 0 : d);
2793                                         if (split.length) {
2794                                                 if (directionalEnd) {
2795                                                         directionalEnd[p] = d + dif;
2796                                                 }
2797                                                 if (v.indexOf("short") !== -1) {
2798                                                         dif = dif % cap;
2799                                                         if (dif !== dif % (cap / 2)) {
2800                                                                 dif = (dif < 0) ? dif + cap : dif - cap;
2801                                                         }
2802                                                 }
2803                                                 if (v.indexOf("_cw") !== -1 && dif < 0) {
2804                                                         dif = ((dif + cap * 9999999999) % cap) - ((dif / cap) | 0) * cap;
2805                                                 } else if (v.indexOf("ccw") !== -1 && dif > 0) {
2806                                                         dif = ((dif - cap * 9999999999) % cap) - ((dif / cap) | 0) * cap;
2807                                                 }
2808                                         }
2809                                         result = d + dif;
2810                                 }
2811                                 if (result < min && result > -min) {
2812                                         result = 0;
2813                                 }
2814                                 return result;
2815                         },
2816
2817                         _colorLookup = {aqua:[0,255,255],
2818                                 lime:[0,255,0],
2819                                 silver:[192,192,192],
2820                                 black:[0,0,0],
2821                                 maroon:[128,0,0],
2822                                 teal:[0,128,128],
2823                                 blue:[0,0,255],
2824                                 navy:[0,0,128],
2825                                 white:[255,255,255],
2826                                 fuchsia:[255,0,255],
2827                                 olive:[128,128,0],
2828                                 yellow:[255,255,0],
2829                                 orange:[255,165,0],
2830                                 gray:[128,128,128],
2831                                 purple:[128,0,128],
2832                                 green:[0,128,0],
2833                                 red:[255,0,0],
2834                                 pink:[255,192,203],
2835                                 cyan:[0,255,255],
2836                                 transparent:[255,255,255,0]},
2837
2838                         _hue = function(h, m1, m2) {
2839                                 h = (h < 0) ? h + 1 : (h > 1) ? h - 1 : h;
2840                                 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;
2841                         },
2842
2843                         /**
2844                          * @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)
2845                          * @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.
2846                          * @return {Array.<number>} An array containing red, green, and blue (and optionally alpha) in that order.
2847                          */
2848                         _parseColor = function(v) {
2849                                 var c1, c2, c3, h, s, l;
2850                                 if (!v || v === "") {
2851                                         return _colorLookup.black;
2852                                 }
2853                                 if (typeof(v) === "number") {
2854                                         return [v >> 16, (v >> 8) & 255, v & 255];
2855                                 }
2856                                 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.
2857                                         v = v.substr(0, v.length - 1);
2858                                 }
2859                                 if (_colorLookup[v]) {
2860                                         return _colorLookup[v];
2861                                 }
2862                                 if (v.charAt(0) === "#") {
2863                                         if (v.length === 4) { //for shorthand like #9F0
2864                                                 c1 = v.charAt(1),
2865                                                 c2 = v.charAt(2),
2866                                                 c3 = v.charAt(3);
2867                                                 v = "#" + c1 + c1 + c2 + c2 + c3 + c3;
2868                                         }
2869                                         v = parseInt(v.substr(1), 16);
2870                                         return [v >> 16, (v >> 8) & 255, v & 255];
2871                                 }
2872                                 if (v.substr(0, 3) === "hsl") {
2873                                         v = v.match(_numExp);
2874                                         h = (Number(v[0]) % 360) / 360;
2875                                         s = Number(v[1]) / 100;
2876                                         l = Number(v[2]) / 100;
2877                                         c2 = (l <= 0.5) ? l * (s + 1) : l + s - l * s;
2878                                         c1 = l * 2 - c2;
2879                                         if (v.length > 3) {
2880                                                 v[3] = Number(v[3]);
2881                                         }
2882                                         v[0] = _hue(h + 1 / 3, c1, c2);
2883                                         v[1] = _hue(h, c1, c2);
2884                                         v[2] = _hue(h - 1 / 3, c1, c2);
2885                                         return v;
2886                                 }
2887                                 v = v.match(_numExp) || _colorLookup.transparent;
2888                                 v[0] = Number(v[0]);
2889                                 v[1] = Number(v[1]);
2890                                 v[2] = Number(v[2]);
2891                                 if (v.length > 3) {
2892                                         v[3] = Number(v[3]);
2893                                 }
2894                                 return v;
2895                         },
2896                         _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.
2897
2898                 for (p in _colorLookup) {
2899                         _colorExp += "|" + p + "\\b";
2900                 }
2901                 _colorExp = new RegExp(_colorExp+")", "gi");
2902
2903                 /**
2904                  * @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.
2905                  * @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.
2906                  * @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.
2907                  * @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.
2908                  * @return {Function} formatter function
2909                  */
2910                 var _getFormatter = function(dflt, clr, collapsible, multi) {
2911                                 if (dflt == null) {
2912                                         return function(v) {return v;};
2913                                 }
2914                                 var dColor = clr ? (dflt.match(_colorExp) || [""])[0] : "",
2915                                         dVals = dflt.split(dColor).join("").match(_valuesExp) || [],
2916                                         pfx = dflt.substr(0, dflt.indexOf(dVals[0])),
2917                                         sfx = (dflt.charAt(dflt.length - 1) === ")") ? ")" : "",
2918                                         delim = (dflt.indexOf(" ") !== -1) ? " " : ",",
2919                                         numVals = dVals.length,
2920                                         dSfx = (numVals > 0) ? dVals[0].replace(_numExp, "") : "",
2921                                         formatter;
2922                                 if (!numVals) {
2923                                         return function(v) {return v;};
2924                                 }
2925                                 if (clr) {
2926                                         formatter = function(v) {
2927                                                 var color, vals, i, a;
2928                                                 if (typeof(v) === "number") {
2929                                                         v += dSfx;
2930                                                 } else if (multi && _commasOutsideParenExp.test(v)) {
2931                                                         a = v.replace(_commasOutsideParenExp, "|").split("|");
2932                                                         for (i = 0; i < a.length; i++) {
2933                                                                 a[i] = formatter(a[i]);
2934                                                         }
2935                                                         return a.join(",");
2936                                                 }
2937                                                 color = (v.match(_colorExp) || [dColor])[0];
2938                                                 vals = v.split(color).join("").match(_valuesExp) || [];
2939                                                 i = vals.length;
2940                                                 if (numVals > i--) {
2941                                                         while (++i < numVals) {
2942                                                                 vals[i] = collapsible ? vals[(((i - 1) / 2) | 0)] : dVals[i];
2943                                                         }
2944                                                 }
2945                                                 return pfx + vals.join(delim) + delim + color + sfx + (v.indexOf("inset") !== -1 ? " inset" : "");
2946                                         };
2947                                         return formatter;
2948
2949                                 }
2950                                 formatter = function(v) {
2951                                         var vals, a, i;
2952                                         if (typeof(v) === "number") {
2953                                                 v += dSfx;
2954                                         } else if (multi && _commasOutsideParenExp.test(v)) {
2955                                                 a = v.replace(_commasOutsideParenExp, "|").split("|");
2956                                                 for (i = 0; i < a.length; i++) {
2957                                                         a[i] = formatter(a[i]);
2958                                                 }
2959                                                 return a.join(",");
2960                                         }
2961                                         vals = v.match(_valuesExp) || [];
2962                                         i = vals.length;
2963                                         if (numVals > i--) {
2964                                                 while (++i < numVals) {
2965                                                         vals[i] = collapsible ? vals[(((i - 1) / 2) | 0)] : dVals[i];
2966                                                 }
2967                                         }
2968                                         return pfx + vals.join(delim) + sfx;
2969                                 };
2970                                 return formatter;
2971                         },
2972
2973                         /**
2974                          * @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.
2975                          * @param {!string} props a comma-delimited list of property names in order from top to left, like "marginTop,marginRight,marginBottom,marginLeft"
2976                          * @return {Function} a formatter function
2977                          */
2978                         _getEdgeParser = function(props) {
2979                                 props = props.split(",");
2980                                 return function(t, e, p, cssp, pt, plugin, vars) {
2981                                         var a = (e + "").split(" "),
2982                                                 i;
2983                                         vars = {};
2984                                         for (i = 0; i < 4; i++) {
2985                                                 vars[props[i]] = a[i] = a[i] || a[(((i - 1) / 2) >> 0)];
2986                                         }
2987                                         return cssp.parse(t, vars, pt, plugin);
2988                                 };
2989                         },
2990
2991                         // @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.
2992                         _setPluginRatio = _internals._setPluginRatio = function(v) {
2993                                 this.plugin.setRatio(v);
2994                                 var d = this.data,
2995                                         proxy = d.proxy,
2996                                         mpt = d.firstMPT,
2997                                         min = 0.000001,
2998                                         val, pt, i, str;
2999                                 while (mpt) {
3000                                         val = proxy[mpt.v];
3001                                         if (mpt.r) {
3002                                                 val = Math.round(val);
3003                                         } else if (val < min && val > -min) {
3004                                                 val = 0;
3005                                         }
3006                                         mpt.t[mpt.p] = val;
3007                                         mpt = mpt._next;
3008                                 }
3009                                 if (d.autoRotate) {
3010                                         d.autoRotate.rotation = proxy.rotation;
3011                                 }
3012                                 //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.
3013                                 if (v === 1) {
3014                                         mpt = d.firstMPT;
3015                                         while (mpt) {
3016                                                 pt = mpt.t;
3017                                                 if (!pt.type) {
3018                                                         pt.e = pt.s + pt.xs0;
3019                                                 } else if (pt.type === 1) {
3020                                                         str = pt.xs0 + pt.s + pt.xs1;
3021                                                         for (i = 1; i < pt.l; i++) {
3022                                                                 str += pt["xn"+i] + pt["xs"+(i+1)];
3023                                                         }
3024                                                         pt.e = str;
3025                                                 }
3026                                                 mpt = mpt._next;
3027                                         }
3028                                 }
3029                         },
3030
3031                         /**
3032                          * @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.
3033                          * @param {!Object} t target object whose property we're tweening (often a CSSPropTween)
3034                          * @param {!string} p property name
3035                          * @param {(number|string|object)} v value
3036                          * @param {MiniPropTween=} next next MiniPropTween in the linked list
3037                          * @param {boolean=} r if true, the tweened value should be rounded to the nearest integer
3038                          */
3039                         MiniPropTween = function(t, p, v, next, r) {
3040                                 this.t = t;
3041                                 this.p = p;
3042                                 this.v = v;
3043                                 this.r = r;
3044                                 if (next) {
3045                                         next._prev = this;
3046                                         this._next = next;
3047                                 }
3048                         },
3049
3050                         /**
3051                          * @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.
3052                          * This method returns an object that has the following properties:
3053                          *  - 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
3054                          *  - 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
3055                          *  - firstMPT: the first MiniPropTween in the linked list
3056                          *  - 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.
3057                          * @param {!Object} t target object to be tweened
3058                          * @param {!(Object|string)} vars the object containing the information about the tweening values (typically the end/destination values) that should be parsed
3059                          * @param {!CSSPlugin} cssp The CSSPlugin instance
3060                          * @param {CSSPropTween=} pt the next CSSPropTween in the linked list
3061                          * @param {TweenPlugin=} plugin the external TweenPlugin instance that will be handling tweening the numeric values
3062                          * @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.
3063                          * @return An object containing the following properties: proxy, end, firstMPT, and pt (see above for descriptions)
3064                          */
3065                         _parseToProxy = _internals._parseToProxy = function(t, vars, cssp, pt, plugin, shallow) {
3066                                 var bpt = pt,
3067                                         start = {},
3068                                         end = {},
3069                                         transform = cssp._transform,
3070                                         oldForce = _forcePT,
3071                                         i, p, xp, mpt, firstPT;
3072                                 cssp._transform = null;
3073                                 _forcePT = vars;
3074                                 pt = firstPT = cssp.parse(t, vars, pt, plugin);
3075                                 _forcePT = oldForce;
3076                                 //break off from the linked list so the new ones are isolated.
3077                                 if (shallow) {
3078                                         cssp._transform = transform;
3079                                         if (bpt) {
3080                                                 bpt._prev = null;
3081                                                 if (bpt._prev) {
3082                                                         bpt._prev._next = null;
3083                                                 }
3084                                         }
3085                                 }
3086                                 while (pt && pt !== bpt) {
3087                                         if (pt.type <= 1) {
3088                                                 p = pt.p;
3089                                                 end[p] = pt.s + pt.c;
3090                                                 start[p] = pt.s;
3091                                                 if (!shallow) {
3092                                                         mpt = new MiniPropTween(pt, "s", p, mpt, pt.r);
3093                                                         pt.c = 0;
3094                                                 }
3095                                                 if (pt.type === 1) {
3096                                                         i = pt.l;
3097                                                         while (--i > 0) {
3098                                                                 xp = "xn" + i;
3099                                                                 p = pt.p + "_" + xp;
3100                                                                 end[p] = pt.data[xp];
3101                                                                 start[p] = pt[xp];
3102                                                                 if (!shallow) {
3103                                                                         mpt = new MiniPropTween(pt, xp, p, mpt, pt.rxp[xp]);
3104                                                                 }
3105                                                         }
3106                                                 }
3107                                         }
3108                                         pt = pt._next;
3109                                 }
3110                                 return {proxy:start, end:end, firstMPT:mpt, pt:firstPT};
3111                         },
3112
3113
3114
3115                         /**
3116                          * @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.
3117                          * CSSPropTweens have the following optional properties as well (not defined through the constructor):
3118                          *  - 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.
3119                          *  - 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)
3120                          *  - 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.
3121                          *  - 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.
3122                          *  - 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.
3123                          * @param {!Object} t Target object whose property will be tweened. Often a DOM element, but not always. It could be anything.
3124                          * @param {string} p Property to tween (name). For example, to tween element.width, p would be "width".
3125                          * @param {number} s Starting numeric value
3126                          * @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.
3127                          * @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.
3128                          * @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.
3129                          * @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"
3130                          * @param {boolean=} r If true, the value(s) should be rounded
3131                          * @param {number=} pr Priority in the linked list order. Higher priority CSSPropTweens will be updated before lower priority ones. The default priority is 0.
3132                          * @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.
3133                          * @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.
3134                          */
3135                         CSSPropTween = _internals.CSSPropTween = function(t, p, s, c, next, type, n, r, pr, b, e) {
3136                                 this.t = t; //target
3137                                 this.p = p; //property
3138                                 this.s = s; //starting value
3139                                 this.c = c; //change value
3140                                 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)
3141                                 if (!(t instanceof CSSPropTween)) {
3142                                         _overwriteProps.push(this.n);
3143                                 }
3144                                 this.r = r; //round (boolean)
3145                                 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
3146                                 if (pr) {
3147                                         this.pr = pr;
3148                                         _hasPriority = true;
3149                                 }
3150                                 this.b = (b === undefined) ? s : b;
3151                                 this.e = (e === undefined) ? s + c : e;
3152                                 if (next) {
3153                                         this._next = next;
3154                                         next._prev = this;
3155                                 }
3156                         },
3157
3158                         /**
3159                          * 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:
3160                          * 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);
3161                          * 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().
3162                          * 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.
3163                          *
3164                          * @param {!Object} t Target whose property will be tweened
3165                          * @param {!string} p Property that will be tweened (its name, like "left" or "backgroundColor" or "boxShadow")
3166                          * @param {string} b Beginning value
3167                          * @param {string} e Ending value
3168                          * @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)
3169                          * @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
3170                          * @param {?CSSPropTween} pt CSSPropTween instance that is the current head of the linked list (we'll prepend to this).
3171                          * @param {number=} pr Priority in the linked list order. Higher priority properties will be updated before lower priority ones. The default priority is 0.
3172                          * @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}
3173                          * @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.
3174                          * @return {CSSPropTween} The first CSSPropTween in the linked list which includes the new one(s) added by the parseComplex() call.
3175                          */
3176                         _parseComplex = CSSPlugin.parseComplex = function(t, p, b, e, clrs, dflt, pt, pr, plugin, setRatio) {
3177                                 //DEBUG: _log("parseComplex: "+p+", b: "+b+", e: "+e);
3178                                 b = b || dflt || "";
3179                                 pt = new CSSPropTween(t, p, 0, 0, pt, (setRatio ? 2 : 1), null, false, pr, b, e);
3180                                 e += ""; //ensures it's a string
3181                                 var ba = b.split(", ").join(",").split(" "), //beginning array
3182                                         ea = e.split(", ").join(",").split(" "), //ending array
3183                                         l = ba.length,
3184                                         autoRound = (_autoRound !== false),
3185                                         i, xi, ni, bv, ev, bnums, enums, bn, rgba, temp, cv, str;
3186                                 if (e.indexOf(",") !== -1 || b.indexOf(",") !== -1) {
3187                                         ba = ba.join(" ").replace(_commasOutsideParenExp, ", ").split(" ");
3188                                         ea = ea.join(" ").replace(_commasOutsideParenExp, ", ").split(" ");
3189                                         l = ba.length;
3190                                 }
3191                                 if (l !== ea.length) {
3192                                         //DEBUG: _log("mismatched formatting detected on " + p + " (" + b + " vs " + e + ")");
3193                                         ba = (dflt || "").split(" ");
3194                                         l = ba.length;
3195                                 }
3196                                 pt.plugin = plugin;
3197                                 pt.setRatio = setRatio;
3198                                 for (i = 0; i < l; i++) {
3199                                         bv = ba[i];
3200                                         ev = ea[i];
3201                                         bn = parseFloat(bv);
3202
3203                                         //if the value begins with a number (most common). It's fine if it has a suffix like px
3204                                         if (bn || bn === 0) {
3205                                                 pt.appendXtra("", bn, _parseChange(ev, bn), ev.replace(_relNumExp, ""), (autoRound && ev.indexOf("px") !== -1), true);
3206
3207                                         //if the value is a color
3208                                         } else if (clrs && (bv.charAt(0) === "#" || _colorLookup[bv] || _rgbhslExp.test(bv))) {
3209                                                 str = ev.charAt(ev.length - 1) === "," ? ")," : ")"; //if there's a comma at the end, retain it.
3210                                                 bv = _parseColor(bv);
3211                                                 ev = _parseColor(ev);
3212                                                 rgba = (bv.length + ev.length > 6);
3213                                                 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
3214                                                         pt["xs" + pt.l] += pt.l ? " transparent" : "transparent";
3215                                                         pt.e = pt.e.split(ea[i]).join("transparent");
3216                                                 } else {
3217                                                         if (!_supportsOpacity) { //old versions of IE don't support rgba().
3218                                                                 rgba = false;
3219                                                         }
3220                                                         pt.appendXtra((rgba ? "rgba(" : "rgb("), bv[0], ev[0] - bv[0], ",", true, true)
3221                                                                 .appendXtra("", bv[1], ev[1] - bv[1], ",", true)
3222                                                                 .appendXtra("", bv[2], ev[2] - bv[2], (rgba ? "," : str), true);
3223                                                         if (rgba) {
3224                                                                 bv = (bv.length < 4) ? 1 : bv[3];
3225                                                                 pt.appendXtra("", bv, ((ev.length < 4) ? 1 : ev[3]) - bv, str, false);
3226                                                         }
3227                                                 }
3228
3229                                         } else {
3230                                                 bnums = bv.match(_numExp); //gets each group of numbers in the beginning value string and drops them into an array
3231
3232                                                 //if no number is found, treat it as a non-tweening value and just append the string to the current xs.
3233                                                 if (!bnums) {
3234                                                         pt["xs" + pt.l] += pt.l ? " " + bv : bv;
3235
3236                                                 //loop through all the numbers that are found and construct the extra values on the pt.
3237                                                 } else {
3238                                                         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
3239                                                         if (!enums || enums.length !== bnums.length) {
3240                                                                 //DEBUG: _log("mismatched formatting detected on " + p + " (" + b + " vs " + e + ")");
3241                                                                 return pt;
3242                                                         }
3243                                                         ni = 0;
3244                                                         for (xi = 0; xi < bnums.length; xi++) {
3245                                                                 cv = bnums[xi];
3246                                                                 temp = bv.indexOf(cv, ni);
3247                                                                 pt.appendXtra(bv.substr(ni, temp - ni), Number(cv), _parseChange(enums[xi], cv), "", (autoRound && bv.substr(temp + cv.length, 2) === "px"), (xi === 0));
3248                                                                 ni = temp + cv.length;
3249                                                         }
3250                                                         pt["xs" + pt.l] += bv.substr(ni);
3251                                                 }
3252                                         }
3253                                 }
3254                                 //if there are relative values ("+=" or "-=" prefix), we need to adjust the ending value to eliminate the prefixes and combine the values properly.
3255                                 if (e.indexOf("=") !== -1) if (pt.data) {
3256                                         str = pt.xs0 + pt.data.s;
3257                                         for (i = 1; i < pt.l; i++) {
3258                                                 str += pt["xs" + i] + pt.data["xn" + i];
3259                                         }
3260                                         pt.e = str + pt["xs" + i];
3261                                 }
3262                                 if (!pt.l) {
3263                                         pt.type = -1;
3264                                         pt.xs0 = pt.e;
3265                                 }
3266                                 return pt.xfirst || pt;
3267                         },
3268                         i = 9;
3269
3270
3271                 p = CSSPropTween.prototype;
3272                 p.l = p.pr = 0; //length (number of extra properties like xn1, xn2, xn3, etc.
3273                 while (--i > 0) {
3274                         p["xn" + i] = 0;
3275                         p["xs" + i] = "";
3276                 }
3277                 p.xs0 = "";
3278                 p._next = p._prev = p.xfirst = p.data = p.plugin = p.setRatio = p.rxp = null;
3279
3280
3281                 /**
3282                  * 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:
3283                  * xs0:"rect(", s:10, xs1:"px, ", xn1:5, xs2:"px, ", xn2:0, xs3:"px, ", xn3:20, xn4:"px)"
3284                  * And they'd all get joined together when the CSSPlugin renders (in the setRatio() method).
3285                  * @param {string=} pfx Prefix (if any)
3286                  * @param {!number} s Starting value
3287                  * @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.
3288                  * @param {string=} sfx Suffix (if any)
3289                  * @param {boolean=} r Round (if true).
3290                  * @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.
3291                  * @return {CSSPropTween} returns itself so that multiple methods can be chained together.
3292                  */
3293                 p.appendXtra = function(pfx, s, c, sfx, r, pad) {
3294                         var pt = this,
3295                                 l = pt.l;
3296                         pt["xs" + l] += (pad && l) ? " " + pfx : pfx || "";
3297                         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!
3298                                 pt["xs" + l] += s + (sfx || "");
3299                                 return pt;
3300                         }
3301                         pt.l++;
3302                         pt.type = pt.setRatio ? 2 : 1;
3303                         pt["xs" + pt.l] = sfx || "";
3304                         if (l > 0) {
3305                                 pt.data["xn" + l] = s + c;
3306                                 pt.rxp["xn" + l] = r; //round extra property (we need to tap into this in the _parseToProxy() method)
3307                                 pt["xn" + l] = s;
3308                                 if (!pt.plugin) {
3309                                         pt.xfirst = new CSSPropTween(pt, "xn" + l, s, c, pt.xfirst || pt, 0, pt.n, r, pt.pr);
3310                                         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.
3311                                 }
3312                                 return pt;
3313                         }
3314                         pt.data = {s:s + c};
3315                         pt.rxp = {};
3316                         pt.s = s;
3317                         pt.c = c;
3318                         pt.r = r;
3319                         return pt;
3320                 };
3321
3322                 /**
3323                  * @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.
3324                  * @param {!string} p Property name (like "boxShadow" or "throwProps")
3325                  * @param {Object=} options An object containing any of the following configuration options:
3326                  *                      - defaultValue: the default value
3327                  *                      - 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)
3328                  *                      - 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.)
3329                  *                      - prefix: if true, we'll determine whether or not this property requires a vendor prefix (like Webkit or Moz or ms or O)
3330                  *                      - color: set this to true if the value for this SpecialProp may contain color-related values like rgb(), rgba(), etc.
3331                  *                      - priority: priority in the linked list order. Higher priority SpecialProps will be updated before lower priority ones. The default priority is 0.
3332                  *                      - multi: if true, the formatter should accommodate a comma-delimited list of values, like boxShadow could have multiple boxShadows listed out.
3333                  *                      - 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.
3334                  *                      - 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).
3335                  */
3336                 var SpecialProp = function(p, options) {
3337                                 options = options || {};
3338                                 this.p = options.prefix ? _checkPropPrefix(p) || p : p;
3339                                 _specialProps[p] = _specialProps[this.p] = this;
3340                                 this.format = options.formatter || _getFormatter(options.defaultValue, options.color, options.collapsible, options.multi);
3341                                 if (options.parser) {
3342                                         this.parse = options.parser;
3343                                 }
3344                                 this.clrs = options.color;
3345                                 this.multi = options.multi;
3346                                 this.keyword = options.keyword;
3347                                 this.dflt = options.defaultValue;
3348                                 this.pr = options.priority || 0;
3349                         },
3350
3351                         //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.
3352                         _registerComplexSpecialProp = _internals._registerComplexSpecialProp = function(p, options, defaults) {
3353                                 if (typeof(options) !== "object") {
3354                                         options = {parser:defaults}; //to make backwards compatible with older versions of BezierPlugin and ThrowPropsPlugin
3355                                 }
3356                                 var a = p.split(","),
3357                                         d = options.defaultValue,
3358                                         i, temp;
3359                                 defaults = defaults || [d];
3360                                 for (i = 0; i < a.length; i++) {
3361                                         options.prefix = (i === 0 && options.prefix);
3362                                         options.defaultValue = defaults[i] || d;
3363                                         temp = new SpecialProp(a[i], options);
3364                                 }
3365                         },
3366
3367                         //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.
3368                         _registerPluginProp = function(p) {
3369                                 if (!_specialProps[p]) {
3370                                         var pluginName = p.charAt(0).toUpperCase() + p.substr(1) + "Plugin";
3371                                         _registerComplexSpecialProp(p, {parser:function(t, e, p, cssp, pt, plugin, vars) {
3372                                                 var pluginClass = (window.GreenSockGlobals || window).com.greensock.plugins[pluginName];
3373                                                 if (!pluginClass) {
3374                                                         _log("Error: " + pluginName + " js file not loaded.");
3375                                                         return pt;
3376                                                 }
3377                                                 pluginClass._cssRegister();
3378                                                 return _specialProps[p].parse(t, e, p, cssp, pt, plugin, vars);
3379                                         }});
3380                                 }
3381                         };
3382
3383
3384                 p = SpecialProp.prototype;
3385
3386                 /**
3387                  * 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)
3388                  * @param {!Object} t target element
3389                  * @param {(string|number|object)} b beginning value
3390                  * @param {(string|number|object)} e ending (destination) value
3391                  * @param {CSSPropTween=} pt next CSSPropTween in the linked list
3392                  * @param {TweenPlugin=} plugin If another plugin will be tweening the complex value, that TweenPlugin instance goes here.
3393                  * @param {function=} setRatio If a custom setRatio() method should be used to handle this complex value, that goes here.
3394                  * @return {CSSPropTween=} First CSSPropTween in the linked list
3395                  */
3396                 p.parseComplex = function(t, b, e, pt, plugin, setRatio) {
3397                         var kwd = this.keyword,
3398                                 i, ba, ea, l, bi, ei;
3399                         //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)
3400                         if (this.multi) if (_commasOutsideParenExp.test(e) || _commasOutsideParenExp.test(b)) {
3401                                 ba = b.replace(_commasOutsideParenExp, "|").split("|");
3402                                 ea = e.replace(_commasOutsideParenExp, "|").split("|");
3403                         } else if (kwd) {
3404                                 ba = [b];
3405                                 ea = [e];
3406                         }
3407                         if (ea) {
3408                                 l = (ea.length > ba.length) ? ea.length : ba.length;
3409                                 for (i = 0; i < l; i++) {
3410                                         b = ba[i] = ba[i] || this.dflt;
3411                                         e = ea[i] = ea[i] || this.dflt;
3412                                         if (kwd) {
3413                                                 bi = b.indexOf(kwd);
3414                                                 ei = e.indexOf(kwd);
3415                                                 if (bi !== ei) {
3416                                                         e = (ei === -1) ? ea : ba;
3417                                                         e[i] += " " + kwd;
3418                                                 }
3419                                         }
3420                                 }
3421                                 b = ba.join(", ");
3422                                 e = ea.join(", ");
3423                         }
3424                         return _parseComplex(t, this.p, b, e, this.clrs, this.dflt, pt, this.pr, plugin, setRatio);
3425                 };
3426
3427                 /**
3428                  * 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:
3429                  * this._firstPT = sp.parse(element, "5px 10px 20px rgb(2550,102,51)", "boxShadow", this);
3430                  * 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).
3431                  * @param {!Object} t Target object whose property is being tweened
3432                  * @param {Object} e End value as provided in the vars object (typically a string, but not always - like a throwProps would be an object).
3433                  * @param {!string} p Property name
3434                  * @param {!CSSPlugin} cssp The CSSPlugin instance that should be associated with this tween.
3435                  * @param {?CSSPropTween} pt The CSSPropTween that is the current head of the linked list (we'll prepend to it)
3436                  * @param {TweenPlugin=} plugin If a plugin will be used to tween the parsed value, this is the plugin instance.
3437                  * @param {Object=} vars Original vars object that contains the data for parsing.
3438                  * @return {CSSPropTween} The first CSSPropTween in the linked list which includes the new one(s) added by the parse() call.
3439                  */
3440                 p.parse = function(t, e, p, cssp, pt, plugin, vars) {
3441                         return this.parseComplex(t.style, this.format(_getStyle(t, this.p, _cs, false, this.dflt)), this.format(e), pt, plugin);
3442                 };
3443
3444                 /**
3445                  * 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:
3446                  *  1) Target object whose property should be tweened (typically a DOM element)
3447                  *  2) The end/destination value (could be a string, number, object, or whatever you want)
3448                  *  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)
3449                  *
3450                  * 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:
3451                  *
3452                  * CSSPlugin.registerSpecialProp("myCustomProp", function(target, value, tween) {
3453                  *      var start = target.style.width;
3454                  *      return function(ratio) {
3455                  *              target.style.width = (start + value * ratio) + "px";
3456                  *              console.log("set width to " + target.style.width);
3457                  *          }
3458                  * }, 0);
3459                  *
3460                  * Then, when I do this tween, it will trigger my special property:
3461                  *
3462                  * TweenLite.to(element, 1, {css:{myCustomProp:100}});
3463                  *
3464                  * In the example, of course, we're just changing the width, but you can do anything you want.
3465                  *
3466                  * @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}})
3467                  * @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.
3468                  * @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.
3469                  */
3470                 CSSPlugin.registerSpecialProp = function(name, onInitTween, priority) {
3471                         _registerComplexSpecialProp(name, {parser:function(t, e, p, cssp, pt, plugin, vars) {
3472                                 var rv = new CSSPropTween(t, p, 0, 0, pt, 2, p, false, priority);
3473                                 rv.plugin = plugin;
3474                                 rv.setRatio = onInitTween(t, e, cssp._tween, p);
3475                                 return rv;
3476                         }, priority:priority});
3477                 };
3478
3479
3480
3481
3482
3483
3484
3485
3486                 //transform-related methods and properties
3487                 var _transformProps = ("scaleX,scaleY,scaleZ,x,y,z,skewX,skewY,rotation,rotationX,rotationY,perspective").split(","),
3488                         _transformProp = _checkPropPrefix("transform"), //the Javascript (camelCase) transform property, like msTransform, WebkitTransform, MozTransform, or OTransform.
3489                         _transformPropCSS = _prefixCSS + "transform",
3490                         _transformOriginProp = _checkPropPrefix("transformOrigin"),
3491                         _supports3D = (_checkPropPrefix("perspective") !== null),
3492                         Transform = _internals.Transform = function() {
3493                                 this.skewY = 0;
3494                         },
3495
3496                         /**
3497                          * 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.
3498                          * @param {!Object} t target element
3499                          * @param {Object=} cs computed style object (optional)
3500                          * @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...}
3501                          * @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)
3502                          * @return {object} object containing all of the transform properties/values like {x:0, y:0, z:0, scaleX:1...}
3503                          */
3504                         _getTransform = _internals.getTransform = function(t, cs, rec, parse) {
3505                                 if (t._gsTransform && rec && !parse) {
3506                                         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.
3507                                 }
3508                                 var tm = rec ? t._gsTransform || new Transform() : new Transform(),
3509                                         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.
3510                                         min = 0.00002,
3511                                         rnd = 100000,
3512                                         minAngle = 179.99,
3513                                         minPI = minAngle * _DEG2RAD,
3514                                         zOrigin = _supports3D ? parseFloat(_getStyle(t, _transformOriginProp, cs, false, "0 0 0").split(" ")[2]) || tm.zOrigin  || 0 : 0,
3515                                         s, m, i, n, dec, scaleX, scaleY, rotation, skewX, difX, difY, difR, difS;
3516                                 if (_transformProp) {
3517                                         s = _getStyle(t, _transformPropCSS, cs, true);
3518                                 } else if (t.currentStyle) {
3519                                         //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.
3520                                         s = t.currentStyle.filter.match(_ieGetMatrixExp);
3521                                         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(",") : "";
3522                                 }
3523                                 //split the matrix values out into an array (m for matrix)
3524                                 m = (s || "").match(/(?:\-|\b)[\d\-\.e]+\b/gi) || [];
3525                                 i = m.length;
3526                                 while (--i > -1) {
3527                                         n = Number(m[i]);
3528                                         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).
3529                                 }
3530                                 if (m.length === 16) {
3531
3532                                         //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)
3533                                         var a13 = m[8], a23 = m[9], a33 = m[10],
3534                                                 a14 = m[12], a24 = m[13], a34 = m[14];
3535
3536                                         //we manually compensate for non-zero z component of transformOrigin to work around bugs in Safari
3537                                         if (tm.zOrigin) {
3538                                                 a34 = -tm.zOrigin;
3539                                                 a14 = a13*a34-m[12];
3540                                                 a24 = a23*a34-m[13];
3541                                                 a34 = a33*a34+tm.zOrigin-m[14];
3542                                         }
3543
3544                                         //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.
3545                                         if (!rec || parse || tm.rotationX == null) {
3546                                                 var a11 = m[0], a21 = m[1], a31 = m[2], a41 = m[3],
3547                                                         a12 = m[4], a22 = m[5], a32 = m[6], a42 = m[7],
3548                                                         a43 = m[11],
3549                                                         angle = Math.atan2(a32, a33),
3550                                                         xFlip = (angle < -minPI || angle > minPI),
3551                                                         t1, t2, t3, cos, sin, yFlip, zFlip;
3552                                                 tm.rotationX = angle * _RAD2DEG;
3553                                                 //rotationX
3554                                                 if (angle) {
3555                                                         cos = Math.cos(-angle);
3556                                                         sin = Math.sin(-angle);
3557                                                         t1 = a12*cos+a13*sin;
3558                                                         t2 = a22*cos+a23*sin;
3559                                                         t3 = a32*cos+a33*sin;
3560                                                         a13 = a12*-sin+a13*cos;
3561                                                         a23 = a22*-sin+a23*cos;
3562                                                         a33 = a32*-sin+a33*cos;
3563                                                         a43 = a42*-sin+a43*cos;
3564                                                         a12 = t1;
3565                                                         a22 = t2;
3566                                                         a32 = t3;
3567                                                 }
3568                                                 //rotationY
3569                                                 angle = Math.atan2(a13, a11);
3570                                                 tm.rotationY = angle * _RAD2DEG;
3571                                                 if (angle) {
3572                                                         yFlip = (angle < -minPI || angle > minPI);
3573                                                         cos = Math.cos(-angle);
3574                                                         sin = Math.sin(-angle);
3575                                                         t1 = a11*cos-a13*sin;
3576                                                         t2 = a21*cos-a23*sin;
3577                                                         t3 = a31*cos-a33*sin;
3578                                                         a23 = a21*sin+a23*cos;
3579                                                         a33 = a31*sin+a33*cos;
3580                                                         a43 = a41*sin+a43*cos;
3581                                                         a11 = t1;
3582                                                         a21 = t2;
3583                                                         a31 = t3;
3584                                                 }
3585                                                 //rotationZ
3586                                                 angle = Math.atan2(a21, a22);
3587                                                 tm.rotation = angle * _RAD2DEG;
3588                                                 if (angle) {
3589                                                         zFlip = (angle < -minPI || angle > minPI);
3590                                                         cos = Math.cos(-angle);
3591                                                         sin = Math.sin(-angle);
3592                                                         a11 = a11*cos+a12*sin;
3593                                                         t2 = a21*cos+a22*sin;
3594                                                         a22 = a21*-sin+a22*cos;
3595                                                         a32 = a31*-sin+a32*cos;
3596                                                         a21 = t2;
3597                                                 }
3598
3599                                                 if (zFlip && xFlip) {
3600                                                         tm.rotation = tm.rotationX = 0;
3601                                                 } else if (zFlip && yFlip) {
3602                                                         tm.rotation = tm.rotationY = 0;
3603                                                 } else if (yFlip && xFlip) {
3604                                                         tm.rotationY = tm.rotationX = 0;
3605                                                 }
3606
3607                                                 tm.scaleX = ((Math.sqrt(a11 * a11 + a21 * a21) * rnd + 0.5) | 0) / rnd;
3608                                                 tm.scaleY = ((Math.sqrt(a22 * a22 + a23 * a23) * rnd + 0.5) | 0) / rnd;
3609                                                 tm.scaleZ = ((Math.sqrt(a32 * a32 + a33 * a33) * rnd + 0.5) | 0) / rnd;
3610                                                 tm.skewX = 0;
3611                                                 tm.perspective = a43 ? 1 / ((a43 < 0) ? -a43 : a43) : 0;
3612                                                 tm.x = a14;
3613                                                 tm.y = a24;
3614                                                 tm.z = a34;
3615                                         }
3616
3617                                 } 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.
3618                                         var k = (m.length >= 6),
3619                                                 a = k ? m[0] : 1,
3620                                                 b = m[1] || 0,
3621                                                 c = m[2] || 0,
3622                                                 d = k ? m[3] : 1;
3623                                         tm.x = m[4] || 0;
3624                                         tm.y = m[5] || 0;
3625                                         scaleX = Math.sqrt(a * a + b * b);
3626                                         scaleY = Math.sqrt(d * d + c * c);
3627                                         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).
3628                                         skewX = (c || d) ? Math.atan2(c, d) * _RAD2DEG + rotation : tm.skewX || 0;
3629                                         difX = scaleX - Math.abs(tm.scaleX || 0);
3630                                         difY = scaleY - Math.abs(tm.scaleY || 0);
3631                                         if (Math.abs(skewX) > 90 && Math.abs(skewX) < 270) {
3632                                                 if (invX) {
3633                                                         scaleX *= -1;
3634                                                         skewX += (rotation <= 0) ? 180 : -180;
3635                                                         rotation += (rotation <= 0) ? 180 : -180;
3636                                                 } else {
3637                                                         scaleY *= -1;
3638                                                         skewX += (skewX <= 0) ? 180 : -180;
3639                                                 }
3640                                         }
3641                                         difR = (rotation - tm.rotation) % 180; //note: matching ranges would be very small (+/-0.0001) or very close to 180.
3642                                         difS = (skewX - tm.skewX) % 180;
3643                                         //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.
3644                                         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)) {
3645                                                 tm.scaleX = scaleX;
3646                                                 tm.scaleY = scaleY;
3647                                                 tm.rotation = rotation;
3648                                                 tm.skewX = skewX;
3649                                         }
3650                                         if (_supports3D) {
3651                                                 tm.rotationX = tm.rotationY = tm.z = 0;
3652                                                 tm.perspective = parseFloat(CSSPlugin.defaultTransformPerspective) || 0;
3653                                                 tm.scaleZ = 1;
3654                                         }
3655                                 }
3656                                 tm.zOrigin = zOrigin;
3657
3658                                 //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.
3659                                 for (i in tm) {
3660                                         if (tm[i] < min) if (tm[i] > -min) {
3661                                                 tm[i] = 0;
3662                                         }
3663                                 }
3664                                 //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);
3665                                 if (rec) {
3666                                         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)
3667                                 }
3668                                 return tm;
3669                         },
3670
3671                         //for setting 2D transforms in IE6, IE7, and IE8 (must use a "filter" to emulate the behavior of modern day browser transforms)
3672                         _setIETransformRatio = function(v) {
3673                                 var t = this.data, //refers to the element's _gsTransform object
3674                                         ang = -t.rotation * _DEG2RAD,
3675                                         skew = ang + t.skewX * _DEG2RAD,
3676                                         rnd = 100000,
3677                                         a = ((Math.cos(ang) * t.scaleX * rnd) | 0) / rnd,
3678                                         b = ((Math.sin(ang) * t.scaleX * rnd) | 0) / rnd,
3679                                         c = ((Math.sin(skew) * -t.scaleY * rnd) | 0) / rnd,
3680                                         d = ((Math.cos(skew) * t.scaleY * rnd) | 0) / rnd,
3681                                         style = this.t.style,
3682                                         cs = this.t.currentStyle,
3683                                         filters, val;
3684                                 if (!cs) {
3685                                         return;
3686                                 }
3687                                 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)
3688                                 b = -c;
3689                                 c = -val;
3690                                 filters = cs.filter;
3691                                 style.filter = ""; //remove filters so that we can accurately measure offsetWidth/offsetHeight
3692                                 var w = this.t.offsetWidth,
3693                                         h = this.t.offsetHeight,
3694                                         clip = (cs.position !== "absolute"),
3695                                         m = "progid:DXImageTransform.Microsoft.Matrix(M11=" + a + ", M12=" + b + ", M21=" + c + ", M22=" + d,
3696                                         ox = t.x,
3697                                         oy = t.y,
3698                                         dx, dy;
3699
3700                                 //if transformOrigin is being used, adjust the offset x and y
3701                                 if (t.ox != null) {
3702                                         dx = ((t.oxp) ? w * t.ox * 0.01 : t.ox) - w / 2;
3703                                         dy = ((t.oyp) ? h * t.oy * 0.01 : t.oy) - h / 2;
3704                                         ox += dx - (dx * a + dy * b);
3705                                         oy += dy - (dx * c + dy * d);
3706                                 }
3707
3708                                 if (!clip) {
3709                                         m += ", sizingMethod='auto expand')";
3710                                 } else {
3711                                         dx = (w / 2);
3712                                         dy = (h / 2);
3713                                         //translate to ensure that transformations occur around the correct origin (default is center).
3714                                         m += ", Dx=" + (dx - (dx * a + dy * b) + ox) + ", Dy=" + (dy - (dx * c + dy * d) + oy) + ")";
3715                                 }
3716                                 if (filters.indexOf("DXImageTransform.Microsoft.Matrix(") !== -1) {
3717                                         style.filter = filters.replace(_ieSetMatrixExp, m);
3718                                 } else {
3719                                         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.
3720                                 }
3721
3722                                 //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.
3723                                 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) {
3724                                         style.removeAttribute("filter");
3725                                 }
3726
3727                                 //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).
3728                                 if (!clip) {
3729                                         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
3730                                                 marg, prop, dif;
3731                                         dx = t.ieOffsetX || 0;
3732                                         dy = t.ieOffsetY || 0;
3733                                         t.ieOffsetX = Math.round((w - ((a < 0 ? -a : a) * w + (b < 0 ? -b : b) * h)) / 2 + ox);
3734                                         t.ieOffsetY = Math.round((h - ((d < 0 ? -d : d) * h + (c < 0 ? -c : c) * w)) / 2 + oy);
3735                                         for (i = 0; i < 4; i++) {
3736                                                 prop = _margins[i];
3737                                                 marg = cs[prop];
3738                                                 //we need to get the current margin in case it is being tweened separately (we want to respect that tween's changes)
3739                                                 val = (marg.indexOf("px") !== -1) ? parseFloat(marg) : _convertToPixels(this.t, prop, parseFloat(marg), marg.replace(_suffixExp, "")) || 0;
3740                                                 if (val !== t[prop]) {
3741                                                         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.
3742                                                 } else {
3743                                                         dif = (i < 2) ? dx - t.ieOffsetX : dy - t.ieOffsetY;
3744                                                 }
3745                                                 style[prop] = (t[prop] = Math.round( val - dif * ((i === 0 || i === 2) ? 1 : mult) )) + "px";
3746                                         }
3747                                 }
3748                         },
3749
3750                         _set3DTransformRatio = _internals.set3DTransformRatio = function(v) {
3751                                 var t = this.data, //refers to the element's _gsTransform object
3752                                         style = this.t.style,
3753                                         angle = t.rotation * _DEG2RAD,
3754                                         sx = t.scaleX,
3755                                         sy = t.scaleY,
3756                                         sz = t.scaleZ,
3757                                         perspective = t.perspective,
3758                                         a11, a12, a13, a14,     a21, a22, a23, a24, a31, a32, a33, a34, a41, a42, a43,
3759                                         zOrigin, rnd, cos, sin, t1, t2, t3, t4;
3760                                 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
3761                                         _set2DTransformRatio.call(this, v);
3762                                         return;
3763                                 }
3764                                 if (_isFirefox) {
3765                                         var n = 0.0001;
3766                                         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.
3767                                                 sx = sz = 0.00002;
3768                                         }
3769                                         if (sy < n && sy > -n) {
3770                                                 sy = sz = 0.00002;
3771                                         }
3772                                         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).
3773                                                 perspective = 0;
3774                                         }
3775                                 }
3776                                 if (angle || t.skewX) {
3777                                         cos = Math.cos(angle);
3778                                         sin = Math.sin(angle);
3779                                         a11 = cos;
3780                                         a21 = sin;
3781                                         if (t.skewX) {
3782                                                 angle -= t.skewX * _DEG2RAD;
3783                                                 cos = Math.cos(angle);
3784                                                 sin = Math.sin(angle);
3785                                                 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
3786                                                         t1 = Math.tan(t.skewX * _DEG2RAD);
3787                                                         t1 = Math.sqrt(1 + t1 * t1);
3788                                                         cos *= t1;
3789                                                         sin *= t1;
3790                                                 }
3791                                         }
3792                                         a12 = -sin;
3793                                         a22 = cos;
3794
3795                                 } else if (!t.rotationY && !t.rotationX && sz === 1 && !perspective) { //if we're only translating and/or 2D scaling, this is faster...
3796                                         style[_transformProp] = "translate3d(" + t.x + "px," + t.y + "px," + t.z +"px)" + ((sx !== 1 || sy !== 1) ? " scale(" + sx + "," + sy + ")" : "");
3797                                         return;
3798                                 } else {
3799                                         a11 = a22 = 1;
3800                                         a12 = a21 = 0;
3801                                 }
3802                                 a33 = 1;
3803                                 a13 = a14 = a23 = a24 = a31 = a32 = a34 = a41 = a42 = 0;
3804                                 a43 = (perspective) ? -1 / perspective : 0;
3805                                 zOrigin = t.zOrigin;
3806                                 rnd = 100000;
3807                                 angle = t.rotationY * _DEG2RAD;
3808                                 if (angle) {
3809                                         cos = Math.cos(angle);
3810                                         sin = Math.sin(angle);
3811                                         a31 = a33*-sin;
3812                                         a41 = a43*-sin;
3813                                         a13 = a11*sin;
3814                                         a23 = a21*sin;
3815                                         a33 *= cos;
3816                                         a43 *= cos;
3817                                         a11 *= cos;
3818                                         a21 *= cos;
3819                                 }
3820                                 angle = t.rotationX * _DEG2RAD;
3821                                 if (angle) {
3822                                         cos = Math.cos(angle);
3823                                         sin = Math.sin(angle);
3824                                         t1 = a12*cos+a13*sin;
3825                                         t2 = a22*cos+a23*sin;
3826                                         t3 = a32*cos+a33*sin;
3827                                         t4 = a42*cos+a43*sin;
3828                                         a13 = a12*-sin+a13*cos;
3829                                         a23 = a22*-sin+a23*cos;
3830                                         a33 = a32*-sin+a33*cos;
3831                                         a43 = a42*-sin+a43*cos;
3832                                         a12 = t1;
3833                                         a22 = t2;
3834                                         a32 = t3;
3835                                         a42 = t4;
3836                                 }
3837                                 if (sz !== 1) {
3838                                         a13*=sz;
3839                                         a23*=sz;
3840                                         a33*=sz;
3841                                         a43*=sz;
3842                                 }
3843                                 if (sy !== 1) {
3844                                         a12*=sy;
3845                                         a22*=sy;
3846                                         a32*=sy;
3847                                         a42*=sy;
3848                                 }
3849                                 if (sx !== 1) {
3850                                         a11*=sx;
3851                                         a21*=sx;
3852                                         a31*=sx;
3853                                         a41*=sx;
3854                                 }
3855                                 if (zOrigin) {
3856                                         a34 -= zOrigin;
3857                                         a14 = a13*a34;
3858                                         a24 = a23*a34;
3859                                         a34 = a33*a34+zOrigin;
3860                                 }
3861                                 //we round the x, y, and z slightly differently to allow even larger values.
3862                                 a14 = (t1 = (a14 += t.x) - (a14 |= 0)) ? ((t1 * rnd + (t1 < 0 ? -0.5 : 0.5)) | 0) / rnd + a14 : a14;
3863                                 a24 = (t1 = (a24 += t.y) - (a24 |= 0)) ? ((t1 * rnd + (t1 < 0 ? -0.5 : 0.5)) | 0) / rnd + a24 : a24;
3864                                 a34 = (t1 = (a34 += t.z) - (a34 |= 0)) ? ((t1 * rnd + (t1 < 0 ? -0.5 : 0.5)) | 0) / rnd + a34 : a34;
3865                                 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(",") + ")";
3866                         },
3867
3868                         _set2DTransformRatio = _internals.set2DTransformRatio = function(v) {
3869                                 var t = this.data, //refers to the element's _gsTransform object
3870                                         targ = this.t,
3871                                         style = targ.style,
3872                                         ang, skew, rnd, sx, sy;
3873                                 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.
3874                                         this.setRatio = _set3DTransformRatio;
3875                                         _set3DTransformRatio.call(this, v);
3876                                         return;
3877                                 }
3878                                 if (!t.rotation && !t.skewX) {
3879                                         style[_transformProp] = "matrix(" + t.scaleX + ",0,0," + t.scaleY + "," + t.x + "," + t.y + ")";
3880                                 } else {
3881                                         ang = t.rotation * _DEG2RAD;
3882                                         skew = ang - t.skewX * _DEG2RAD;
3883                                         rnd = 100000;
3884                                         sx = t.scaleX * rnd;
3885                                         sy = t.scaleY * rnd;
3886                                         //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.
3887                                         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 + ")";
3888                                 }
3889                         };
3890
3891                 _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) {
3892                         if (cssp._transform) { return pt; } //only need to parse the transform once, and only if the browser supports it.
3893                         var m1 = cssp._transform = _getTransform(t, _cs, true, vars.parseTransform),
3894                                 style = t.style,
3895                                 min = 0.000001,
3896                                 i = _transformProps.length,
3897                                 v = vars,
3898                                 endRotations = {},
3899                                 m2, skewY, copy, orig, has3D, hasChange, dr;
3900                         if (typeof(v.transform) === "string" && _transformProp) { //for values like transform:"rotate(60deg) scale(0.5, 0.8)"
3901                                 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.
3902                                 copy[_transformProp] = v.transform;
3903                                 copy.display = "block"; //if display is "none", the browser often refuses to report the transform properties correctly.
3904                                 copy.position = "absolute";
3905                                 _doc.body.appendChild(_tempDiv);
3906                                 m2 = _getTransform(_tempDiv, null, false);
3907                                 _doc.body.removeChild(_tempDiv);
3908                         } else if (typeof(v) === "object") { //for values like scaleX, scaleY, rotation, x, y, skewX, and skewY or transform:{...} (object)
3909                                 m2 = {scaleX:_parseVal((v.scaleX != null) ? v.scaleX : v.scale, m1.scaleX),
3910                                         scaleY:_parseVal((v.scaleY != null) ? v.scaleY : v.scale, m1.scaleY),
3911                                         scaleZ:_parseVal(v.scaleZ, m1.scaleZ),
3912                                         x:_parseVal(v.x, m1.x),
3913                                         y:_parseVal(v.y, m1.y),
3914                                         z:_parseVal(v.z, m1.z),
3915                                         perspective:_parseVal(v.transformPerspective, m1.perspective)};
3916                                 dr = v.directionalRotation;
3917                                 if (dr != null) {
3918                                         if (typeof(dr) === "object") {
3919                                                 for (copy in dr) {
3920                                                         v[copy] = dr[copy];
3921                                                 }
3922                                         } else {
3923                                                 v.rotation = dr;
3924                                         }
3925                                 }
3926                                 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);
3927                                 if (_supports3D) {
3928                                         m2.rotationX = _parseAngle(("rotationX" in v) ? v.rotationX : ("shortRotationX" in v) ? v.shortRotationX + "_short" : m1.rotationX || 0, m1.rotationX, "rotationX", endRotations);
3929                                         m2.rotationY = _parseAngle(("rotationY" in v) ? v.rotationY : ("shortRotationY" in v) ? v.shortRotationY + "_short" : m1.rotationY || 0, m1.rotationY, "rotationY", endRotations);
3930                                 }
3931                                 m2.skewX = (v.skewX == null) ? m1.skewX : _parseAngle(v.skewX, m1.skewX);
3932
3933                                 //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.
3934                                 m2.skewY = (v.skewY == null) ? m1.skewY : _parseAngle(v.skewY, m1.skewY);
3935                                 if ((skewY = m2.skewY - m1.skewY)) {
3936                                         m2.skewX += skewY;
3937                                         m2.rotation += skewY;
3938                                 }
3939                         }
3940
3941                         if (_supports3D && v.force3D != null) {
3942                                 m1.force3D = v.force3D;
3943                                 hasChange = true;
3944                         }
3945
3946                         m1.skewType = v.skewType || m1.skewType || CSSPlugin.defaultSkewType;
3947
3948                         has3D = (m1.force3D || m1.z || m1.rotationX || m1.rotationY || m2.z || m2.rotationX || m2.rotationY || m2.perspective);
3949                         if (!has3D && v.scale != null) {
3950                                 m2.scaleZ = 1; //no need to tween scaleZ.
3951                         }
3952
3953                         while (--i > -1) {
3954                                 p = _transformProps[i];
3955                                 orig = m2[p] - m1[p];
3956                                 if (orig > min || orig < -min || _forcePT[p] != null) {
3957                                         hasChange = true;
3958                                         pt = new CSSPropTween(m1, p, m1[p], orig, pt);
3959                                         if (p in endRotations) {
3960                                                 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
3961                                         }
3962                                         pt.xs0 = 0; //ensures the value stays numeric in setRatio()
3963                                         pt.plugin = plugin;
3964                                         cssp._overwriteProps.push(pt.n);
3965                                 }
3966                         }
3967
3968                         orig = v.transformOrigin;
3969                         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).
3970                                 if (_transformProp) {
3971                                         hasChange = true;
3972                                         p = _transformOriginProp;
3973                                         orig = (orig || _getStyle(t, p, _cs, false, "50% 50%")) + ""; //cast as string to avoid errors
3974                                         pt = new CSSPropTween(style, p, 0, 0, pt, -1, "transformOrigin");
3975                                         pt.b = style[p];
3976                                         pt.plugin = plugin;
3977                                         if (_supports3D) {
3978                                                 copy = m1.zOrigin;
3979                                                 orig = orig.split(" ");
3980                                                 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.
3981                                                 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)!
3982                                                 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)
3983                                                 pt.b = copy;
3984                                                 pt.xs0 = pt.e = m1.zOrigin;
3985                                         } else {
3986                                                 pt.xs0 = pt.e = orig;
3987                                         }
3988
3989                                 //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).
3990                                 } else {
3991                                         _parsePosition(orig + "", m1);
3992                                 }
3993                         }
3994
3995                         if (hasChange) {
3996                                 cssp._transformType = (has3D || this._transformType === 3) ? 3 : 2; //quicker than calling cssp._enableTransforms();
3997                         }
3998                         return pt;
3999                 }, prefix:true});
4000
4001                 _registerComplexSpecialProp("boxShadow", {defaultValue:"0px 0px 0px 0px #999", prefix:true, color:true, multi:true, keyword:"inset"});
4002
4003                 _registerComplexSpecialProp("borderRadius", {defaultValue:"0px", parser:function(t, e, p, cssp, pt, plugin) {
4004                         e = this.format(e);
4005                         var props = ["borderTopLeftRadius","borderTopRightRadius","borderBottomRightRadius","borderBottomLeftRadius"],
4006                                 style = t.style,
4007                                 ea1, i, es2, bs2, bs, es, bn, en, w, h, esfx, bsfx, rel, hn, vn, em;
4008                         w = parseFloat(t.offsetWidth);
4009                         h = parseFloat(t.offsetHeight);
4010                         ea1 = e.split(" ");
4011                         for (i = 0; i < props.length; i++) { //if we're dealing with percentages, we must convert things separately for the horizontal and vertical axis!
4012                                 if (this.p.indexOf("border")) { //older browsers used a prefix
4013                                         props[i] = _checkPropPrefix(props[i]);
4014                                 }
4015                                 bs = bs2 = _getStyle(t, props[i], _cs, false, "0px");
4016                                 if (bs.indexOf(" ") !== -1) {
4017                                         bs2 = bs.split(" ");
4018                                         bs = bs2[0];
4019                                         bs2 = bs2[1];
4020                                 }
4021                                 es = es2 = ea1[i];
4022                                 bn = parseFloat(bs);
4023                                 bsfx = bs.substr((bn + "").length);
4024                                 rel = (es.charAt(1) === "=");
4025                                 if (rel) {
4026                                         en = parseInt(es.charAt(0)+"1", 10);
4027                                         es = es.substr(2);
4028                                         en *= parseFloat(es);
4029                                         esfx = es.substr((en + "").length - (en < 0 ? 1 : 0)) || "";
4030                                 } else {
4031                                         en = parseFloat(es);
4032                                         esfx = es.substr((en + "").length);
4033                                 }
4034                                 if (esfx === "") {
4035                                         esfx = _suffixMap[p] || bsfx;
4036                                 }
4037                                 if (esfx !== bsfx) {
4038                                         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.
4039                                         vn = _convertToPixels(t, "borderTop", bn, bsfx); //vertical number
4040                                         if (esfx === "%") {
4041                                                 bs = (hn / w * 100) + "%";
4042                                                 bs2 = (vn / h * 100) + "%";
4043                                         } else if (esfx === "em") {
4044                                                 em = _convertToPixels(t, "borderLeft", 1, "em");
4045                                                 bs = (hn / em) + "em";
4046                                                 bs2 = (vn / em) + "em";
4047                                         } else {
4048                                                 bs = hn + "px";
4049                                                 bs2 = vn + "px";
4050                                         }
4051                                         if (rel) {
4052                                                 es = (parseFloat(bs) + en) + esfx;
4053                                                 es2 = (parseFloat(bs2) + en) + esfx;
4054                                         }
4055                                 }
4056                                 pt = _parseComplex(style, props[i], bs + " " + bs2, es + " " + es2, false, "0px", pt);
4057                         }
4058                         return pt;
4059                 }, prefix:true, formatter:_getFormatter("0px 0px 0px 0px", false, true)});
4060                 _registerComplexSpecialProp("backgroundPosition", {defaultValue:"0 0", parser:function(t, e, p, cssp, pt, plugin) {
4061                         var bp = "background-position",
4062                                 cs = (_cs || _getComputedStyle(t, null)),
4063                                 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
4064                                 es = this.format(e),
4065                                 ba, ea, i, pct, overlap, src;
4066                         if ((bs.indexOf("%") !== -1) !== (es.indexOf("%") !== -1)) {
4067                                 src = _getStyle(t, "backgroundImage").replace(_urlExp, "");
4068                                 if (src && src !== "none") {
4069                                         ba = bs.split(" ");
4070                                         ea = es.split(" ");
4071                                         _tempImg.setAttribute("src", src); //set the temp <img>'s src to the background-image so that we can measure its width/height
4072                                         i = 2;
4073                                         while (--i > -1) {
4074                                                 bs = ba[i];
4075                                                 pct = (bs.indexOf("%") !== -1);
4076                                                 if (pct !== (ea[i].indexOf("%") !== -1)) {
4077                                                         overlap = (i === 0) ? t.offsetWidth - _tempImg.width : t.offsetHeight - _tempImg.height;
4078                                                         ba[i] = pct ? (parseFloat(bs) / 100 * overlap) + "px" : (parseFloat(bs) / overlap * 100) + "%";
4079                                                 }
4080                                         }
4081                                         bs = ba.join(" ");
4082                                 }
4083                         }
4084                         return this.parseComplex(t.style, bs, es, pt, plugin);
4085                 }, formatter:_parsePosition});
4086                 _registerComplexSpecialProp("backgroundSize", {defaultValue:"0 0", formatter:_parsePosition});
4087                 _registerComplexSpecialProp("perspective", {defaultValue:"0px", prefix:true});
4088                 _registerComplexSpecialProp("perspectiveOrigin", {defaultValue:"50% 50%", prefix:true});
4089                 _registerComplexSpecialProp("transformStyle", {prefix:true});
4090                 _registerComplexSpecialProp("backfaceVisibility", {prefix:true});
4091                 _registerComplexSpecialProp("userSelect", {prefix:true});
4092                 _registerComplexSpecialProp("margin", {parser:_getEdgeParser("marginTop,marginRight,marginBottom,marginLeft")});
4093                 _registerComplexSpecialProp("padding", {parser:_getEdgeParser("paddingTop,paddingRight,paddingBottom,paddingLeft")});
4094                 _registerComplexSpecialProp("clip", {defaultValue:"rect(0px,0px,0px,0px)", parser:function(t, e, p, cssp, pt, plugin){
4095                         var b, cs, delim;
4096                         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.
4097                                 cs = t.currentStyle;
4098                                 delim = _ieVers < 8 ? " " : ",";
4099                                 b = "rect(" + cs.clipTop + delim + cs.clipRight + delim + cs.clipBottom + delim + cs.clipLeft + ")";
4100                                 e = this.format(e).split(",").join(delim);
4101                         } else {
4102                                 b = this.format(_getStyle(t, this.p, _cs, false, this.dflt));
4103                                 e = this.format(e);
4104                         }
4105                         return this.parseComplex(t.style, b, e, pt, plugin);
4106                 }});
4107                 _registerComplexSpecialProp("textShadow", {defaultValue:"0px 0px 0px #999", color:true, multi:true});
4108                 _registerComplexSpecialProp("autoRound,strictUnits", {parser:function(t, e, p, cssp, pt) {return pt;}}); //just so that we can ignore these properties (not tween them)
4109                 _registerComplexSpecialProp("border", {defaultValue:"0px solid #000", parser:function(t, e, p, cssp, pt, plugin) {
4110                                 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);
4111                         }, color:true, formatter:function(v) {
4112                                 var a = v.split(" ");
4113                                 return a[0] + " " + (a[1] || "solid") + " " + (v.match(_colorExp) || ["#000"])[0];
4114                         }});
4115                 _registerComplexSpecialProp("borderWidth", {parser:_getEdgeParser("borderTopWidth,borderRightWidth,borderBottomWidth,borderLeftWidth")}); //Firefox doesn't pick up on borderWidth set in style sheets (only inline).
4116                 _registerComplexSpecialProp("float,cssFloat,styleFloat", {parser:function(t, e, p, cssp, pt, plugin) {
4117                         var s = t.style,
4118                                 prop = ("cssFloat" in s) ? "cssFloat" : "styleFloat";
4119                         return new CSSPropTween(s, prop, 0, 0, pt, -1, p, false, 0, s[prop], e);
4120                 }});
4121
4122                 //opacity-related
4123                 var _setIEOpacityRatio = function(v) {
4124                                 var t = this.t, //refers to the element's style property
4125                                         filters = t.filter || _getStyle(this.data, "filter"),
4126                                         val = (this.s + this.c * v) | 0,
4127                                         skip;
4128                                 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.
4129                                         if (filters.indexOf("atrix(") === -1 && filters.indexOf("radient(") === -1 && filters.indexOf("oader(") === -1) {
4130                                                 t.removeAttribute("filter");
4131                                                 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.
4132                                         } else {
4133                                                 t.filter = filters.replace(_alphaFilterExp, "");
4134                                                 skip = true;
4135                                         }
4136                                 }
4137                                 if (!skip) {
4138                                         if (this.xn1) {
4139                                                 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.
4140                                         }
4141                                         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
4142                                                 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)
4143                                                         t.filter = filters + " alpha(opacity=" + val + ")"; //we round the value because otherwise, bugs in IE7/8 can prevent "visibility" changes from being applied properly.
4144                                                 }
4145                                         } else {
4146                                                 t.filter = filters.replace(_opacityExp, "opacity=" + val);
4147                                         }
4148                                 }
4149                         };
4150                 _registerComplexSpecialProp("opacity,alpha,autoAlpha", {defaultValue:"1", parser:function(t, e, p, cssp, pt, plugin) {
4151                         var b = parseFloat(_getStyle(t, "opacity", _cs, false, "1")),
4152                                 style = t.style,
4153                                 isAutoAlpha = (p === "autoAlpha");
4154                         if (typeof(e) === "string" && e.charAt(1) === "=") {
4155                                 e = ((e.charAt(0) === "-") ? -1 : 1) * parseFloat(e.substr(2)) + b;
4156                         }
4157                         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)
4158                                 b = 0;
4159                         }
4160                         if (_supportsOpacity) {
4161                                 pt = new CSSPropTween(style, "opacity", b, e - b, pt);
4162                         } else {
4163                                 pt = new CSSPropTween(style, "opacity", b * 100, (e - b) * 100, pt);
4164                                 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.
4165                                 style.zoom = 1; //helps correct an IE issue.
4166                                 pt.type = 2;
4167                                 pt.b = "alpha(opacity=" + pt.s + ")";
4168                                 pt.e = "alpha(opacity=" + (pt.s + pt.c) + ")";
4169                                 pt.data = t;
4170                                 pt.plugin = plugin;
4171                                 pt.setRatio = _setIEOpacityRatio;
4172                         }
4173                         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
4174                                 pt = new CSSPropTween(style, "visibility", 0, 0, pt, -1, null, false, 0, ((b !== 0) ? "inherit" : "hidden"), ((e === 0) ? "hidden" : "inherit"));
4175                                 pt.xs0 = "inherit";
4176                                 cssp._overwriteProps.push(pt.n);
4177                                 cssp._overwriteProps.push(p);
4178                         }
4179                         return pt;
4180                 }});
4181
4182
4183                 var _removeProp = function(s, p) {
4184                                 if (p) {
4185                                         if (s.removeProperty) {
4186                                                 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)
4187                                                         p = "M" + p.substr(1);
4188                                                 }
4189                                                 s.removeProperty(p.replace(_capsExp, "-$1").toLowerCase());
4190                                         } else { //note: old versions of IE use "removeAttribute()" instead of "removeProperty()"
4191                                                 s.removeAttribute(p);
4192                                         }
4193                                 }
4194                         },
4195                         _setClassNameRatio = function(v) {
4196                                 this.t._gsClassPT = this;
4197                                 if (v === 1 || v === 0) {
4198                                         this.t.setAttribute("class", (v === 0) ? this.b : this.e);
4199                                         var mpt = this.data, //first MiniPropTween
4200                                                 s = this.t.style;
4201                                         while (mpt) {
4202                                                 if (!mpt.v) {
4203                                                         _removeProp(s, mpt.p);
4204                                                 } else {
4205                                                         s[mpt.p] = mpt.v;
4206                                                 }
4207                                                 mpt = mpt._next;
4208                                         }
4209                                         if (v === 1 && this.t._gsClassPT === this) {
4210                                                 this.t._gsClassPT = null;
4211                                         }
4212                                 } else if (this.t.getAttribute("class") !== this.e) {
4213                                         this.t.setAttribute("class", this.e);
4214                                 }
4215                         };
4216                 _registerComplexSpecialProp("className", {parser:function(t, e, p, cssp, pt, plugin, vars) {
4217                         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.
4218                                 cssText = t.style.cssText,
4219                                 difData, bs, cnpt, cnptLookup, mpt;
4220                         pt = cssp._classNamePT = new CSSPropTween(t, p, 0, 0, pt, 2);
4221                         pt.setRatio = _setClassNameRatio;
4222                         pt.pr = -11;
4223                         _hasPriority = true;
4224                         pt.b = b;
4225                         bs = _getAllStyles(t, _cs);
4226                         //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)
4227                         cnpt = t._gsClassPT;
4228                         if (cnpt) {
4229                                 cnptLookup = {};
4230                                 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.
4231                                 while (mpt) {
4232                                         cnptLookup[mpt.p] = 1;
4233                                         mpt = mpt._next;
4234                                 }
4235                                 cnpt.setRatio(1);
4236                         }
4237                         t._gsClassPT = pt;
4238                         pt.e = (e.charAt(1) !== "=") ? e : b.replace(new RegExp("\\s*\\b" + e.substr(2) + "\\b"), "") + ((e.charAt(0) === "+") ? " " + e.substr(2) : "");
4239                         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.
4240                                 t.setAttribute("class", pt.e);
4241                                 difData = _cssDif(t, bs, _getAllStyles(t), vars, cnptLookup);
4242                                 t.setAttribute("class", b);
4243                                 pt.data = difData.firstMPT;
4244                                 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).
4245                                 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)
4246                         }
4247                         return pt;
4248                 }});
4249
4250
4251                 var _setClearPropsRatio = function(v) {
4252                         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).
4253                                 var s = this.t.style,
4254                                         transformParse = _specialProps.transform.parse,
4255                                         a, p, i, clearTransform;
4256                                 if (this.e === "all") {
4257                                         s.cssText = "";
4258                                         clearTransform = true;
4259                                 } else {
4260                                         a = this.e.split(",");
4261                                         i = a.length;
4262                                         while (--i > -1) {
4263                                                 p = a[i];
4264                                                 if (_specialProps[p]) {
4265                                                         if (_specialProps[p].parse === transformParse) {
4266                                                                 clearTransform = true;
4267                                                         } else {
4268                                                                 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"
4269                                                         }
4270                                                 }
4271                                                 _removeProp(s, p);
4272                                         }
4273                                 }
4274                                 if (clearTransform) {
4275                                         _removeProp(s, _transformProp);
4276                                         if (this.t._gsTransform) {
4277                                                 delete this.t._gsTransform;
4278                                         }
4279                                 }
4280
4281                         }
4282                 };
4283                 _registerComplexSpecialProp("clearProps", {parser:function(t, e, p, cssp, pt) {
4284                         pt = new CSSPropTween(t, p, 0, 0, pt, 2);
4285                         pt.setRatio = _setClearPropsRatio;
4286                         pt.e = e;
4287                         pt.pr = -10;
4288                         pt.data = cssp._tween;
4289                         _hasPriority = true;
4290                         return pt;
4291                 }});
4292
4293                 p = "bezier,throwProps,physicsProps,physics2D".split(",");
4294                 i = p.length;
4295                 while (i--) {
4296                         _registerPluginProp(p[i]);
4297                 }
4298
4299
4300
4301
4302
4303
4304
4305
4306                 p = CSSPlugin.prototype;
4307                 p._firstPT = null;
4308
4309                 //gets called when the tween renders for the first time. This kicks everything off, recording start/end values, etc.
4310                 p._onInitTween = function(target, vars, tween) {
4311                         if (!target.nodeType) { //css is only for dom elements
4312                                 return false;
4313                         }
4314                         this._target = target;
4315                         this._tween = tween;
4316                         this._vars = vars;
4317                         _autoRound = vars.autoRound;
4318                         _hasPriority = false;
4319                         _suffixMap = vars.suffixMap || CSSPlugin.suffixMap;
4320                         _cs = _getComputedStyle(target, "");
4321                         _overwriteProps = this._overwriteProps;
4322                         var style = target.style,
4323                                 v, pt, pt2, first, last, next, zIndex, tpt, threeD;
4324                         if (_reqSafariFix) if (style.zIndex === "") {
4325                                 v = _getStyle(target, "zIndex", _cs);
4326                                 if (v === "auto" || v === "") {
4327                                         //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.
4328                                         this._addLazySet(style, "zIndex", 0);
4329                                 }
4330                         }
4331
4332                         if (typeof(vars) === "string") {
4333                                 first = style.cssText;
4334                                 v = _getAllStyles(target, _cs);
4335                                 style.cssText = first + ";" + vars;
4336                                 v = _cssDif(target, v, _getAllStyles(target)).difs;
4337                                 if (!_supportsOpacity && _opacityValExp.test(vars)) {
4338                                         v.opacity = parseFloat( RegExp.$1 );
4339                                 }
4340                                 vars = v;
4341                                 style.cssText = first;
4342                         }
4343                         this._firstPT = pt = this.parse(target, vars, null);
4344
4345                         if (this._transformType) {
4346                                 threeD = (this._transformType === 3);
4347                                 if (!_transformProp) {
4348                                         style.zoom = 1; //helps correct an IE issue.
4349                                 } else if (_isSafari) {
4350                                         _reqSafariFix = true;
4351                                         //if zIndex isn't set, iOS Safari doesn't repaint things correctly sometimes (seemingly at random).
4352                                         if (style.zIndex === "") {
4353                                                 zIndex = _getStyle(target, "zIndex", _cs);
4354                                                 if (zIndex === "auto" || zIndex === "") {
4355                                                         this._addLazySet(style, "zIndex", 0);
4356                                                 }
4357                                         }
4358                                         //Setting WebkitBackfaceVisibility corrects 3 bugs:
4359                                         // 1) [non-Android] Safari skips rendering changes to "top" and "left" that are made on the same frame/render as a transform update.
4360                                         // 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.
4361                                         // 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.
4362                                         //Note: we allow the user to override the auto-setting by defining WebkitBackfaceVisibility in the vars of the tween.
4363                                         if (_isSafariLT6) {
4364                                                 this._addLazySet(style, "WebkitBackfaceVisibility", this._vars.WebkitBackfaceVisibility || (threeD ? "visible" : "hidden"));
4365                                         }
4366                                 }
4367                                 pt2 = pt;
4368                                 while (pt2 && pt2._next) {
4369                                         pt2 = pt2._next;
4370                                 }
4371                                 tpt = new CSSPropTween(target, "transform", 0, 0, null, 2);
4372                                 this._linkCSSP(tpt, null, pt2);
4373                                 tpt.setRatio = (threeD && _supports3D) ? _set3DTransformRatio : _transformProp ? _set2DTransformRatio : _setIETransformRatio;
4374                                 tpt.data = this._transform || _getTransform(target, _cs, true);
4375                                 _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.
4376                         }
4377
4378                         if (_hasPriority) {
4379                                 //reorders the linked list in order of pr (priority)
4380                                 while (pt) {
4381                                         next = pt._next;
4382                                         pt2 = first;
4383                                         while (pt2 && pt2.pr > pt.pr) {
4384                                                 pt2 = pt2._next;
4385                                         }
4386                                         if ((pt._prev = pt2 ? pt2._prev : last)) {
4387                                                 pt._prev._next = pt;
4388                                         } else {
4389                                                 first = pt;
4390                                         }
4391                                         if ((pt._next = pt2)) {
4392                                                 pt2._prev = pt;
4393                                         } else {
4394                                                 last = pt;
4395                                         }
4396                                         pt = next;
4397                                 }
4398                                 this._firstPT = first;
4399                         }
4400                         return true;
4401                 };
4402
4403
4404                 p.parse = function(target, vars, pt, plugin) {
4405                         var style = target.style,
4406                                 p, sp, bn, en, bs, es, bsfx, esfx, isStr, rel;
4407                         for (p in vars) {
4408                                 es = vars[p]; //ending value string
4409                                 sp = _specialProps[p]; //SpecialProp lookup.
4410                                 if (sp) {
4411                                         pt = sp.parse(target, es, p, this, pt, plugin, vars);
4412
4413                                 } else {
4414                                         bs = _getStyle(target, p, _cs) + "";
4415                                         isStr = (typeof(es) === "string");
4416                                         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:
4417                                                 if (!isStr) {
4418                                                         es = _parseColor(es);
4419                                                         es = ((es.length > 3) ? "rgba(" : "rgb(") + es.join(",") + ")";
4420                                                 }
4421                                                 pt = _parseComplex(style, p, bs, es, true, "transparent", pt, 0, plugin);
4422
4423                                         } else if (isStr && (es.indexOf(" ") !== -1 || es.indexOf(",") !== -1)) {
4424                                                 pt = _parseComplex(style, p, bs, es, true, null, pt, 0, plugin);
4425
4426                                         } else {
4427                                                 bn = parseFloat(bs);
4428                                                 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.
4429
4430                                                 if (bs === "" || bs === "auto") {
4431                                                         if (p === "width" || p === "height") {
4432                                                                 bn = _getDimension(target, p, _cs);
4433                                                                 bsfx = "px";
4434                                                         } else if (p === "left" || p === "top") {
4435                                                                 bn = _calculateOffset(target, p, _cs);
4436                                                                 bsfx = "px";
4437                                                         } else {
4438                                                                 bn = (p !== "opacity") ? 0 : 1;
4439                                                                 bsfx = "";
4440                                                         }
4441                                                 }
4442
4443                                                 rel = (isStr && es.charAt(1) === "=");
4444                                                 if (rel) {
4445                                                         en = parseInt(es.charAt(0) + "1", 10);
4446                                                         es = es.substr(2);
4447                                                         en *= parseFloat(es);
4448                                                         esfx = es.replace(_suffixExp, "");
4449                                                 } else {
4450                                                         en = parseFloat(es);
4451                                                         esfx = isStr ? es.substr((en + "").length) || "" : "";
4452                                                 }
4453
4454                                                 if (esfx === "") {
4455                                                         esfx = (p in _suffixMap) ? _suffixMap[p] : bsfx; //populate the end suffix, prioritizing the map, then if none is found, use the beginning suffix.
4456                                                 }
4457
4458                                                 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.
4459
4460                                                 //if the beginning/ending suffixes don't match, normalize them...
4461                                                 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!
4462                                                         bn = _convertToPixels(target, p, bn, bsfx);
4463                                                         if (esfx === "%") {
4464                                                                 bn /= _convertToPixels(target, p, 100, "%") / 100;
4465                                                                 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.
4466                                                                         bs = bn + "%";
4467                                                                 }
4468
4469                                                         } else if (esfx === "em") {
4470                                                                 bn /= _convertToPixels(target, p, 1, "em");
4471
4472                                                         //otherwise convert to pixels.
4473                                                         } else if (esfx !== "px") {
4474                                                                 en = _convertToPixels(target, p, en, esfx);
4475                                                                 esfx = "px"; //we don't use bsfx after this, so we don't need to set it to px too.
4476                                                         }
4477                                                         if (rel) if (en || en === 0) {
4478                                                                 es = (en + bn) + esfx; //the changes we made affect relative calculations, so adjust the end value here.
4479                                                         }
4480                                                 }
4481
4482                                                 if (rel) {
4483                                                         en += bn;
4484                                                 }
4485
4486                                                 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.
4487                                                         pt = new CSSPropTween(style, p, bn, en - bn, pt, 0, p, (_autoRound !== false && (esfx === "px" || p === "zIndex")), 0, bs, es);
4488                                                         pt.xs0 = esfx;
4489                                                         //DEBUG: _log("tween "+p+" from "+pt.b+" ("+bn+esfx+") to "+pt.e+" with suffix: "+pt.xs0);
4490                                                 } else if (style[p] === undefined || !es && (es + "" === "NaN" || es == null)) {
4491                                                         _log("invalid " + p + " tween value: " + vars[p]);
4492                                                 } else {
4493                                                         pt = new CSSPropTween(style, p, en || bn || 0, 0, pt, -1, p, false, 0, bs, es);
4494                                                         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.
4495                                                         //DEBUG: _log("non-tweening value "+p+": "+pt.xs0);
4496                                                 }
4497                                         }
4498                                 }
4499                                 if (plugin) if (pt && !pt.plugin) {
4500                                         pt.plugin = plugin;
4501                                 }
4502                         }
4503                         return pt;
4504                 };
4505
4506
4507                 //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.
4508                 p.setRatio = function(v) {
4509                         var pt = this._firstPT,
4510                                 min = 0.000001,
4511                                 val, str, i;
4512
4513                         //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).
4514                         if (v === 1 && (this._tween._time === this._tween._duration || this._tween._time === 0)) {
4515                                 while (pt) {
4516                                         if (pt.type !== 2) {
4517                                                 pt.t[pt.p] = pt.e;
4518                                         } else {
4519                                                 pt.setRatio(v);
4520                                         }
4521                                         pt = pt._next;
4522                                 }
4523
4524                         } else if (v || !(this._tween._time === this._tween._duration || this._tween._time === 0) || this._tween._rawPrevTime === -0.000001) {
4525                                 while (pt) {
4526                                         val = pt.c * v + pt.s;
4527                                         if (pt.r) {
4528                                                 val = Math.round(val);
4529                                         } else if (val < min) if (val > -min) {
4530                                                 val = 0;
4531                                         }
4532                                         if (!pt.type) {
4533                                                 pt.t[pt.p] = val + pt.xs0;
4534                                         } else if (pt.type === 1) { //complex value (one that typically has multiple numbers inside a string, like "rect(5px,10px,20px,25px)"
4535                                                 i = pt.l;
4536                                                 if (i === 2) {
4537                                                         pt.t[pt.p] = pt.xs0 + val + pt.xs1 + pt.xn1 + pt.xs2;
4538                                                 } else if (i === 3) {
4539                                                         pt.t[pt.p] = pt.xs0 + val + pt.xs1 + pt.xn1 + pt.xs2 + pt.xn2 + pt.xs3;
4540                                                 } else if (i === 4) {
4541                                                         pt.t[pt.p] = pt.xs0 + val + pt.xs1 + pt.xn1 + pt.xs2 + pt.xn2 + pt.xs3 + pt.xn3 + pt.xs4;
4542                                                 } else if (i === 5) {
4543                                                         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;
4544                                                 } else {
4545                                                         str = pt.xs0 + val + pt.xs1;
4546                                                         for (i = 1; i < pt.l; i++) {
4547                                                                 str += pt["xn"+i] + pt["xs"+(i+1)];
4548                                                         }
4549                                                         pt.t[pt.p] = str;
4550                                                 }
4551
4552                                         } else if (pt.type === -1) { //non-tweening value
4553                                                 pt.t[pt.p] = pt.xs0;
4554
4555                                         } else if (pt.setRatio) { //custom setRatio() for things like SpecialProps, external plugins, etc.
4556                                                 pt.setRatio(v);
4557                                         }
4558                                         pt = pt._next;
4559                                 }
4560
4561                         //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).
4562                         } else {
4563                                 while (pt) {
4564                                         if (pt.type !== 2) {
4565                                                 pt.t[pt.p] = pt.b;
4566                                         } else {
4567                                                 pt.setRatio(v);
4568                                         }
4569                                         pt = pt._next;
4570                                 }
4571                         }
4572                 };
4573
4574                 /**
4575                  * @private
4576                  * Forces rendering of the target's transforms (rotation, scale, etc.) whenever the CSSPlugin's setRatio() is called.
4577                  * Basically, this tells the CSSPlugin to create a CSSPropTween (type 2) after instantiation that runs last in the linked
4578                  * list and calls the appropriate (3D or 2D) rendering function. We separate this into its own method so that we can call
4579                  * it from other plugins like BezierPlugin if, for example, it needs to apply an autoRotation and this CSSPlugin
4580                  * doesn't have any transform-related properties of its own. You can call this method as many times as you
4581                  * want and it won't create duplicate CSSPropTweens.
4582                  *
4583                  * @param {boolean} threeD if true, it should apply 3D tweens (otherwise, just 2D ones are fine and typically faster)
4584                  */
4585                 p._enableTransforms = function(threeD) {
4586                         this._transformType = (threeD || this._transformType === 3) ? 3 : 2;
4587                         this._transform = this._transform || _getTransform(this._target, _cs, true); //ensures that the element has a _gsTransform property with the appropriate values.
4588                 };
4589
4590                 var lazySet = function(v) {
4591                         this.t[this.p] = this.e;
4592                         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.
4593                 };
4594                 /** @private Gives us a way to set a value on the first render (and only the first render). **/
4595                 p._addLazySet = function(t, p, v) {
4596                         var pt = this._firstPT = new CSSPropTween(t, p, 0, 0, this._firstPT, 2);
4597                         pt.e = v;
4598                         pt.setRatio = lazySet;
4599                         pt.data = this;
4600                 };
4601
4602                 /** @private **/
4603                 p._linkCSSP = function(pt, next, prev, remove) {
4604                         if (pt) {
4605                                 if (next) {
4606                                         next._prev = pt;
4607                                 }
4608                                 if (pt._next) {
4609                                         pt._next._prev = pt._prev;
4610                                 }
4611                                 if (pt._prev) {
4612                                         pt._prev._next = pt._next;
4613                                 } else if (this._firstPT === pt) {
4614                                         this._firstPT = pt._next;
4615                                         remove = true; //just to prevent resetting this._firstPT 5 lines down in case pt._next is null. (optimized for speed)
4616                                 }
4617                                 if (prev) {
4618                                         prev._next = pt;
4619                                 } else if (!remove && this._firstPT === null) {
4620                                         this._firstPT = pt;
4621                                 }
4622                                 pt._next = next;
4623                                 pt._prev = prev;
4624                         }
4625                         return pt;
4626                 };
4627
4628                 //we need to make sure that if alpha or autoAlpha is killed, opacity is too. And autoAlpha affects the "visibility" property.
4629                 p._kill = function(lookup) {
4630                         var copy = lookup,
4631                                 pt, p, xfirst;
4632                         if (lookup.autoAlpha || lookup.alpha) {
4633                                 copy = {};
4634                                 for (p in lookup) { //copy the lookup so that we're not changing the original which may be passed elsewhere.
4635                                         copy[p] = lookup[p];
4636                                 }
4637                                 copy.opacity = 1;
4638                                 if (copy.autoAlpha) {
4639                                         copy.visibility = 1;
4640                                 }
4641                         }
4642                         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".
4643                                 xfirst = pt.xfirst;
4644                                 if (xfirst && xfirst._prev) {
4645                                         this._linkCSSP(xfirst._prev, pt._next, xfirst._prev._prev); //break off the prev
4646                                 } else if (xfirst === this._firstPT) {
4647                                         this._firstPT = pt._next;
4648                                 }
4649                                 if (pt._next) {
4650                                         this._linkCSSP(pt._next, pt._next._next, xfirst._prev);
4651                                 }
4652                                 this._classNamePT = null;
4653                         }
4654                         return TweenPlugin.prototype._kill.call(this, copy);
4655                 };
4656
4657
4658
4659                 //used by cascadeTo() for gathering all the style properties of each child element into an array for comparison.
4660                 var _getChildStyles = function(e, props, targets) {
4661                                 var children, i, child, type;
4662                                 if (e.slice) {
4663                                         i = e.length;
4664                                         while (--i > -1) {
4665                                                 _getChildStyles(e[i], props, targets);
4666                                         }
4667                                         return;
4668                                 }
4669                                 children = e.childNodes;
4670                                 i = children.length;
4671                                 while (--i > -1) {
4672                                         child = children[i];
4673                                         type = child.type;
4674                                         if (child.style) {
4675                                                 props.push(_getAllStyles(child));
4676                                                 if (targets) {
4677                                                         targets.push(child);
4678                                                 }
4679                                         }
4680                                         if ((type === 1 || type === 9 || type === 11) && child.childNodes.length) {
4681                                                 _getChildStyles(child, props, targets);
4682                                         }
4683                                 }
4684                         };
4685
4686                 /**
4687                  * Typically only useful for className tweens that may affect child elements, this method creates a TweenLite
4688                  * and then compares the style properties of all the target's child elements at the tween's start and end, and
4689                  * if any are different, it also creates tweens for those and returns an array containing ALL of the resulting
4690                  * tweens (so that you can easily add() them to a TimelineLite, for example). The reason this functionality is
4691                  * wrapped into a separate static method of CSSPlugin instead of being integrated into all regular className tweens
4692                  * is because it creates entirely new tweens that may have completely different targets than the original tween,
4693                  * so if they were all lumped into the original tween instance, it would be inconsistent with the rest of the API
4694                  * and it would create other problems. For example:
4695                  *  - 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)
4696                  *  - 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.
4697                  *  - 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.
4698                  *
4699                  * @param {Object} target object to be tweened
4700                  * @param {number} Duration in seconds (or frames for frames-based tweens)
4701                  * @param {Object} Object containing the end values, like {className:"newClass", ease:Linear.easeNone}
4702                  * @return {Array} An array of TweenLite instances
4703                  */
4704                 CSSPlugin.cascadeTo = function(target, duration, vars) {
4705                         var tween = TweenLite.to(target, duration, vars),
4706                                 results = [tween],
4707                                 b = [],
4708                                 e = [],
4709                                 targets = [],
4710                                 _reservedProps = TweenLite._internals.reservedProps,
4711                                 i, difs, p;
4712                         target = tween._targets || tween.target;
4713                         _getChildStyles(target, b, targets);
4714                         tween.render(duration, true);
4715                         _getChildStyles(target, e);
4716                         tween.render(0, true);
4717                         tween._enabled(true);
4718                         i = targets.length;
4719                         while (--i > -1) {
4720                                 difs = _cssDif(targets[i], b[i], e[i]);
4721                                 if (difs.firstMPT) {
4722                                         difs = difs.difs;
4723                                         for (p in vars) {
4724                                                 if (_reservedProps[p]) {
4725                                                         difs[p] = vars[p];
4726                                                 }
4727                                         }
4728                                         results.push( TweenLite.to(targets[i], duration, difs) );
4729                                 }
4730                         }
4731                         return results;
4732                 };
4733
4734                 TweenPlugin.activate([CSSPlugin]);
4735                 return CSSPlugin;
4736
4737         }, true);
4738
4739         
4740         
4741         
4742         
4743         
4744         
4745         
4746         
4747         
4748         
4749 /*
4750  * ----------------------------------------------------------------
4751  * RoundPropsPlugin
4752  * ----------------------------------------------------------------
4753  */
4754         (function() {
4755
4756                 var RoundPropsPlugin = window._gsDefine.plugin({
4757                                 propName: "roundProps",
4758                                 priority: -1,
4759                                 API: 2,
4760
4761                                 //called when the tween renders for the first time. This is where initial values should be recorded and any setup routines should run.
4762                                 init: function(target, value, tween) {
4763                                         this._tween = tween;
4764                                         return true;
4765                                 }
4766
4767                         }),
4768                         p = RoundPropsPlugin.prototype;
4769
4770                 p._onInitAllProps = function() {
4771                         var tween = this._tween,
4772                                 rp = (tween.vars.roundProps instanceof Array) ? tween.vars.roundProps : tween.vars.roundProps.split(","),
4773                                 i = rp.length,
4774                                 lookup = {},
4775                                 rpt = tween._propLookup.roundProps,
4776                                 prop, pt, next;
4777                         while (--i > -1) {
4778                                 lookup[rp[i]] = 1;
4779                         }
4780                         i = rp.length;
4781                         while (--i > -1) {
4782                                 prop = rp[i];
4783                                 pt = tween._firstPT;
4784                                 while (pt) {
4785                                         next = pt._next; //record here, because it may get removed
4786                                         if (pt.pg) {
4787                                                 pt.t._roundProps(lookup, true);
4788                                         } else if (pt.n === prop) {
4789                                                 this._add(pt.t, prop, pt.s, pt.c);
4790                                                 //remove from linked list
4791                                                 if (next) {
4792                                                         next._prev = pt._prev;
4793                                                 }
4794                                                 if (pt._prev) {
4795                                                         pt._prev._next = next;
4796                                                 } else if (tween._firstPT === pt) {
4797                                                         tween._firstPT = next;
4798                                                 }
4799                                                 pt._next = pt._prev = null;
4800                                                 tween._propLookup[prop] = rpt;
4801                                         }
4802                                         pt = next;
4803                                 }
4804                         }
4805                         return false;
4806                 };
4807
4808                 p._add = function(target, p, s, c) {
4809                         this._addTween(target, p, s, s + c, p, true);
4810                         this._overwriteProps.push(p);
4811                 };
4812
4813         }());
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824 /*
4825  * ----------------------------------------------------------------
4826  * AttrPlugin
4827  * ----------------------------------------------------------------
4828  */
4829         window._gsDefine.plugin({
4830                 propName: "attr",
4831                 API: 2,
4832                 version: "0.3.2",
4833
4834                 //called when the tween renders for the first time. This is where initial values should be recorded and any setup routines should run.
4835                 init: function(target, value, tween) {
4836                         var p, start, end;
4837                         if (typeof(target.setAttribute) !== "function") {
4838                                 return false;
4839                         }
4840                         this._target = target;
4841                         this._proxy = {};
4842                         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.
4843                         this._end = {};
4844                         for (p in value) {
4845                                 this._start[p] = this._proxy[p] = start = target.getAttribute(p);
4846                                 end = this._addTween(this._proxy, p, parseFloat(start), value[p], p);
4847                                 this._end[p] = end ? end.s + end.c : value[p];
4848                                 this._overwriteProps.push(p);
4849                         }
4850                         return true;
4851                 },
4852
4853                 //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.)
4854                 set: function(ratio) {
4855                         this._super.setRatio.call(this, ratio);
4856                         var props = this._overwriteProps,
4857                                 i = props.length,
4858                                 lookup = (ratio === 1) ? this._end : ratio ? this._proxy : this._start,
4859                                 p;
4860                         while (--i > -1) {
4861                                 p = props[i];
4862                                 this._target.setAttribute(p, lookup[p] + "");
4863                         }
4864                 }
4865
4866         });
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877 /*
4878  * ----------------------------------------------------------------
4879  * DirectionalRotationPlugin
4880  * ----------------------------------------------------------------
4881  */
4882         window._gsDefine.plugin({
4883                 propName: "directionalRotation",
4884                 API: 2,
4885                 version: "0.2.0",
4886
4887                 //called when the tween renders for the first time. This is where initial values should be recorded and any setup routines should run.
4888                 init: function(target, value, tween) {
4889                         if (typeof(value) !== "object") {
4890                                 value = {rotation:value};
4891                         }
4892                         this.finals = {};
4893                         var cap = (value.useRadians === true) ? Math.PI * 2 : 360,
4894                                 min = 0.000001,
4895                                 p, v, start, end, dif, split;
4896                         for (p in value) {
4897                                 if (p !== "useRadians") {
4898                                         split = (value[p] + "").split("_");
4899                                         v = split[0];
4900                                         start = parseFloat( (typeof(target[p]) !== "function") ? target[p] : target[ ((p.indexOf("set") || typeof(target["get" + p.substr(3)]) !== "function") ? p : "get" + p.substr(3)) ]() );
4901                                         end = this.finals[p] = (typeof(v) === "string" && v.charAt(1) === "=") ? start + parseInt(v.charAt(0) + "1", 10) * Number(v.substr(2)) : Number(v) || 0;
4902                                         dif = end - start;
4903                                         if (split.length) {
4904                                                 v = split.join("_");
4905                                                 if (v.indexOf("short") !== -1) {
4906                                                         dif = dif % cap;
4907                                                         if (dif !== dif % (cap / 2)) {
4908                                                                 dif = (dif < 0) ? dif + cap : dif - cap;
4909                                                         }
4910                                                 }
4911                                                 if (v.indexOf("_cw") !== -1 && dif < 0) {
4912                                                         dif = ((dif + cap * 9999999999) % cap) - ((dif / cap) | 0) * cap;
4913                                                 } else if (v.indexOf("ccw") !== -1 && dif > 0) {
4914                                                         dif = ((dif - cap * 9999999999) % cap) - ((dif / cap) | 0) * cap;
4915                                                 }
4916                                         }
4917                                         if (dif > min || dif < -min) {
4918                                                 this._addTween(target, p, start, start + dif, p);
4919                                                 this._overwriteProps.push(p);
4920                                         }
4921                                 }
4922                         }
4923                         return true;
4924                 },
4925
4926                 //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.)
4927                 set: function(ratio) {
4928                         var pt;
4929                         if (ratio !== 1) {
4930                                 this._super.setRatio.call(this, ratio);
4931                         } else {
4932                                 pt = this._firstPT;
4933                                 while (pt) {
4934                                         if (pt.f) {
4935                                                 pt.t[pt.p](this.finals[pt.p]);
4936                                         } else {
4937                                                 pt.t[pt.p] = this.finals[pt.p];
4938                                         }
4939                                         pt = pt._next;
4940                                 }
4941                         }
4942                 }
4943
4944         })._autoCSS = true;
4945
4946
4947
4948
4949
4950
4951
4952         
4953         
4954         
4955         
4956 /*
4957  * ----------------------------------------------------------------
4958  * EasePack
4959  * ----------------------------------------------------------------
4960  */
4961         window._gsDefine("easing.Back", ["easing.Ease"], function(Ease) {
4962                 
4963                 var w = (window.GreenSockGlobals || window),
4964                         gs = w.com.greensock,
4965                         _2PI = Math.PI * 2,
4966                         _HALF_PI = Math.PI / 2,
4967                         _class = gs._class,
4968                         _create = function(n, f) {
4969                                 var C = _class("easing." + n, function(){}, true),
4970                                         p = C.prototype = new Ease();
4971                                 p.constructor = C;
4972                                 p.getRatio = f;
4973                                 return C;
4974                         },
4975                         _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.
4976                         _wrap = function(name, EaseOut, EaseIn, EaseInOut, aliases) {
4977                                 var C = _class("easing."+name, {
4978                                         easeOut:new EaseOut(),
4979                                         easeIn:new EaseIn(),
4980                                         easeInOut:new EaseInOut()
4981                                 }, true);
4982                                 _easeReg(C, name);
4983                                 return C;
4984                         },
4985                         EasePoint = function(time, value, next) {
4986                                 this.t = time;
4987                                 this.v = value;
4988                                 if (next) {
4989                                         this.next = next;
4990                                         next.prev = this;
4991                                         this.c = next.v - value;
4992                                         this.gap = next.t - time;
4993                                 }
4994                         },
4995
4996                         //Back
4997                         _createBack = function(n, f) {
4998                                 var C = _class("easing." + n, function(overshoot) {
4999                                                 this._p1 = (overshoot || overshoot === 0) ? overshoot : 1.70158;
5000                                                 this._p2 = this._p1 * 1.525;
5001                                         }, true),
5002                                         p = C.prototype = new Ease();
5003                                 p.constructor = C;
5004                                 p.getRatio = f;
5005                                 p.config = function(overshoot) {
5006                                         return new C(overshoot);
5007                                 };
5008                                 return C;
5009                         },
5010
5011                         Back = _wrap("Back",
5012                                 _createBack("BackOut", function(p) {
5013                                         return ((p = p - 1) * p * ((this._p1 + 1) * p + this._p1) + 1);
5014                                 }),
5015                                 _createBack("BackIn", function(p) {
5016                                         return p * p * ((this._p1 + 1) * p - this._p1);
5017                                 }),
5018                                 _createBack("BackInOut", function(p) {
5019                                         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);
5020                                 })
5021                         ),
5022
5023
5024                         //SlowMo
5025                         SlowMo = _class("easing.SlowMo", function(linearRatio, power, yoyoMode) {
5026                                 power = (power || power === 0) ? power : 0.7;
5027                                 if (linearRatio == null) {
5028                                         linearRatio = 0.7;
5029                                 } else if (linearRatio > 1) {
5030                                         linearRatio = 1;
5031                                 }
5032                                 this._p = (linearRatio !== 1) ? power : 0;
5033                                 this._p1 = (1 - linearRatio) / 2;
5034                                 this._p2 = linearRatio;
5035                                 this._p3 = this._p1 + this._p2;
5036                                 this._calcEnd = (yoyoMode === true);
5037                         }, true),
5038                         p = SlowMo.prototype = new Ease(),
5039                         SteppedEase, RoughEase, _createElastic;
5040
5041                 p.constructor = SlowMo;
5042                 p.getRatio = function(p) {
5043                         var r = p + (0.5 - p) * this._p;
5044                         if (p < this._p1) {
5045                                 return this._calcEnd ? 1 - ((p = 1 - (p / this._p1)) * p) : r - ((p = 1 - (p / this._p1)) * p * p * p * r);
5046                         } else if (p > this._p3) {
5047                                 return this._calcEnd ? 1 - (p = (p - this._p3) / this._p1) * p : r + ((p - r) * (p = (p - this._p3) / this._p1) * p * p * p);
5048                         }
5049                         return this._calcEnd ? 1 : r;
5050                 };
5051                 SlowMo.ease = new SlowMo(0.7, 0.7);
5052
5053                 p.config = SlowMo.config = function(linearRatio, power, yoyoMode) {
5054                         return new SlowMo(linearRatio, power, yoyoMode);
5055                 };
5056
5057
5058                 //SteppedEase
5059                 SteppedEase = _class("easing.SteppedEase", function(steps) {
5060                                 steps = steps || 1;
5061                                 this._p1 = 1 / steps;
5062                                 this._p2 = steps + 1;
5063                         }, true);
5064                 p = SteppedEase.prototype = new Ease();
5065                 p.constructor = SteppedEase;
5066                 p.getRatio = function(p) {
5067                         if (p < 0) {
5068                                 p = 0;
5069                         } else if (p >= 1) {
5070                                 p = 0.999999999;
5071                         }
5072                         return ((this._p2 * p) >> 0) * this._p1;
5073                 };
5074                 p.config = SteppedEase.config = function(steps) {
5075                         return new SteppedEase(steps);
5076                 };
5077
5078
5079                 //RoughEase
5080                 RoughEase = _class("easing.RoughEase", function(vars) {
5081                         vars = vars || {};
5082                         var taper = vars.taper || "none",
5083                                 a = [],
5084                                 cnt = 0,
5085                                 points = (vars.points || 20) | 0,
5086                                 i = points,
5087                                 randomize = (vars.randomize !== false),
5088                                 clamp = (vars.clamp === true),
5089                                 template = (vars.template instanceof Ease) ? vars.template : null,
5090                                 strength = (typeof(vars.strength) === "number") ? vars.strength * 0.4 : 0.4,
5091                                 x, y, bump, invX, obj, pnt;
5092                         while (--i > -1) {
5093                                 x = randomize ? Math.random() : (1 / points) * i;
5094                                 y = template ? template.getRatio(x) : x;
5095                                 if (taper === "none") {
5096                                         bump = strength;
5097                                 } else if (taper === "out") {
5098                                         invX = 1 - x;
5099                                         bump = invX * invX * strength;
5100                                 } else if (taper === "in") {
5101                                         bump = x * x * strength;
5102                                 } else if (x < 0.5) {  //"both" (start)
5103                                         invX = x * 2;
5104                                         bump = invX * invX * 0.5 * strength;
5105                                 } else {                                //"both" (end)
5106                                         invX = (1 - x) * 2;
5107                                         bump = invX * invX * 0.5 * strength;
5108                                 }
5109                                 if (randomize) {
5110                                         y += (Math.random() * bump) - (bump * 0.5);
5111                                 } else if (i % 2) {
5112                                         y += bump * 0.5;
5113                                 } else {
5114                                         y -= bump * 0.5;
5115                                 }
5116                                 if (clamp) {
5117                                         if (y > 1) {
5118                                                 y = 1;
5119                                         } else if (y < 0) {
5120                                                 y = 0;
5121                                         }
5122                                 }
5123                                 a[cnt++] = {x:x, y:y};
5124                         }
5125                         a.sort(function(a, b) {
5126                                 return a.x - b.x;
5127                         });
5128
5129                         pnt = new EasePoint(1, 1, null);
5130                         i = points;
5131                         while (--i > -1) {
5132                                 obj = a[i];
5133                                 pnt = new EasePoint(obj.x, obj.y, pnt);
5134                         }
5135
5136                         this._prev = new EasePoint(0, 0, (pnt.t !== 0) ? pnt : pnt.next);
5137                 }, true);
5138                 p = RoughEase.prototype = new Ease();
5139                 p.constructor = RoughEase;
5140                 p.getRatio = function(p) {
5141                         var pnt = this._prev;
5142                         if (p > pnt.t) {
5143                                 while (pnt.next && p >= pnt.t) {
5144                                         pnt = pnt.next;
5145                                 }
5146                                 pnt = pnt.prev;
5147                         } else {
5148                                 while (pnt.prev && p <= pnt.t) {
5149                                         pnt = pnt.prev;
5150                                 }
5151                         }
5152                         this._prev = pnt;
5153                         return (pnt.v + ((p - pnt.t) / pnt.gap) * pnt.c);
5154                 };
5155                 p.config = function(vars) {
5156                         return new RoughEase(vars);
5157                 };
5158                 RoughEase.ease = new RoughEase();
5159
5160
5161                 //Bounce
5162                 _wrap("Bounce",
5163                         _create("BounceOut", function(p) {
5164                                 if (p < 1 / 2.75) {
5165                                         return 7.5625 * p * p;
5166                                 } else if (p < 2 / 2.75) {
5167                                         return 7.5625 * (p -= 1.5 / 2.75) * p + 0.75;
5168                                 } else if (p < 2.5 / 2.75) {
5169                                         return 7.5625 * (p -= 2.25 / 2.75) * p + 0.9375;
5170                                 }
5171                                 return 7.5625 * (p -= 2.625 / 2.75) * p + 0.984375;
5172                         }),
5173                         _create("BounceIn", function(p) {
5174                                 if ((p = 1 - p) < 1 / 2.75) {
5175                                         return 1 - (7.5625 * p * p);
5176                                 } else if (p < 2 / 2.75) {
5177                                         return 1 - (7.5625 * (p -= 1.5 / 2.75) * p + 0.75);
5178                                 } else if (p < 2.5 / 2.75) {
5179                                         return 1 - (7.5625 * (p -= 2.25 / 2.75) * p + 0.9375);
5180                                 }
5181                                 return 1 - (7.5625 * (p -= 2.625 / 2.75) * p + 0.984375);
5182                         }),
5183                         _create("BounceInOut", function(p) {
5184                                 var invert = (p < 0.5);
5185                                 if (invert) {
5186                                         p = 1 - (p * 2);
5187                                 } else {
5188                                         p = (p * 2) - 1;
5189                                 }
5190                                 if (p < 1 / 2.75) {
5191                                         p = 7.5625 * p * p;
5192                                 } else if (p < 2 / 2.75) {
5193                                         p = 7.5625 * (p -= 1.5 / 2.75) * p + 0.75;
5194                                 } else if (p < 2.5 / 2.75) {
5195                                         p = 7.5625 * (p -= 2.25 / 2.75) * p + 0.9375;
5196                                 } else {
5197                                         p = 7.5625 * (p -= 2.625 / 2.75) * p + 0.984375;
5198                                 }
5199                                 return invert ? (1 - p) * 0.5 : p * 0.5 + 0.5;
5200                         })
5201                 );
5202
5203
5204                 //CIRC
5205                 _wrap("Circ",
5206                         _create("CircOut", function(p) {
5207                                 return Math.sqrt(1 - (p = p - 1) * p);
5208                         }),
5209                         _create("CircIn", function(p) {
5210                                 return -(Math.sqrt(1 - (p * p)) - 1);
5211                         }),
5212                         _create("CircInOut", function(p) {
5213                                 return ((p*=2) < 1) ? -0.5 * (Math.sqrt(1 - p * p) - 1) : 0.5 * (Math.sqrt(1 - (p -= 2) * p) + 1);
5214                         })
5215                 );
5216
5217
5218                 //Elastic
5219                 _createElastic = function(n, f, def) {
5220                         var C = _class("easing." + n, function(amplitude, period) {
5221                                         this._p1 = amplitude || 1;
5222                                         this._p2 = period || def;
5223                                         this._p3 = this._p2 / _2PI * (Math.asin(1 / this._p1) || 0);
5224                                 }, true),
5225                                 p = C.prototype = new Ease();
5226                         p.constructor = C;
5227                         p.getRatio = f;
5228                         p.config = function(amplitude, period) {
5229                                 return new C(amplitude, period);
5230                         };
5231                         return C;
5232                 };
5233                 _wrap("Elastic",
5234                         _createElastic("ElasticOut", function(p) {
5235                                 return this._p1 * Math.pow(2, -10 * p) * Math.sin( (p - this._p3) * _2PI / this._p2 ) + 1;
5236                         }, 0.3),
5237                         _createElastic("ElasticIn", function(p) {
5238                                 return -(this._p1 * Math.pow(2, 10 * (p -= 1)) * Math.sin( (p - this._p3) * _2PI / this._p2 ));
5239                         }, 0.3),
5240                         _createElastic("ElasticInOut", function(p) {
5241                                 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;
5242                         }, 0.45)
5243                 );
5244
5245
5246                 //Expo
5247                 _wrap("Expo",
5248                         _create("ExpoOut", function(p) {
5249                                 return 1 - Math.pow(2, -10 * p);
5250                         }),
5251                         _create("ExpoIn", function(p) {
5252                                 return Math.pow(2, 10 * (p - 1)) - 0.001;
5253                         }),
5254                         _create("ExpoInOut", function(p) {
5255                                 return ((p *= 2) < 1) ? 0.5 * Math.pow(2, 10 * (p - 1)) : 0.5 * (2 - Math.pow(2, -10 * (p - 1)));
5256                         })
5257                 );
5258
5259
5260                 //Sine
5261                 _wrap("Sine",
5262                         _create("SineOut", function(p) {
5263                                 return Math.sin(p * _HALF_PI);
5264                         }),
5265                         _create("SineIn", function(p) {
5266                                 return -Math.cos(p * _HALF_PI) + 1;
5267                         }),
5268                         _create("SineInOut", function(p) {
5269                                 return -0.5 * (Math.cos(Math.PI * p) - 1);
5270                         })
5271                 );
5272
5273                 _class("easing.EaseLookup", {
5274                                 find:function(s) {
5275                                         return Ease.map[s];
5276                                 }
5277                         }, true);
5278
5279                 //register the non-standard eases
5280                 _easeReg(w.SlowMo, "SlowMo", "ease,");
5281                 _easeReg(RoughEase, "RoughEase", "ease,");
5282                 _easeReg(SteppedEase, "SteppedEase", "ease,");
5283
5284                 return Back;
5285                 
5286         }, true);
5287
5288
5289 }); 
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301 /*
5302  * ----------------------------------------------------------------
5303  * Base classes like TweenLite, SimpleTimeline, Ease, Ticker, etc.
5304  * ----------------------------------------------------------------
5305  */
5306 (function(window) {
5307
5308                 "use strict";
5309                 var _globals = window.GreenSockGlobals || window;
5310                 if (_globals.TweenLite) {
5311                         return; //in case the core set of classes is already loaded, don't instantiate twice.
5312                 }
5313                 var _namespace = function(ns) {
5314                                 var a = ns.split("."),
5315                                         p = _globals, i;
5316                                 for (i = 0; i < a.length; i++) {
5317                                         p[a[i]] = p = p[a[i]] || {};
5318                                 }
5319                                 return p;
5320                         },
5321                         gs = _namespace("com.greensock"),
5322                         _tinyNum = 0.0000000001,
5323                         _slice = [].slice,
5324                         _emptyFunc = function() {},
5325                         _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)
5326                                 var toString = Object.prototype.toString,
5327                                         array = toString.call([]);
5328                                 return function(obj) {
5329                                         return obj != null && (obj instanceof Array || (typeof(obj) === "object" && !!obj.push && toString.call(obj) === array));
5330                                 };
5331                         }()),
5332                         a, i, p, _ticker, _tickerActive,
5333                         _defLookup = {},
5334
5335                         /**
5336                          * @constructor
5337                          * Defines a GreenSock class, optionally with an array of dependencies that must be instantiated first and passed into the definition.
5338                          * This allows users to load GreenSock JS files in any order even if they have interdependencies (like CSSPlugin extends TweenPlugin which is
5339                          * inside TweenLite.js, but if CSSPlugin is loaded first, it should wait to run its code until TweenLite.js loads and instantiates TweenPlugin
5340                          * and then pass TweenPlugin to CSSPlugin's definition). This is all done automatically and internally.
5341                          *
5342                          * Every definition will be added to a "com.greensock" global object (typically window, but if a window.GreenSockGlobals object is found,
5343                          * 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,
5344                          * it is ALSO referenced at window.TweenLite. However some classes aren't considered global, like the base com.greensock.core.Animation class, so
5345                          * those will only be at the package like window.com.greensock.core.Animation. Again, if you define a GreenSockGlobals object on the window, everything
5346                          * gets tucked neatly inside there instead of on the window directly. This allows you to do advanced things like load multiple versions of GreenSock
5347                          * 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
5348                          * sandbox the banner one like:
5349                          *
5350                          * <script>
5351                          *     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.
5352                          * </script>
5353                          * <script src="js/greensock/v1.7/TweenMax.js"></script>
5354                          * <script>
5355                          *     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(...)
5356                          * </script>
5357                          * <script src="js/greensock/v1.6/TweenMax.js"></script>
5358                          * <script>
5359                          *     gs.TweenLite.to(...); //would use v1.7
5360                          *     TweenLite.to(...); //would use v1.6
5361                          * </script>
5362                          *
5363                          * @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".
5364                          * @param {!Array.<string>} dependencies An array of dependencies (described as their namespaces minus "com.greensock." prefix). For example ["TweenLite","plugins.TweenPlugin","core.Animation"]
5365                          * @param {!function():Object} func The function that should be called and passed the resolved dependencies which will return the actual class for this definition.
5366                          * @param {boolean=} global If true, the class will be added to the global scope (typically window unless you define a window.GreenSockGlobals object)
5367                          */
5368                         Definition = function(ns, dependencies, func, global) {
5369                                 this.sc = (_defLookup[ns]) ? _defLookup[ns].sc : []; //subclasses
5370                                 _defLookup[ns] = this;
5371                                 this.gsClass = null;
5372                                 this.func = func;
5373                                 var _classes = [];
5374                                 this.check = function(init) {
5375                                         var i = dependencies.length,
5376                                                 missing = i,
5377                                                 cur, a, n, cl;
5378                                         while (--i > -1) {
5379                                                 if ((cur = _defLookup[dependencies[i]] || new Definition(dependencies[i], [])).gsClass) {
5380                                                         _classes[i] = cur.gsClass;
5381                                                         missing--;
5382                                                 } else if (init) {
5383                                                         cur.sc.push(this);
5384                                                 }
5385                                         }
5386                                         if (missing === 0 && func) {
5387                                                 a = ("com.greensock." + ns).split(".");
5388                                                 n = a.pop();
5389                                                 cl = _namespace(a.join("."))[n] = this.gsClass = func.apply(func, _classes);
5390
5391                                                 //exports to multiple environments
5392                                                 if (global) {
5393                                                         _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.)
5394                                                         if (typeof(define) === "function" && define.amd){ //AMD
5395                                                                 define((window.GreenSockAMDPath ? window.GreenSockAMDPath + "/" : "") + ns.split(".").join("/"), [], function() { return cl; });
5396                                                         } else if (typeof(module) !== "undefined" && module.exports){ //node
5397                                                                 module.exports = cl;
5398                                                         }
5399                                                 }
5400                                                 for (i = 0; i < this.sc.length; i++) {
5401                                                         this.sc[i].check();
5402                                                 }
5403                                         }
5404                                 };
5405                                 this.check(true);
5406                         },
5407
5408                         //used to create Definition instances (which basically registers a class that has dependencies).
5409                         _gsDefine = window._gsDefine = function(ns, dependencies, func, global) {
5410                                 return new Definition(ns, dependencies, func, global);
5411                         },
5412
5413                         //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).
5414                         _class = gs._class = function(ns, func, global) {
5415                                 func = func || function() {};
5416                                 _gsDefine(ns, [], function(){ return func; }, global);
5417                                 return func;
5418                         };
5419
5420                 _gsDefine.globals = _globals;
5421
5422
5423
5424 /*
5425  * ----------------------------------------------------------------
5426  * Ease
5427  * ----------------------------------------------------------------
5428  */
5429                 var _baseParams = [0, 0, 1, 1],
5430                         _blankArray = [],
5431                         Ease = _class("easing.Ease", function(func, extraParams, type, power) {
5432                                 this._func = func;
5433                                 this._type = type || 0;
5434                                 this._power = power || 0;
5435                                 this._params = extraParams ? _baseParams.concat(extraParams) : _baseParams;
5436                         }, true),
5437                         _easeMap = Ease.map = {},
5438                         _easeReg = Ease.register = function(ease, names, types, create) {
5439                                 var na = names.split(","),
5440                                         i = na.length,
5441                                         ta = (types || "easeIn,easeOut,easeInOut").split(","),
5442                                         e, name, j, type;
5443                                 while (--i > -1) {
5444                                         name = na[i];
5445                                         e = create ? _class("easing."+name, null, true) : gs.easing[name] || {};
5446                                         j = ta.length;
5447                                         while (--j > -1) {
5448                                                 type = ta[j];
5449                                                 _easeMap[name + "." + type] = _easeMap[type + name] = e[type] = ease.getRatio ? ease : ease[type] || new ease();
5450                                         }
5451                                 }
5452                         };
5453
5454                 p = Ease.prototype;
5455                 p._calcEnd = false;
5456                 p.getRatio = function(p) {
5457                         if (this._func) {
5458                                 this._params[0] = p;
5459                                 return this._func.apply(null, this._params);
5460                         }
5461                         var t = this._type,
5462                                 pw = this._power,
5463                                 r = (t === 1) ? 1 - p : (t === 2) ? p : (p < 0.5) ? p * 2 : (1 - p) * 2;
5464                         if (pw === 1) {
5465                                 r *= r;
5466                         } else if (pw === 2) {
5467                                 r *= r * r;
5468                         } else if (pw === 3) {
5469                                 r *= r * r * r;
5470                         } else if (pw === 4) {
5471                                 r *= r * r * r * r;
5472                         }
5473                         return (t === 1) ? 1 - r : (t === 2) ? r : (p < 0.5) ? r / 2 : 1 - (r / 2);
5474                 };
5475
5476                 //create all the standard eases like Linear, Quad, Cubic, Quart, Quint, Strong, Power0, Power1, Power2, Power3, and Power4 (each with easeIn, easeOut, and easeInOut)
5477                 a = ["Linear","Quad","Cubic","Quart","Quint,Strong"];
5478                 i = a.length;
5479                 while (--i > -1) {
5480                         p = a[i]+",Power"+i;
5481                         _easeReg(new Ease(null,null,1,i), p, "easeOut", true);
5482                         _easeReg(new Ease(null,null,2,i), p, "easeIn" + ((i === 0) ? ",easeNone" : ""));
5483                         _easeReg(new Ease(null,null,3,i), p, "easeInOut");
5484                 }
5485                 _easeMap.linear = gs.easing.Linear.easeIn;
5486                 _easeMap.swing = gs.easing.Quad.easeInOut; //for jQuery folks
5487
5488
5489 /*
5490  * ----------------------------------------------------------------
5491  * EventDispatcher
5492  * ----------------------------------------------------------------
5493  */
5494                 var EventDispatcher = _class("events.EventDispatcher", function(target) {
5495                         this._listeners = {};
5496                         this._eventTarget = target || this;
5497                 });
5498                 p = EventDispatcher.prototype;
5499
5500                 p.addEventListener = function(type, callback, scope, useParam, priority) {
5501                         priority = priority || 0;
5502                         var list = this._listeners[type],
5503                                 index = 0,
5504                                 listener, i;
5505                         if (list == null) {
5506                                 this._listeners[type] = list = [];
5507                         }
5508                         i = list.length;
5509                         while (--i > -1) {
5510                                 listener = list[i];
5511                                 if (listener.c === callback && listener.s === scope) {
5512                                         list.splice(i, 1);
5513                                 } else if (index === 0 && listener.pr < priority) {
5514                                         index = i + 1;
5515                                 }
5516                         }
5517                         list.splice(index, 0, {c:callback, s:scope, up:useParam, pr:priority});
5518                         if (this === _ticker && !_tickerActive) {
5519                                 _ticker.wake();
5520                         }
5521                 };
5522
5523                 p.removeEventListener = function(type, callback) {
5524                         var list = this._listeners[type], i;
5525                         if (list) {
5526                                 i = list.length;
5527                                 while (--i > -1) {
5528                                         if (list[i].c === callback) {
5529                                                 list.splice(i, 1);
5530                                                 return;
5531                                         }
5532                                 }
5533                         }
5534                 };
5535
5536                 p.dispatchEvent = function(type) {
5537                         var list = this._listeners[type],
5538                                 i, t, listener;
5539                         if (list) {
5540                                 i = list.length;
5541                                 t = this._eventTarget;
5542                                 while (--i > -1) {
5543                                         listener = list[i];
5544                                         if (listener.up) {
5545                                                 listener.c.call(listener.s || t, {type:type, target:t});
5546                                         } else {
5547                                                 listener.c.call(listener.s || t);
5548                                         }
5549                                 }
5550                         }
5551                 };
5552
5553
5554 /*
5555  * ----------------------------------------------------------------
5556  * Ticker
5557  * ----------------------------------------------------------------
5558  */
5559                 var _reqAnimFrame = window.requestAnimationFrame,
5560                         _cancelAnimFrame = window.cancelAnimationFrame,
5561                         _getTime = Date.now || function() {return new Date().getTime();},
5562                         _lastUpdate = _getTime();
5563
5564                 //now try to determine the requestAnimationFrame and cancelAnimationFrame functions and if none are found, we'll use a setTimeout()/clearTimeout() polyfill.
5565                 a = ["ms","moz","webkit","o"];
5566                 i = a.length;
5567                 while (--i > -1 && !_reqAnimFrame) {
5568                         _reqAnimFrame = window[a[i] + "RequestAnimationFrame"];
5569                         _cancelAnimFrame = window[a[i] + "CancelAnimationFrame"] || window[a[i] + "CancelRequestAnimationFrame"];
5570                 }
5571
5572                 _class("Ticker", function(fps, useRAF) {
5573                         var _self = this,
5574                                 _startTime = _getTime(),
5575                                 _useRAF = (useRAF !== false && _reqAnimFrame),
5576                                 _lagThreshold = 500,
5577                                 _adjustedLag = 33,
5578                                 _fps, _req, _id, _gap, _nextTime,
5579                                 _tick = function(manual) {
5580                                         var elapsed = _getTime() - _lastUpdate,
5581                                                 overlap, dispatch;
5582                                         if (elapsed > _lagThreshold) {
5583                                                 _startTime += elapsed - _adjustedLag;
5584                                         }
5585                                         _lastUpdate += elapsed;
5586                                         _self.time = (_lastUpdate - _startTime) / 1000;
5587                                         overlap = _self.time - _nextTime;
5588                                         if (!_fps || overlap > 0 || manual === true) {
5589                                                 _self.frame++;
5590                                                 _nextTime += overlap + (overlap >= _gap ? 0.004 : _gap - overlap);
5591                                                 dispatch = true;
5592                                         }
5593                                         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.
5594                                                 _id = _req(_tick);
5595                                         }
5596                                         if (dispatch) {
5597                                                 _self.dispatchEvent("tick");
5598                                         }
5599                                 };
5600
5601                         EventDispatcher.call(_self);
5602                         _self.time = _self.frame = 0;
5603                         _self.tick = function() {
5604                                 _tick(true);
5605                         };
5606
5607                         _self.lagSmoothing = function(threshold, adjustedLag) {
5608                                 _lagThreshold = threshold || (1 / _tinyNum); //zero should be interpreted as basically unlimited
5609                                 _adjustedLag = Math.min(adjustedLag, _lagThreshold, 0);
5610                         };
5611
5612                         _self.sleep = function() {
5613                                 if (_id == null) {
5614                                         return;
5615                                 }
5616                                 if (!_useRAF || !_cancelAnimFrame) {
5617                                         clearTimeout(_id);
5618                                 } else {
5619                                         _cancelAnimFrame(_id);
5620                                 }
5621                                 _req = _emptyFunc;
5622                                 _id = null;
5623                                 if (_self === _ticker) {
5624                                         _tickerActive = false;
5625                                 }
5626                         };
5627
5628                         _self.wake = function() {
5629                                 if (_id !== null) {
5630                                         _self.sleep();
5631                                 } 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().
5632                                         _lastUpdate = _getTime() - _lagThreshold + 5;
5633                                 }
5634                                 _req = (_fps === 0) ? _emptyFunc : (!_useRAF || !_reqAnimFrame) ? function(f) { return setTimeout(f, ((_nextTime - _self.time) * 1000 + 1) | 0); } : _reqAnimFrame;
5635                                 if (_self === _ticker) {
5636                                         _tickerActive = true;
5637                                 }
5638                                 _tick(2);
5639                         };
5640
5641                         _self.fps = function(value) {
5642                                 if (!arguments.length) {
5643                                         return _fps;
5644                                 }
5645                                 _fps = value;
5646                                 _gap = 1 / (_fps || 60);
5647                                 _nextTime = this.time + _gap;
5648                                 _self.wake();
5649                         };
5650
5651                         _self.useRAF = function(value) {
5652                                 if (!arguments.length) {
5653                                         return _useRAF;
5654                                 }
5655                                 _self.sleep();
5656                                 _useRAF = value;
5657                                 _self.fps(_fps);
5658                         };
5659                         _self.fps(fps);
5660
5661                         //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.
5662                         setTimeout(function() {
5663                                 if (_useRAF && (!_id || _self.frame < 5)) {
5664                                         _self.useRAF(false);
5665                                 }
5666                         }, 1500);
5667                 });
5668
5669                 p = gs.Ticker.prototype = new gs.events.EventDispatcher();
5670                 p.constructor = gs.Ticker;
5671
5672
5673 /*
5674  * ----------------------------------------------------------------
5675  * Animation
5676  * ----------------------------------------------------------------
5677  */
5678                 var Animation = _class("core.Animation", function(duration, vars) {
5679                                 this.vars = vars = vars || {};
5680                                 this._duration = this._totalDuration = duration || 0;
5681                                 this._delay = Number(vars.delay) || 0;
5682                                 this._timeScale = 1;
5683                                 this._active = (vars.immediateRender === true);
5684                                 this.data = vars.data;
5685                                 this._reversed = (vars.reversed === true);
5686
5687                                 if (!_rootTimeline) {
5688                                         return;
5689                                 }
5690                                 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.
5691                                         _ticker.wake();
5692                                 }
5693
5694                                 var tl = this.vars.useFrames ? _rootFramesTimeline : _rootTimeline;
5695                                 tl.add(this, tl._time);
5696
5697                                 if (this.vars.paused) {
5698                                         this.paused(true);
5699                                 }
5700                         });
5701
5702                 _ticker = Animation.ticker = new gs.Ticker();
5703                 p = Animation.prototype;
5704                 p._dirty = p._gc = p._initted = p._paused = false;
5705                 p._totalTime = p._time = 0;
5706                 p._rawPrevTime = -1;
5707                 p._next = p._last = p._onUpdate = p._timeline = p.timeline = null;
5708                 p._paused = false;
5709
5710
5711                 //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.
5712                 var _checkTimeout = function() {
5713                                 if (_tickerActive && _getTime() - _lastUpdate > 2000) {
5714                                         _ticker.wake();
5715                                 }
5716                                 setTimeout(_checkTimeout, 2000);
5717                         };
5718                 _checkTimeout();
5719
5720
5721                 p.play = function(from, suppressEvents) {
5722                         if (from != null) {
5723                                 this.seek(from, suppressEvents);
5724                         }
5725                         return this.reversed(false).paused(false);
5726                 };
5727
5728                 p.pause = function(atTime, suppressEvents) {
5729                         if (atTime != null) {
5730                                 this.seek(atTime, suppressEvents);
5731                         }
5732                         return this.paused(true);
5733                 };
5734
5735                 p.resume = function(from, suppressEvents) {
5736                         if (from != null) {
5737                                 this.seek(from, suppressEvents);
5738                         }
5739                         return this.paused(false);
5740                 };
5741
5742                 p.seek = function(time, suppressEvents) {
5743                         return this.totalTime(Number(time), suppressEvents !== false);
5744                 };
5745
5746                 p.restart = function(includeDelay, suppressEvents) {
5747                         return this.reversed(false).paused(false).totalTime(includeDelay ? -this._delay : 0, (suppressEvents !== false), true);
5748                 };
5749
5750                 p.reverse = function(from, suppressEvents) {
5751                         if (from != null) {
5752                                 this.seek((from || this.totalDuration()), suppressEvents);
5753                         }
5754                         return this.reversed(true).paused(false);
5755                 };
5756
5757                 p.render = function(time, suppressEvents, force) {
5758                         //stub - we override this method in subclasses.
5759                 };
5760
5761                 p.invalidate = function() {
5762                         return this;
5763                 };
5764
5765                 p.isActive = function() {
5766                         var tl = this._timeline, //the 2 root timelines won't have a _timeline; they're always active.
5767                                 startTime = this._startTime,
5768                                 rawTime;
5769                         return (!tl || (!this._gc && !this._paused && tl.isActive() && (rawTime = tl.rawTime()) >= startTime && rawTime < startTime + this.totalDuration() / this._timeScale));
5770                 };
5771
5772                 p._enabled = function (enabled, ignoreTimeline) {
5773                         if (!_tickerActive) {
5774                                 _ticker.wake();
5775                         }
5776                         this._gc = !enabled;
5777                         this._active = this.isActive();
5778                         if (ignoreTimeline !== true) {
5779                                 if (enabled && !this.timeline) {
5780                                         this._timeline.add(this, this._startTime - this._delay);
5781                                 } else if (!enabled && this.timeline) {
5782                                         this._timeline._remove(this, true);
5783                                 }
5784                         }
5785                         return false;
5786                 };
5787
5788
5789                 p._kill = function(vars, target) {
5790                         return this._enabled(false, false);
5791                 };
5792
5793                 p.kill = function(vars, target) {
5794                         this._kill(vars, target);
5795                         return this;
5796                 };
5797
5798                 p._uncache = function(includeSelf) {
5799                         var tween = includeSelf ? this : this.timeline;
5800                         while (tween) {
5801                                 tween._dirty = true;
5802                                 tween = tween.timeline;
5803                         }
5804                         return this;
5805                 };
5806
5807                 p._swapSelfInParams = function(params) {
5808                         var i = params.length,
5809                                 copy = params.concat();
5810                         while (--i > -1) {
5811                                 if (params[i] === "{self}") {
5812                                         copy[i] = this;
5813                                 }
5814                         }
5815                         return copy;
5816                 };
5817
5818 //----Animation getters/setters --------------------------------------------------------
5819
5820                 p.eventCallback = function(type, callback, params, scope) {
5821                         if ((type || "").substr(0,2) === "on") {
5822                                 var v = this.vars;
5823                                 if (arguments.length === 1) {
5824                                         return v[type];
5825                                 }
5826                                 if (callback == null) {
5827                                         delete v[type];
5828                                 } else {
5829                                         v[type] = callback;
5830                                         v[type + "Params"] = (_isArray(params) && params.join("").indexOf("{self}") !== -1) ? this._swapSelfInParams(params) : params;
5831                                         v[type + "Scope"] = scope;
5832                                 }
5833                                 if (type === "onUpdate") {
5834                                         this._onUpdate = callback;
5835                                 }
5836                         }
5837                         return this;
5838                 };
5839
5840                 p.delay = function(value) {
5841                         if (!arguments.length) {
5842                                 return this._delay;
5843                         }
5844                         if (this._timeline.smoothChildTiming) {
5845                                 this.startTime( this._startTime + value - this._delay );
5846                         }
5847                         this._delay = value;
5848                         return this;
5849                 };
5850
5851                 p.duration = function(value) {
5852                         if (!arguments.length) {
5853                                 this._dirty = false;
5854                                 return this._duration;
5855                         }
5856                         this._duration = this._totalDuration = value;
5857                         this._uncache(true); //true in case it's a TweenMax or TimelineMax that has a repeat - we'll need to refresh the totalDuration.
5858                         if (this._timeline.smoothChildTiming) if (this._time > 0) if (this._time < this._duration) if (value !== 0) {
5859                                 this.totalTime(this._totalTime * (value / this._duration), true);
5860                         }
5861                         return this;
5862                 };
5863
5864                 p.totalDuration = function(value) {
5865                         this._dirty = false;
5866                         return (!arguments.length) ? this._totalDuration : this.duration(value);
5867                 };
5868
5869                 p.time = function(value, suppressEvents) {
5870                         if (!arguments.length) {
5871                                 return this._time;
5872                         }
5873                         if (this._dirty) {
5874                                 this.totalDuration();
5875                         }
5876                         return this.totalTime((value > this._duration) ? this._duration : value, suppressEvents);
5877                 };
5878
5879                 p.totalTime = function(time, suppressEvents, uncapped) {
5880                         if (!_tickerActive) {
5881                                 _ticker.wake();
5882                         }
5883                         if (!arguments.length) {
5884                                 return this._totalTime;
5885                         }
5886                         if (this._timeline) {
5887                                 if (time < 0 && !uncapped) {
5888                                         time += this.totalDuration();
5889                                 }
5890                                 if (this._timeline.smoothChildTiming) {
5891                                         if (this._dirty) {
5892                                                 this.totalDuration();
5893                                         }
5894                                         var totalDuration = this._totalDuration,
5895                                                 tl = this._timeline;
5896                                         if (time > totalDuration && !uncapped) {
5897                                                 time = totalDuration;
5898                                         }
5899                                         this._startTime = (this._paused ? this._pauseTime : tl._time) - ((!this._reversed ? time : totalDuration - time) / this._timeScale);
5900                                         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.
5901                                                 this._uncache(false);
5902                                         }
5903                                         //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.
5904                                         if (tl._timeline) {
5905                                                 while (tl._timeline) {
5906                                                         if (tl._timeline._time !== (tl._startTime + tl._totalTime) / tl._timeScale) {
5907                                                                 tl.totalTime(tl._totalTime, true);
5908                                                         }
5909                                                         tl = tl._timeline;
5910                                                 }
5911                                         }
5912                                 }
5913                                 if (this._gc) {
5914                                         this._enabled(true, false);
5915                                 }
5916                                 if (this._totalTime !== time || this._duration === 0) {
5917                                         this.render(time, suppressEvents, false);
5918                                         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.
5919                                                 _lazyRender();
5920                                         }
5921                                 }
5922                         }
5923                         return this;
5924                 };
5925
5926                 p.progress = p.totalProgress = function(value, suppressEvents) {
5927                         return (!arguments.length) ? this._time / this.duration() : this.totalTime(this.duration() * value, suppressEvents);
5928                 };
5929
5930                 p.startTime = function(value) {
5931                         if (!arguments.length) {
5932                                 return this._startTime;
5933                         }
5934                         if (value !== this._startTime) {
5935                                 this._startTime = value;
5936                                 if (this.timeline) if (this.timeline._sortChildren) {
5937                                         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.
5938                                 }
5939                         }
5940                         return this;
5941                 };
5942
5943                 p.timeScale = function(value) {
5944                         if (!arguments.length) {
5945                                 return this._timeScale;
5946                         }
5947                         value = value || _tinyNum; //can't allow zero because it'll throw the math off
5948                         if (this._timeline && this._timeline.smoothChildTiming) {
5949                                 var pauseTime = this._pauseTime,
5950                                         t = (pauseTime || pauseTime === 0) ? pauseTime : this._timeline.totalTime();
5951                                 this._startTime = t - ((t - this._startTime) * this._timeScale / value);
5952                         }
5953                         this._timeScale = value;
5954                         return this._uncache(false);
5955                 };
5956
5957                 p.reversed = function(value) {
5958                         if (!arguments.length) {
5959                                 return this._reversed;
5960                         }
5961                         if (value != this._reversed) {
5962                                 this._reversed = value;
5963                                 this.totalTime(((this._timeline && !this._timeline.smoothChildTiming) ? this.totalDuration() - this._totalTime : this._totalTime), true);
5964                         }
5965                         return this;
5966                 };
5967
5968                 p.paused = function(value) {
5969                         if (!arguments.length) {
5970                                 return this._paused;
5971                         }
5972                         if (value != this._paused) if (this._timeline) {
5973                                 if (!_tickerActive && !value) {
5974                                         _ticker.wake();
5975                                 }
5976                                 var tl = this._timeline,
5977                                         raw = tl.rawTime(),
5978                                         elapsed = raw - this._pauseTime;
5979                                 if (!value && tl.smoothChildTiming) {
5980                                         this._startTime += elapsed;
5981                                         this._uncache(false);
5982                                 }
5983                                 this._pauseTime = value ? raw : null;
5984                                 this._paused = value;
5985                                 this._active = this.isActive();
5986                                 if (!value && elapsed !== 0 && this._initted && this.duration()) {
5987                                         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.
5988                                 }
5989                         }
5990                         if (this._gc && !value) {
5991                                 this._enabled(true, false);
5992                         }
5993                         return this;
5994                 };
5995
5996
5997 /*
5998  * ----------------------------------------------------------------
5999  * SimpleTimeline
6000  * ----------------------------------------------------------------
6001  */
6002                 var SimpleTimeline = _class("core.SimpleTimeline", function(vars) {
6003                         Animation.call(this, 0, vars);
6004                         this.autoRemoveChildren = this.smoothChildTiming = true;
6005                 });
6006
6007                 p = SimpleTimeline.prototype = new Animation();
6008                 p.constructor = SimpleTimeline;
6009                 p.kill()._gc = false;
6010                 p._first = p._last = null;
6011                 p._sortChildren = false;
6012
6013                 p.add = p.insert = function(child, position, align, stagger) {
6014                         var prevTween, st;
6015                         child._startTime = Number(position || 0) + child._delay;
6016                         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).
6017                                 child._pauseTime = child._startTime + ((this.rawTime() - child._startTime) / child._timeScale);
6018                         }
6019                         if (child.timeline) {
6020                                 child.timeline._remove(child, true); //removes from existing timeline so that it can be properly added to this one.
6021                         }
6022                         child.timeline = child._timeline = this;
6023                         if (child._gc) {
6024                                 child._enabled(true, true);
6025                         }
6026                         prevTween = this._last;
6027                         if (this._sortChildren) {
6028                                 st = child._startTime;
6029                                 while (prevTween && prevTween._startTime > st) {
6030                                         prevTween = prevTween._prev;
6031                                 }
6032                         }
6033                         if (prevTween) {
6034                                 child._next = prevTween._next;
6035                                 prevTween._next = child;
6036                         } else {
6037                                 child._next = this._first;
6038                                 this._first = child;
6039                         }
6040                         if (child._next) {
6041                                 child._next._prev = child;
6042                         } else {
6043                                 this._last = child;
6044                         }
6045                         child._prev = prevTween;
6046                         if (this._timeline) {
6047                                 this._uncache(true);
6048                         }
6049                         return this;
6050                 };
6051
6052                 p._remove = function(tween, skipDisable) {
6053                         if (tween.timeline === this) {
6054                                 if (!skipDisable) {
6055                                         tween._enabled(false, true);
6056                                 }
6057                                 tween.timeline = null;
6058
6059                                 if (tween._prev) {
6060                                         tween._prev._next = tween._next;
6061                                 } else if (this._first === tween) {
6062                                         this._first = tween._next;
6063                                 }
6064                                 if (tween._next) {
6065                                         tween._next._prev = tween._prev;
6066                                 } else if (this._last === tween) {
6067                                         this._last = tween._prev;
6068                                 }
6069
6070                                 if (this._timeline) {
6071                                         this._uncache(true);
6072                                 }
6073                         }
6074                         return this;
6075                 };
6076
6077                 p.render = function(time, suppressEvents, force) {
6078                         var tween = this._first,
6079                                 next;
6080                         this._totalTime = this._time = this._rawPrevTime = time;
6081                         while (tween) {
6082                                 next = tween._next; //record it here because the value could change after rendering...
6083                                 if (tween._active || (time >= tween._startTime && !tween._paused)) {
6084                                         if (!tween._reversed) {
6085                                                 tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force);
6086                                         } else {
6087                                                 tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force);
6088                                         }
6089                                 }
6090                                 tween = next;
6091                         }
6092                 };
6093
6094                 p.rawTime = function() {
6095                         if (!_tickerActive) {
6096                                 _ticker.wake();
6097                         }
6098                         return this._totalTime;
6099                 };
6100
6101 /*
6102  * ----------------------------------------------------------------
6103  * TweenLite
6104  * ----------------------------------------------------------------
6105  */
6106                 var TweenLite = _class("TweenLite", function(target, duration, vars) {
6107                                 Animation.call(this, duration, vars);
6108                                 this.render = TweenLite.prototype.render; //speed optimization (avoid prototype lookup on this "hot" method)
6109
6110                                 if (target == null) {
6111                                         throw "Cannot tween a null target.";
6112                                 }
6113
6114                                 this.target = target = (typeof(target) !== "string") ? target : TweenLite.selector(target) || target;
6115
6116                                 var isSelector = (target.jquery || (target.length && target !== window && target[0] && (target[0] === window || (target[0].nodeType && target[0].style && !target.nodeType)))),
6117                                         overwrite = this.vars.overwrite,
6118                                         i, targ, targets;
6119
6120                                 this._overwrite = overwrite = (overwrite == null) ? _overwriteLookup[TweenLite.defaultOverwrite] : (typeof(overwrite) === "number") ? overwrite >> 0 : _overwriteLookup[overwrite];
6121
6122                                 if ((isSelector || target instanceof Array || (target.push && _isArray(target))) && typeof(target[0]) !== "number") {
6123                                         this._targets = targets = _slice.call(target, 0);
6124                                         this._propLookup = [];
6125                                         this._siblings = [];
6126                                         for (i = 0; i < targets.length; i++) {
6127                                                 targ = targets[i];
6128                                                 if (!targ) {
6129                                                         targets.splice(i--, 1);
6130                                                         continue;
6131                                                 } else if (typeof(targ) === "string") {
6132                                                         targ = targets[i--] = TweenLite.selector(targ); //in case it's an array of strings
6133                                                         if (typeof(targ) === "string") {
6134                                                                 targets.splice(i+1, 1); //to avoid an endless loop (can't imagine why the selector would return a string, but just in case)
6135                                                         }
6136                                                         continue;
6137                                                 } 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.
6138                                                         targets.splice(i--, 1);
6139                                                         this._targets = targets = targets.concat(_slice.call(targ, 0));
6140                                                         continue;
6141                                                 }
6142                                                 this._siblings[i] = _register(targ, this, false);
6143                                                 if (overwrite === 1) if (this._siblings[i].length > 1) {
6144                                                         _applyOverwrite(targ, this, null, 1, this._siblings[i]);
6145                                                 }
6146                                         }
6147
6148                                 } else {
6149                                         this._propLookup = {};
6150                                         this._siblings = _register(target, this, false);
6151                                         if (overwrite === 1) if (this._siblings.length > 1) {
6152                                                 _applyOverwrite(target, this, null, 1, this._siblings);
6153                                         }
6154                                 }
6155                                 if (this.vars.immediateRender || (duration === 0 && this._delay === 0 && this.vars.immediateRender !== false)) {
6156                                         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)
6157                                         this.render(-this._delay);
6158                                 }
6159                         }, true),
6160                         _isSelector = function(v) {
6161                                 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.
6162                         },
6163                         _autoCSS = function(vars, target) {
6164                                 var css = {},
6165                                         p;
6166                                 for (p in vars) {
6167                                         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.
6168                                                 css[p] = vars[p];
6169                                                 delete vars[p];
6170                                         }
6171                                 }
6172                                 vars.css = css;
6173                         };
6174
6175                 p = TweenLite.prototype = new Animation();
6176                 p.constructor = TweenLite;
6177                 p.kill()._gc = false;
6178
6179 //----TweenLite defaults, overwrite management, and root updates ----------------------------------------------------
6180
6181                 p.ratio = 0;
6182                 p._firstPT = p._targets = p._overwrittenProps = p._startAt = null;
6183                 p._notifyPluginsOfEnabled = p._lazy = false;
6184
6185                 TweenLite.version = "1.12.1";
6186                 TweenLite.defaultEase = p._ease = new Ease(null, null, 1, 1);
6187                 TweenLite.defaultOverwrite = "auto";
6188                 TweenLite.ticker = _ticker;
6189                 TweenLite.autoSleep = true;
6190                 TweenLite.lagSmoothing = function(threshold, adjustedLag) {
6191                         _ticker.lagSmoothing(threshold, adjustedLag);
6192                 };
6193                 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; };
6194
6195                 var _lazyTweens = [],
6196                         _lazyLookup = {},
6197                         _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.
6198                         _plugins = TweenLite._plugins = {},
6199                         _tweenLookup = _internals.tweenLookup = {},
6200                         _tweenLookupNum = 0,
6201                         _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},
6202                         _overwriteLookup = {none:0, all:1, auto:2, concurrent:3, allOnStart:4, preexisting:5, "true":1, "false":0},
6203                         _rootFramesTimeline = Animation._rootFramesTimeline = new SimpleTimeline(),
6204                         _rootTimeline = Animation._rootTimeline = new SimpleTimeline(),
6205                         _lazyRender = function() {
6206                                 var i = _lazyTweens.length;
6207                                 _lazyLookup = {};
6208                                 while (--i > -1) {
6209                                         a = _lazyTweens[i];
6210                                         if (a && a._lazy !== false) {
6211                                                 a.render(a._lazy, false, true);
6212                                                 a._lazy = false;
6213                                         }
6214                                 }
6215                                 _lazyTweens.length = 0;
6216                         };
6217
6218                 _rootTimeline._startTime = _ticker.time;
6219                 _rootFramesTimeline._startTime = _ticker.frame;
6220                 _rootTimeline._active = _rootFramesTimeline._active = true;
6221                 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".
6222
6223                 Animation._updateRoot = TweenLite.render = function() {
6224                                 var i, a, p;
6225                                 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.
6226                                         _lazyRender();
6227                                 }
6228                                 _rootTimeline.render((_ticker.time - _rootTimeline._startTime) * _rootTimeline._timeScale, false, false);
6229                                 _rootFramesTimeline.render((_ticker.frame - _rootFramesTimeline._startTime) * _rootFramesTimeline._timeScale, false, false);
6230                                 if (_lazyTweens.length) {
6231                                         _lazyRender();
6232                                 }
6233                                 if (!(_ticker.frame % 120)) { //dump garbage every 120 frames...
6234                                         for (p in _tweenLookup) {
6235                                                 a = _tweenLookup[p].tweens;
6236                                                 i = a.length;
6237                                                 while (--i > -1) {
6238                                                         if (a[i]._gc) {
6239                                                                 a.splice(i, 1);
6240                                                         }
6241                                                 }
6242                                                 if (a.length === 0) {
6243                                                         delete _tweenLookup[p];
6244                                                 }
6245                                         }
6246                                         //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
6247                                         p = _rootTimeline._first;
6248                                         if (!p || p._paused) if (TweenLite.autoSleep && !_rootFramesTimeline._first && _ticker._listeners.tick.length === 1) {
6249                                                 while (p && p._paused) {
6250                                                         p = p._next;
6251                                                 }
6252                                                 if (!p) {
6253                                                         _ticker.sleep();
6254                                                 }
6255                                         }
6256                                 }
6257                         };
6258
6259                 _ticker.addEventListener("tick", Animation._updateRoot);
6260
6261                 var _register = function(target, tween, scrub) {
6262                                 var id = target._gsTweenID, a, i;
6263                                 if (!_tweenLookup[id || (target._gsTweenID = id = "t" + (_tweenLookupNum++))]) {
6264                                         _tweenLookup[id] = {target:target, tweens:[]};
6265                                 }
6266                                 if (tween) {
6267                                         a = _tweenLookup[id].tweens;
6268                                         a[(i = a.length)] = tween;
6269                                         if (scrub) {
6270                                                 while (--i > -1) {
6271                                                         if (a[i] === tween) {
6272                                                                 a.splice(i, 1);
6273                                                         }
6274                                                 }
6275                                         }
6276                                 }
6277                                 return _tweenLookup[id].tweens;
6278                         },
6279
6280                         _applyOverwrite = function(target, tween, props, mode, siblings) {
6281                                 var i, changed, curTween, l;
6282                                 if (mode === 1 || mode >= 4) {
6283                                         l = siblings.length;
6284                                         for (i = 0; i < l; i++) {
6285                                                 if ((curTween = siblings[i]) !== tween) {
6286                                                         if (!curTween._gc) if (curTween._enabled(false, false)) {
6287                                                                 changed = true;
6288                                                         }
6289                                                 } else if (mode === 5) {
6290                                                         break;
6291                                                 }
6292                                         }
6293                                         return changed;
6294                                 }
6295                                 //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)
6296                                 var startTime = tween._startTime + _tinyNum,
6297                                         overlaps = [],
6298                                         oCount = 0,
6299                                         zeroDur = (tween._duration === 0),
6300                                         globalStart;
6301                                 i = siblings.length;
6302                                 while (--i > -1) {
6303                                         if ((curTween = siblings[i]) === tween || curTween._gc || curTween._paused) {
6304                                                 //ignore
6305                                         } else if (curTween._timeline !== tween._timeline) {
6306                                                 globalStart = globalStart || _checkOverlap(tween, 0, zeroDur);
6307                                                 if (_checkOverlap(curTween, globalStart, zeroDur) === 0) {
6308                                                         overlaps[oCount++] = curTween;
6309                                                 }
6310                                         } else if (curTween._startTime <= startTime) if (curTween._startTime + curTween.totalDuration() / curTween._timeScale > startTime) if (!((zeroDur || !curTween._initted) && startTime - curTween._startTime <= 0.0000000002)) {
6311                                                 overlaps[oCount++] = curTween;
6312                                         }
6313                                 }
6314
6315                                 i = oCount;
6316                                 while (--i > -1) {
6317                                         curTween = overlaps[i];
6318                                         if (mode === 2) if (curTween._kill(props, target)) {
6319                                                 changed = true;
6320                                         }
6321                                         if (mode !== 2 || (!curTween._firstPT && curTween._initted)) {
6322                                                 if (curTween._enabled(false, false)) { //if all property tweens have been overwritten, kill the tween.
6323                                                         changed = true;
6324                                                 }
6325                                         }
6326                                 }
6327                                 return changed;
6328                         },
6329
6330                         _checkOverlap = function(tween, reference, zeroDur) {
6331                                 var tl = tween._timeline,
6332                                         ts = tl._timeScale,
6333                                         t = tween._startTime;
6334                                 while (tl._timeline) {
6335                                         t += tl._startTime;
6336                                         ts *= tl._timeScale;
6337                                         if (tl._paused) {
6338                                                 return -100;
6339                                         }
6340                                         tl = tl._timeline;
6341                                 }
6342                                 t /= ts;
6343                                 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;
6344                         };
6345
6346
6347 //---- TweenLite instance methods -----------------------------------------------------------------------------
6348
6349                 p._init = function() {
6350                         var v = this.vars,
6351                                 op = this._overwrittenProps,
6352                                 dur = this._duration,
6353                                 immediate = !!v.immediateRender,
6354                                 ease = v.ease,
6355                                 i, initPlugins, pt, p, startVars;
6356                         if (v.startAt) {
6357                                 if (this._startAt) {
6358                                         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.
6359                                         this._startAt.kill();
6360                                 }
6361                                 startVars = {};
6362                                 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);
6363                                         startVars[p] = v.startAt[p];
6364                                 }
6365                                 startVars.overwrite = false;
6366                                 startVars.immediateRender = true;
6367                                 startVars.lazy = (immediate && v.lazy !== false);
6368                                 startVars.startAt = startVars.delay = null; //no nesting of startAt objects allowed (otherwise it could cause an infinite loop).
6369                                 this._startAt = TweenLite.to(this.target, 0, startVars);
6370                                 if (immediate) {
6371                                         if (this._time > 0) {
6372                                                 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()).
6373                                         } else if (dur !== 0) {
6374                                                 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.
6375                                         }
6376                                 }
6377                         } else if (v.runBackwards && dur !== 0) {
6378                                 //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)
6379                                 if (this._startAt) {
6380                                         this._startAt.render(-1, true);
6381                                         this._startAt.kill();
6382                                         this._startAt = null;
6383                                 } else {
6384                                         pt = {};
6385                                         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.
6386                                                 if (!_reservedProps[p] || p === "autoCSS") {
6387                                                         pt[p] = v[p];
6388                                                 }
6389                                         }
6390                                         pt.overwrite = 0;
6391                                         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.
6392                                         pt.lazy = (immediate && v.lazy !== false);
6393                                         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)
6394                                         this._startAt = TweenLite.to(this.target, 0, pt);
6395                                         if (!immediate) {
6396                                                 this._startAt._init(); //ensures that the initial values are recorded
6397                                                 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.
6398                                         } else if (this._time === 0) {
6399                                                 return;
6400                                         }
6401                                 }
6402                         }
6403                         if (!ease) {
6404                                 this._ease = TweenLite.defaultEase;
6405                         } else if (ease instanceof Ease) {
6406                                 this._ease = (v.easeParams instanceof Array) ? ease.config.apply(ease, v.easeParams) : ease;
6407                         } else {
6408                                 this._ease = (typeof(ease) === "function") ? new Ease(ease, v.easeParams) : _easeMap[ease] || TweenLite.defaultEase;
6409                         }
6410                         this._easeType = this._ease._type;
6411                         this._easePower = this._ease._power;
6412                         this._firstPT = null;
6413
6414                         if (this._targets) {
6415                                 i = this._targets.length;
6416                                 while (--i > -1) {
6417                                         if ( this._initProps( this._targets[i], (this._propLookup[i] = {}), this._siblings[i], (op ? op[i] : null)) ) {
6418                                                 initPlugins = true;
6419                                         }
6420                                 }
6421                         } else {
6422                                 initPlugins = this._initProps(this.target, this._propLookup, this._siblings, op);
6423                         }
6424
6425                         if (initPlugins) {
6426                                 TweenLite._onPluginEvent("_onInitAllProps", this); //reorders the array in order of priority. Uses a static TweenPlugin method in order to minimize file size in TweenLite
6427                         }
6428                         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.
6429                                 this._enabled(false, false);
6430                         }
6431                         if (v.runBackwards) {
6432                                 pt = this._firstPT;
6433                                 while (pt) {
6434                                         pt.s += pt.c;
6435                                         pt.c = -pt.c;
6436                                         pt = pt._next;
6437                                 }
6438                         }
6439                         this._onUpdate = v.onUpdate;
6440                         this._initted = true;
6441                 };
6442
6443                 p._initProps = function(target, propLookup, siblings, overwrittenProps) {
6444                         var p, i, initPlugins, plugin, pt, v;
6445                         if (target == null) {
6446                                 return false;
6447                         }
6448
6449                         if (_lazyLookup[target._gsTweenID]) {
6450                                 _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)
6451                         }
6452
6453                         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.
6454                                 _autoCSS(this.vars, target);
6455                         }
6456                         for (p in this.vars) {
6457                                 v = this.vars[p];
6458                                 if (_reservedProps[p]) {
6459                                         if (v) if ((v instanceof Array) || (v.push && _isArray(v))) if (v.join("").indexOf("{self}") !== -1) {
6460                                                 this.vars[p] = v = this._swapSelfInParams(v, this);
6461                                         }
6462
6463                                 } else if (_plugins[p] && (plugin = new _plugins[p]())._onInitTween(target, this.vars[p], this)) {
6464
6465                                         //t - target            [object]
6466                                         //p - property          [string]
6467                                         //s - start                     [number]
6468                                         //c - change            [number]
6469                                         //f - isFunction        [boolean]
6470                                         //n - name                      [string]
6471                                         //pg - isPlugin         [boolean]
6472                                         //pr - priority         [number]
6473                                         this._firstPT = pt = {_next:this._firstPT, t:plugin, p:"setRatio", s:0, c:1, f:true, n:p, pg:true, pr:plugin._priority};
6474                                         i = plugin._overwriteProps.length;
6475                                         while (--i > -1) {
6476                                                 propLookup[plugin._overwriteProps[i]] = this._firstPT;
6477                                         }
6478                                         if (plugin._priority || plugin._onInitAllProps) {
6479                                                 initPlugins = true;
6480                                         }
6481                                         if (plugin._onDisable || plugin._onEnable) {
6482                                                 this._notifyPluginsOfEnabled = true;
6483                                         }
6484
6485                                 } else {
6486                                         this._firstPT = propLookup[p] = pt = {_next:this._firstPT, t:target, p:p, f:(typeof(target[p]) === "function"), n:p, pg:false, pr:0};
6487                                         pt.s = (!pt.f) ? parseFloat(target[p]) : target[ ((p.indexOf("set") || typeof(target["get" + p.substr(3)]) !== "function") ? p : "get" + p.substr(3)) ]();
6488                                         pt.c = (typeof(v) === "string" && v.charAt(1) === "=") ? parseInt(v.charAt(0) + "1", 10) * Number(v.substr(2)) : (Number(v) - pt.s) || 0;
6489                                 }
6490                                 if (pt) if (pt._next) {
6491                                         pt._next._prev = pt;
6492                                 }
6493                         }
6494
6495                         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)
6496                                 return this._initProps(target, propLookup, siblings, overwrittenProps);
6497                         }
6498                         if (this._overwrite > 1) if (this._firstPT) if (siblings.length > 1) if (_applyOverwrite(target, this, propLookup, this._overwrite, siblings)) {
6499                                 this._kill(propLookup, target);
6500                                 return this._initProps(target, propLookup, siblings, overwrittenProps);
6501                         }
6502                         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.
6503                                 _lazyLookup[target._gsTweenID] = true;
6504                         }
6505                         return initPlugins;
6506                 };
6507
6508                 p.render = function(time, suppressEvents, force) {
6509                         var prevTime = this._time,
6510                                 duration = this._duration,
6511                                 prevRawPrevTime = this._rawPrevTime,
6512                                 isComplete, callback, pt, rawPrevTime;
6513                         if (time >= duration) {
6514                                 this._totalTime = this._time = duration;
6515                                 this.ratio = this._ease._calcEnd ? this._ease.getRatio(1) : 1;
6516                                 if (!this._reversed ) {
6517                                         isComplete = true;
6518                                         callback = "onComplete";
6519                                 }
6520                                 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.
6521                                         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.
6522                                                 time = 0;
6523                                         }
6524                                         if (time === 0 || prevRawPrevTime < 0 || prevRawPrevTime === _tinyNum) if (prevRawPrevTime !== time) {
6525                                                 force = true;
6526                                                 if (prevRawPrevTime > _tinyNum) {
6527                                                         callback = "onReverseComplete";
6528                                                 }
6529                                         }
6530                                         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.
6531                                 }
6532
6533                         } else if (time < 0.0000001) { //to work around occasional floating point math artifacts, round super small values to 0.
6534                                 this._totalTime = this._time = 0;
6535                                 this.ratio = this._ease._calcEnd ? this._ease.getRatio(0) : 0;
6536                                 if (prevTime !== 0 || (duration === 0 && prevRawPrevTime > 0 && prevRawPrevTime !== _tinyNum)) {
6537                                         callback = "onReverseComplete";
6538                                         isComplete = this._reversed;
6539                                 }
6540                                 if (time < 0) {
6541                                         this._active = false;
6542                                         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.
6543                                                 if (prevRawPrevTime >= 0) {
6544                                                         force = true;
6545                                                 }
6546                                                 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.
6547                                         }
6548                                 } 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.
6549                                         force = true;
6550                                 }
6551                         } else {
6552                                 this._totalTime = this._time = time;
6553
6554                                 if (this._easeType) {
6555                                         var r = time / duration, type = this._easeType, pow = this._easePower;
6556                                         if (type === 1 || (type === 3 && r >= 0.5)) {
6557                                                 r = 1 - r;
6558                                         }
6559                                         if (type === 3) {
6560                                                 r *= 2;
6561                                         }
6562                                         if (pow === 1) {
6563                                                 r *= r;
6564                                         } else if (pow === 2) {
6565                                                 r *= r * r;
6566                                         } else if (pow === 3) {
6567                                                 r *= r * r * r;
6568                                         } else if (pow === 4) {
6569                                                 r *= r * r * r * r;
6570                                         }
6571
6572                                         if (type === 1) {
6573                                                 this.ratio = 1 - r;
6574                                         } else if (type === 2) {
6575                                                 this.ratio = r;
6576                                         } else if (time / duration < 0.5) {
6577                                                 this.ratio = r / 2;
6578                                         } else {
6579                                                 this.ratio = 1 - (r / 2);
6580                                         }
6581
6582                                 } else {
6583                                         this.ratio = this._ease.getRatio(time / duration);
6584                                 }
6585                         }
6586
6587                         if (this._time === prevTime && !force) {
6588                                 return;
6589                         } else if (!this._initted) {
6590                                 this._init();
6591                                 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.
6592                                         return;
6593                                 } else if (!force && this._firstPT && ((this.vars.lazy !== false && this._duration) || (this.vars.lazy && !this._duration))) {
6594                                         this._time = this._totalTime = prevTime;
6595                                         this._rawPrevTime = prevRawPrevTime;
6596                                         _lazyTweens.push(this);
6597                                         this._lazy = time;
6598                                         return;
6599                                 }
6600                                 //_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.
6601                                 if (this._time && !isComplete) {
6602                                         this.ratio = this._ease.getRatio(this._time / duration);
6603                                 } else if (isComplete && this._ease._calcEnd) {
6604                                         this.ratio = this._ease.getRatio((this._time === 0) ? 0 : 1);
6605                                 }
6606                         }
6607                         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.
6608                                 this._lazy = false;
6609                         }
6610                         if (!this._active) if (!this._paused && this._time !== prevTime && time >= 0) {
6611                                 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.
6612                         }
6613                         if (prevTime === 0) {
6614                                 if (this._startAt) {
6615                                         if (time >= 0) {
6616                                                 this._startAt.render(time, suppressEvents, force);
6617                                         } else if (!callback) {
6618                                                 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.
6619                                         }
6620                                 }
6621                                 if (this.vars.onStart) if (this._time !== 0 || duration === 0) if (!suppressEvents) {
6622                                         this.vars.onStart.apply(this.vars.onStartScope || this, this.vars.onStartParams || _blankArray);
6623                                 }
6624                         }
6625
6626                         pt = this._firstPT;
6627                         while (pt) {
6628                                 if (pt.f) {
6629                                         pt.t[pt.p](pt.c * this.ratio + pt.s);
6630                                 } else {
6631                                         pt.t[pt.p] = pt.c * this.ratio + pt.s;
6632                                 }
6633                                 pt = pt._next;
6634                         }
6635
6636                         if (this._onUpdate) {
6637                                 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.
6638                                         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.
6639                                 }
6640                                 if (!suppressEvents) if (this._time !== prevTime || isComplete) {
6641                                         this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray);
6642                                 }
6643                         }
6644
6645                         if (callback) if (!this._gc) { //check _gc because there's a chance that kill() could be called in an onUpdate
6646                                 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.
6647                                         this._startAt.render(time, suppressEvents, force);
6648                                 }
6649                                 if (isComplete) {
6650                                         if (this._timeline.autoRemoveChildren) {
6651                                                 this._enabled(false, false);
6652                                         }
6653                                         this._active = false;
6654                                 }
6655                                 if (!suppressEvents && this.vars[callback]) {
6656                                         this.vars[callback].apply(this.vars[callback + "Scope"] || this, this.vars[callback + "Params"] || _blankArray);
6657                                 }
6658                                 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.
6659                                         this._rawPrevTime = 0;
6660                                 }
6661                         }
6662
6663                 };
6664
6665                 p._kill = function(vars, target) {
6666                         if (vars === "all") {
6667                                 vars = null;
6668                         }
6669                         if (vars == null) if (target == null || target === this.target) {
6670                                 this._lazy = false;
6671                                 return this._enabled(false, false);
6672                         }
6673                         target = (typeof(target) !== "string") ? (target || this._targets || this.target) : TweenLite.selector(target) || target;
6674                         var i, overwrittenProps, p, pt, propLookup, changed, killProps, record;
6675                         if ((_isArray(target) || _isSelector(target)) && typeof(target[0]) !== "number") {
6676                                 i = target.length;
6677                                 while (--i > -1) {
6678                                         if (this._kill(vars, target[i])) {
6679                                                 changed = true;
6680                                         }
6681                                 }
6682                         } else {
6683                                 if (this._targets) {
6684                                         i = this._targets.length;
6685                                         while (--i > -1) {
6686                                                 if (target === this._targets[i]) {
6687                                                         propLookup = this._propLookup[i] || {};
6688                                                         this._overwrittenProps = this._overwrittenProps || [];
6689                                                         overwrittenProps = this._overwrittenProps[i] = vars ? this._overwrittenProps[i] || {} : "all";
6690                                                         break;
6691                                                 }
6692                                         }
6693                                 } else if (target !== this.target) {
6694                                         return false;
6695                                 } else {
6696                                         propLookup = this._propLookup;
6697                                         overwrittenProps = this._overwrittenProps = vars ? this._overwrittenProps || {} : "all";
6698                                 }
6699
6700                                 if (propLookup) {
6701                                         killProps = vars || propLookup;
6702                                         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)
6703                                         for (p in killProps) {
6704                                                 if ((pt = propLookup[p])) {
6705                                                         if (pt.pg && pt.t._kill(killProps)) {
6706                                                                 changed = true; //some plugins need to be notified so they can perform cleanup tasks first
6707                                                         }
6708                                                         if (!pt.pg || pt.t._overwriteProps.length === 0) {
6709                                                                 if (pt._prev) {
6710                                                                         pt._prev._next = pt._next;
6711                                                                 } else if (pt === this._firstPT) {
6712                                                                         this._firstPT = pt._next;
6713                                                                 }
6714                                                                 if (pt._next) {
6715                                                                         pt._next._prev = pt._prev;
6716                                                                 }
6717                                                                 pt._next = pt._prev = null;
6718                                                         }
6719                                                         delete propLookup[p];
6720                                                 }
6721                                                 if (record) {
6722                                                         overwrittenProps[p] = 1;
6723                                                 }
6724                                         }
6725                                         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.
6726                                                 this._enabled(false, false);
6727                                         }
6728                                 }
6729                         }
6730                         return changed;
6731                 };
6732
6733                 p.invalidate = function() {
6734                         if (this._notifyPluginsOfEnabled) {
6735                                 TweenLite._onPluginEvent("_onDisable", this);
6736                         }
6737                         this._firstPT = null;
6738                         this._overwrittenProps = null;
6739                         this._onUpdate = null;
6740                         this._startAt = null;
6741                         this._initted = this._active = this._notifyPluginsOfEnabled = this._lazy = false;
6742                         this._propLookup = (this._targets) ? {} : [];
6743                         return this;
6744                 };
6745
6746                 p._enabled = function(enabled, ignoreTimeline) {
6747                         if (!_tickerActive) {
6748                                 _ticker.wake();
6749                         }
6750                         if (enabled && this._gc) {
6751                                 var targets = this._targets,
6752                                         i;
6753                                 if (targets) {
6754                                         i = targets.length;
6755                                         while (--i > -1) {
6756                                                 this._siblings[i] = _register(targets[i], this, true);
6757                                         }
6758                                 } else {
6759                                         this._siblings = _register(this.target, this, true);
6760                                 }
6761                         }
6762                         Animation.prototype._enabled.call(this, enabled, ignoreTimeline);
6763                         if (this._notifyPluginsOfEnabled) if (this._firstPT) {
6764                                 return TweenLite._onPluginEvent((enabled ? "_onEnable" : "_onDisable"), this);
6765                         }
6766                         return false;
6767                 };
6768
6769
6770 //----TweenLite static methods -----------------------------------------------------
6771
6772                 TweenLite.to = function(target, duration, vars) {
6773                         return new TweenLite(target, duration, vars);
6774                 };
6775
6776                 TweenLite.from = function(target, duration, vars) {
6777                         vars.runBackwards = true;
6778                         vars.immediateRender = (vars.immediateRender != false);
6779                         return new TweenLite(target, duration, vars);
6780                 };
6781
6782                 TweenLite.fromTo = function(target, duration, fromVars, toVars) {
6783                         toVars.startAt = fromVars;
6784                         toVars.immediateRender = (toVars.immediateRender != false && fromVars.immediateRender != false);
6785                         return new TweenLite(target, duration, toVars);
6786                 };
6787
6788                 TweenLite.delayedCall = function(delay, callback, params, scope, useFrames) {
6789                         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});
6790                 };
6791
6792                 TweenLite.set = function(target, vars) {
6793                         return new TweenLite(target, 0, vars);
6794                 };
6795
6796                 TweenLite.getTweensOf = function(target, onlyActive) {
6797                         if (target == null) { return []; }
6798                         target = (typeof(target) !== "string") ? target : TweenLite.selector(target) || target;
6799                         var i, a, j, t;
6800                         if ((_isArray(target) || _isSelector(target)) && typeof(target[0]) !== "number") {
6801                                 i = target.length;
6802                                 a = [];
6803                                 while (--i > -1) {
6804                                         a = a.concat(TweenLite.getTweensOf(target[i], onlyActive));
6805                                 }
6806                                 i = a.length;
6807                                 //now get rid of any duplicates (tweens of arrays of objects could cause duplicates)
6808                                 while (--i > -1) {
6809                                         t = a[i];
6810                                         j = i;
6811                                         while (--j > -1) {
6812                                                 if (t === a[j]) {
6813                                                         a.splice(i, 1);
6814                                                 }
6815                                         }
6816                                 }
6817                         } else {
6818                                 a = _register(target).concat();
6819                                 i = a.length;
6820                                 while (--i > -1) {
6821                                         if (a[i]._gc || (onlyActive && !a[i].isActive())) {
6822                                                 a.splice(i, 1);
6823                                         }
6824                                 }
6825                         }
6826                         return a;
6827                 };
6828
6829                 TweenLite.killTweensOf = TweenLite.killDelayedCallsTo = function(target, onlyActive, vars) {
6830                         if (typeof(onlyActive) === "object") {
6831                                 vars = onlyActive; //for backwards compatibility (before "onlyActive" parameter was inserted)
6832                                 onlyActive = false;
6833                         }
6834                         var a = TweenLite.getTweensOf(target, onlyActive),
6835                                 i = a.length;
6836                         while (--i > -1) {
6837                                 a[i]._kill(vars, target);
6838                         }
6839                 };
6840
6841
6842
6843 /*
6844  * ----------------------------------------------------------------
6845  * 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)
6846  * ----------------------------------------------------------------
6847  */
6848                 var TweenPlugin = _class("plugins.TweenPlugin", function(props, priority) {
6849                                         this._overwriteProps = (props || "").split(",");
6850                                         this._propName = this._overwriteProps[0];
6851                                         this._priority = priority || 0;
6852                                         this._super = TweenPlugin.prototype;
6853                                 }, true);
6854
6855                 p = TweenPlugin.prototype;
6856                 TweenPlugin.version = "1.10.1";
6857                 TweenPlugin.API = 2;
6858                 p._firstPT = null;
6859
6860                 p._addTween = function(target, prop, start, end, overwriteProp, round) {
6861                         var c, pt;
6862                         if (end != null && (c = (typeof(end) === "number" || end.charAt(1) !== "=") ? Number(end) - start : parseInt(end.charAt(0) + "1", 10) * Number(end.substr(2)))) {
6863                                 this._firstPT = pt = {_next:this._firstPT, t:target, p:prop, s:start, c:c, f:(typeof(target[prop]) === "function"), n:overwriteProp || prop, r:round};
6864                                 if (pt._next) {
6865                                         pt._next._prev = pt;
6866                                 }
6867                                 return pt;
6868                         }
6869                 };
6870
6871                 p.setRatio = function(v) {
6872                         var pt = this._firstPT,
6873                                 min = 0.000001,
6874                                 val;
6875                         while (pt) {
6876                                 val = pt.c * v + pt.s;
6877                                 if (pt.r) {
6878                                         val = Math.round(val);
6879                                 } else if (val < min) if (val > -min) { //prevents issues with converting very small numbers to strings in the browser
6880                                         val = 0;
6881                                 }
6882                                 if (pt.f) {
6883                                         pt.t[pt.p](val);
6884                                 } else {
6885                                         pt.t[pt.p] = val;
6886                                 }
6887                                 pt = pt._next;
6888                         }
6889                 };
6890
6891                 p._kill = function(lookup) {
6892                         var a = this._overwriteProps,
6893                                 pt = this._firstPT,
6894                                 i;
6895                         if (lookup[this._propName] != null) {
6896                                 this._overwriteProps = [];
6897                         } else {
6898                                 i = a.length;
6899                                 while (--i > -1) {
6900                                         if (lookup[a[i]] != null) {
6901                                                 a.splice(i, 1);
6902                                         }
6903                                 }
6904                         }
6905                         while (pt) {
6906                                 if (lookup[pt.n] != null) {
6907                                         if (pt._next) {
6908                                                 pt._next._prev = pt._prev;
6909                                         }
6910                                         if (pt._prev) {
6911                                                 pt._prev._next = pt._next;
6912                                                 pt._prev = null;
6913                                         } else if (this._firstPT === pt) {
6914                                                 this._firstPT = pt._next;
6915                                         }
6916                                 }
6917                                 pt = pt._next;
6918                         }
6919                         return false;
6920                 };
6921
6922                 p._roundProps = function(lookup, value) {
6923                         var pt = this._firstPT;
6924                         while (pt) {
6925                                 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.
6926                                         pt.r = value;
6927                                 }
6928                                 pt = pt._next;
6929                         }
6930                 };
6931
6932                 TweenLite._onPluginEvent = function(type, tween) {
6933                         var pt = tween._firstPT,
6934                                 changed, pt2, first, last, next;
6935                         if (type === "_onInitAllProps") {
6936                                 //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.
6937                                 while (pt) {
6938                                         next = pt._next;
6939                                         pt2 = first;
6940                                         while (pt2 && pt2.pr > pt.pr) {
6941                                                 pt2 = pt2._next;
6942                                         }
6943                                         if ((pt._prev = pt2 ? pt2._prev : last)) {
6944                                                 pt._prev._next = pt;
6945                                         } else {
6946                                                 first = pt;
6947                                         }
6948                                         if ((pt._next = pt2)) {
6949                                                 pt2._prev = pt;
6950                                         } else {
6951                                                 last = pt;
6952                                         }
6953                                         pt = next;
6954                                 }
6955                                 pt = tween._firstPT = first;
6956                         }
6957                         while (pt) {
6958                                 if (pt.pg) if (typeof(pt.t[type]) === "function") if (pt.t[type]()) {
6959                                         changed = true;
6960                                 }
6961                                 pt = pt._next;
6962                         }
6963                         return changed;
6964                 };
6965
6966                 TweenPlugin.activate = function(plugins) {
6967                         var i = plugins.length;
6968                         while (--i > -1) {
6969                                 if (plugins[i].API === TweenPlugin.API) {
6970                                         _plugins[(new plugins[i]())._propName] = plugins[i];
6971                                 }
6972                         }
6973                         return true;
6974                 };
6975
6976                 //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.
6977                 _gsDefine.plugin = function(config) {
6978                         if (!config || !config.propName || !config.init || !config.API) { throw "illegal plugin definition."; }
6979                         var propName = config.propName,
6980                                 priority = config.priority || 0,
6981                                 overwriteProps = config.overwriteProps,
6982                                 map = {init:"_onInitTween", set:"setRatio", kill:"_kill", round:"_roundProps", initAll:"_onInitAllProps"},
6983                                 Plugin = _class("plugins." + propName.charAt(0).toUpperCase() + propName.substr(1) + "Plugin",
6984                                         function() {
6985                                                 TweenPlugin.call(this, propName, priority);
6986                                                 this._overwriteProps = overwriteProps || [];
6987                                         }, (config.global === true)),
6988                                 p = Plugin.prototype = new TweenPlugin(propName),
6989                                 prop;
6990                         p.constructor = Plugin;
6991                         Plugin.API = config.API;
6992                         for (prop in map) {
6993                                 if (typeof(config[prop]) === "function") {
6994                                         p[map[prop]] = config[prop];
6995                                 }
6996                         }
6997                         Plugin.version = config.version;
6998                         TweenPlugin.activate([Plugin]);
6999                         return Plugin;
7000                 };
7001
7002
7003                 //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.
7004                 a = window._gsQueue;
7005                 if (a) {
7006                         for (i = 0; i < a.length; i++) {
7007                                 a[i]();
7008                         }
7009                         for (p in _defLookup) {
7010                                 if (!_defLookup[p].func) {
7011                                         //window.console.log("GSAP encountered missing dependency: com.greensock." + p);
7012                                 }
7013                         }
7014                 }
7015
7016                 _tickerActive = false; //ensures that the first official animation forces a ticker.tick() to update the time when it is instantiated
7017
7018 })(window);
7019
7020 angular.module('att.abs.transition', [])
7021
7022 .factory('$transition', ['$q', '$timeout', '$rootScope', function($q, $timeout, $rootScope) {
7023
7024   var $transition = function(element, trigger, options) {
7025     options = options || {};
7026     var deferred = $q.defer();
7027     var endEventName = $transition[options.animation ? "animationEndEventName" : "transitionEndEventName"];
7028
7029     var transitionEndHandler = function() {
7030       $rootScope.$apply(function() {
7031         element.unbind(endEventName, transitionEndHandler);
7032         deferred.resolve(element);
7033       });
7034     };
7035
7036     if (endEventName) {
7037       element.bind(endEventName, transitionEndHandler);
7038     }
7039
7040     // Wrap in a timeout to allow the browser time to update the DOM before the transition is to occur
7041     $timeout(function() {
7042       if ( angular.isString(trigger) ) {
7043         element.addClass(trigger);
7044       } else if ( angular.isFunction(trigger) ) {
7045         trigger(element);
7046       } else if ( angular.isObject(trigger) ) {
7047         element.css(trigger);
7048       }
7049       //If browser does not support transitions, instantly resolve
7050       if ( !endEventName ) {
7051         deferred.resolve(element);
7052       }
7053     }, 100);
7054
7055     // Add our custom cancel function to the promise that is returned
7056     // We can call this if we are about to run a new transition, which we know will prevent this transition from ending,
7057     // i.e. it will therefore never raise a transitionEnd event for that transition
7058     deferred.promise.cancel = function() {
7059       if ( endEventName ) {
7060         element.unbind(endEventName, transitionEndHandler);
7061       }
7062       deferred.reject('Transition cancelled');
7063     };
7064
7065     return deferred.promise;
7066   };
7067
7068   // Work out the name of the transitionEnd event
7069   var transElement = document.createElement('trans');
7070   var transitionEndEventNames = {
7071     'WebkitTransition': 'webkitTransitionEnd',
7072     'MozTransition': 'transitionend',
7073     'OTransition': 'oTransitionEnd',
7074     'transition': 'transitionend'
7075   };
7076   var animationEndEventNames = {
7077     'WebkitTransition': 'webkitAnimationEnd',
7078     'MozTransition': 'animationend',
7079     'OTransition': 'oAnimationEnd',
7080     'transition': 'animationend'
7081   };
7082   function findEndEventName(endEventNames) {
7083     for (var name in endEventNames){
7084       if (transElement.style[name] !== undefined) {
7085         return endEventNames[name];
7086       }
7087     }
7088   }
7089   $transition.transitionEndEventName = findEndEventName(transitionEndEventNames);
7090   $transition.animationEndEventName = findEndEventName(animationEndEventNames);
7091   return $transition;
7092 }])
7093
7094 .factory('$scrollTo', ['$window', function($window) {
7095     var $scrollTo = function(offsetLeft, offsetTop, duration) {
7096         TweenMax.to($window, duration || 1, {scrollTo: {y: offsetTop, x: offsetLeft}, ease: Power4.easeOut});
7097     };
7098     return $scrollTo;
7099 }])
7100 .factory('animation', function(){
7101     return TweenMax;
7102 })
7103 .factory('$progressBar', function(){
7104
7105    //Provides a function to pass in code for closure purposes
7106    var loadingAnimationCreator = function(onUpdateCallback){
7107
7108       //Use closure to setup some resuable code
7109       var loadingAnimation = function(callback, duration){
7110           TweenMax.to({}, duration, {
7111               onUpdateParams: ["{self}"],
7112               onUpdate: onUpdateCallback,
7113               onComplete: callback
7114           });
7115       };
7116       //Returns a function that takes a callback function and a duration for the animation
7117       return (function(){
7118         return loadingAnimation;
7119       })();
7120     };
7121
7122   return loadingAnimationCreator;
7123 })
7124 .factory('$height', function(){
7125   var heightAnimation = function(element,duration,height,alpha){
7126     TweenMax.to(element,
7127       duration,
7128       {height:height, autoAlpha:alpha},
7129       0);
7130   };
7131   return heightAnimation;
7132 });
7133 angular.module('att.abs.accordion', ['att.abs.position', 'att.abs.transition'])
7134         .constant('accordionConfig', {
7135             closeOthers: false
7136         }).controller('AccordionController', ['$scope', '$attrs', 'accordionConfig', '$log',
7137     function ($scope, $attrs, accordionConfig, $log) {
7138         // This array keeps track of the accordion groups
7139         this.groups = [];
7140         this.index = -1;
7141         // Keep reference to user's scope to properly assign `is-open`
7142         this.scope = $scope;
7143         $scope.forceExpand = false;
7144         // Ensure that all the groups in this accordion are closed, unless close-others explicitly says not to
7145         this.closeOthers = function (openGroup) {
7146             var closeOthers = angular.isDefined($attrs.closeOthers) ? $scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers;
7147             if (closeOthers && !$scope.forceExpand) {
7148                 angular.forEach(this.groups, function (group) {
7149                     if (group !== openGroup) {
7150                         group.isOpen = false;
7151                     }
7152                 });
7153             }
7154             if (this.groups.indexOf(openGroup) === (this.groups.length - 1) && $scope.forceExpand) {
7155                 $scope.forceExpand = false;
7156             }
7157         };
7158         this.expandAll = function () {
7159             $scope.forceExpand = true;
7160             angular.forEach(this.groups, function (group) {
7161                 group.isOpen = true;
7162             });
7163         };
7164         this.collapseAll = function () {
7165             angular.forEach(this.groups, function (group) {
7166                 group.isOpen = false;
7167             });
7168         };
7169         /**function focus @param focusGroup */
7170         this.focus = function (focusGroup) {
7171             var self = this;
7172             angular.forEach(this.groups, function (group, index) {
7173                 if (group !== focusGroup) {
7174                     group.focused = false;
7175                 } else {
7176                     self.index = index;
7177                     group.focused = true;
7178                 }
7179             });
7180         };
7181         /** @param blurGroup*/
7182         this.blur = function (blurGroup) {
7183             blurGroup.focused = false;
7184             this.index = -1;
7185             $log.log("accordion.blur()", blurGroup);
7186         };
7187         /** @param group - the group in current focus @param down - cycling down */
7188         this.cycle = function (group, down, noRecycle) {
7189             if (!down) {
7190                 if (this.index <= 0 && !noRecycle) {
7191                     this.index = this.groups.length - 1;
7192                 } else {
7193                     this.index--;
7194                 }
7195             } else {
7196                 if (this.index === (this.groups.length - 1))
7197                 {
7198                     if (noRecycle) {
7199                         this.index = 0;
7200                         group.focused = false;
7201                         $scope.$apply();
7202                         return;
7203                     }
7204                     else
7205                     {
7206                         this.index = 0;
7207                     }
7208                 } else {
7209                     this.index++;
7210                 }
7211             }
7212
7213             group.focused = false;
7214             this.groups[this.index].setFocus = true;
7215             this.groups[this.index].focused = true;
7216             $scope.$apply();
7217         };
7218         // This is called from the accordion-group directive to add itself to the accordion
7219         this.addGroup = function (groupScope) {
7220             var that = this;
7221             groupScope.index = this.groups.length;
7222             groupScope.focused = false;
7223             this.groups.push(groupScope);
7224
7225             if(this.groups.length > 0){
7226                 this.index = 0;
7227             }
7228
7229             groupScope.$on('$destroy', function () {
7230                 that.removeGroup(groupScope);
7231             });
7232         };
7233         // This is called from the accordion-group directive when to remove itself
7234         this.removeGroup = function (group) {
7235             var index = this.groups.indexOf(group);
7236             if (index !== -1) {
7237                 this.groups.splice(this.groups.indexOf(group), 1);
7238             }
7239         };
7240     }])
7241 // The accordion directive simply sets up the directive controller and adds an accordion CSS class to itself element.
7242         .directive('accordion', function () {
7243             return {
7244                 restrict: 'EA',
7245                 controller: 'AccordionController',
7246                 transclude: true,
7247                 replace: false,
7248                 scope: {
7249                     cClass: '@css',
7250                     expandAll: "=?",
7251                     collapseAll: "=?"
7252                 },
7253                 template: '<div class="{{cClass}}" ng-transclude></div>',
7254                 link: function (scope, elem, attribute, ctrl) {
7255                     scope.$watch("expandAll", function (value) {
7256                         if (value) {
7257                             ctrl.expandAll();
7258                             scope.expandAll = false;
7259                         }
7260                     });
7261                     scope.$watch("collapseAll", function (value) {
7262                         if (value) {
7263                             ctrl.collapseAll();
7264                             scope.collapseAll = false;
7265                         }
7266                     });
7267                 }
7268             };
7269         })
7270 // The accordion-group directive indicates a block of html that will expand and collapse in an accordion
7271         .directive('accordionGroup', ['$parse', '$transition', '$scrollTo', '$timeout', '$log', function ($parse, $transition, $scrollTo, $timeout, $log) {
7272                 return {
7273                     // We need this directive to be inside an accordion
7274                     require: ['^accordion', 'accordionGroup'],
7275                     restrict: 'EA',
7276                     // It transcludes the contents of the directive into the template
7277                     transclude: true,
7278                     // The element containing the directive will be replaced with the template
7279                     replace: true,
7280                     templateUrl: 'app/scripts/ng_js_att_tpls/accordion/accordion.html',
7281                     scope: {
7282                         // Create an isolated scope and interpolate the heading attribute onto this scope
7283                         heading: '@',
7284                         isOpen: '=?'
7285                     },
7286                     controller: ['$scope', function ($scope)
7287                         {
7288                             $scope.showico = true;
7289                             this.setHeading = function (element)
7290                             {
7291                                 this.heading = element;
7292                                 $scope.showico = false;
7293                             };
7294                             this.isIsOpen = function ()
7295                             {
7296                                 return $scope.isOpen;
7297                             };
7298                         }],
7299                     link: function (scope, element, attrs, ctrl) {
7300                         var accordionCtrl = ctrl[0];
7301                         var accordionGroupCtrl = ctrl[1];
7302                         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};
7303                         //not a fix
7304                         var tab = element.children().eq(0);
7305
7306                         scope.setFocus = false;
7307
7308                         var handleKeydown = function (ev) {
7309                             var boolFlag = true;
7310                             switch (ev.keyCode)
7311                             {
7312                                 case keys.enter:
7313                                     ev.preventDefault();
7314                                     scope.toggle();
7315                                     scope.$apply();
7316                                     break;
7317                                 case keys.up:
7318                                 case keys.left:
7319                                     ev.preventDefault();
7320                                     accordionCtrl.cycle(scope, false);
7321                                     break;
7322                                 case keys.down:
7323                                 case keys.right:
7324                                     ev.preventDefault();
7325                                     accordionCtrl.cycle(scope, true);
7326                                     break;
7327                                 default:
7328                                     boolFlag = false;
7329                                     break;
7330                             }
7331                             ev.stopPropagation();
7332                             return boolFlag;
7333                         };
7334
7335                         if (angular.isUndefined(scope.isOpen)) {
7336                             scope.isOpen = false;
7337                         }
7338
7339                         tab.bind("keydown", handleKeydown);
7340
7341                         accordionCtrl.addGroup(scope);
7342
7343                         if (scope.index === 0) {
7344                             scope.focused = true;
7345                         }
7346
7347                         accordionGroupCtrl.toggle = scope.toggle = function () {
7348                             scope.isOpen = !scope.isOpen;
7349                             accordionCtrl.focus(scope);
7350                             return scope.isOpen;
7351                         };
7352
7353                         scope.$watch('isOpen', function (value) {
7354                             if (value) {
7355                                 accordionCtrl.closeOthers(scope);
7356                             }
7357                         });
7358
7359                         scope.$watch("focused", function (value) {
7360                             if (!!value) {
7361                                 tab.attr("tabindex", "0");
7362                                 if(scope.setFocus){
7363                                     tab[0].focus();
7364                                 }
7365                             }
7366                             else{
7367                                 scope.setFocus = false;
7368                                 tab.attr("tabindex", "-1");
7369                             }
7370                         });
7371                     }
7372                 };
7373             }])
7374 // Use accordion-heading below an accordion-group to provide a heading containing HTML
7375 // <accordion-group>
7376 //   <accordion-heading>Heading containing HTML - <img src="..."></accordion-heading>
7377 // </accordion-group>
7378         .directive('accordionToggle', function () {
7379             return{
7380                 restrict: 'EA',
7381                 require: '^accordionGroup',
7382                 scope: {
7383                     expandIcon: '@',
7384                     collapseIcon: '@'
7385                 },
7386                 link: function (scope, element, attr, accordionCtrl)
7387                 {
7388                     var setIcon = function (isOpen) {
7389                         if (scope.expandIcon && scope.collapseIcon)
7390                         {
7391                             if (isOpen) {
7392                                 element.removeClass(scope.expandIcon);
7393                                 element.addClass(scope.collapseIcon);
7394                             }
7395                             else {
7396                                 element.removeClass(scope.collapseIcon);
7397                                 element.addClass(scope.expandIcon);
7398                             }
7399                         }
7400                     };
7401                     element.bind('click', function ()
7402                     {
7403                         accordionCtrl.toggle();
7404                         scope.$apply();
7405                     });
7406                     scope.$watch(function () {
7407                         return accordionCtrl.isIsOpen();
7408                     }, function (value) {
7409                         setIcon(value);
7410                     });
7411                 }
7412             };
7413         }).directive('accordionHeading', function () {
7414     return {
7415         restrict: 'EA',
7416         transclude: true,
7417         template: '',
7418         require: '^accordionGroup',
7419         compile: function (element, attr, transclude) {
7420             var link = function (scope, element, attr, accordionGroupCtrl) {
7421                 // Pass the heading to the accordion-group controller
7422                 // so that it can be transcluded into the right place in the template
7423                 // [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat]
7424                 transclude(scope, function (clone) {
7425                     element.append(clone);
7426                     accordionGroupCtrl.setHeading(element);
7427                 });
7428             };
7429             return link;
7430         }
7431     };
7432 })
7433 // Use in the accordion-group template to indicate where you want the heading to be transcluded
7434 // You must provide the property on the accordion-group controller that will hold the transcluded element
7435         .directive('accordionTransclude', function () {
7436             return {
7437                 require: '^accordionGroup',
7438                 link: function (scope, element, attr, controller) {
7439                     scope.$watch(function () {
7440                         return controller[attr.accordionTransclude];
7441                     }, function (heading) {
7442                         if (heading) {
7443                             element.find("span").eq(0).prepend(heading);
7444                         }
7445                     });
7446                 }
7447             };
7448         })
7449         .directive('attGoTop', ['$scrollTo', function ($scrollTo) {
7450                 return {
7451                     restrict: 'A',
7452                     transclude: false,
7453                     link: function (scope, elem, attrs)
7454                     {
7455                         elem.bind('click', function ()
7456                         {
7457                             $scrollTo(0, attrs["attGoTop"]);
7458                         });
7459                     }
7460                 };
7461             }])
7462         .directive('attGoTo', ['$anchorScroll', '$location', function ($anchorScroll, $location) {
7463                 return {
7464                     restrict: 'A',
7465                     transclude: false,
7466                     link: function (scope, elem, attrs)
7467                     {
7468                         elem.bind('click', function ()
7469                         {
7470                             var newHash = attrs["attGoTo"];
7471                             if ($location.hash() !== newHash)
7472                             {
7473                                 $location.hash(attrs["attGoTo"]);
7474                             }
7475                             else
7476                             {
7477                                 $anchorScroll();
7478                             }
7479                         });
7480                     }
7481                 };
7482             }])
7483         .directive('freeStanding', function () {
7484             return {
7485                 restrict: 'EA',
7486                 transclude: true,
7487                 replace: true,
7488                 scope: true,
7489                 template: "<div><span class='att-accordion__freestanding' ng-show='showAccordion'></span>\n" +
7490                         "<div class='section-toggle'>\n" +
7491                         "<button class='section-toggle__button' ng-click='fsToggle()'>\n" +
7492                         "    {{btnText}}<i style='font-size:0.875rem' ng-class='{\"icon-chevron-up\": showAccordion,\"icon-chevron-down\": !showAccordion, }'></i> \n" +
7493                         "</button>\n" +
7494                         "</div></div>",
7495                 compile: function (element, attr, transclude)
7496                 {
7497                     var link = function (scope, elem, attrs) {
7498                         scope.content = "";
7499                         transclude(scope, function (clone)
7500                         {
7501                             elem.find("span").append(clone);
7502                         });
7503                         scope.showAccordion = false;
7504                         scope.btnText = scope.showAccordion ? attrs.hideMsg : attrs.showMsg;
7505                         scope.fsToggle = function ()
7506                         {
7507                             scope.showAccordion = !scope.showAccordion;
7508                             scope.btnText = scope.showAccordion ? attrs.hideMsg : attrs.showMsg;
7509                         };
7510                     };
7511                     return link;
7512                 }
7513             };
7514         }).directive('expanders', function () {
7515     return{
7516         restrict: 'EA',
7517         replace: true,
7518         transclude: true,
7519         template: "<div ng-transclude></div>",
7520         controller: [function () {
7521                 var bodyScope = null;
7522                 this.setScope = function (scope) {
7523                     bodyScope = scope;
7524                 };
7525                 this.toggle = function () {
7526                     bodyScope.isOpen = !bodyScope.isOpen;
7527                     return bodyScope.isOpen;
7528                 };
7529             }],
7530         link: function (scope, element)
7531         {
7532             scope.isOpen = false;
7533             element.bind('click', function ()
7534             {
7535                 scope.isOpen = !scope.isOpen;
7536             });
7537         }
7538     };
7539 }).directive('expanderHeading', function () {
7540     return{
7541         require: "^expanders",
7542         restrict: 'EA',
7543         replace: true,
7544         transclude: true,
7545         scope: true,
7546         template: "<div style='padding:10px !important' ng-transclude></div>"
7547     };
7548 }).directive('expanderBody', function () {
7549     return{
7550         restrict: 'EA',
7551         require: "^expanders",
7552         replace: true,
7553         transclude: true,
7554         scope: {},
7555         template: "<div collapse='!isOpen'><div ng-transclude></div></div>",
7556         link: function (scope, elem, attr, myCtrl) {
7557             scope.isOpen = false;
7558             myCtrl.setScope(scope);
7559         }
7560     };
7561 }).directive('expanderToggle', function () {
7562     return{
7563         restrict: 'EA',
7564         require: "^expanders",
7565         scope: {
7566             expandIcon: '@',
7567             collapseIcon: '@'
7568         },
7569         link: function (scope, element, attr, myCtrl)
7570         {
7571             var isOpen = false;
7572             var setIcon = function () {
7573                 if (scope.expandIcon && scope.collapseIcon)
7574                 {
7575                     if (isOpen) {
7576                         element.removeClass(scope.expandIcon);
7577                         element.addClass(scope.collapseIcon);
7578                     }
7579                     else {
7580                         element.removeClass(scope.collapseIcon);
7581                         element.addClass(scope.expandIcon);
7582                     }
7583                 }
7584             };
7585             element.bind("keydown", function (e) {
7586                 if (e.keyCode === 13)
7587                 {
7588                     scope.toggleit();
7589                 }
7590             });
7591             element.bind('click', function ()
7592             {
7593                 scope.toggleit();
7594             });
7595             scope.toggleit = function ()
7596             {
7597                 isOpen = myCtrl.toggle();
7598                 setIcon();
7599                 scope.$apply();
7600             };
7601             setIcon();
7602         }
7603     };
7604 }).directive('collapse', ['$transition', function ($transition) {
7605         // CSS transitions don't work with height: auto, so we have to manually change the height to a
7606         // specific value and then once the animation completes, we can reset the height to auto.
7607         // Unfortunately if you do this while the CSS transitions are specified (i.e. in the CSS class
7608         // "collapse") then you trigger a change to height 0 in between.
7609         // The fix is to remove the "collapse" CSS class while changing the height back to auto - phew!
7610         var props = {
7611             open: {
7612                 marginTop: null,
7613                 marginBottom: null,
7614                 paddingTop: null,
7615                 paddingBottom: null,
7616                 display: 'block'
7617             },
7618             closed: {
7619                 marginTop: 0,
7620                 marginBottom: 0,
7621                 paddingTop: 0,
7622                 paddingBottom: 0,
7623                 display: 'none'
7624             }
7625         };
7626         var fixUpHeight = function (scope, element, height) {
7627             // We remove the collapse CSS class to prevent a transition when we change to height: auto
7628             element.removeClass('collapse');
7629             element.css({height: height});
7630             //adjusting for any margin or padding
7631             if (height === 0) {
7632                 element.css(props.closed);
7633             } else {
7634                 element.css(props.open);
7635             }
7636             // It appears that  reading offsetWidth makes the browser realise that we have changed the
7637             // height already :-/
7638             element.addClass('collapse');
7639         };
7640         return {
7641             link: function (scope, element, attrs) {
7642                 var isCollapsed;
7643                 var initialAnimSkip = true;
7644                 scope.$watch(function () {
7645                     return element[0].scrollHeight;
7646                 }, function () {
7647                     //The listener is called when scrollHeight changes
7648                     //It actually does on 2 scenarios:
7649                     // 1. Parent is set to display none
7650                     // 2. angular bindings inside are resolved
7651                     //When we have a change of scrollHeight we are setting again the correct height if the group is opened
7652                     if (element[0].scrollHeight !== 0 && !isCollapsed) {
7653                         if (initialAnimSkip) {
7654                             fixUpHeight(scope, element, element[0].scrollHeight + 'px');
7655                         } else {
7656                             fixUpHeight(scope, element, 'auto');
7657                         }
7658                     }
7659                 });
7660                 var currentTransition;
7661                 var doTransition = function (change) {
7662                     if (currentTransition) {
7663                         currentTransition.cancel();
7664                     }
7665                     currentTransition = $transition(element, change);
7666                     currentTransition.then(
7667                             function () {
7668                                 currentTransition = undefined;
7669                             },
7670                             function () {
7671                                 currentTransition = undefined;
7672                             }
7673                     );
7674                     return currentTransition;
7675                 };
7676                 var expand = function () {
7677                     scope.postTransition = true;
7678                     if (initialAnimSkip) {
7679                         initialAnimSkip = false;
7680                         if (!isCollapsed) {
7681                             fixUpHeight(scope, element, 'auto');
7682                         }
7683                     } else {
7684                         doTransition(angular.extend({height: element[0].scrollHeight + 'px'}, props.open))
7685                                 .then(function () {
7686                                     // This check ensures that we don't accidentally update the height if the user has closed
7687                                     // the group while the animation was still running
7688                                     if (!isCollapsed)
7689                                     {
7690                                         fixUpHeight(scope, element, 'auto');
7691                                     }
7692                                 });
7693                     }
7694                     isCollapsed = false;
7695                 };
7696                 var collapse = function () {
7697                     isCollapsed = true;
7698                     if (initialAnimSkip) {
7699                         initialAnimSkip = false;
7700                         fixUpHeight(scope, element, 0);
7701                     } else {
7702                         fixUpHeight(scope, element, element[0].scrollHeight + 'px');
7703                         doTransition(angular.extend({height: 0}, props.closed)).then(function () {
7704                             scope.postTransition = false;
7705                         });
7706                     }
7707                 };
7708                 scope.$watch(attrs.collapse, function (value) {
7709                     if (value) {
7710                         collapse();
7711                     } else {
7712                         expand();
7713                     }
7714                 });
7715             }
7716         };
7717     }])
7718         .directive('attAccord', function () {
7719             return {
7720                 restrict: 'EA',
7721                 transclude: true,
7722                 replace: true,
7723                 scope: {},
7724                 controller: 'AttAccordCtrl',
7725                 templateUrl: 'app/scripts/ng_js_att_tpls/accordion/attAccordHeader.html'
7726             };
7727         })
7728         .controller('AttAccordCtrl', [function () {
7729                 this.type = 'attAccord';
7730                 this.headerCtrl;
7731                 this.bodyCtrl;
7732                 var isOpen = true;
7733                 this.toggleBody = function () {
7734                     if (isOpen) {
7735                         this.expandBody();
7736                     }
7737                     else {
7738                         this.collapseBody();
7739                     }
7740                     isOpen = !isOpen;
7741                 };
7742                 this.expandBody = function () {
7743                     this.bodyCtrl.expand();
7744                 };
7745                 this.collapseBody = function () {
7746                     this.bodyCtrl.collapse();
7747                 };
7748             }])
7749         .controller('AttAccordHeaderCtrl', [function () {
7750                 this.type = 'header';
7751             }])
7752         .directive('attAccordHeader', function () {
7753             return {
7754                 restrict: 'EA',
7755                 transclude: true,
7756                 replace: true,
7757                 require: ['^attAccord', 'attAccordHeader'],
7758                 controller: 'AttAccordHeaderCtrl',
7759                 templateUrl: 'app/scripts/ng_js_att_tpls/accordion/attAccordHeader.html',
7760                 link: function (scope, element, attr, ctrls) {
7761                     var attAccordCtrl = ctrls[0];
7762                     var attAccordHeaderCtrl = ctrls[1];
7763                     attAccordCtrl.headerCtrl = attAccordHeaderCtrl;
7764                     scope.clickFunc = function () {
7765                         attAccordCtrl.toggleBody();
7766                     };
7767                 }
7768             };
7769         })
7770         .controller('AttAccordBodyCtrl', ['$scope', function ($scope) {
7771                 this.type = 'body';
7772                 this.expand = function () {
7773                     $scope.expand();
7774                 };
7775                 this.collapse = function () {
7776                     $scope.collapse();
7777                 };
7778             }])
7779         .directive('attAccordBody', ['$timeout', '$height', function ($timeout, $height) {
7780                 return {
7781                     restrict: 'EA',
7782                     transclude: true,
7783                     replace: true,
7784                     require: ['^attAccord', 'attAccordBody'],
7785                     controller: 'AttAccordBodyCtrl',
7786                     templateUrl: 'app/scripts/ng_js_att_tpls/accordion/attAccordBody.html',
7787                     link: function (scope, element, attr, ctrls) {
7788                         var attAccordCtrl = ctrls[0];
7789                         var attAccordBodyCtrl = ctrls[1];
7790                         attAccordCtrl.bodyCtrl = attAccordBodyCtrl;
7791                         var originalHeight;
7792                         $timeout(function () {
7793                             originalHeight = element[0].offsetHeight;
7794                             $height(element, 0, 0, 0);
7795                         });
7796                         scope.expand = function () {
7797                             $height(element, 0.05, originalHeight, 1);
7798                         };
7799                         scope.collapse = function () {
7800                             $height(element, 0.25, 0, 0);
7801                         };
7802                     }
7803                 };
7804             }]);
7805 angular.module('att.abs.alert', [])
7806 .directive('attAlert', [function()
7807 {
7808     return {
7809         restrict:'EA',
7810         replace : true,
7811         transclude : true,
7812         scope: {
7813             alertType : "@type",
7814             showTop : "@topPos",
7815             showAlert : "="
7816         },
7817        templateUrl : 'app/scripts/ng_js_att_tpls/alert/alert.html',
7818        link: function(scope)
7819         {
7820             if(scope.showTop === 'true'){
7821                 scope.cssStyle = {'top':'50px'};
7822             }
7823             else{
7824                scope.cssStyle = {'top':'0px'};
7825             }
7826            scope.close = function(){
7827                scope.showAlert = false;
7828             };
7829         }
7830     };
7831 }]);
7832
7833 angular.module('att.abs.breadCrumbs', [])
7834     .constant("classConstant",{
7835             "defaultClass" : "breadcrumbs__link",
7836             "activeClass": "breadcrumbs__link--active"
7837         })
7838     .directive('attCrumb', ['classConstant', function(classConstant) {
7839         return {
7840             restrict: 'A',
7841             link: function(scope, elem, attr) {
7842                 elem.addClass(classConstant.defaultClass);
7843                 if(attr.attCrumb === 'active'){
7844                      elem.addClass(classConstant.activeClass);
7845                 }
7846                if(!elem.hasClass('last')){
7847                    elem.after('<i class="breadcrumbs__item"></i>');
7848                }
7849             }
7850         };
7851     }
7852 ]);
7853 angular.module('att.abs.utilities', [])
7854
7855 .filter('unsafe',[ '$sce', function ($sce) {    
7856     return function(val){
7857        return $sce.trustAsHtml(val);
7858     };
7859 }])
7860
7861 .filter('highlight', function () {
7862     function escapeRegexp(queryToEscape) {
7863         return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1');
7864     }
7865     return function (matchItem, query, className) {
7866         return query && matchItem ? matchItem.replace(new RegExp(escapeRegexp(query), 'gi'), '<span class=\"' + className + '\">$&</span>') : matchItem;
7867     };
7868 })
7869
7870 .filter('attLimitTo', function() {
7871     return function(actualArray, _limit, _begin) {
7872         var finalArray = [];
7873         var limit = _limit;
7874         var begin = _begin;
7875         if(isNaN(begin)) {
7876             begin = 0;
7877         }
7878         if(actualArray && !isNaN(limit)) {
7879             finalArray = actualArray.slice(begin, begin+limit);
7880         } else {
7881             finalArray = actualArray;
7882         }
7883         return finalArray;
7884     };
7885 })
7886
7887 .filter('startsWith', function() {
7888     if (typeof String.prototype.startsWith !== 'function') {
7889         // see below for better implementation!
7890         String.prototype.startsWith = function (str){
7891             return this.indexOf(str) === 0;
7892         };
7893     }
7894
7895     return function(items, searchString) {
7896         if (searchString === undefined || searchString === "") {
7897             return items;
7898         }
7899
7900         var filtered = [];
7901         angular.forEach(items, function(item) {
7902             if (item.title.toLowerCase().startsWith(searchString.toLowerCase())) {
7903                 filtered.push(item);
7904             }
7905         });
7906         return filtered;
7907     };
7908 })
7909
7910 .directive('attInputDeny', [function() {
7911     return {
7912         restrict: 'A',
7913         require: 'ngModel',
7914         link: function (scope, elem, attr, ctrl) {
7915             var regexExpression = null;
7916             attr.$observe('attInputDeny', function (value) {
7917                 if (value) {
7918                     regexExpression = new RegExp(value, 'g');
7919                 }
7920             });
7921             elem.bind('input', function () {
7922                 var inputString = ctrl.$viewValue && ctrl.$viewValue.replace(regexExpression, '');
7923                 if (inputString !== ctrl.$viewValue) {
7924                     ctrl.$setViewValue(inputString);
7925                     ctrl.$render();
7926                     scope.$apply();
7927                 }
7928             });
7929         }
7930     };
7931 }])
7932
7933 .directive('attAccessibilityClick', [function() {
7934     return {
7935         restrict: 'A',
7936         link: function (scope, elem, attr) {
7937             var keyCode = [];
7938             attr.$observe('attAccessibilityClick', function (value) {
7939                 if (value) {
7940                     keyCode = value.split(',');
7941                 }
7942             });
7943             elem.bind('keydown', function (ev) {
7944                 var keyCodeCondition = function(){
7945                     var flag = false;
7946                     if(!(ev.keyCode)){
7947                         if(ev.which){
7948                             ev.keyCode = ev.which;
7949                         }
7950                         else if(ev.charCode){
7951                             ev.keyCode = ev.charCode;
7952                         }
7953                     }
7954                     if((ev.keyCode && keyCode.indexOf(ev.keyCode.toString()) > -1)){
7955                         flag = true;
7956                     }
7957                     return flag;
7958                 };
7959                 if(keyCode.length > 0 && keyCodeCondition()) {
7960                     elem[0].click();
7961                     ev.preventDefault();
7962                 }
7963             });
7964         }
7965     };
7966 }]).directive('attElementFocus', [function() {
7967     return {
7968         restrict: 'A',
7969         link: function(scope, elem, attr) {
7970             scope.$watch(attr.attElementFocus, function (value) {
7971                 if (value) {
7972                     elem[0].focus();
7973                 }
7974             });
7975         }
7976     };
7977 }])
7978
7979 .factory('events', function(){
7980     var s =  function(e){
7981         if(e.stopPropagation) {
7982             e.stopPropagation();
7983         } else {
7984             e.returnValue = false;
7985         }
7986     };
7987     return {
7988         stopPropagation: s
7989     };
7990 })
7991
7992 .factory('$documentBind', ['$document', '$timeout', function($document, $timeout) {
7993     var _click = function (flag, callbackFunc, scope) {
7994         scope.$watch(flag, function (val) {
7995             $timeout(function () {
7996                 if (val) {
7997                     $document.bind('click', callbackFunc);
7998                 } else {
7999                     $document.unbind('click', callbackFunc);
8000                 }
8001             });
8002         });
8003     };
8004
8005     return {
8006         click: _click
8007     };
8008 }])
8009
8010 .factory('keymap', function(){        
8011     return {       
8012         KEY:{
8013         TAB: 9,
8014         ENTER: 13,
8015         ESC: 27,
8016         SPACE: 32,
8017         LEFT: 37,
8018         UP: 38,
8019         RIGHT: 39,
8020         DOWN: 40,
8021         SHIFT: 16,
8022         CTRL: 17,
8023         ALT: 18,
8024         PAGE_UP: 33,
8025         PAGE_DOWN: 34,
8026         HOME: 36,
8027         END: 35,
8028         BACKSPACE: 8,
8029         DELETE: 46,
8030         COMMAND: 91
8031         },        
8032         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 : "'"
8033         },
8034         isControl: function (e) {
8035             var k = e.keyCode;
8036             switch (k) {
8037             case this.KEY.COMMAND:
8038             case this.KEY.SHIFT:
8039             case this.KEY.CTRL:
8040             case this.KEY.ALT:
8041                 return true;
8042             default:;
8043             }
8044
8045             if (e.metaKey) {
8046                 return true;
8047             }
8048
8049             return false;
8050         },
8051         isFunctionKey: function (k) {
8052             k = k.keyCode ? k.keyCode : k;
8053             return k >= 112 && k <= 123;
8054         },
8055         isVerticalMovement: function (k){
8056           return ~[this.KEY.UP, this.KEY.DOWN].indexOf(k);
8057         },
8058         isHorizontalMovement: function (k){
8059           return ~[this.KEY.LEFT, this.KEY.RIGHT, this.KEY.BACKSPACE, this.KEY.DELETE].indexOf(k);
8060         },
8061         isAllowedKey: function (k){
8062           return (~[this.KEY.SPACE, this.KEY.ESC, this.KEY.ENTER].indexOf(k)) || this.isHorizontalMovement(k) || this.isVerticalMovement(k);
8063         }               
8064     };
8065 });
8066
8067
8068 (function () {
8069     String.prototype.toSnakeCase = function () {
8070         return this.replace(/([A-Z])/g, function ($1) {
8071             return "-" + $1.toLowerCase();
8072         });
8073     };
8074     var concat = function (character, times) {
8075         character = character || '';
8076         times = (!isNaN(times) && times) || 0;
8077         var finalChar = '';
8078         for (var i = 0; i < times; i++) {
8079             finalChar += character;
8080         }
8081         return finalChar;
8082     };
8083
8084     // direction: true for left and false for right
8085     var pad = function (actualString, width, character, direction) {
8086         actualString = actualString || '';
8087         width = (!isNaN(width) && width) || 0;
8088         character = character || '';
8089         direction = (direction !== undefined && direction) || true;
8090         if (width > actualString.length) {
8091             if (direction) {
8092                 return concat(character, (width - actualString.length)) + actualString;
8093             } else {
8094                 return actualString + concat(character, (width - actualString.length));
8095             }
8096         }
8097         return actualString;
8098     };
8099
8100     String.prototype.lPad = function (width, character) {
8101         return pad(this, width, character, true);
8102     };
8103
8104     String.prototype.rPad = function (width, character) {
8105         return pad(this, width, character, false);
8106     };
8107
8108     if (!Array.prototype.indexOf) {
8109         Array.prototype.indexOf = function (val) {
8110             for (var index = 0; index < this.length; index++) {
8111                 if (this[index] === val) {
8112                     return index;
8113                 }
8114             }
8115             return -1;
8116         };
8117     }
8118 })();
8119
8120 angular.module('att.abs.buttons', ['att.abs.position', 'att.abs.utilities'])
8121         .constant('btnConfig', {
8122             btnClass: 'button',
8123             btnPrimaryClass: 'button--primary',
8124             btnSecondaryClass: 'button--secondary',
8125             btnDisabledClass: 'button--inactive',
8126             btnSmallClass: 'button--small'
8127         })
8128         .directive('attButton', ['btnConfig', function (btnConfig) {
8129                 return {
8130                     restrict: 'A',
8131                     link: function (scope, element, attrs) {
8132                         element.addClass(btnConfig.btnClass);
8133                         if (attrs.size === 'small') {
8134                             element.addClass(btnConfig.btnSmallClass);
8135                         }
8136                         attrs.$observe('btnType', function (value) {
8137                             if (value === 'primary') {
8138                                 element.addClass(btnConfig.btnPrimaryClass);
8139                                 element.removeClass(btnConfig.btnSecondaryClass);
8140                                 element.removeClass(btnConfig.btnDisabledClass);
8141                                 element.removeAttr('disabled');
8142                             } else if (value === 'secondary') {
8143                                 element.addClass(btnConfig.btnSecondaryClass);
8144                                 element.removeClass(btnConfig.btnPrimaryClass);
8145                                 element.removeClass(btnConfig.btnDisabledClass);
8146                                 element.removeAttr('disabled');
8147                             } else if (value === 'disabled') {
8148                                 element.addClass(btnConfig.btnDisabledClass);
8149                                 element.removeClass(btnConfig.btnPrimaryClass);
8150                                 element.removeClass(btnConfig.btnSecondaryClass);
8151                                 element.attr('disabled', 'disabled');
8152                             }
8153                         });
8154                     }
8155                 };
8156             }])
8157         .directive('attButtonLoader', [function () {
8158                 return {
8159                     restrict: 'A',
8160                     replace: false,
8161                     scope: {
8162                         size: '@'
8163                     },
8164                     template: '<div ng-class="{\'button--loading\': size === \'large\',\'button--loading__small\': size === \'small\'}"><i></i><i></i><i></i></div>',
8165                     link: function (scope, element) {
8166                         element.addClass('button button--inactive');
8167                     }
8168                 };
8169             }])
8170         .directive('attButtonHero', [function () {
8171                 return {
8172                     restrict: 'A',
8173                     replace: false,
8174                     transclude: true,
8175                     scope: {
8176                         icon: '@'
8177                     },
8178                     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>',
8179                     link: function (scope, element) {
8180                         element.addClass('button button--hero');
8181                         element.attr("tabindex", "0");
8182                     }
8183                 };
8184             }])
8185         .directive('attBtnDropdown', ['$document', '$isElement', '$documentBind', function ($document, $isElement, $documentBind) {
8186                 return {
8187                     restrict: 'EA',
8188                     scope: {
8189                         type: "@dropdowntype"
8190                     },
8191                     replace: true,
8192                     transclude: true,
8193                     template: '<div class="att-btn-dropdown"> <div class="buttons-dropdown--small btn-group" ng-class="{\'open\': isOpen}" ng-click="toggleDropdown()"> <button class="button button--secondary button--small buttons-dropdown__drop dropdown-toggle ng-isolate-scope" ng-if="type==\'dots\'"> <div class="circle" ng-click="toggleDropdownCircle()"></div> <div class="circle" ng-click="toggleDropdownCircle()"></div> <div class="circle" ng-click="toggleDropdownCircle()"></div> </button> <button class="button button--secondary button--small buttons-dropdown__drop dropdown-toggle ng-isolate-scope actions-title" ng-if="type==\'actions\'"> Actions </button> <ul ng-class="{\'dropdown-menu dots-dropdwn\':type==\'dots\', \'dropdown-menu actions-dropdwn\':type==\'actions\'}" role="menu"  ng-transclude></ul></div></div>',
8194                     link: function (scope, element) {
8195                         scope.isOpen = false;
8196                         var toggle = scope.toggle = function (show) {
8197                             if (show === undefined || show === '') {
8198                                 scope.isOpen = !scope.isOpen;
8199                             }
8200                             else {
8201                                 scope.isOpen = show;
8202                             }
8203                         };
8204                         scope.toggleDropdownCircle = function () {
8205                             toggle(false);
8206                         };
8207                         scope.toggleDropdown = function () {
8208                             toggle();
8209                         };
8210                         var outsideClick = function (e) {
8211                             var isElement = $isElement(angular.element(e.target), element, $document);
8212                             if (!isElement) {
8213                                 toggle(false);
8214                                 scope.$apply();
8215                             }
8216                         };
8217                         $documentBind.click('isOpen', outsideClick, scope);
8218                     }
8219                 };
8220             }]);
8221
8222 angular.module('att.abs.checkbox', [])
8223 .constant("attCheckboxConfig", {
8224     activeClass : "att-checkbox--on",
8225     disabledClass : "att-checkbox--disabled"
8226 })
8227 .directive('checkboxLimit', function () {
8228 return {
8229     scope: {
8230         checkboxLimit:'=',
8231         selectLimit:'@?',
8232         maxSelected:'&?'
8233     },
8234     restrict: 'A',
8235     require:'checkboxLimit',
8236     controller: ['$scope',function($scope)
8237     {
8238         $scope.limit=true;
8239         this.getMaxLimits=function(){
8240             return $scope.limit;
8241         };
8242         this.setMaxLimits=function(value){
8243             $scope.limit=value;
8244         };
8245         this.maxCheckboxSelected=function(){
8246             $scope.maxSelected();
8247         };
8248     }],
8249     link: function (scope, element, attribute, ctrl) {
8250         scope.$watch('checkboxLimit', function()
8251         {
8252             var countTrue = 0;
8253             for (var keys in scope.checkboxLimit) {
8254                 if (scope.checkboxLimit.hasOwnProperty(keys) && scope.checkboxLimit[keys]) {
8255                         countTrue = countTrue + 1;
8256                 }
8257             };
8258             if(countTrue>=parseInt(scope.selectLimit)){
8259                 ctrl.setMaxLimits(false);
8260             }
8261             else{
8262                 ctrl.setMaxLimits(true);
8263             }
8264             }, true);
8265     }
8266 };
8267 })
8268 .directive('attCheckbox', ['$compile', "attCheckboxConfig", function ($compile, attCheckboxConfig) {
8269     return {
8270         scope: {},
8271         restrict: 'A',
8272         require: ['ngModel','^?checkboxLimit'],
8273         link: function (scope, element, attribute, ctrl) {
8274             var ngCtrl = ctrl[0];
8275             var checkboxLimitCtrl = ctrl[1];
8276             var parentDiv = $compile('<div tabindex="0" role="checkbox" att-accessibility-click="13,32" ng-click="updateModel($event)" class="att-checkbox"></div>')(scope);
8277             element.css({display:'none'});
8278             element.wrap(parentDiv);
8279             element.parent().append('<div class="att-checkbox__indicator"></div>');
8280             element.parent().attr("title", attribute.title);
8281             element.parent().attr("id", attribute.id);
8282             element.removeAttr("id");
8283             //model -> UI
8284             ngCtrl.$render = function () {
8285                 var selected = ngCtrl.$modelValue ? true : false;
8286                 element.parent().toggleClass(attCheckboxConfig.activeClass, selected);
8287                 element.parent().attr("aria-checked", selected);
8288             };
8289
8290             //ui->model
8291             scope.updateModel = function (evt) {
8292                 if (!scope.disabled) {
8293                     ngCtrl.$setViewValue(element.parent().hasClass(attCheckboxConfig.activeClass) ? false : true);
8294                     if(checkboxLimitCtrl && !(checkboxLimitCtrl.getMaxLimits())){
8295                         if(!ngCtrl.$modelValue){
8296                             ngCtrl.$render();
8297                         }
8298                         else{
8299                             checkboxLimitCtrl.maxCheckboxSelected();
8300                             ngCtrl.$setViewValue(element.parent().hasClass(attCheckboxConfig.activeClass) ? true : false);
8301                         }
8302                     }
8303                     else{
8304                         ngCtrl.$render();
8305                     }
8306                 }
8307                 evt.preventDefault();
8308             };
8309
8310             attribute.$observe('disabled', function(val) {
8311                 scope.disabled = (val || val === "disabled" || val === "true");
8312                 element.parent().toggleClass(attCheckboxConfig.disabledClass, scope.disabled);
8313                 element.parent().attr("tabindex", scope.disabled ? "-1" : "0");
8314             });
8315         }
8316     };
8317 }])
8318 .directive('checkboxGroup', ['$compile',function($compile) {
8319     return {
8320         scope:{
8321             checkboxGroup: "=",
8322             checkboxGroupValue: "=?"
8323         },
8324         restrict: 'A',
8325         link: function(scope, element, attribute){
8326                 scope.checkboxState = 'none';
8327                 scope.checkboxGroupValue="indeterminate";
8328                 element.css({display:'none'});
8329                 element.wrap($compile('<div tabindex="0" role="checkbox" att-accessibility-click="13,32" ng-click="updateModel($event)" class="att-checkbox"></div>')(scope));
8330                 element.parent().append('<div class="att-checkbox__indicator"></div>');
8331                 element.parent().attr("title", attribute.title);
8332                 scope.$watch('checkboxState', function(val) {
8333                     if (val === 'all') {
8334                         element.parent().addClass('att-checkbox--on');
8335                         element.parent().removeClass('att-checkbox--indeterminate');
8336                         element.parent().attr("aria-checked", true);
8337                     }
8338                     else if (val === 'none') {
8339                         element.parent().removeClass('att-checkbox--on');
8340                         element.parent().removeClass('att-checkbox--indeterminate');
8341                         element.parent().attr("aria-checked", false);
8342                     }
8343                     else if (val === 'indeterminate') {
8344                         element.parent().removeClass('att-checkbox--on');
8345                         element.parent().addClass('att-checkbox--indeterminate');
8346                         element.parent().attr("aria-checked", true);
8347                     }
8348                 });
8349                 scope.updateModel = function(evt){
8350                     if (element.parent().hasClass('att-checkbox--on')) {
8351                             element.parent().removeClass('att-checkbox--on');
8352                             for (var keys in scope.checkboxGroup) {
8353                                 if (scope.checkboxGroup.hasOwnProperty(keys)) {
8354                                     scope.checkboxGroup[keys] = false;
8355                                 }
8356                             };
8357                             }
8358                     else {
8359                         element.parent().addClass('att-checkbox--on');
8360                         for (var key in scope.checkboxGroup) {
8361                             if (scope.checkboxGroup.hasOwnProperty(key)) {
8362                                 scope.checkboxGroup[key] = true;
8363                             }
8364                         };
8365                     }
8366                     evt.preventDefault();
8367                 };
8368                 scope.$watch('checkboxGroupValue', function (value) {
8369                     if (value==="false") {
8370                             element.parent().removeClass('att-checkbox--on');
8371                             for (var keys in scope.checkboxGroup) {
8372                                 if (scope.checkboxGroup.hasOwnProperty(keys)) {
8373                                         scope.checkboxGroup[keys] = false;
8374                                 }
8375                             };
8376                             }
8377                     else if (value === "true"){
8378                         element.parent().addClass('att-checkbox--on');
8379                         for (var key in scope.checkboxGroup) {
8380                             if (scope.checkboxGroup.hasOwnProperty(key)) {
8381                                     scope.checkboxGroup[key] = true;
8382                             }
8383                         };
8384                     }
8385                 });
8386             scope.$watch('checkboxGroup', function(){
8387                 var countTrue = 0;
8388                 var countFalse = 0;
8389                 var count = 0;
8390                 for (var keys in scope.checkboxGroup) {
8391                     if (scope.checkboxGroup.hasOwnProperty(keys)) {
8392                         count = count + 1;
8393                         if (scope.checkboxGroup[keys]) {
8394                             countTrue = countTrue + 1;
8395                         }
8396                         else if (!scope.checkboxGroup[keys]) {
8397                             countFalse = countFalse + 1;
8398                         }
8399                     }
8400                 };
8401                 if (count === countTrue) {
8402                     scope.checkboxState = "all";
8403                      scope.checkboxGroupValue="true";
8404                 }
8405                 else if (count === countFalse) {
8406                     scope.checkboxState = "none";
8407                     scope.checkboxGroupValue="false";
8408                 }
8409                 else {
8410                     scope.checkboxState = "indeterminate";
8411                     scope.checkboxGroupValue="indeterminate";
8412                 }
8413                 }, true);
8414         }
8415     };
8416 }]);
8417
8418 angular.module('att.abs.colorselector', [])
8419     .directive('colorSelectorWrapper', [function() {
8420         return {
8421             scope: {
8422                 selected: '=',
8423                 iconColor: '@'
8424             },
8425             restrict: 'AE',
8426             transclude: true,
8427             templateUrl: 'app/scripts/ng_js_att_tpls/colorselector/colorselector.html',
8428             link: function(scope) {
8429                 scope.applycolor = {'background-color': scope.iconColor};
8430                 scope.selectedcolor = function(iconColor) {
8431                     scope.selected = iconColor;
8432                 };
8433             }
8434         };
8435      }])
8436     .directive('colorSelector', ['$compile', function($compile) {
8437         return{
8438             restrict: 'A',
8439             scope: {
8440                 colorSelector: '@',
8441                 ngModel: '='
8442             },
8443             link: function(scope, element) {
8444                 element.removeAttr('color-selector');
8445                 var wrapcont = angular.element('<color-selector-wrapper selected="ngModel" icon-color="{{colorSelector}}">' + element.prop('outerHTML') + '</color-selector-wrapper>');
8446                 var newWrapcont = $compile(wrapcont)(scope);
8447                 element.replaceWith(newWrapcont);
8448             }
8449         };
8450     }]);
8451 angular.module('att.abs.datepicker', ['att.abs.position', 'att.abs.utilities'])
8452
8453 .constant('datepickerConfig', {
8454     dateFormat: 'MM/dd/yyyy',
8455     dayFormat: 'd',
8456     monthFormat: 'MMMM',
8457     yearFormat: 'yyyy',
8458     dayHeaderFormat: 'EEEE',
8459     dayTitleFormat: 'MMMM yyyy',
8460     disableWeekend: false,
8461     disableSunday: false,
8462     startingDay: 0,
8463     minDate: null,
8464     maxDate: null,
8465     mode: 0,
8466     dateFilter: {
8467         defaultText: 'Select from list'
8468     },
8469     datepickerEvalAttributes: ['dateFormat', 'dayFormat', 'monthFormat', 'yearFormat', 'dayHeaderFormat', 'dayTitleFormat', 'disableWeekend', 'disableSunday', 'startingDay', 'mode'],
8470         datepickerWatchAttributes: ['min', 'max']
8471 })
8472
8473 .factory('datepickerService', ['datepickerConfig', 'dateFilter', function (datepickerConfig, dateFilter) {
8474     var setAttributes = function (attr, elem) {
8475         if (angular.isDefined(attr) && attr !== null && angular.isDefined(elem) && elem !== null) {
8476             var attributes = datepickerConfig.datepickerEvalAttributes.concat(datepickerConfig.datepickerWatchAttributes);
8477             for (var key in attr) {
8478                 var val = attr[key];
8479                 if (attributes.indexOf(key) !== -1 && angular.isDefined(val)) {
8480                     elem.attr(key.toSnakeCase(), key);
8481                 }
8482             }
8483         }
8484     };
8485
8486     var bindScope = function (attr, scope) {
8487         if (angular.isDefined(attr) && attr !== null && angular.isDefined(scope) && scope !== null) {
8488             var evalFunction = function (key, val) {
8489                 scope[key] = scope.$parent.$eval(val);
8490             };
8491             
8492             var watchFunction = function (key, val) {
8493                 scope.$parent.$watch(val, function (value) {
8494                     scope[key] = value;
8495                 });
8496                 scope.$watch(key, function (value) {
8497                     scope.$parent[val] = value;
8498                 });
8499             };
8500
8501             var evalAttributes = datepickerConfig.datepickerEvalAttributes;
8502             var watchAttributes = datepickerConfig.datepickerWatchAttributes;
8503             for (var key in attr) {
8504                 var val = attr[key];
8505                 if (evalAttributes.indexOf(key) !== -1 && angular.isDefined(val)) {
8506                     evalFunction(key, val);
8507                 } else if (watchAttributes.indexOf(key) !== -1 && angular.isDefined(val)) {
8508                     watchFunction(key, val);
8509                 }
8510             }
8511         }
8512     };
8513
8514     var validateDateString = function (dateString, dateFormat) {
8515         if (dateString && dateFormat) {
8516             var delimiter;
8517             if (dateFormat.indexOf('/') !== -1) {
8518                 delimiter = '/';
8519             } else if (dateFormat.indexOf('-') !== -1) {
8520                 delimiter = '-';
8521             } else if (dateFormat.indexOf('.') !== -1) {
8522                 delimiter = '.';
8523             }
8524
8525             var dateStringArray = dateString.split(delimiter);
8526             var dateFormatArray = dateFormat.split(delimiter);
8527             if (dateStringArray.length !== dateFormatArray.length) {
8528                 return false;
8529             }
8530
8531             for (var i = 0; i < dateStringArray.length; i++) {
8532                 dateStringArray[i] = dateStringArray[i].lPad(dateFormatArray[i].length, '0');
8533             }
8534             var intermediateDateString = dateStringArray.join(delimiter);
8535
8536             var actualDateString = dateFilter(new Date(intermediateDateString), dateFormat);
8537             if (intermediateDateString === actualDateString) {
8538                 return true;
8539             } else {
8540                 return false;
8541             }
8542         }
8543     };
8544
8545     return {
8546         setAttributes: setAttributes,
8547         bindScope: bindScope,
8548         validateDateString: validateDateString
8549     };
8550 }])
8551
8552 .controller('DatepickerController', ['$scope', '$attrs', 'dateFilter', 'datepickerConfig', function($scope, $attrs, dateFilter, dtConfig) {
8553     var format = {
8554         date: getValue($attrs.dateFormat, dtConfig.dateFormat),
8555         day: getValue($attrs.dayFormat, dtConfig.dayFormat),
8556         month: getValue($attrs.monthFormat, dtConfig.monthFormat),
8557         year: getValue($attrs.yearFormat, dtConfig.yearFormat),
8558         dayHeader: getValue($attrs.dayHeaderFormat, dtConfig.dayHeaderFormat),
8559         dayTitle: getValue($attrs.dayTitleFormat, dtConfig.dayTitleFormat),
8560         disableWeekend: getValue($attrs.disableWeekend, dtConfig.disableWeekend),
8561         disableSunday: getValue($attrs.disableSunday, dtConfig.disableSunday)
8562     },
8563     startingDay = getValue($attrs.startingDay, dtConfig.startingDay);
8564     $scope.mode = getValue($attrs.mode, dtConfig.mode);
8565
8566     $scope.minDate = dtConfig.minDate ? $scope.resetTime(dtConfig.minDate) : null;
8567     $scope.maxDate = dtConfig.maxDate ? $scope.resetTime(dtConfig.maxDate) : null;
8568
8569     function getValue(value, defaultValue) {
8570         return angular.isDefined(value) ? $scope.$parent.$eval(value) : defaultValue;
8571     }
8572
8573     function getDaysInMonth(year, month) {
8574         return new Date(year, month, 0).getDate();
8575     }
8576
8577     function getDates(startDate, n) {
8578         var dates = new Array(n);
8579         var current = startDate, i = 0;
8580         while (i < n) {
8581             dates[i++] = new Date(current);
8582             current.setDate(current.getDate() + 1);
8583         }
8584         return dates;
8585     }
8586     
8587     function isSelected(dt) {
8588         if (dt && angular.isDate($scope.currentDate) && compare(dt, $scope.currentDate) === 0) {
8589             return true;
8590         }
8591         return false;
8592     }
8593     
8594     function isFromDate(dt) {
8595         if (dt && angular.isDate($scope.fromDate) && compare(dt, $scope.fromDate) === 0) {
8596             return true;
8597         }
8598         return false;
8599     }
8600
8601     function isToDate(dt) {
8602         if (dt && angular.isDate($scope.fromDate) && angular.isDate($scope.currentDate) && compare(dt, $scope.currentDate) === 0) {
8603             return true;
8604         }
8605         return false;
8606     }
8607
8608     function isDateRange(dt) {
8609         if (dt && angular.isDate($scope.fromDate) && angular.isDate($scope.currentDate) && (compare(dt, $scope.fromDate) >= 0) && (compare(dt, $scope.currentDate) <= 0)) {
8610             return true;
8611         }
8612         return false;
8613     }
8614
8615     function isWeekend(date) {
8616         if (dateFilter(date, format.dayHeader) === "Saturday" || dateFilter(date, format.dayHeader) === "Sunday") {
8617             return true;
8618         }
8619         return false;
8620     }
8621
8622     function isToday(date) {
8623         if (compare(date, $scope.resetTime(new Date())) === 0) {
8624             return true;
8625         }
8626         return false;
8627     }   
8628     function isFocused(date) {
8629         if (date && angular.isDate($scope.focusedDate) && compare(date, $scope.focusedDate) === 0) {
8630             return true;
8631         }
8632         return false;
8633     }
8634
8635     var isDisabled = this.isDisabled = function(date) {
8636         if (format.disableWeekend === true && (dateFilter(date, format.dayHeader) === "Saturday" || dateFilter(date, format.dayHeader) === "Sunday")) {
8637             return true;
8638         }
8639         if (format.disableSunday === true && (dateFilter(date, format.dayHeader) === "Sunday")) {
8640             return true;
8641         }
8642         return (($scope.minDate && compare(date, $scope.minDate) < 0) || ($scope.maxDate && compare(date, $scope.maxDate) > 0));
8643     };
8644     
8645     var compare = this.compare = function(date1, date2) {
8646         return (new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate()));
8647     };
8648         
8649         
8650     function isMinDateAvailable(startDate, endDate) {
8651         if(($scope.minDate && $scope.minDate.getTime() >= startDate.getTime()) && ($scope.minDate.getTime() <= endDate.getTime())) {
8652             return true;
8653         }
8654         else {
8655             return false;
8656         }
8657     }
8658     
8659     function isMaxDateAvailable(startDate, endDate) {
8660         if(($scope.maxDate && $scope.maxDate.getTime() >= startDate.getTime()) && ($scope.maxDate.getTime() <= endDate.getTime())) {
8661             return true;
8662         }
8663         else {
8664             return false;
8665         }
8666     }
8667
8668     function getLabel(label) {
8669         if (label)
8670         {
8671             var labelObj = {
8672                 pre: label.substr(0, 3),
8673                 post: label
8674             };
8675             return labelObj;
8676         }
8677         return;
8678     }
8679
8680     function makeDate(date, dayFormat, dayHeaderFormat, isFocused, isSelected, isFromDate, isToDate, isDateRange, isOld, isNew, isDisabled, isToday, isWeekend) {
8681         return {date: date, label: dateFilter(date, dayFormat), header: dateFilter(date, dayHeaderFormat), focused: !!isFocused, selected: !!isSelected, from: !!isFromDate, to: !!isToDate, dateRange: !!isDateRange, oldMonth: !!isOld, nextMonth: !!isNew, disabled: !!isDisabled, today: !!isToday, weekend: !!isWeekend};
8682     }
8683
8684     this.modes = [
8685         {
8686             name: 'day',
8687             getVisibleDates: function(date, calendar) {
8688                 var year = date.getFullYear(), month = date.getMonth(), firstDayOfMonth = new Date(year, month, 1), lastDayOfMonth = new Date(year, month+1, 0);
8689                 var difference = startingDay - firstDayOfMonth.getDay(),
8690                         numDisplayedFromPreviousMonth = (difference > 0) ? 7 - difference : -difference,
8691                         firstDate = new Date(firstDayOfMonth), numDates = 0;
8692
8693                 if (numDisplayedFromPreviousMonth > 0) {
8694                     firstDate.setDate(-numDisplayedFromPreviousMonth + 1);
8695                     numDates += numDisplayedFromPreviousMonth; // Previous
8696                 }
8697                 numDates += getDaysInMonth(year, month + 1); // Current
8698                 numDates += (7 - numDates % 7) % 7; // Next
8699
8700                 var days = getDates(firstDate, numDates), labels = new Array(7);
8701                 for (var i = 0; i < numDates; i++) {
8702                     var dt = new Date(days[i]);
8703                     days[i] = makeDate(dt,
8704                                 format.day,
8705                                 format.dayHeader,
8706                                 isFocused(dt),
8707                                 isSelected(dt),
8708                                 isFromDate(dt),
8709                                 isToDate(dt),
8710                                 isDateRange(dt),
8711                                 (new Date(dt.getFullYear(), dt.getMonth(), 1, 0, 0, 0).getTime() < new Date(year, month, 1, 0, 0, 0).getTime()),
8712                                 (new Date(dt.getFullYear(), dt.getMonth(), 1, 0, 0, 0).getTime() > new Date(year, month, 1, 0, 0, 0).getTime()),
8713                                 isDisabled(dt),
8714                                 isToday(dt),
8715                                 isWeekend(dt));
8716                 }
8717                 for (var j = 0; j < 7; j++) {
8718                     labels[j] = getLabel(dateFilter(days[j].date, format.dayHeader));
8719                 }
8720                 if (calendar === 'top') {
8721                     $scope.disablePrevTop = isMinDateAvailable(firstDayOfMonth, lastDayOfMonth);
8722                     $scope.disableNextTop = isMaxDateAvailable(firstDayOfMonth, lastDayOfMonth);
8723                 } else if (calendar === 'bottom') {
8724                     $scope.disablePrevBottom = isMinDateAvailable(firstDayOfMonth, lastDayOfMonth);
8725                     $scope.disableNextBottom = isMaxDateAvailable(firstDayOfMonth, lastDayOfMonth);
8726                 } else {
8727                     $scope.disablePrevTop = $scope.disablePrevBottom = isMinDateAvailable(firstDayOfMonth, lastDayOfMonth);
8728                     $scope.disableNextTop = $scope.disableNextBottom = isMaxDateAvailable(firstDayOfMonth, lastDayOfMonth);
8729                 }
8730                 $scope.disablePrev = $scope.disablePrevTop || $scope.disablePrevBottom;
8731                 $scope.disableNext = $scope.disableNextTop || $scope.disableNextBottom;
8732                 return {objects: days, title: dateFilter(date, format.dayTitle), labels: labels};
8733             },                                          
8734             split: 7,           
8735             step: {months: 1}
8736         },              
8737                 {
8738             name: 'month',
8739             getVisibleDates: function(date, calendar) {
8740                 var months = new Array(12), labels = [], year = date.getFullYear(), month = date.getMonth();
8741                 for (var i = 0; i < 12; i++) {
8742                    var dt = new Date(year,i,1);
8743                     months[i] = makeDate(dt,
8744                                                                 format.month,
8745                                                                 format.month,                                                           
8746                                 isFocused(dt),
8747                                 isSelected(dt),
8748                                 isFromDate(dt),
8749                                 isToDate(dt),
8750                                 isDateRange(dt),
8751                                 false,
8752                                 false,          
8753                                 isDisabled(dt),
8754                                                                 isToday(dt),
8755                                                                 false
8756                                                                 );
8757                 }                                               
8758                                 return {objects: months, title: dateFilter(date, format.year), labels: labels};
8759             },         
8760                         split:3,
8761             step: {years: 1}
8762         }
8763     ];
8764         
8765 }])
8766
8767 .directive('datepicker', ['$timeout', function ($timeout) {
8768     return {
8769         restrict: 'EA',
8770         replace: true,
8771         transclude: true,
8772         templateUrl: 'app/scripts/ng_js_att_tpls/datepicker/datepicker.html',
8773         scope: {
8774             currentDate: "=?current",
8775             fromDate: "=?from"
8776         },
8777         require: 'datepicker',
8778         controller: 'DatepickerController',
8779         link: function(scope, element, attrs, ctrl) {
8780             var datepickerCtrl = ctrl;
8781             var selected, calendarSelected = false;
8782             scope.focusedDate;
8783            
8784             scope.resetTime = function(date) {
8785                 var dt;
8786                 if (!isNaN(new Date(date))) {
8787                     dt = new Date(date);
8788                                         if(scope.mode === 1){
8789                                                 dt = new Date(dt.getFullYear(), dt.getMonth());
8790                                         }else{
8791                                                 dt = new Date(dt.getFullYear(), dt.getMonth(), dt.getDate());
8792                                         }
8793                 } else {
8794                     return null;
8795                 }                               
8796                 return dt;
8797             };
8798
8799             if (attrs.min) {
8800                 scope.$parent.$watch(attrs.min, function(value) {
8801                     scope.minDate = value ? scope.resetTime(value) : null;
8802                     refill();
8803                 });
8804             }
8805             if (attrs.max) {
8806                 scope.$parent.$watch(attrs.max, function(value) {
8807                     scope.maxDate = value ? scope.resetTime(value) : null;
8808                     refill();
8809                 });
8810             }
8811             
8812             // Split array into smaller arrays
8813             function split(arr, size) {
8814                 var arrays = [];
8815                 while (arr.length > 0) {
8816                     arrays.push(arr.splice(0, size));
8817                 }
8818                 return arrays;
8819             }
8820
8821             function refill(date) {
8822                 if (angular.isDate(date) && !isNaN(date)) {
8823                     selected = new Date(date);
8824                 } else {
8825                     if (!selected) {
8826                         selected = new Date();
8827                     }
8828                 }
8829                                 
8830                                 if (selected) {
8831                                         var selectedCalendar;
8832                                         if(scope.mode === 1){
8833                                                 selected = new Date();
8834                                                 selectedCalendar = moveMonth(angular.copy(selected), -1);
8835                                         } else {
8836                                                 selectedCalendar = angular.copy(selected);
8837                                         }
8838                                         
8839                                         var currentMode = datepickerCtrl.modes[scope.mode];
8840                                         var currentData = currentMode.getVisibleDates(selectedCalendar, 'top');
8841                     scope.currentRows = split(currentData.objects, currentMode.split);
8842                     scope.currentTitle = currentData.title;
8843                     scope.labels = currentData.labels || [];
8844
8845                     var nextData = currentMode.getVisibleDates(moveMonth(angular.copy(selectedCalendar), 1), 'bottom');
8846                     scope.nextRows = split(nextData.objects, currentMode.split);
8847                     scope.nextTitle = nextData.title;                                   
8848                                 }
8849             }
8850         
8851             scope.select = function(date) {
8852                 calendarSelected = true;
8853                 if(attrs.from) {
8854                     if(!(angular.isDate(scope.fromDate) && angular.isDate(scope.currentDate))) {
8855                         if(angular.isDate(scope.fromDate)) {
8856                             selectCurrentDate(date);
8857                         } else if(!angular.isDate(scope.fromDate)) {
8858                             selectFromDate(date);
8859                         }
8860                     }
8861                 } else {
8862                     selectCurrentDate(date);
8863                 }
8864                 scope.focusedDate = date;
8865             };
8866             
8867             var selectCurrentDate = function(date) {
8868                 var dt = new Date(date.getFullYear(), date.getMonth(), date.getDate());
8869                 scope.currentDate = dt;
8870             };
8871             
8872             var selectFromDate = function(date) {
8873                 var dt = new Date(date.getFullYear(), date.getMonth(), date.getDate());
8874                 scope.fromDate = dt;
8875             };
8876
8877             var swapDate = function(fromDate, currentDate) {
8878                 selectFromDate(currentDate);
8879                 $timeout(function () {
8880                     calendarSelected = true;
8881                     scope.focusedDate = currentDate;
8882                     selectCurrentDate(fromDate);
8883                 });
8884             }                   
8885             var moveMonth = function(selectedDate, direction) {
8886                 var step = datepickerCtrl.modes[scope.mode].step;
8887                 selectedDate.setDate(1);
8888                 selectedDate.setMonth(selectedDate.getMonth() + direction * (step.months || 0));
8889                 selectedDate.setFullYear(selectedDate.getFullYear() + direction * (step.years || 0));
8890
8891                 return selectedDate;
8892             };
8893
8894             scope.move = function(direction) {
8895                 selected = moveMonth(angular.copy(selected), direction);
8896                 refill();
8897             };
8898
8899             scope.$watch('currentDate', function (value) {
8900                 if(angular.isDate(value) && !isNaN(value) && datepickerCtrl.isDisabled(value)) {
8901                     scope.currentDate = null;
8902                     return;
8903                 }
8904                 if (attrs.from) {
8905                     if (!isNaN(value) && !isNaN(scope.fromDate) && datepickerCtrl.compare(value, scope.fromDate) < 0) {
8906                         swapDate(scope.fromDate, value);
8907                         return;
8908                     }
8909                 }
8910                 if (calendarSelected) {
8911                     refill();
8912                     calendarSelected = false;
8913                 } else {
8914                     if (angular.isDefined(value) && value !== null) {
8915                         refill(value);
8916                     } else {
8917                         refill();
8918                     }
8919                 }
8920                 scope.focusedDate = undefined;
8921             });
8922             
8923             scope.$watch('fromDate', function (value) {
8924                 if(angular.isDate(value) && !isNaN(value) && datepickerCtrl.isDisabled(value)) {
8925                     scope.fromDate = null;
8926                     return;
8927                 }
8928                 if (attrs.from) {
8929                     if (!isNaN(scope.currentDate) && !isNaN(value) && datepickerCtrl.compare(scope.currentDate, value) < 0) {
8930                         swapDate(value, scope.currentDate);
8931                         return;
8932                     }
8933                     if (calendarSelected) {
8934                         refill();
8935                         calendarSelected = false;
8936                     } else {
8937                         if (angular.isDefined(value) && value !== null) {
8938                             refill(value);
8939                         } else {
8940                             refill();
8941                         }
8942                     }
8943                 }
8944                 scope.focusedDate = undefined;
8945             });
8946         }
8947     };
8948 }])
8949 .directive('datepickerPopup', ['$document', 'datepickerService', '$isElement', '$documentBind', function($document, datepickerService, $isElement, $documentBind) {
8950     var link = function (scope, elem, attr, ctrl) {
8951         datepickerService.bindScope(attr, scope);
8952
8953         scope.isOpen = false;
8954
8955         var toggle = scope.toggle = function (show) {
8956             if(show === true || show === false) {
8957                 scope.isOpen = show;
8958             } else {
8959                 scope.isOpen = !scope.isOpen;
8960             }
8961         };
8962
8963         scope.$watch('current', function () {
8964             toggle(false);
8965         });
8966
8967         var outsideClick = function (e) {
8968             var isElement = $isElement(angular.element(e.target), elem, $document);
8969             if(!isElement) {
8970                 toggle(false);
8971                 scope.$apply();
8972             }
8973         };
8974
8975         $documentBind.click('isOpen', outsideClick, scope);
8976     };
8977
8978     return {
8979         restrict: 'EA',
8980         replace: true,
8981         transclude: true,
8982         templateUrl: 'app/scripts/ng_js_att_tpls/datepicker/datepickerPopup.html',
8983         scope: {
8984             current: "=current"
8985         },
8986         compile: function (elem, attr) {
8987             var wrapperElement = elem.find('span').eq(1);
8988             wrapperElement.attr('current', 'current');
8989             datepickerService.setAttributes(attr, wrapperElement);
8990
8991             return link;
8992         }
8993     };
8994 }])
8995
8996 .directive('attDatepicker', ['$log', function($log) {
8997     return {
8998         restrict: 'A',
8999         require: 'ngModel',
9000         scope: {},
9001         controller: ['$scope', '$element', '$attrs', '$compile', 'datepickerConfig', 'datepickerService', function($scope, $element, $attrs, $compile, datepickerConfig, datepickerService) {
9002             var dateFormatString = angular.isDefined($attrs.dateFormat) ? $scope.$parent.$eval($attrs.dateFormat) : datepickerConfig.dateFormat;
9003             var selectedDateMessage = '<div class="sr-focus hidden-spoken" tabindex="-1">the date you selected is {{$parent.current | date : \'' + dateFormatString + '\'}}</div>';
9004
9005             $element.removeAttr('att-datepicker');
9006             $element.removeAttr('ng-model');
9007             $element.attr('ng-model', '$parent.current');
9008             $element.attr('aria-describedby', 'datepicker');
9009             $element.attr('format-date', dateFormatString);
9010             $element.attr('att-input-deny', '[^0-9\/-]');
9011             $element.attr('maxlength', 10);
9012
9013             var wrapperElement = angular.element('<div></div>');
9014             wrapperElement.attr('datepicker-popup', '');
9015             wrapperElement.attr('current', 'current');
9016             
9017             datepickerService.setAttributes($attrs, wrapperElement);
9018             datepickerService.bindScope($attrs, $scope);
9019             
9020             wrapperElement.html('');
9021             wrapperElement.append($element.prop('outerHTML'));
9022             if (navigator.userAgent.match(/MSIE 8/) === null) {
9023                 wrapperElement.append(selectedDateMessage);
9024             }
9025             var elm = wrapperElement.prop('outerHTML');
9026             elm = $compile(elm)($scope);
9027             $element.replaceWith(elm);
9028         }],
9029         link: function(scope, elem, attr, ctrl) {
9030             if (!ctrl) {
9031                 $log.error("ng-model is required.");
9032                 return; // do nothing if no ng-model
9033             }
9034
9035             scope.$watch('current', function(value) {
9036                 ctrl.$setViewValue(value);
9037             });
9038             ctrl.$render = function() {
9039                 scope.current = ctrl.$viewValue;
9040             };
9041         }
9042     };
9043 }])
9044
9045 .directive('formatDate', ['dateFilter', 'datepickerService', function(dateFilter, datepickerService) {
9046     return {
9047         restrict: 'A',
9048         require: 'ngModel',
9049         link: function(scope, elem, attr, ctrl) {
9050             var formatDate = "";
9051             attr.$observe('formatDate', function (value) {
9052                 formatDate = value;
9053             });
9054             var dateToString = function(value) {
9055                 if (value) {
9056                     ctrl.$setValidity('invalidDate', true);
9057                     return dateFilter(value, formatDate);
9058                 } else {
9059                     ctrl.$setValidity('invalidDate', false);
9060                     return elem.val();
9061                 }
9062             };
9063             var stringToDate = function(value) {
9064                 if(datepickerService.validateDateString(value, formatDate)) {
9065                     ctrl.$setValidity('invalidDate', true);
9066                     return new Date(value);
9067                 } else {
9068                     ctrl.$setValidity('invalidDate', false);
9069                     return null;
9070                 }
9071             };
9072             ctrl.$formatters.unshift(dateToString);
9073             ctrl.$parsers.unshift(stringToDate);
9074         }
9075     };
9076 }])
9077
9078 .directive('attDateFilter', ['$document', 'dateFilter', 'datepickerConfig', 'datepickerService', '$isElement', '$documentBind', function($document, dateFilter, datepickerConfig, datepickerService, $isElement, $documentBind) {
9079         
9080     var link = function (scope, elem, attr, ctrl) {
9081         datepickerService.bindScope(attr, scope);
9082
9083         scope.selectedOption = datepickerConfig.dateFilter.defaultText;
9084         scope.showDropdownList = false;
9085         scope.showCalendar = false;
9086         scope.applyButtonType = "disabled";
9087
9088         scope.currentSelection = "";
9089         var dateFormatString = angular.isDefined(attr.dateFormat) ? scope.$parent.$eval(attr.dateFormat) : datepickerConfig.dateFormat;
9090         var inputChange = false;
9091
9092         
9093
9094         var showDropdown = scope.showDropdown = function (show) {
9095             if(show === true || show === false) {
9096                 scope.showDropdownList = show;
9097             } else {
9098                 scope.showDropdownList = !scope.showDropdownList;
9099             }
9100
9101             if (!scope.showDropdownList) {
9102                                 scope.focusInputButton = true;
9103                 hideCalendar();
9104             } else {
9105                 if (scope.currentSelection === 'Custom Single Date' || scope.currentSelection === 'Custom Range') {
9106                     showCalendar();
9107                 }
9108             }
9109         };
9110
9111         var resetTime = scope.resetTime = function(date) {
9112             var dt;
9113             if (!isNaN(new Date(date))) {
9114                 dt = new Date(date);
9115             } else {
9116                 return null;
9117             }
9118             return new Date(dt.getFullYear(), dt.getMonth(), dt.getDate());
9119         };
9120
9121         var addDays = scope.addDays = function (date, days) {
9122             var dt;
9123             if (!isNaN(new Date(date)) && !isNaN(days)) {
9124                 dt = new Date(date);
9125                 dt.setDate(dt.getDate() + days);
9126             } else {
9127                 dt = new Date();
9128             }
9129             return dt;
9130         };
9131                 var addMonth = scope.addMonth = function (date, months) {
9132             var dt;
9133             if (!isNaN(new Date(date)) && !isNaN(months)) {
9134                 dt = new Date(date);
9135                 dt.setMonth(dt.getMonth() + months);
9136             } else {
9137                 dt = new Date();
9138             }
9139             return dt;
9140         };      
9141
9142         var showCalendar = function() {
9143             scope.showCalendar = true;
9144         };
9145
9146         var hideCalendar = function() {
9147             scope.showCalendar = false;
9148             if(scope.currentSelection !== 'Custom Single Date' && scope.currentSelection !== 'Custom Range') {
9149                 clear(true);
9150             }
9151         };
9152
9153         var setDropdownText = function(value) {
9154             if(inputChange) {
9155                 return;
9156             }
9157
9158             var fromDateText = dateFormatString.toUpperCase();
9159             var currentDateText = dateFormatString.toUpperCase();
9160
9161             if(!isNaN(new Date(scope.fromDate))) {
9162                 fromDateText = dateFilter(scope.fromDate, dateFormatString);
9163             }
9164             if(!isNaN(new Date(scope.currentDate))) {
9165                 currentDateText = dateFilter(scope.currentDate, dateFormatString);
9166             }
9167
9168             if(value === 'Custom Single Date') {
9169                 ctrl.$setValidity('invalidDate', true);
9170                 scope.maxLength = 10;
9171                 scope.selectedOption = currentDateText;
9172             } else if(value === 'Custom Range') {
9173                 ctrl.$setValidity('invalidDate', true);
9174                 ctrl.$setValidity('invalidDateRange', true);
9175                 scope.maxLength = 21;
9176                 scope.selectedOption = fromDateText + '-' + currentDateText;
9177             }
9178         };
9179
9180         scope.getDropdownText = function () {
9181             inputChange = true;
9182             var dropdownText = scope.selectedOption;
9183
9184             if (scope.currentSelection === 'Custom Single Date') {
9185                 if (!isNaN(new Date(dropdownText)) && datepickerService.validateDateString(dropdownText, dateFormatString)) {
9186                     ctrl.$setValidity('invalidDate', true);
9187                     scope.fromDate = undefined;
9188                     scope.currentDate = new Date(dropdownText);
9189                 } else {
9190                     ctrl.$setValidity('invalidDate', false);
9191                     clear(true);
9192                 }
9193             } else if (scope.currentSelection === 'Custom Range') {
9194                 if (dropdownText.indexOf('-') !== -1 && (dropdownText.split('-').length === 2 || dropdownText.split('-').length === 6)) {
9195                     ctrl.$setValidity('invalidDateRange', true);
9196                     var resultDropdownText = dropdownText.split('-');
9197                     if (resultDropdownText.length === 2) {
9198                         resultDropdownText[0] = resultDropdownText[0].trim();
9199                         resultDropdownText[1] = resultDropdownText[1].trim();
9200                     } else if (resultDropdownText.length === 6) {
9201                         var firstDateString = resultDropdownText[0].trim() + '-' + resultDropdownText[1].trim() + '-' + resultDropdownText[2].trim();
9202                         var secondDateString = resultDropdownText[3].trim() + '-' + resultDropdownText[4].trim() + '-' + resultDropdownText[5].trim();
9203                         resultDropdownText[0] = firstDateString;
9204                         resultDropdownText[1] = secondDateString;
9205                     }
9206
9207                     if (!isNaN(new Date(resultDropdownText[0])) && !isNaN(new Date(resultDropdownText[1])) && datepickerService.validateDateString(resultDropdownText[0], dateFormatString) && datepickerService.validateDateString(resultDropdownText[1], dateFormatString)) {
9208                         ctrl.$setValidity('invalidDate', true);
9209                         var fromDate = new Date(resultDropdownText[0]);
9210                         var currentDate = new Date(resultDropdownText[1]);
9211                         if(fromDate.getTime() < currentDate.getTime()) {
9212                             ctrl.$setValidity('invalidDateRange', true);
9213                             scope.fromDate = fromDate;
9214                             scope.currentDate = currentDate;
9215                         } else {
9216                             ctrl.$setValidity('invalidDateRange', false);
9217                             clear(true);
9218                         }
9219                     } else {
9220                         ctrl.$setValidity('invalidDate', false);
9221                         clear(true);
9222                     }
9223                 } else {
9224                     ctrl.$setValidity('invalidDateRange', false);
9225                     clear(true);
9226                 }
9227             }
9228         };
9229
9230         scope.untrackInputChange = function(ev) {
9231             inputChange = false;
9232         };
9233
9234         scope.selectAdvancedOption = function (value, notClearFlag) {
9235             scope.currentSelection = value;
9236                         if(!notClearFlag){
9237                                 clear();
9238                                 showCalendar();
9239                         }               
9240             scope.$watch('currentDate', function(val) {
9241                 if(!isNaN(new Date(val))) {
9242                     scope.applyButtonType = "primary";
9243                     setDropdownText(value);
9244                     if (!inputChange) {
9245                         scope.focusApplyButton = true;
9246                     }
9247                 }
9248             });
9249             scope.$watch('fromDate', function(val) {
9250                 if(!isNaN(new Date(val))) {
9251                     setDropdownText(value);
9252                 }
9253             });
9254             if (value === 'Custom Single Date') {
9255                 scope.focusSingleDateCalendar = true;
9256             } else if (value === 'Custom Range') {
9257                 scope.focusRangeCalendar = true;
9258             }
9259         };
9260         
9261         scope.resetFocus = function (ev) {
9262             scope.focusSingleDateCalendar = false;
9263             scope.focusRangeCalendar = false;
9264             scope.focusApplyButton = false;
9265         };
9266
9267         scope.apply = function() {
9268             scope.dateRange.selection = scope.selectedOption;
9269             if(!isNaN(new Date(scope.fromDate))) {
9270                 scope.from = scope.fromDate;
9271                 scope.dateRange.from = scope.fromDate;
9272             } else {
9273                 scope.from = undefined;
9274                 scope.dateRange.from = undefined;
9275             }
9276             if(!isNaN(new Date(scope.currentDate))) {
9277                 scope.current = scope.currentDate;
9278                 scope.dateRange.current = scope.currentDate;
9279             } else {
9280                 scope.current = undefined;
9281                 scope.dateRange.current = undefined;
9282             }
9283
9284             showDropdown();
9285         };
9286
9287         scope.$watchCollection(function() {
9288             return scope.dateRange;
9289         }, function(value) {
9290             if(ctrl) {
9291                 var finalDateRange = angular.copy(value);
9292                 ctrl.$setViewValue(finalDateRange);
9293             }
9294         });
9295
9296         ctrl.$render = function() {
9297             if (ctrl.$viewValue) {
9298                 var inputRange = ctrl.$viewValue;
9299                 scope.selectedOption = inputRange.selection;
9300                 scope.fromDate = inputRange.from;
9301                 scope.currentDate = inputRange.current;
9302                                 if(scope.fromDate !== undefined && scope.currentDate !== undefined){
9303                                         scope.selectAdvancedOption('Custom Range',true);
9304                                         scope.dateRange.from= scope.fromDate;
9305                                         scope.dateRange.current = scope.currentDate;
9306                                 }else if(scope.currentDate !== undefined){
9307                                         scope.selectAdvancedOption('Custom Single Date',true);                                  
9308                                 }
9309             }
9310         };
9311
9312         var cancel = scope.cancel = function() {
9313             scope.currentSelection = "";
9314             scope.selectedOption = datepickerConfig.dateFilter.defaultText;
9315                         showDropdown();
9316         };
9317
9318         var clear = scope.clear = function(partial) {
9319             scope.fromDate = undefined;
9320             scope.currentDate = undefined;
9321             scope.applyButtonType = "disabled";
9322             if(!partial) {
9323                 ctrl.$setValidity('invalidDate', true);
9324                 ctrl.$setValidity('invalidDateRange', true);
9325                 setDropdownText(scope.currentSelection);
9326             }
9327         };
9328
9329         var outsideClick = function (e) {
9330             var isElement = $isElement(angular.element(e.target), elem, $document);
9331             if(!isElement) {
9332                                 scope.cancel();
9333                 scope.$apply();
9334             }
9335         };
9336
9337         $documentBind.click('showDropdownList', outsideClick, scope);
9338     };
9339
9340     return {
9341         restrict: 'EA',
9342         scope: {
9343             from: '=?from',
9344             current: "=?current"
9345         },
9346         replace: true,
9347         require: '?ngModel',
9348                 transclude:true,
9349         templateUrl: 'app/scripts/ng_js_att_tpls/datepicker/dateFilter.html',
9350                 controller:['$scope', '$element', '$attrs',function($scope, $element, $attrs){
9351                         $scope.dateRange = {
9352                                 selection: undefined,
9353                                 from: undefined,
9354                                 current: undefined
9355                         };
9356                         this.selectOption = function (fromDate,toDate,caption) {
9357                                 $scope.selectedOption = caption;
9358                                 $scope.currentSelection =caption;
9359                                 $scope.dateRange.selection = caption;
9360                                 $scope.dateRange.current = $scope.resetTime(toDate);
9361                                 $scope.dateRange.from = $scope.resetTime(fromDate);
9362                                 $scope.showDropdown();
9363         };
9364                  $scope.checkCurrentSelection=this.checkCurrentSelection = function(value) {    
9365             if(value === $scope.currentSelection) {
9366                 return true;
9367             }
9368             return false;
9369         };
9370                 }],
9371         compile: function(elem, attr) {
9372             var singleDateCalendar = elem.find('span').eq(4);
9373             var rangeCalendar = elem.find('span').eq(5);
9374             rangeCalendar.attr('from', 'fromDate');
9375             singleDateCalendar.attr('current', 'currentDate');
9376             rangeCalendar.attr('current', 'currentDate');
9377             datepickerService.setAttributes(attr, singleDateCalendar);
9378             datepickerService.setAttributes(attr, rangeCalendar);
9379
9380             return link;
9381         }
9382     };
9383 }])
9384 .directive('attDateFilterList',function(){
9385         return{
9386                 restrict:'EA',
9387                 scope:{
9388                         fromDate:'=fromDate',
9389                         toDate:'=toDate',
9390                         caption:'=caption',
9391                         disabled:'=disabled'
9392                 },
9393                 require:'^attDateFilter',
9394                 transclude:true,
9395                 replace:true,
9396                 templateUrl:'app/scripts/ng_js_att_tpls/datepicker/dateFilterList.html',
9397                 link:function(scope,elem,attr,ctrl){
9398                         scope.selectOption=function(fromDate,toDate,caption){                           
9399                                 ctrl.selectOption(fromDate,toDate,caption);
9400                         }
9401                         scope.checkCurrentSelection=ctrl.checkCurrentSelection;
9402                         
9403                 }               
9404         }
9405 });
9406 angular.module('att.abs.devNotes', [])
9407
9408   .directive('attDevNotes', function() {
9409     return {
9410       restrict: 'EA',
9411       transclude: true,
9412       scope: {},
9413       controller: function($scope){
9414         var panes = $scope.panes = [];
9415         $scope.select = function(pane)
9416         {
9417             angular.forEach(panes, function(pane)
9418             {
9419                 pane.selected = false;
9420             });
9421             pane.selected = true;
9422         };
9423         this.addPane = function(pane) {
9424             if (panes.length === 0) {
9425                 $scope.select(pane);
9426             }
9427           panes.push(pane);
9428         };
9429       },
9430       template:'<div>'+
9431         '<ul class="tabs">' +
9432             '<li ng-repeat="pane in panes" ng-class="{active:pane.selected}">'+
9433               '<a href="javascript:void(0)" ng-click="select(pane)">{{pane.title}}</a>' +
9434             '</li>' +
9435           '</ul>' +
9436           '<div ng-transclude></div>'+
9437           '</div>',
9438           replace: true
9439     };
9440   })
9441
9442   .directive('pane', function() {
9443     return {
9444       require: '^attDevNotes',
9445       restrict: 'EA',
9446       transclude: true,
9447       scope: {
9448           title: '@'
9449       },
9450       link: function(scope, element, attrs, tabsCtrl) {
9451         tabsCtrl.addPane(scope);
9452       },
9453       template:
9454         '<div class="tab-pane" ng-class="{active: selected}">' +
9455         '<pre ng-class="{\'language-markup\':title==\'HTML\',\'language-javascript\':title==\'JavaScript\'}"  class=" line-numbers">' +
9456          '<code ng-transclude></code>' +
9457          '</pre>' +
9458         '</div>',
9459       replace: true
9460     };
9461   });
9462
9463 angular.module('att.abs.dividerLines', [])
9464         .directive('attDividerLines', [function()
9465             {
9466                 return {
9467                     scope: {
9468                         attDividerLines: '@'
9469                     },
9470                     restrict: 'A',
9471                     replace: true,
9472                     templateUrl: 'app/scripts/ng_js_att_tpls/dividerLines/dividerLines.html',
9473                     link: function(scope, element, attribute)
9474                     {
9475                         scope.lightContainer = attribute.attDividerLines;
9476                     }
9477                 };
9478             }]);
9479
9480 angular.module('att.abs.dragdrop', [])
9481         .directive('attFileDrop', ['$parse', function($parse) {
9482                 return {
9483                     restrict: 'A',
9484                     scope: {
9485                         fileModel : '=',
9486                         onDrop : '&',
9487                         attFileDrop : '&'
9488                     },
9489                     controller: ['$scope', '$attrs', function($scope, $attrs){
9490                         if($attrs.attFileDrop!==""){
9491                             $scope.onDrop=$scope.attFileDrop;
9492                         }
9493                         this.onDrop = $scope.onDrop;
9494                     }],
9495                     link: function(scope, element) {
9496                         element.addClass('dragdrop');
9497                         element.bind(
9498                             'dragover',
9499                             function(e) {
9500                                 if(e.originalEvent){
9501                                     e.dataTransfer = e.originalEvent.dataTransfer;
9502                                 }
9503                                 e.dataTransfer.dropEffect = 'move';
9504                                 // allows us to drop
9505                                 if (e.preventDefault) {
9506                                     e.preventDefault();
9507                                 }
9508                                 element.addClass('dragdrop-over');
9509                                 return false;
9510                             }
9511                         );
9512                         element.bind(
9513                             'dragenter',
9514                             function(e) {
9515                                 // allows us to drop
9516                                 if (e.preventDefault) {
9517                                     e.preventDefault();
9518                                 }
9519                                 element.addClass('dragdrop-over');
9520                                 return false;
9521                             }
9522                         );
9523                         element.bind(
9524                             'dragleave',
9525                             function() {
9526                                 element.removeClass('dragdrop-over');
9527                                 return false;
9528                             }
9529                         );
9530                         element.bind(
9531                             'drop',
9532                             function(e) {
9533                                 // Stops some browsers from redirecting.
9534                                 if(e.preventDefault) {
9535                                     e.preventDefault();
9536                                 }
9537                                 if (e.stopPropagation) {
9538                                     e.stopPropagation();
9539                                 }
9540                                 if(e.originalEvent){
9541                                     e.dataTransfer = e.originalEvent.dataTransfer;
9542                                 }
9543                                 element.removeClass('dragdrop-over');
9544                                 if(e.dataTransfer.files && e.dataTransfer.files.length > 0){
9545                                     scope.fileModel = e.dataTransfer.files[0];
9546                                     scope.$apply();
9547                                     if(typeof scope.onDrop === "function"){
9548                                         scope.onDrop = $parse(scope.onDrop);
9549                                         scope.onDrop();
9550                                     }
9551                                 }
9552                                 return false;
9553                             }
9554                         );
9555                     }
9556                 };
9557             }])
9558         .directive('attFileLink', [ function() {
9559                 return {
9560                     restrict: 'EA',
9561                     require: '^?attFileDrop',
9562                     replace: true,
9563                     transclude: true,
9564                     templateUrl: 'app/scripts/ng_js_att_tpls/dragdrop/fileUpload.html',
9565                     scope: {
9566                         fileModel : '=?',
9567                         onFileSelect : '&',
9568                         attFileLink : '&'
9569                     },
9570                     controller: ['$scope', '$parse', function($scope, $parse){
9571                         this.setFileModel= function(fileModel){
9572                             if($scope.takeFileModelFromParent){
9573                                 $scope.$parent.fileModel = fileModel;
9574                                 $scope.$parent.$apply();
9575                             }
9576                             else{
9577                                 $scope.fileModel = fileModel;
9578                                 $scope.$apply();
9579                             }
9580                         };
9581                         this.callbackFunction= function(){
9582                             if(typeof $scope.onFileSelect === "function"){
9583                                 $scope.onFileSelect = $parse($scope.onFileSelect);
9584                                 $scope.onFileSelect();
9585                             }
9586                         };
9587                     }],
9588                     link: function(scope, element, attr, attFileDropCtrl) {
9589                         scope.takeFileModelFromParent = false;
9590                         if(!(attr.fileModel) && attFileDropCtrl){
9591                             scope.takeFileModelFromParent = true;
9592                         }
9593                         if(attr.attFileLink!==""){
9594                             scope.onFileSelect=scope.attFileLink;
9595                         }
9596                         else if(!(attr.onFileSelect) && attFileDropCtrl){
9597                             scope.onFileSelect = attFileDropCtrl.onDrop;
9598                         }
9599                     }
9600                 };
9601             }])
9602         .directive('attFileChange', [function() {
9603                 return {
9604                     restrict: 'A',
9605                     require: '^attFileLink',
9606                     link: function(scope, element, attr, attFileLinkCtrl) {
9607                         element.bind(
9608                             'change',
9609                             function (e) {
9610                                 if(e.target.files && e.target.files.length > 0){
9611                                     attFileLinkCtrl.setFileModel(e.target.files[0]);
9612                                     attFileLinkCtrl.callbackFunction();
9613                                 }
9614                                 else{
9615                                     var strFileName = e.target.value;
9616                                     var objFSO = new ActiveXObject("Scripting.FileSystemObject");
9617                                     attFileLinkCtrl.setFileModel(objFSO.getFile(strFileName));
9618                                     attFileLinkCtrl.callbackFunction();
9619                                 }
9620                             }
9621                         );
9622                     }
9623                 };
9624             }]);
9625 angular.module("att.abs.drawer", [])
9626 .directive('attDrawer', ['$document', '$timeout', function ($document, $timeout) {
9627         return {
9628             restrict: 'EA',
9629             replace: true,
9630             transclude: true,
9631             scope: {
9632                 drawerOpen: "=?",
9633                 drawerAutoClose: "=?"
9634             },
9635             template: '<div><div class="att-drawer" ng-transclude></div><div ng-class="{\'drawer-backdrop\':drawerOpen}"></div></div>',
9636             link: function ($scope, element, attrs) {
9637                 var param = {};
9638                 // Override default parameters
9639                 param.side = attrs.drawerSlide || 'top';
9640                 param.speed = attrs.drawerSpeed || '0.25';
9641                 param.size = attrs.drawerSize || '300px';
9642                 param.zindex = attrs.drawerZindex || 1000;
9643                 param.className = attrs.drawerClass || 'att-drawer';
9644                 var slider = element.eq(0).children()[0];
9645                 var content = angular.element(slider).children()[0];
9646                 slider.className = param.className;
9647                 /* Style setup */
9648                 slider.style.transitionDuration = param.speed + 's';
9649                 slider.style.webkitTransitionDuration = param.speed + 's';
9650                 slider.style.zIndex = param.zindex;
9651                 slider.style.position = 'fixed';
9652                 slider.style.width = 0;
9653                 slider.style.height = 0;
9654                 slider.style.transitionProperty = 'width, height';
9655                 if(param.side==='right' || param.side==='left'){
9656                     slider.style.height = attrs.drawerCustomHeight || '100%';
9657                     slider.style.top = attrs.drawerCustomTop ||  '0px';
9658                     slider.style.bottom = attrs.drawerCustomBottom ||  '0px';
9659                     slider.style.right = attrs.drawerCustomRight ||  '0px';
9660                 }
9661                 else if(param.side==='top' || param.side==='bottom'){
9662                     slider.style.width = attrs.drawerCustomWidth || '100%';
9663                     slider.style.left = attrs.drawerCustomLeft || '0px';
9664                     slider.style.top = attrs.drawerCustomTop || '0px';
9665                     slider.style.right = attrs.drawerCustomRight || '0px';
9666                 }
9667                 /* Closed */
9668                 function drawerClose(slider, param) {
9669                     if (slider && slider.style.width !== 0 && slider.style.height !== 0){
9670                         content.style.display = 'none';
9671                         if(param.side==='right' || param.side==='left'){
9672                             slider.style.width = '0px';
9673                         }
9674                         else if(param.side==='top' || param.side==='bottom'){
9675                             slider.style.height = '0px';
9676                         }
9677                     }
9678                     $scope.drawerOpen = false;
9679                 }
9680                 /* Open */
9681                 function drawerOpen(slider, param) {
9682                     if (slider.style.width !== 0 && slider.style.height !== 0){
9683                         if(param.side==='right' || param.side==='left'){
9684                             slider.style.width = param.size;
9685                         }
9686                         else if(param.side==='top' || param.side==='bottom'){
9687                             slider.style.height = param.size;
9688                         }
9689                         $timeout(function() {
9690                             content.style.display = 'block';
9691                         },(param.speed * 1000));
9692                     }
9693                 }
9694                 function isFunction(functionToCheck) {
9695                     var getType = {};
9696                     return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
9697                 }
9698                 /*
9699                 * Watchers
9700                 * */
9701                 if(attrs.drawerSize) {
9702                     $scope.$watch(function() {
9703                         return attrs.drawerSize;
9704                     }, function(newVal) {
9705                         param.size = newVal;
9706                         if($scope.drawerOpen) {
9707                             drawerOpen(slider,param);
9708                         }
9709                     });
9710                 }
9711                 $scope.$watch("drawerOpen", function (value){
9712                     if (!!value) {
9713                         // Open
9714                         drawerOpen(slider,param);
9715                     } else {
9716                         // Close
9717                         drawerClose(slider,param);
9718                     }
9719                 });
9720                 // close panel on location change
9721                 if($scope.drawerAutoClose) {
9722                     $scope.$on("$locationChangeStart", function(){
9723                         drawerClose(slider, param);
9724                         if(isFunction($scope.drawerAutoClose)) {
9725                             $scope.drawerAutoClose();
9726                         }
9727                     });
9728                     $scope.$on("$stateChangeStart", function(){
9729                         drawerClose(slider, param);
9730                         if(isFunction($scope.drawerAutoClose)) {
9731                             $scope.drawerAutoClose();
9732                         }
9733                     });
9734                 }
9735             }
9736         };
9737     }
9738 ]);
9739 angular.module('att.abs.message', [])
9740
9741 .directive('attMessages', [function() {
9742     return {
9743         restrict: 'EA',
9744         scope: true,
9745         controller: ['$scope', '$element', '$attrs', function($scope, $element, $attrs) {
9746             $scope.messageType;
9747             $scope.$watchCollection($attrs['for'], function(errors) {
9748                 for (var key in errors) {
9749                     if (errors[key]) {
9750                         $scope.error = key;
9751                         break;
9752                     } else {
9753                         $scope.error = null;
9754                     }
9755                 };
9756                 if ($scope.error === null) {
9757                     $scope.messageType = null;
9758                     $element.removeAttr('message-type');
9759                 }
9760             });
9761             this.setMessageType = function(messageType) {
9762                 $scope.messageType = messageType;
9763             };
9764             $scope.$watch('messageType', function(value) {
9765                 if (angular.isDefined(value) && value !== null) {
9766                     $element.attr('message-type', value);
9767                 }
9768             });
9769         }]
9770     };
9771 }])
9772
9773 .directive('attMessage', [function() {
9774     return {
9775         restrict: 'EA',
9776         scope: {},
9777         require: '^attMessages',
9778         link: function(scope, elem, attr, ctrl) {
9779             scope.when = attr.when || attr.attMessage;
9780             scope.type = attr.type;
9781             elem.css({display: 'none'});
9782             scope.$parent.$watch('error', function(value) {
9783                 if (value === scope.when) {
9784                     elem.css({display: 'block'});
9785                     ctrl.setMessageType(scope.type);
9786                 } else {
9787                     elem.css({display: 'none'});
9788                 }
9789             });
9790         }
9791     };
9792 }]);
9793
9794 angular.module('att.abs.formField', ['att.abs.message'])
9795
9796 .directive('attFormField', [function() {
9797     return {
9798         priority: 101,
9799         restrict: 'A',
9800         controller:function() {
9801         },
9802         link: function(scope, elem, attr) {
9803             elem.wrap('<div class="form-field"></div>');
9804             elem.parent().append('<label class="form-field__label">' + attr.placeholder || attr.attFormField + '</label>');
9805             elem.wrap('<div class="form-field-input-container"></div>');
9806
9807             elem.bind('keyup', function() {
9808                 if (this.value !== '') {
9809                     elem.parent().parent().find('label').addClass('form-field__label--show').removeClass('form-field__label--hide');
9810                 } else {
9811                     elem.parent().parent().find('label').addClass('form-field__label--hide').removeClass('form-field__label--show');
9812                 }
9813             });
9814
9815             elem.bind('blur', function() {
9816                 if (this.value === '') {
9817                     elem.parent().parent().find('label').removeClass('form-field__label--hide');
9818                 }
9819             });
9820         }
9821     };
9822 }])
9823
9824 .directive('attFormFieldValidation', ['$compile', '$log', function($compile, $log) {
9825     return {
9826         priority: 102,
9827         scope: {},
9828         restrict: 'A',
9829         require: ['?ngModel', '?attFormField'],
9830         link: function(scope, elem, attr, ctrl) {
9831             var ngCtrl = ctrl[0];
9832             var attFormFieldCtrl = ctrl[1];
9833             scope.valid = "";
9834             if (!ngCtrl) {
9835                 $log.error("att-form-field-validation :: ng-model directive is required.");
9836                 return;
9837             }
9838             if (!attFormFieldCtrl) {
9839                 $log.error("att-form-field-validation :: att-form-field directive is required.");
9840                 return;
9841             }
9842
9843             elem.parent().append($compile(angular.element('<i class="icon-info-alert error" ng-show="valid===false">&nbsp;</i>'))(scope));
9844             elem.parent().append($compile(angular.element('<i class="icon-info-success success" ng-show="valid===true">&nbsp;</i>'))(scope));
9845
9846             scope.$watch('valid', function(value) {
9847                 if (value) {
9848                     elem.parent().parent().addClass('success');
9849                 } else if (value === false) {
9850                     elem.parent().parent().addClass('error');
9851                 } else {
9852                     elem.parent().parent().removeClass('success').removeClass('error');
9853                 }
9854             });
9855
9856             elem.bind('keyup', function() {
9857                 if (ngCtrl.$valid) {
9858                     scope.valid = true;
9859                 } else if (ngCtrl.$invalid) {
9860                     scope.valid = false;
9861                 } else {
9862                     scope.valid = "";
9863                 }
9864                 scope.$apply();
9865             });
9866         }
9867     };
9868 }])
9869
9870 .directive('attFormFieldValidationAlert', ['$timeout', function($timeout) {
9871         return {
9872         scope: {},
9873         restrict: 'EA',
9874         replace: true,
9875         transclude: true,
9876         templateUrl: 'app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlert.html',
9877         link: function(scope, elem) {
9878             scope.showLabel = false;
9879             scope.hideLabel = false;
9880             scope.errorMessage = false;
9881             scope.warningMessage = false;
9882             var checkMessageType = function() {
9883                 if (elem.find('att-messages').attr('message-type') === 'error') {
9884                     scope.errorMessage = true;
9885                     scope.warningMessage = false;
9886                 } else if (elem.find('att-messages').attr('message-type') === 'warning') {
9887                     scope.errorMessage = false;
9888                     scope.warningMessage = true;
9889                 } else {
9890                     scope.errorMessage = false;
9891                     scope.warningMessage = false;
9892                 }
9893             };
9894
9895             elem.find('label').text(elem.find('input').attr('placeholder'));
9896             elem.find('input').bind('keyup', function() {
9897                 if (this.value !== '') {
9898                     scope.showLabel = true;
9899                     scope.hideLabel = false;
9900                 } else {
9901                     scope.showLabel = false;
9902                     scope.hideLabel = true;
9903                 }
9904                 checkMessageType();
9905                 scope.$apply();
9906             });
9907
9908             elem.find('input').bind('blur', function() {
9909                 if (this.value === '') {
9910                     scope.showLabel = false;
9911                     scope.hideLabel = false;
9912                 }
9913                 scope.$apply();
9914             });
9915             $timeout(function() {
9916                 checkMessageType();
9917             }, 100);
9918         }
9919     };
9920 }]);
9921
9922 angular.module('att.abs.hourpicker', ['att.abs.utilities'])
9923   .constant('hourpickerConfig', {
9924             days: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
9925             customOption: 'Custom'
9926         })
9927
9928         .controller('hourPickerController', ['$scope', function($scope) {
9929
9930                 $scope.options = [];
9931                 this.setOptions = function(value, fromtime, totime, preselect, uncheckedFromTime,uncheckedToTime) {
9932                     $scope.options.push(value);
9933
9934                     if (preselect !== undefined) {
9935                         $scope.preselect = preselect;
9936                     }
9937
9938                     var daycount;
9939
9940                     if (fromtime !== undefined) {
9941                         $scope.fromtime = fromtime;
9942                         for (daycount in $scope.days) {
9943                             if ($scope.days.hasOwnProperty(daycount)) {
9944                                 $scope.FrtimeList[$scope.days[daycount]] = {};
9945                                 if(uncheckedFromTime !== undefined){
9946                                     $scope.FrtimeList[$scope.days[daycount]].value = uncheckedFromTime;
9947                                     $scope.selectedFromOption[$scope.days[daycount]] = uncheckedFromTime;
9948                                 }else{
9949                                     $scope.FrtimeList[$scope.days[daycount]].value = fromtime[0].value;
9950                                     $scope.selectedFromOption[$scope.days[daycount]] = fromtime[0].value;
9951                                 }
9952                             }
9953                         }
9954                     }
9955                     if (totime !== undefined) {
9956                         $scope.totime = totime;
9957                         for (daycount in $scope.days) {
9958                             if ($scope.days.hasOwnProperty(daycount)) {
9959                                 $scope.TotimeList[$scope.days[daycount]] = {};
9960                                 if(uncheckedToTime !== undefined){
9961                                     $scope.TotimeList[$scope.days[daycount]].value = uncheckedToTime;
9962                                     $scope.selectedToOption[$scope.days[daycount]] = uncheckedToTime;
9963                                 }else{
9964                                     $scope.TotimeList[$scope.days[daycount]].value = totime[0].value;
9965                                     $scope.selectedToOption[$scope.days[daycount]] = totime[0].value;
9966                                 }
9967                             }
9968                         }
9969                     }
9970
9971                     if(uncheckedFromTime !== undefined){
9972                         $scope.uncheckedFromTime = uncheckedFromTime;
9973                     }
9974                     if(uncheckedToTime !== undefined){
9975                         $scope.uncheckedToTime = uncheckedToTime;
9976                     }
9977                 };
9978             }])
9979
9980         .directive('attHourpickerOption', [function() {
9981                 return {
9982                     restrict: 'EA',
9983                     require: '^attHourpicker',
9984                     scope: {
9985                         option: "=option",
9986                         fromtime: "=fromtime",
9987                         totime: "=totime",
9988                         preselect: "=preselect",
9989                         uncheckedFromTime: "=",
9990                         uncheckedToTime: "="
9991                     },
9992                     link: function(scope, element, attr, ctrl) {
9993                         ctrl.setOptions(scope.option,
9994                             scope.fromtime,
9995                             scope.totime,
9996                             scope.preselect,
9997                             scope.uncheckedFromTime,
9998                             scope.uncheckedToTime);
9999                     }
10000                 };
10001             }])
10002
10003         .directive('attHourpicker', ["hourpickerConfig", "$document", "$log", "$documentBind", "$timeout", function(hourpickerConfig, $document, $log, $documentBind, $timeout) {
10004                 return{
10005                     require: 'ngModel',
10006                     restrict: 'EA',
10007                     controller: 'hourPickerController',
10008                     transclude: true,
10009                     scope:{
10010                       model: "=ngModel",
10011                       resetFlag: "=?"
10012                     },
10013                     templateUrl: 'app/scripts/ng_js_att_tpls/hourpicker/hourpicker.html',
10014                     link: function(scope, element, attr, ctrl) {
10015                         var flag = false;
10016                         scope.isFromDropDownOpen = false;
10017                         scope.isToDropDownOpen = false;
10018                         var dropDownOpenValue = "";
10019                         var custTime = {};
10020                         scope.days = hourpickerConfig.days;
10021                         scope.daysList = {};
10022                         scope.FrtimeList = {};
10023                         scope.FrtimeListDay = {};
10024                         scope.TotimeListDay = {};
10025                         scope.selectedFromOption = {};
10026                         scope.selectedToOption = {};
10027                         scope.TotimeList = {};
10028                         scope.selectedIndex = 0;
10029                         scope.selectedOption = "Select from list";
10030                         scope.customTime = [];
10031
10032                         scope.resetFlag = false;
10033
10034                         scope.$watch('resetFlag', function(newVal, oldVal){
10035                             if(newVal !== oldVal){
10036                                 if( newVal && scope.selectedOption === hourpickerConfig.customOption ){
10037                                     //disable and reset all days checkbox
10038                                     for (day in scope.daysList) {
10039                                         if (scope.daysList.hasOwnProperty(day)) {
10040                                             scope.daysList[day] = false;
10041                                             scope.addSelectedValue(day);
10042                                         }
10043                                     }
10044                                     scope.preselectUpdateFxn(scope.preselect);
10045                                 }
10046                                 scope.resetFlag = false;
10047                             }
10048                         });
10049
10050                         scope.$watch('selCategory', function(value) {
10051                             if (value){
10052                                 ctrl.$setViewValue(value);
10053                             }
10054                         });
10055                         scope.$watch('model', function(value,oldValue) {
10056                             if (value && oldValue && angular.toJson(value) !== angular.toJson(oldValue)) {
10057                                scope.updateData(value);
10058                             }});
10059
10060                         scope.updateData = function(value) {
10061                             if (value.constructor === Array) {
10062                                 scope.showDaysSelector = true;
10063                                 scope.selectedOption = hourpickerConfig.customOption;
10064                                 for (var arry in value) {
10065                                     if (value.hasOwnProperty(arry)) {
10066                                         var day = value[arry].day;
10067                                         scope.daysList[day] = true;
10068
10069                                         for (var fromcount in scope.fromtime) {
10070                                             if (scope.fromtime[fromcount].value === value[arry].FromTime) {
10071                                                 scope.FrtimeList[day].value = scope.fromtime[fromcount].value;
10072                                                 scope.selectedFromOption[day] = scope.FrtimeList[day].value;
10073                                             }
10074                                         }
10075                                         for (var tocount in scope.totime) {
10076                                             if (scope.totime[tocount].value === value[arry].ToTime) {
10077                                                 scope.TotimeList[day].value = scope.totime[tocount].value;
10078                                                 scope.selectedToOption[day] = scope.TotimeList[day].value;
10079                                             }
10080                                         }
10081                                         scope.addSelectedValue(day, value[arry].FromTime, value[arry].ToTime);
10082                                         //for IE8 Fix
10083                                         if (parseInt(arry) + 1 === value.length) {
10084                                             break;
10085                                         }
10086                                     }
10087                                 }
10088                             }
10089                             else {
10090                                 scope.selectOption(value.day);
10091                             }
10092                         };
10093
10094                         scope.$watch('preselect', function(value){
10095                             scope.preselectUpdateFxn(value);
10096                         });
10097
10098                         scope.preselectUpdateFxn = function(value){
10099                             if (value !== undefined) {
10100                                 if(scope.options){
10101                                     value = scope.validatePreselectData(value);
10102                                 }
10103                                 if (value === "") {
10104                                     return;
10105                                 }
10106                                 scope.updateData(value);
10107                             }
10108                         };
10109
10110                         scope.validatePreselectData = function(value){
10111                             if (value.constructor === Array) {
10112                                 for (var arry in value) {
10113                                     if (value.hasOwnProperty(arry)) {
10114                                         var day = value[arry].day;
10115                                         var isDayFound = false;
10116                                         var isFrmFound = false;
10117                                         var isToFound = false;
10118                                         for (var daycount in scope.days) {
10119                                             if (scope.days[daycount] === day) {
10120                                                 isDayFound = true;
10121                                                 break;
10122                                             }
10123                                         }
10124                                         if (!isDayFound) {
10125                                             value.splice(arry, 1);
10126                                             continue;
10127                                         }
10128                                         for (var fromcount in scope.fromtime) {
10129                                             if (scope.fromtime[fromcount].value === value[arry].FromTime) {
10130                                                 isFrmFound = true;
10131                                                 break;
10132                                             }
10133                                         }
10134                                         if (!isFrmFound) {
10135                                             value[arry].FromTime = scope.fromtime[0].value;
10136                                         }
10137                                         for (var tocount in scope.totime) {
10138                                             if (scope.totime[tocount].value === value[arry].ToTime) {
10139                                                 isToFound = true;
10140                                                 break;
10141                                             }
10142                                         }
10143                                         if (!isToFound) {
10144                                             value[arry].ToTime = scope.totime[0].value;
10145                                         }
10146                                         //for IE8 Fix
10147                                         if (parseInt(arry) + 1 === value.length) {
10148                                             break;
10149                                         }
10150                                     }
10151                                 }
10152                             }
10153                             else {
10154                                 var isOptionFound = false;
10155                                 for (var optcount in scope.options) {
10156                                     if (scope.options[optcount] === value.day) {
10157                                         isOptionFound = true;
10158                                         break;
10159                                     }
10160                                 }
10161                                 if (!isOptionFound) {
10162                                     value = "";
10163                                 }
10164                             }
10165                             return value;
10166                         };
10167
10168                         scope.selectPrevNextValue = function($event, arrayValues, currValue) {
10169
10170                             var value;
10171                             var index = 0;
10172                             if ($event.keyCode === 38) {
10173                                 value = -1;
10174                             } else if ($event.keyCode === 40) {
10175                                 value = 1;
10176                             } else {
10177                                 return currValue;
10178                             }
10179
10180                             if (arrayValues.indexOf(currValue) !== -1) {
10181                                 index = arrayValues.indexOf(currValue) + value;
10182                             } else {
10183                                 for (var count in arrayValues) {
10184                                     if (arrayValues[count].value === currValue) {
10185                                         index = parseInt(count) + value;
10186                                         break;
10187                                     }
10188                                 }
10189                             }
10190
10191                             if (index === arrayValues.length) {
10192                                 index = index - 1;
10193                             } else if (index === -1) {
10194                                 index = index + 1;
10195                             }
10196
10197                             $event.preventDefault();
10198                             if (arrayValues[index].value){
10199                                 return arrayValues[index].value;
10200                             }
10201                             else{
10202                                 return arrayValues[index];
10203                             }
10204                         };
10205
10206                         scope.showDropdown = function()
10207                         {
10208                             scope.showlist = !scope.showlist;
10209                             flag = !flag;
10210                         };
10211
10212                         scope.showfromDayDropdown = function(value)
10213                         {
10214                             //close dropdown if any other From drop down is opened
10215                             for (count in scope.FrtimeListDay) {
10216                                 if (count !== value && scope.FrtimeListDay[count]) {
10217                                     scope.FrtimeListDay[count] = false;
10218                                 }
10219                             }
10220                             for (count in scope.TotimeListDay) {
10221                                 if (scope.TotimeListDay[count]) {
10222                                     scope.TotimeListDay[count] = false;
10223                                 }
10224                             }
10225                             scope.FrtimeListDay[value] = !scope.FrtimeListDay[value];
10226                             flag = !flag;
10227                             scope.showlist = false;
10228
10229                             //save model value so we can close current dropdown on click of other part of the document
10230                             if (scope.FrtimeListDay[value]) {
10231                                 scope.isFromDropDownOpen = true;
10232                                 dropDownOpenValue = value;
10233                             } else {
10234                                 scope.isFromDropDownOpen = false;
10235                             }
10236
10237                             $timeout(function () {
10238                                 if(scope.FrtimeListDay[value]){
10239                                     var daysContainerDIV = angular.element(element)[0].querySelector(".customdays-width");
10240                                     var containerUL = angular.element(daysContainerDIV.querySelector('.select2-container-active')).parent()[0].querySelector("ul");
10241                                     var selectedElemTopPos = angular.element(containerUL.querySelector('.selectedItemInDropDown'))[0].offsetTop;
10242                                     angular.element(containerUL)[0].scrollTop = selectedElemTopPos;
10243                                 }
10244                             });
10245                         };
10246
10247                         scope.showtoDayDropdown = function(value)
10248                         {
10249                             //close dropdown if any other To drop down is opened
10250                             for (count in scope.TotimeListDay) {
10251                                 if (count !== value && scope.TotimeListDay[count]) {
10252                                     scope.TotimeListDay[count] = false;
10253                                 }
10254                             }
10255                             for (count in scope.FrtimeListDay) {
10256                                 if (scope.FrtimeListDay[count]) {
10257                                     scope.FrtimeListDay[count] = false;
10258                                 }
10259                             }
10260                             scope.TotimeListDay[value] = !scope.TotimeListDay[value];
10261                             flag = !flag;
10262                             scope.showlist = false;
10263
10264                             //save model value so we can close current dropdown on click of other part of the document
10265                             if (scope.TotimeListDay[value]) {
10266                                 scope.isToDropDownOpen = true;
10267                                 dropDownOpenValue = value;
10268
10269                             } else {
10270                                 scope.isToDropDownOpen = false;
10271                             }
10272
10273                             $timeout(function () {
10274                                 if(scope.FrtimeListDay[value]){
10275                                     var daysContainerDIV = angular.element(element)[0].querySelector(".customdays-width");
10276                                     var containerUL = angular.element(daysContainerDIV.querySelector('.select2-container-active')).parent()[0].querySelector("ul");
10277                                     var selectedElemTopPos = angular.element(containerUL.querySelector('.selectedItemInDropDown'))[0].offsetTop;
10278                                     angular.element(containerUL)[0].scrollTop = selectedElemTopPos;
10279                                 }
10280                             });
10281                         };
10282
10283                         scope.selectFromDayOption = function(day, value)
10284                         {
10285                             scope.selectedFromOption[day] = value;
10286                             scope.FrtimeList[day].value = value;
10287                             scope.FrtimeListDay[day] = false;
10288                             scope.isFromDropDownOpen = false;
10289                         };
10290
10291                         scope.selectToDayOption = function(day, value)
10292                         {
10293                             scope.selectedToOption[day] = value;
10294                             scope.TotimeList[day].value = value;
10295                             scope.TotimeListDay[day] = false;
10296                             scope.isToDropDownOpen = false;
10297                         };
10298
10299                         scope.addSelectedValue = function(value, fromtime, totime) {
10300                             var count,len;
10301                             if (scope.daysList[value] !== undefined && !scope.daysList[value]) {
10302                                for (count = 0, len = scope.customTime.length; count < len; count++) {
10303                                     if (scope.customTime[count].day === value) {
10304                                         if(scope.uncheckedFromTime){
10305                                             scope.selectedFromOption[scope.customTime[count].day] = scope.uncheckedFromTime;
10306                                         }
10307                                         else{
10308                                             scope.selectedFromOption[scope.customTime[count].day]  = scope.FrtimeList[scope.customTime[count].day].value;
10309                                         }
10310
10311                                         if(scope.uncheckedToTime){
10312                                             scope.selectedToOption[scope.customTime[count].day] = scope.uncheckedToTime;
10313                                         }
10314                                         else{
10315                                             scope.selectedToOption[scope.customTime[count].day] = scope.TotimeList[scope.customTime[count].day].value;
10316                                         }
10317
10318                                         scope.customTime.splice(count, 1);
10319                                         break;
10320                                     }
10321                                 }
10322                             }
10323                             else {
10324                                 if(scope.selectedFromOption[value] === scope.uncheckedFromTime){
10325                                     scope.selectedFromOption[value] = scope.fromtime[0].value;
10326                                     fromtime = scope.fromtime[0].value;
10327                                     scope.FrtimeList[value].value = scope.fromtime[0].value;
10328                                 }
10329
10330                                 if(scope.selectedToOption[value] === scope.uncheckedToTime){
10331                                     scope.selectedToOption[value] = scope.totime[0].value;
10332                                     totime = scope.totime[0].value;
10333                                     scope.TotimeList[value].value = scope.totime[0].value;
10334                                 }
10335
10336                                 custTime["day"] = value;
10337                                 custTime["FromTime"] =  scope.FrtimeList[value].value;
10338                                 custTime["ToTime"] = scope.TotimeList[value].value;
10339
10340                                 for (count = 0, len = scope.customTime.length; count < len; count++) {
10341                                     if (scope.customTime[count].day === value) {
10342                                         scope.customTime[count].FromTime = custTime["FromTime"];
10343                                         scope.customTime[count].ToTime = custTime["ToTime"];
10344                                         break;
10345                                     }
10346                                 }
10347                                 if (count === len) {
10348                                     var x = angular.copy(custTime);
10349                                     scope.customTime.push(x);
10350                                 }
10351                             }
10352                             scope.selCategory = scope.customTime;
10353                         };
10354
10355
10356                         var outsideClick = function() {
10357                             if (scope.showlist) {
10358                                 scope.$apply(function() {
10359                                     scope.showlist = false;
10360                                 });
10361                             }
10362                         };
10363
10364                         $documentBind.click('showlist', outsideClick, scope);
10365
10366                         var outsideClickFromDropdown = function() {
10367                             scope.$apply(function() {
10368                                 if (scope.isFromDropDownOpen) {
10369                                     scope.FrtimeListDay[dropDownOpenValue] = false;
10370                                     scope.isFromDropDownOpen = false;
10371                                 }
10372                             });
10373                         };
10374
10375                         $documentBind.click('isFromDropDownOpen', outsideClickFromDropdown, scope);
10376
10377                         var outsideClickToDropdown = function() {
10378                             scope.$apply(function() {
10379                                 if (scope.isToDropDownOpen) {
10380                                     scope.TotimeListDay[dropDownOpenValue] = false;
10381                                     scope.isToDropDownOpen = false;
10382                                 }
10383                             });
10384                         };
10385
10386                         $documentBind.click('isToDropDownOpen', outsideClickToDropdown, scope);
10387
10388                         scope.selectOption = function(sItem)
10389                         {
10390
10391                             if (sItem === hourpickerConfig.customOption) {
10392                                 scope.showDaysSelector = true;
10393                                 scope.selCategory = scope.customTime;
10394                             } else {
10395                                 scope.showDaysSelector = false;
10396                                 var fromTime = /[0-9]\s?am/i.exec(sItem);
10397                                 var toTime = /[0-9]\s?pm/i.exec(sItem);
10398                                 scope.selCategory = {day: sItem, FromTime: fromTime === null ? 'NA' : fromTime[0], ToTime: toTime === null ? 'NA' : toTime[0]};
10399                             }
10400
10401                             scope.showlist = false;
10402                             flag = false;
10403                             scope.selectedOption = sItem;
10404                         };
10405                     }
10406                 };
10407             }]);
10408
10409 angular.module('att.abs.iconButtons', [])
10410         .constant('buttonConfig', {
10411             activeClass: 'active--button',
10412             toggleEvent: 'click'
10413         })
10414         .directive('attIconBtnRadio', ['buttonConfig', function(buttonConfig) {
10415                 var activeClass = buttonConfig.activeClass || 'active--button';
10416                 var toggleEvent = buttonConfig.toggleEvent || 'click';
10417                 return {
10418                     require: 'ngModel',
10419                     link: function(scope, element, attrs, ngModelCtrl) {
10420                         element.attr("role","button");
10421                         element.attr("tabindex","0");
10422                         element.append("<span class='hidden-spoken'>"+attrs.attIconBtnRadio+"</span>");
10423                         //model -> UI
10424                         ngModelCtrl.$render = function() {
10425                             element.parent().toggleClass(activeClass, angular.equals(ngModelCtrl.$modelValue, attrs.attIconBtnRadio));
10426                         };
10427                         //ui->model
10428                         element.parent().bind(toggleEvent, function() {
10429                             if (!element.parent().hasClass(activeClass)) {
10430                                 scope.$apply(function() {
10431                                     ngModelCtrl.$setViewValue(attrs.attIconBtnRadio);
10432                                     ngModelCtrl.$render();
10433                                 });
10434                             }
10435                         });
10436                     }
10437                 };
10438             }])
10439         .directive('attIconBtnCheckbox', ['buttonConfig', function(buttonConfig) {
10440                 var activeClass = buttonConfig.activeClass || 'active--button';
10441                 var toggleEvent = buttonConfig.toggleEvent || 'click';
10442                 return {
10443                     require: 'ngModel',
10444                     link: function(scope, element, attrs, ngModelCtrl) {
10445                         element.attr("role","button");
10446                         element.attr("tabindex","0");
10447                         element.append("<span class='hidden-spoken'>"+attrs.attIconBtnCheckbox+"</span>");
10448                         function getTrueValue() {
10449                             var trueValue = scope.$eval(attrs.btnCheckboxTrue);
10450                             return angular.isDefined(trueValue) ? trueValue : true;
10451                         }
10452                         function getFalseValue() {
10453                             var falseValue = scope.$eval(attrs.btnCheckboxFalse);
10454                             return angular.isDefined(falseValue) ? falseValue : false;
10455                         }
10456                         //model -> UI
10457                         ngModelCtrl.$render = function() {
10458                             element.parent().toggleClass(activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue()));
10459                         };
10460                         //ui->model
10461                         element.parent().bind(toggleEvent, function() {
10462                             scope.$apply(function() {
10463                                 ngModelCtrl.$setViewValue(element.parent().hasClass(activeClass) ? getFalseValue() : getTrueValue());
10464                                 ngModelCtrl.$render();
10465                             });
10466                         });
10467                     }
10468                 };
10469             }]);
10470
10471 angular.module('att.abs.links', ['ngSanitize'])
10472         .directive('attLink', [function() {
10473                 return {
10474                     restrict: 'A',
10475                     link: function(scope, elem) {
10476                         elem.addClass('link');
10477                         if(!(elem.attr('href'))){
10478                             elem.attr("tabindex", "0");
10479                         }
10480                     }
10481                 };
10482             }])
10483         .directive('attLinkVisited', [function() {
10484                 return {
10485                     restrict: 'A',
10486                     link: function(scope, elem) {
10487                         elem.addClass('link--visited');
10488                         if(!(elem.attr('href'))){
10489                             elem.attr("tabindex", "0");
10490                         }
10491                     }
10492                 };
10493             }])
10494         .directive('attReadmore', ['$timeout',function($timeout) {
10495                 return {
10496                     restrict: 'A',
10497                     scope: {
10498                         lines:"@noOfLines",
10499                         textModel: "=",
10500                         //attribute to use readmore inside accordion
10501                         isOpen: "="
10502                     },
10503                     templateUrl: 'app/scripts/ng_js_att_tpls/links/readMore.html',
10504                     link: function(scope, elem) {
10505                         var height = 1;
10506                         scope.$watch('textModel', function(val){
10507                             if(!val){
10508                                 scope.textToDisplay = '';
10509                                 scope.readMoreLink = false;
10510                                 scope.readLessLink = false;
10511                                 scope.readFlag = false;
10512                             }
10513                             else{
10514                                 if (typeof String.prototype.trim !== 'function') {
10515                                     String.prototype.trim = function() {
10516                                        return this.replace(/^\s+|\s+$/g, '');
10517                                     };
10518                                 }
10519                                 scope.textToDisplay = val.trim();
10520                                 scope.readFlag = true;
10521                                 $timeout(function() {
10522                                     var readElem = elem[0].children[0].children[0];
10523                                     if(height===1){
10524                                         if(window.getComputedStyle){
10525                                             height = parseInt(scope.lines) * parseFloat(window.getComputedStyle(readElem,null).getPropertyValue("height"));
10526                                         }
10527                                         else {
10528                                             height = parseInt(scope.lines) * parseFloat(readElem.currentStyle.height);
10529                                         }
10530                                         scope.elemHeight = height;
10531                                         scope.readLinkStyle = {'height': scope.elemHeight + 'px'};
10532                                     }
10533                                 });
10534                                 scope.readMoreLink = true;
10535                                 scope.readLessLink = false;
10536                             }
10537                         });
10538                         // Code to use readmore inside accordion
10539                         var parentElem = elem.parent();
10540                         if (parentElem.hasClass('att-accordion__body')) {
10541                             scope.$watch('isOpen', function(val) {
10542                                 if (!val) {
10543                                     scope.readLess();
10544                                 }
10545                             });
10546                         }
10547                         scope.readMore = function() {
10548                             scope.readMoreLink = false;
10549                             scope.readLessLink = true;
10550                             scope.readLinkStyle = {'height': 'auto'};
10551                             scope.readFlag = false;
10552                         };
10553                         scope.readLess = function() {
10554                             scope.readMoreLink = true;
10555                             scope.readLessLink = false;
10556                             scope.readLinkStyle = {'height': scope.elemHeight + 'px'};
10557                             scope.readFlag = true;
10558                         };
10559                     }
10560                 };
10561             }])
10562         .directive('attLinksList', [function() {
10563                 return {
10564                     restrict: 'A',
10565                     controller: function() {
10566                     },
10567                     link: function(scope, elem) {
10568                         elem.addClass('links-list');
10569                     }
10570                 };
10571             }])
10572         .directive('attLinksListItem', [function() {
10573                 return {
10574                     restrict: 'A',
10575                     require: '^attLinksList',
10576                     link: function(scope, elem) {
10577                         elem.addClass('links-list__item');
10578                         if(!(elem.attr('href'))){
10579                             elem.attr("tabindex", "0");
10580                         }
10581                     }
10582                 };
10583             }]);
10584 angular.module('att.abs.loading', [])
10585         .directive('attLoading', ['$window',function($window) {
10586                 return {
10587                     restrict: 'A',
10588                     replace: true,
10589                     scope: {
10590                         icon: '@attLoading',
10591                         progressStatus: '=?',
10592                         colorClass: '=?'
10593                     },
10594                     templateUrl: 'app/scripts/ng_js_att_tpls/loading/loading.html',
10595                     link: function(scope, element) {
10596                         var progressvalue = scope.progressStatus;
10597                         scope.progressStatus = Math.min(100, Math.max(0, progressvalue));
10598                         if($window.navigator.userAgent.indexOf("MSIE 8.")!==-1){
10599                             var shiftX = 0, shiftY = scope.progressStatus * 36;
10600                             element.css({
10601                                 'background-position-x' : shiftX,
10602                                 'background-position-y' : -shiftY
10603                             });
10604                         }
10605                     }
10606             };
10607         }]);
10608 angular.module('att.abs.modal', [])
10609 /**
10610  * A helper, internal data structure that acts as a map but also allows getting / removing
10611  * elements in the LIFO order
10612  */
10613   .factory('$$stackedMap', function () {
10614     return {
10615       createNew: function () {
10616         var stack = [];
10617
10618         return {
10619           add: function (key, value) {
10620             stack.push({
10621               key: key,
10622               value: value
10623             });
10624           },
10625           get: function (key) {
10626             for (var i = 0; i < stack.length; i++) {
10627               if (key === stack[i].key) {
10628                 return stack[i];
10629               }
10630             }
10631           },
10632           keys: function() {
10633             var keys = [];
10634             for (var i = 0; i < stack.length; i++) {
10635               keys.push(stack[i].key);
10636             }
10637             return keys;
10638           },
10639           top: function () {
10640             return stack[stack.length - 1];
10641           },
10642           remove: function (key) {
10643             var idx = -1;
10644             for (var i = 0; i < stack.length; i++) {
10645               if (key === stack[i].key) {
10646                 idx = i;
10647                 break;
10648               }
10649             }
10650             return stack.splice(idx, 1)[0];
10651           },
10652           removeTop: function () {
10653             return stack.splice(stack.length - 1, 1)[0];
10654           },
10655           length: function () {
10656             return stack.length;
10657           }
10658         };
10659       }
10660     };
10661   })
10662
10663 /**
10664  * A helper directive for the $modal service. It creates a backdrop element.
10665  */
10666   .directive('modalBackdrop', ['$timeout', function ($timeout) {
10667     return {
10668       restrict: 'EA',
10669       replace: true,
10670       templateUrl: 'app/scripts/ng_js_att_tpls/modal/backdrop.html',
10671       link: function (scope) {
10672         scope.animate = false;
10673         //trigger CSS transitions
10674         $timeout(function () {
10675           scope.animate = true;
10676         });
10677     }
10678     };
10679   }])
10680
10681   .directive('modalWindow', ['$modalStack','$timeout','$document', function ($modalStack,$timeout,$document) {
10682     return {
10683       restrict: 'EA',
10684       scope: {
10685         index: '@'
10686       },
10687       replace: true,
10688       transclude: true,
10689       templateUrl: 'app/scripts/ng_js_att_tpls/modal/window.html',
10690       link: function (scope, element, attrs) {
10691         scope.windowClass = attrs.windowClass || '';
10692         $timeout(function () {
10693             // trigger CSS transitions
10694             scope.focusModalFlag = true;
10695             scope.animate = true;
10696         });
10697                 $document.on('focus keydown', function(e){
10698                     if (e.which ===9) {
10699                         String.prototype.contains = function(it) {
10700                             return this.indexOf(it) !== -1;
10701                         };
10702                         if (element[0] !== e.target && !element[0].contains( e.target )) {
10703                                 element[0].focus();
10704                         }
10705                         }
10706                 });
10707         scope.close = function (evt) {
10708             var modal = $modalStack.getTop();
10709             if (modal && modal.value.backdrop && modal.value.backdrop !== 'static'  && (evt.target === evt.currentTarget)) {
10710             // Check if preventDefault exists due to lack of support for IE8
10711             if (evt.preventDefault) {
10712               evt.preventDefault();
10713               evt.stopPropagation();
10714           } else {
10715               evt.returnValue = false;
10716             }
10717             $modalStack.dismiss(modal.key, 'backdrop click');
10718           }
10719         };
10720       }
10721     };
10722   }])
10723
10724   .factory('$modalStack', ['$document', '$compile', '$rootScope', '$$stackedMap',
10725     function ($document, $compile, $rootScope, $$stackedMap) {
10726       var OPENED_MODAL_CLASS = 'modal-open';
10727       var backdropjqLiteEl, backdropDomEl;
10728       var backdropScope = $rootScope.$new(true);
10729       var openedWindows = $$stackedMap.createNew();
10730       var $modalStack = {};
10731       function backdropIndex() {
10732         var topBackdropIndex = -1;
10733         var opened = openedWindows.keys();
10734         for (var i = 0; i < opened.length; i++) {
10735           if (openedWindows.get(opened[i]).value.backdrop) {
10736             topBackdropIndex = i;
10737           }
10738         }
10739         return topBackdropIndex;
10740       }
10741
10742       $rootScope.$watch(backdropIndex, function(newBackdropIndex){
10743         backdropScope.index = newBackdropIndex;
10744       });
10745
10746       function removeModalWindow(modalInstance) {
10747
10748         var body = $document.find('body').eq(0);
10749         var modalWindow = openedWindows.get(modalInstance).value;
10750         //clean up the stack
10751         openedWindows.remove(modalInstance);
10752         ////remove window DOM element
10753         modalWindow.modalDomEl.remove();
10754         body.toggleClass(OPENED_MODAL_CLASS, openedWindows.length() > 0);
10755
10756         //remove backdrop if no longer needed
10757         if (backdropDomEl && backdropIndex() === -1) {
10758           backdropDomEl.remove();
10759           backdropDomEl = undefined;
10760         }
10761         //destroy scope
10762         modalWindow.modalScope.$destroy();
10763       }
10764       $document.bind('keydown', function (evt) {
10765         var modal;
10766         if (evt.which === 27) {
10767           modal = openedWindows.top();
10768           if (modal && modal.value.keyboard) {
10769             $rootScope.$apply(function () {
10770               $modalStack.dismiss(modal.key);
10771             });
10772           }
10773         }
10774       });
10775
10776       $modalStack.open = function (modalInstance, modal) {
10777           openedWindows.add(modalInstance, {
10778           deferred: modal.deferred,
10779           modalScope: modal.scope,
10780           backdrop: modal.backdrop,
10781           keyboard: modal.keyboard
10782         });
10783         var body = $document.find('body').eq(0);
10784
10785         if (backdropIndex() >= 0 && !backdropDomEl) {
10786             backdropjqLiteEl = angular.element('<div modal-backdrop></div>');
10787             backdropDomEl = $compile(backdropjqLiteEl)(backdropScope);
10788             body.append(backdropDomEl);
10789         }
10790         var angularDomEl = angular.element('<div modal-window></div>');
10791         angularDomEl.attr('window-class', modal.windowClass);
10792         angularDomEl.attr('index', openedWindows.length() - 1);
10793         angularDomEl.html(modal.content);
10794
10795         var modalDomEl = $compile(angularDomEl)(modal.scope);
10796         openedWindows.top().value.modalDomEl = modalDomEl;
10797         body.append(modalDomEl);
10798         body.addClass(OPENED_MODAL_CLASS);
10799       };
10800
10801       $modalStack.close = function (modalInstance, result) {
10802         var modal = openedWindows.get(modalInstance);
10803         if (modal) {
10804           modal.value.deferred.resolve(result);
10805           removeModalWindow(modalInstance);
10806         }
10807       };
10808
10809       $modalStack.dismiss = function (modalInstance, reason) {
10810         var modalWindow = openedWindows.get(modalInstance).value;
10811         if (modalWindow) {
10812           modalWindow.deferred.reject(reason);
10813           removeModalWindow(modalInstance);
10814         }
10815       };
10816
10817       $modalStack.getTop = function () {
10818         return openedWindows.top();
10819       };
10820
10821       return $modalStack;
10822     }])
10823
10824   .provider('$modal', function () {
10825
10826     var $modalProvider = {
10827       options: {
10828         //can be also false or 'static'
10829         backdrop: true,
10830         keyboard: true
10831       },
10832       $get: ['$injector', '$rootScope', '$q', '$http', '$templateCache', '$controller', '$modalStack',
10833         function ($injector, $rootScope, $q, $http, $templateCache, $controller, $modalStack) {
10834             var $modal = {};
10835             function getTemplatePromise(options) {
10836             return options.template ? $q.when(options.template) :
10837               $http.get(options.templateUrl, {cache: $templateCache}).then(function (result) {
10838                 return result.data;
10839               });
10840           }
10841
10842           function getResolvePromises(resolves) {
10843             var promisesArr = [];
10844             angular.forEach(resolves, function (value) {
10845               if (angular.isFunction(value) || angular.isArray(value)) {
10846                 promisesArr.push($q.when($injector.invoke(value)));
10847               }
10848             });
10849             return promisesArr;
10850           }
10851           $modal.open = function (modalOptions) {
10852             var modalResultDeferred = $q.defer();
10853             var modalOpenedDeferred = $q.defer();
10854
10855             //prepare an instance of a modal to be injected into controllers and returned to a caller
10856             var modalInstance = {
10857               result: modalResultDeferred.promise,
10858               opened: modalOpenedDeferred.promise,
10859               close: function (result) {
10860                 $modalStack.close(modalInstance, result);
10861               },
10862               dismiss: function (reason) {
10863                 $modalStack.dismiss(modalInstance, reason);
10864               }
10865             };
10866             //merge and clean up options
10867             modalOptions = angular.extend({}, $modalProvider.options, modalOptions);
10868             modalOptions.resolve = modalOptions.resolve || {};
10869
10870             //verify options
10871             if (!modalOptions.template && !modalOptions.templateUrl) {
10872               throw new Error('One of template or templateUrl options is required.');
10873             }
10874
10875             var templateAndResolvePromise =
10876               $q.all([getTemplatePromise(modalOptions)].concat(getResolvePromises(modalOptions.resolve)));
10877               templateAndResolvePromise.then(function(tplAndVars) {
10878               var modalScope = (modalOptions.scope || $rootScope).$new();
10879               modalScope.$close = modalInstance.close;
10880               modalScope.$dismiss = modalInstance.dismiss;
10881
10882               var ctrlInstance, ctrlLocals = {};
10883               var resolveIter = 1;
10884
10885               //controllers
10886               if (modalOptions.controller) {
10887                 ctrlLocals.$scope = modalScope;
10888                 ctrlLocals.$modalInstance = modalInstance;
10889                 angular.forEach(modalOptions.resolve, function (value, key) {
10890                   ctrlLocals[key] = tplAndVars[resolveIter++];
10891                 });
10892
10893                 ctrlInstance = $controller(modalOptions.controller, ctrlLocals);
10894               }
10895
10896               $modalStack.open(modalInstance, {
10897                 scope: modalScope,
10898                 deferred: modalResultDeferred,
10899                 content: tplAndVars[0],
10900                 backdrop: modalOptions.backdrop,
10901                 keyboard: modalOptions.keyboard,
10902                 windowClass: modalOptions.windowClass
10903               });
10904
10905             }, function(reason) {
10906               modalResultDeferred.reject(reason);
10907             });
10908
10909             templateAndResolvePromise.then(function () {
10910               modalOpenedDeferred.resolve(true);
10911             }, function () {
10912               modalOpenedDeferred.reject(false);
10913             });
10914
10915             return modalInstance;
10916           };
10917
10918           return $modal;
10919         }]
10920     };
10921
10922     return $modalProvider;
10923   })
10924
10925 .directive("simpleModal", ["$modal", function($modal) {
10926         return {
10927             restrict: 'EA',
10928             scope: {
10929                 simpleModal: '@',
10930                 backdrop:'@',
10931                 keyboard:'@',
10932                 modalOk:'&',
10933                 modalCancel:'&',
10934                 windowClass:'@',
10935                 controller:'@'
10936             },
10937             link: function(scope, elm) {
10938                 elm.bind('click', function(ev) {
10939                     ev.preventDefault();
10940                     if (angular.isDefined(elm.attr("href")) && elm.attr("href") !== "") {
10941                         scope.simpleModal = elm.attr("href");
10942                     }
10943                     if(!scope.backdrop){
10944                        scope.backdropclick='static';
10945                    }
10946                     else
10947                     {
10948                         scope.backdropclick=true;
10949                     }
10950                     if(!scope.keyboard ){
10951                         scope.keyboardev=false;
10952                     }
10953                     else{
10954                         scope.keyboardev=true;
10955                     }
10956                     $modal.open({
10957                         templateUrl: scope.simpleModal,
10958                         backdrop:scope.backdropclick,
10959                         keyboard:scope.keyboardev,
10960                         windowClass:scope.windowClass,
10961                         controller: scope.controller
10962                     }).result.then(scope.modalOk, scope.modalCancel);
10963                 });
10964             }
10965         };
10966     }]);
10967
10968 angular.module('att.abs.pagination', ['att.abs.utilities'])
10969 .directive('attPagination', [ function() {
10970      return {
10971         restrict: 'EA',
10972         scope: {
10973             totalPages: '=',
10974             currentPage: '=',
10975             showInput: '=',
10976             clickHandler: '=?'
10977         },
10978         replace: true,
10979         templateUrl: 'app/scripts/ng_js_att_tpls/pagination/pagination.html',
10980         link: function(scope) {
10981             scope.focusedPage;
10982             scope.$watch('totalPages', function(value) {
10983                 if(angular.isDefined(value) && value !== null){
10984                     scope.pages = [];
10985                     if (value < 1) {
10986                         scope.totalPages = 1;
10987                         return;
10988                     }
10989                     if (value <= 7) {
10990                         for (var i = 1; i <= value; i++) {
10991                             scope.pages.push(i);
10992                         }
10993                     } else if (value > 7) {
10994                         var midVal = Math.ceil(value / 2);
10995                         scope.pages = [midVal - 1, midVal, midVal + 1];
10996                     }
10997                     currentPageChanged(1);
10998                 }
10999             });
11000             scope.$watch('currentPage', function(value) {
11001                 currentPageChanged(value);
11002             });
11003             var callbackHandler = function(num) {
11004                 if (angular.isFunction(scope.clickHandler)){
11005                     scope.clickHandler(num);
11006                 }
11007             };
11008             function currentPageChanged(value) {
11009                 if (angular.isDefined(value) && value !== null) {
11010                     if (!value || value < 1) {
11011                         value = 1;
11012                     }
11013                     if (value > scope.totalPages) {
11014                         value = scope.totalPages;
11015                     }
11016                     if(scope.currentPage !== value) {
11017                         scope.currentPage = value;
11018                         callbackHandler(scope.currentPage);
11019                     }
11020                     if (scope.totalPages > 7) {
11021                         if (value < scope.pages[0] && value > 3) {
11022                             scope.pages = [value, value + 1, value + 2];
11023                         } else if (value > scope.pages[2] && value < scope.totalPages - 2) {
11024                            scope.pages = [value - 2, value - 1, value];
11025                         } else if (value <= 3) {
11026                              scope.pages = [1, 2, 3];
11027                         } else if (value >= scope.totalPages - 2) {
11028                              scope.pages = [scope.totalPages - 2, scope.totalPages - 1, scope.totalPages];
11029                         }
11030                     }
11031                 }
11032             }
11033             scope.next = function(event) {
11034                 event.preventDefault();
11035                 if (scope.currentPage < scope.totalPages) {
11036                     scope.currentPage += 1;
11037                     callbackHandler(scope.currentPage);
11038                 }
11039             };
11040             scope.prev = function(event) {
11041                 event.preventDefault();
11042                 if (scope.currentPage > 1) {
11043                     scope.currentPage -= 1;
11044                     callbackHandler(scope.currentPage);
11045                 }
11046             };
11047             scope.selectPage = function(value, event) {
11048                 event.preventDefault();
11049                 scope.currentPage = value;
11050                 scope.focusedPage = value;
11051                 callbackHandler(scope.currentPage);
11052             };
11053             scope.checkSelectedPage = function(value) {
11054                 if(scope.currentPage === value) {
11055                     return true;
11056                 }
11057                 return false;
11058             };
11059             scope.isFocused = function(page) {
11060                  return scope.focusedPage === page;
11061             };
11062         }
11063     };
11064 }]);
11065
11066 angular.module('att.abs.paneSelector',[])
11067 .constant('paneGroupConstants',{
11068     SIDE_WIDTH_DEFAULT: '33%',
11069     INNER_PANE_DEFAULT: '67%',
11070     SIDE_PANE_ID: 'sidePane',
11071     NO_DRILL_DOWN: 'none'
11072 })
11073 .factory('animation', function(){
11074     return TweenLite;
11075 })
11076 .directive('sideRow', [function(){
11077     return {
11078         restrict: 'A',
11079                 replace:true,
11080                 require: ['^sidePane','^paneGroup'],
11081                 link: function(scope,element,attr,ctrls){
11082                         var sidePaneCtrl = ctrls[0];
11083                         var paneGroupCtrl = ctrls[1];
11084                         if(scope.$first){
11085                                 /*
11086                                         Reset the sidePaneId array if a new
11087                                         set of ngRepeat data appeared
11088                                 */
11089                                 sidePaneCtrl.sidePaneIds = [];
11090                         }
11091
11092                         var paneId =attr['paneId'];
11093                         var drillDownTo = attr['drillDownTo'];
11094
11095                         sidePaneCtrl.sidePaneRows.push({'paneId':paneId, 'drillDownTo':drillDownTo});
11096                         element.on('click', function(){
11097                                 sidePaneCtrl.currentSelectedRowPaneId = paneId;
11098                                 paneGroupCtrl.slideOutPane(paneId,true);
11099                         });
11100                 }
11101         };
11102 }])
11103 .controller('SidePaneCtrl',['$scope', '$element','animation', 'paneGroupConstants',
11104  function($scope,$element,animation, paneGroupConstants){
11105
11106         this.sidePaneTracker = {};
11107         this.currentWidth = paneGroupConstants.SIDE_WIDTH_DEFAULT;
11108         this.paneId = paneGroupConstants.SIDE_PANE_ID;
11109         this.currentSelectedRowPaneId;
11110
11111         this.drillDownToMapper = {};
11112
11113         this.sidePaneRows = [];
11114
11115         this.init = function(){
11116
11117                 var sidePaneRows = this.sidePaneRows;
11118
11119                 if(sidePaneRows){
11120                         for(var index in sidePaneRows){
11121                 if (sidePaneRows.hasOwnProperty(index)) {
11122                     var paneId = sidePaneRows[index].paneId;
11123                     var drillDownTo = sidePaneRows[index].drillDownTo;
11124
11125                     this.drillDownToMapper[paneId] = drillDownTo;
11126
11127                     if(index === 0){
11128                         this.currentSelectedRowPaneId = paneId;
11129                         this.sidePaneTracker[paneId] = [];
11130                     }
11131                 }
11132                         }
11133                 }
11134         };
11135
11136         this.getSidePanesList = function(){
11137                 return this.sidePaneTracker[this.currentSelectedRowPaneId];
11138         };
11139
11140         this.addToSidePanesList = function(newPaneId){
11141                 if(this.sidePaneTracker[this.currentSelectedRowPaneId] === undefined){
11142                         this.sidePaneTracker[this.currentSelectedRowPaneId] = [];
11143         }
11144                 else if(newPaneId){
11145             this.sidePaneTracker[this.currentSelectedRowPaneId].push(newPaneId);
11146                 }
11147         };
11148
11149         this.setWidth = function(val){
11150                 if(val){
11151                         this.currentWidth = val;
11152         }
11153                 animation.set($element,{width:this.currentWidth});
11154         };
11155
11156         this.resizeWidth = function(val){
11157                 if(val){
11158                         this.currentWidth = val;
11159         }
11160                 animation.to($element,.5,{width:val});
11161         };
11162
11163 }])
11164 .directive('sidePane', ['paneGroupConstants', function(paneGroupConstants){
11165         return {
11166                 restrict: 'EA',
11167                 transclude: true,
11168                 replace: true,
11169                 templateUrl: 'app/scripts/ng_js_att_tpls/paneSelector/sidePane.html',
11170                 require: ['^paneGroup', 'sidePane'],
11171                 controller: 'SidePaneCtrl',
11172                 scope:{},
11173                 link: function(scope,element,attr, ctrls){
11174                         var paneGroupCtrl = ctrls[0];
11175                         var sidePaneCtrl = ctrls[1];
11176                         paneGroupCtrl.addPaneCtrl(paneGroupConstants.SIDE_PANE_ID, sidePaneCtrl);
11177                 }
11178         };
11179 }])
11180 .directive('drillDownRow', ['$parse', 'paneGroupConstants',function($parse,paneGroupConstants){
11181         return {
11182                 restrict: 'A',
11183                 replace:true,
11184                 require: ['^innerPane','^paneGroup'],
11185                 link: function(scope,element,attr,ctrls){
11186                         var innerPaneCtrl = ctrls[0];
11187                         var paneGroupCtrl = ctrls[1];
11188
11189                         element.on('click', function(){
11190                                 var drillDownTo = innerPaneCtrl.drillDownTo;
11191
11192                                 if(innerPaneCtrl.drillDownTo !== paneGroupConstants.NO_DRILL_DOWN){
11193                                         paneGroupCtrl.slideOutPane(drillDownTo);
11194                 }
11195                         });
11196                 }
11197         };
11198 }])
11199 .controller('InnerPaneCtrl', ['$scope', '$element','animation', 'paneGroupConstants',
11200         function($scope,$element,animation,paneGroupConstants){
11201
11202         this.paneId = $scope.paneId;
11203         this.drillDownTo;
11204         this.currentWidth = paneGroupConstants.INNER_PANE_DEFAULT;
11205
11206         this.setWidth = function(val){
11207                 if(val){
11208                         this.currentWidth = val;
11209         }
11210                 animation.set($element,{width:this.currentWidth});
11211         };
11212
11213         this.resizeWidth = function(val,callback){
11214                 animation.to($element,.25,{width:val,onComplete: callback});
11215         };
11216
11217         this.displayNone = function(){
11218                 animation.set($element, {display:'none'});
11219         };
11220
11221         this.displayBlock = function(){
11222                 animation.set($element,{display:'block'});
11223                 if(this){
11224                         this.hideRightBorder();
11225         }
11226         };
11227
11228         this.floatLeft = function(){
11229                 animation.set($element,{float:'left'});
11230         };
11231
11232         this.hideLeftBorder = function(){
11233                 animation.set($element, {borderLeftWidth: '0px'});
11234         };
11235
11236         this.showLeftBorder = function(){
11237                 animation.set($element,{borderLeftWidth: '1px'});
11238         };
11239
11240         this.hideRightBorder = function(){
11241                 animation.set($element,{borderRightWidth: '0px'});
11242         };
11243
11244         this.showRightBorder = function(){
11245                 animation.set($element, {borderRightWidth: '1px'});
11246         };
11247
11248         this.slideFromRight = function(){
11249                 animation.set($element, {float:'right'});
11250                 animation.set($element, {width: this.currentWidth});
11251         };
11252
11253         this.startOpen = function(){
11254                 return $scope.startOpen;
11255         };
11256
11257 }])
11258 .directive('innerPane', function(){
11259         return {
11260                 restrict: 'EA',
11261                 replace: true,
11262                 transclude: true,
11263                 templateUrl: 'app/scripts/ng_js_att_tpls/paneSelector/innerPane.html',
11264                 require: ['^paneGroup', 'innerPane'],
11265                 controller: 'InnerPaneCtrl',
11266                 scope:{
11267                         paneId:'@'
11268                 },
11269                 link: function(scope,element,attr,ctrls){
11270
11271                         if(attr.startOpen === ""){
11272                                 scope.startOpen  = true;
11273                         }
11274
11275                         var paneGroupCtrl = ctrls[0];
11276                         var innerPaneCtrl = ctrls[1];
11277                         paneGroupCtrl.addPaneCtrl(scope.paneId,innerPaneCtrl);
11278                 }
11279         };
11280 })
11281 .controller('PaneGroupCtrl', ['$scope', '$element', 'paneGroupConstants',function($scope,$element,paneGroupConstants){
11282         this.panes = {};
11283         this.accountLevelPaneModel = [];
11284
11285         this.title = $scope.title;
11286
11287         this.init = function(){
11288                 var sidePane = this.panes[paneGroupConstants.SIDE_PANE_ID];
11289
11290                 if(sidePane){
11291
11292                         sidePane.init();
11293
11294                         //Show the other panes that may be set to startOpen
11295                         //numOpen starts at 1 because of the side pane
11296                         var numOpen = 1;
11297             var key;
11298                         for(key in this.panes){
11299                 if(this.panes[key].startOpen && this.panes[key].startOpen()){
11300                     numOpen++;
11301                 }
11302             }
11303                         var width;
11304                         if(numOpen >= 3){
11305                                 width = ((100/numOpen)) + '%';
11306                         }
11307
11308
11309                         if(this.panes[sidePane.currentSelectedRowPaneId])
11310                         {
11311                                 if(width){
11312                                         sidePane.setWidth(width);
11313                                         this.panes[sidePane.currentSelectedRowPaneId].setWidth(width);
11314                                 }
11315                                 else{
11316                                         sidePane.setWidth();
11317                                         this.panes[sidePane.currentSelectedRowPaneId].setWidth();
11318                                 }
11319
11320                                 this.panes[sidePane.currentSelectedRowPaneId].displayBlock();
11321
11322                                 for(key in this.panes){
11323                     if(key !== paneGroupConstants.SIDE_PANE_ID && key !== sidePane.currentSelectedRowPaneId){
11324                         this.panes[key].displayNone();
11325                     }
11326                     this.panes[key].drillDownTo = sidePane.drillDownToMapper[key];
11327                 }
11328             }
11329             openOtherPanesOnStart(sidePane, this.panes);
11330         }
11331
11332                 function openOtherPanesOnStart(sidePane, panes){
11333                         //Build an array of the panes that need to be out
11334                         var otherPanesStartOpened = [];
11335             var index;
11336                         for(index in sidePane.sidePaneRows){
11337                 if (sidePane.sidePaneRows.hasOwnProperty(index)) {
11338                     var pane = sidePane.sidePaneRows[index];
11339
11340                     //Skip the first pane row since we handled it in the begining
11341                     if(index > 0 && panes[pane.paneId].startOpen && panes[pane.paneId].startOpen()){
11342                         otherPanesStartOpened.push(pane);
11343                         //Remember the panes that are opened for the first pane row Index
11344                         sidePane.addToSidePanesList(pane.paneId);
11345                     }
11346                 }
11347                         }
11348
11349             if(width){
11350                 for(index in otherPanesStartOpened){
11351                     if (otherPanesStartOpened.hasOwnProperty(index)) {
11352                         var paneId = otherPanesStartOpened[index].paneId;
11353                         var paneCtrl = panes[paneId];
11354
11355                         if(paneCtrl && paneCtrl.setWidth && paneCtrl.displayBlock){
11356                             paneCtrl.setWidth(width);
11357                             paneCtrl.displayBlock();
11358                         }
11359                     }
11360                 }
11361             }
11362
11363                 }
11364         };
11365
11366         /*
11367           Resets all the panels to their original positions at the end of a sidebar click
11368           By setting the sideBar to its default width
11369           Setting all panes to float left and displaynone
11370           Setting the pane that was clicked to default width and slide right
11371         */
11372
11373         this.resetPanes = function(){
11374                 for(var key in this.panes){
11375             if(this.panes.hasOwnProperty(key)){
11376                 var pane = this.panes[key];
11377                 if(pane && (pane.paneId !== paneGroupConstants.SIDE_PANE_ID)){
11378                     pane.floatLeft();
11379                     pane.displayNone();
11380                 }
11381             }
11382                 }
11383
11384                 if(this.panes[paneGroupConstants.SIDE_PANE_ID]){
11385                         this.panes[paneGroupConstants.SIDE_PANE_ID].setWidth(paneGroupConstants.SIDE_WIDTH_DEFAULT);
11386         }
11387         };
11388
11389         this.addPaneCtrl = function(paneId,paneCtrl){
11390                 this.panes[paneId] = paneCtrl;
11391         };
11392
11393         this._slideOutPane = function(paneId,isFromSidePane){
11394
11395                 this.resetPanes();
11396                 //Check current side pane stack to see how many panes are already open for that side pane choice
11397                 //then add the new pane that needs to be there
11398         var panesList;
11399                 if(isFromSidePane){
11400
11401                         //Check if the side pane id has already been clicked
11402                         if(this.panes[paneGroupConstants.SIDE_PANE_ID]){
11403                                         panesList = this.panes[paneGroupConstants.SIDE_PANE_ID].getSidePanesList();
11404             }
11405
11406                         if(!panesList){
11407
11408                                 if(this.panes && this.panes[paneGroupConstants.SIDE_PANE_ID] && this.panes[paneId]){
11409                                         this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId = paneId;
11410                                         this.panes[paneGroupConstants.SIDE_PANE_ID].addToSidePanesList();
11411
11412                                         this.panes[paneId].slideFromRight();
11413                                         this.panes[paneId].displayBlock();
11414
11415                                         this.panes[paneId].setWidth(paneGroupConstants.INNER_PANE_DEFAULT);
11416                                 }
11417
11418                         }
11419             else if(this.panes && this.panes[paneGroupConstants.SIDE_PANE_ID]){
11420                                 //Restore the panes based on the panelist
11421                                 if(panesList.length === 0 && this.panes[paneId]){
11422                                         //Only one pane is out
11423                     this.panes[paneGroupConstants.SIDE_PANE_ID].setWidth(paneGroupConstants.SIDE_WIDTH_DEFAULT);
11424                     this.panes[paneId].displayBlock();
11425                     this.panes[paneId].setWidth(paneGroupConstants.INNER_PANE_DEFAULT);
11426                                 }
11427                 else{
11428                     //Multiple panes out
11429                     var numPanes = panesList.length + 2;
11430                     var width = ((100/numPanes)) + '%';
11431                     this.panes[paneGroupConstants.SIDE_PANE_ID].setWidth(width);
11432
11433                     //Set the sidePanes pane
11434                     //set the panes children list
11435                     if(this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId]){
11436                         this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId].displayBlock();
11437                         this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId].setWidth(width);
11438                     }
11439
11440                     for(var i in panesList){
11441                         if(this.panes[panesList[i]]){
11442                             this.panes[panesList[i]].displayBlock();
11443                             this.panes[panesList[i]].setWidth(width);
11444                         }
11445                     }
11446                                 }
11447                         }
11448                 }
11449                 else{
11450
11451                         //Have to check the paneId that was given and where it is drilling down to
11452                         var isPaneInStack = false;
11453
11454                         var stackPaneList;
11455
11456                         if(this.panes[paneGroupConstants.SIDE_PANE_ID]){
11457                                 stackPaneList = this.panes[paneGroupConstants.SIDE_PANE_ID].getSidePanesList();
11458             }
11459
11460                         for(var j in stackPaneList){
11461                 if(stackPaneList.hasOwnProperty(j)){
11462                     var pId = stackPaneList[j];
11463                     if(pId === paneId){
11464                         isPaneInStack = true;
11465                         break;
11466                     }
11467                 }
11468                         }
11469
11470                         if(!isPaneInStack && this.panes[paneGroupConstants.SIDE_PANE_ID]){
11471                 this.panes[paneGroupConstants.SIDE_PANE_ID].addToSidePanesList(paneId);
11472                         }
11473
11474                         var sidePanesListLength;
11475
11476                         if(this.panes[paneGroupConstants.SIDE_PANE_ID]){
11477                                 sidePanesListLength = this.panes[paneGroupConstants.SIDE_PANE_ID].getSidePanesList().length;
11478             }
11479
11480                         var numberPanes = sidePanesListLength + 2;
11481                         var widthToSet = ((100/numberPanes)) + '%';
11482
11483                         if(this.panes[paneGroupConstants.SIDE_PANE_ID]){
11484                                 this.panes[paneGroupConstants.SIDE_PANE_ID].setWidth(widthToSet);
11485             }
11486
11487                         var slideInPaneId;
11488
11489                         if(this.panes[paneGroupConstants.SIDE_PANE_ID]){
11490                                 slideInPaneId = this.panes[paneGroupConstants.SIDE_PANE_ID].getSidePanesList()[sidePanesListLength - 1];
11491             }
11492
11493                         var that = this;
11494
11495                         if(that.panes[paneGroupConstants.SIDE_PANE_ID]){
11496                                 panesList = that.panes[paneGroupConstants.SIDE_PANE_ID].getSidePanesList();
11497             }
11498
11499                         for(var p in panesList){
11500                 if(panesList.hasOwnProperty(p)){
11501                     var paneListPaneId = panesList[p];
11502                     var pane = this.panes[paneListPaneId];
11503                     if(paneListPaneId !== slideInPaneId && pane){
11504                         pane.setWidth(widthToSet);
11505                         pane.displayBlock();
11506                         pane.floatLeft();
11507                     }
11508                 }
11509                         }
11510
11511                         if(this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId]){
11512                                 this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId].displayBlock();
11513                                 this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId].showRightBorder();
11514
11515                                 this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId].resizeWidth(width,function(){
11516
11517                                         if(that.panes[slideInPaneId] && that.panes[that.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId]){
11518                                                 that.panes[that.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId].hideRightBorder();
11519                                                 that.panes[slideInPaneId].setWidth(width);
11520                                                 that.panes[slideInPaneId].slideFromRight();
11521                                                 that.panes[slideInPaneId].displayBlock();
11522                                                 that.panes[slideInPaneId].floatLeft();
11523                                         }
11524
11525                                 });
11526                         }
11527                 }
11528         };
11529
11530         this.slideOutPane = function(paneId,isFromSidePane){
11531                 this._slideOutPane(paneId,isFromSidePane);
11532         };
11533
11534 }])
11535 .directive('paneGroup', ['$timeout',function($timeout){
11536         return {
11537                 restrict: 'EA',
11538                 transclude: true,
11539                 replace: true,
11540                 templateUrl: 'app/scripts/ng_js_att_tpls/paneSelector/paneGroup.html',
11541                 scope:{
11542                 },
11543                 controller: 'PaneGroupCtrl',
11544                 link: function(scope,element,attr,ctrl){
11545
11546                         $timeout(initialize,100);
11547
11548                         function initialize(){
11549                                 ctrl.init();
11550                         }
11551
11552                 }
11553         };
11554 }]);
11555 angular.module('att.abs.profileCard', [])
11556             .constant('profileStatus',{
11557                 status:{
11558                     ACTIVE:{status:"Active",color:"green"},
11559                     DEACTIVATED:{status:"Deactivated",color:"red"},
11560                     LOCKED:{status:"Locked",color:"red"},
11561                     IDLE:{status:"Idle",color:"yellow"},
11562                     PENDING:{status:"Pending",color:"blue"}
11563                     },
11564                 role:"COMPANY ADMINISTRATOR"
11565                 })
11566             .directive('profileCard',['$http','$q','profileStatus', function($http,$q,profileStatus) {
11567                return {
11568                     restrict: 'EA',
11569                     replace:'true',
11570                     templateUrl:function(element, attrs){
11571                         if(!attrs.addUser){
11572                             return 'app/scripts/ng_js_att_tpls/profileCard/profileCard.html';
11573                         }
11574                         else{
11575                             return 'app/scripts/ng_js_att_tpls/profileCard/addUser.html';
11576                         }
11577                     },
11578                     scope:{
11579                         profile:'='
11580                     },
11581                     link: function(scope, elem, attr){
11582                         scope.image=true;
11583                         function isImage(src) {
11584                             var deferred = $q.defer();
11585                             var image = new Image();
11586                             image.onerror = function() {
11587                                 deferred.reject(false);
11588                             };
11589                             image.onload = function() {
11590                                 deferred.resolve(true);
11591                             };
11592                             if(src!==undefined && src.length>0 ){
11593                                 image.src = src;
11594                             }else{
11595                                  deferred.reject(false);
11596                             }
11597                             return deferred.promise;
11598                         }
11599                         if(!attr.addUser){
11600                         scope.image=false;
11601                         isImage(scope.profile.img).then(function(img) {
11602                             scope.image=img;
11603                         });
11604                         var splitName=(scope.profile.name).split(' ');
11605                         scope.initials='';
11606                         for(var i=0;i<splitName.length;i++){
11607                             scope.initials += splitName[i][0];
11608                         }
11609                         if(scope.profile.role.toUpperCase()===profileStatus.role){
11610                             scope.badge=true;
11611                         }
11612                         var profileState=profileStatus.status[scope.profile.state.toUpperCase()];
11613                         if(profileState) {
11614                             scope.profile.state=profileStatus.status[scope.profile.state.toUpperCase()].status;
11615                             scope.colorIcon=profileStatus.status[scope.profile.state.toUpperCase()].color;
11616                             if(scope.profile.state.toUpperCase()===profileStatus.status.PENDING.status.toUpperCase()||scope.profile.state.toUpperCase()===profileStatus.status.LOCKED.status.toUpperCase()){
11617                                     scope.profile.lastLogin=scope.profile.state;
11618                             }
11619                         }
11620                         var today=new Date().getTime();
11621                         var lastlogin=new Date(scope.profile.lastLogin).getTime();
11622                         var diff=(today-lastlogin)/(1000*60*60*24);
11623                         if(diff<=1){
11624                             scope.profile.lastLogin="Today";
11625                         }
11626                         else if(diff<=2){
11627                             scope.profile.lastLogin="Yesterday";
11628                         }
11629                     }
11630                 }
11631             };
11632         }]);
11633 angular.module('att.abs.progressBars', [])
11634
11635 .directive('attProgressBar', [function(){
11636     return {
11637         restrict: 'A',
11638         replace: true,
11639         templateUrl : 'app/scripts/ng_js_att_tpls/progressBars/progressBars.html'
11640     };
11641 }]);
11642 angular.module('att.abs.radio', [])
11643     .constant('attRadioConfig', {
11644         activeClass : "att-radio--on",
11645         disabledClass : "att-radio--disabled"
11646     })
11647 .directive('attRadio', ['$compile','attRadioConfig', function ($compile, attRadioConfig) {
11648     return {
11649         scope: {},
11650         restrict: 'A',
11651         require: 'ngModel',
11652         link: function (scope, element, attr, ctrl) {
11653             var ngCtrl = ctrl;
11654             var parentDiv = $compile('<div tabindex="0" role="radio" att-accessibility-click="13,32" ng-click="updateModel($event)" class="att-radio"></div>')(scope);
11655
11656             element.wrap(parentDiv);
11657             element.parent().append('<div class="att-radio__indicator"></div>');
11658             element.parent().attr("title", attr.title);
11659             element.attr("tabindex","-1");
11660
11661             ngCtrl.$render = function () {
11662                 var selected = angular.equals(ngCtrl.$modelValue, attr.attRadio);
11663                 element.parent().toggleClass(attRadioConfig.activeClass, selected);
11664                 element.parent().attr("aria-checked", selected);
11665             };
11666
11667             scope.updateModel = function (evt) {
11668                 var isActive = element.parent().hasClass(attRadioConfig.activeClass);
11669
11670                 if (!isActive && !scope.disabled) {
11671                     ngCtrl.$setViewValue(isActive ? null : attr.attRadio);
11672                     ngCtrl.$render();
11673                 }
11674                 evt.preventDefault();
11675             };
11676
11677             attr.$observe('disabled', function (val) {
11678                 scope.disabled = (val || val === "disabled" || val === "true");
11679                 element.parent().toggleClass(attRadioConfig.disabledClass, scope.disabled);
11680                 element.parent().attr("tabindex", scope.disabled ? "-1" : "0");
11681             });
11682         }
11683     };
11684 }]);
11685
11686 angular.module('att.abs.scrollbar', [])
11687     .constant('attScrollbarConstant', {
11688         defaults : {
11689              // Vertical or horizontal scrollbar? ( x || y ).
11690                 axis: 'y',
11691                 // Enable or disable the mousewheel.
11692                 wheel: true,
11693                 // How many pixels must the mouswheel scroll at a time.
11694                 wheelSpeed: 40,
11695                 // Lock default scrolling window when there is no more content.
11696                 wheelLock: true,
11697                 //// Enable invert style scrolling
11698                 scrollInvert: false,
11699                 // Set the size of the scrollbar to auto or a fixed number.
11700                 trackSize: false,
11701                 // Set the size of the thumb to auto or a fixed number.
11702                 thumbSize: false,
11703                 // Set to false to hide the scrollbar if not being used
11704                alwaysVisible: true
11705            }
11706     })
11707             .directive('attScrollbar', ['$window', '$timeout', '$parse', '$animate', 'attScrollbarConstant',
11708         function ($window, $timeout, $parse, $animate, attScrollbarConstant) {
11709     return {
11710         restrict: 'A',
11711         transclude: true,
11712         templateUrl: 'app/scripts/ng_js_att_tpls/scrollbar/scrollbar.html',
11713         controller: ['$scope','$element','$attrs', function($scope, $element, $attrs)  {
11714             var defaults =attScrollbarConstant.defaults;
11715             var options = $attrs.scrollbar;
11716             if (options) {
11717                 options = $parse(options)($scope);
11718             } else {
11719                 options = {};
11720             }
11721             this.options = angular.extend({}, defaults, options);
11722             this._defaults = defaults;
11723
11724             var self = this,
11725                     $body = angular.element(document.querySelectorAll('body')[0]),
11726                     $document = angular.element(document),
11727                     $viewport = angular.element($element[0].querySelectorAll('.scroll-viewport')[0]),
11728                     $overview = angular.element($element[0].querySelectorAll('.scroll-overview')[0]),
11729                     $scrollbar = angular.element($element[0].querySelectorAll('.scroll-bar')[0]),
11730                     $thumb = angular.element($element[0].querySelectorAll('.scroll-thumb')[0]),
11731                     mousePosition = 0,
11732                     isHorizontal = this.options.axis === 'x',
11733                     hasTouchEvents=false,
11734                     // Modern browsers support "wheel"
11735                     wheelEvent = ("onwheel" in document ? "wheel" :
11736                             // Webkit and IE support at least "mousewheel"
11737                             document.onmousewheel !== undefined ? "mousewheel" :
11738                                     // let's assume that remaining browsers are older Firefox
11739                             "DOMMouseScroll"),
11740                             sizeLabel = isHorizontal ? 'width' : 'height',
11741                     sizeLabelCap = sizeLabel.charAt(0).toUpperCase() + sizeLabel.slice(1).toLowerCase(),
11742                     posiLabel = isHorizontal ? 'left' : 'top',
11743                     // moveEvent = document.createEvent('HTMLEvents'),
11744                     restoreVisibilityAfterWheel,
11745                     thumbscrolltouch=false,documnetscrolltouch=false;
11746                 if(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
11747                     hasTouchEvents = true;
11748                 }
11749                             this.contentPosition = 0;
11750                             this.viewportSize = 0;
11751                             this.contentSize = 0;
11752                             this.contentRatio = 0;
11753                             this.trackSize = 0;
11754                             this.trackRatio = 0;
11755                             this.thumbSize = 0;
11756                             this.thumbPosition = 0;
11757
11758             this.initialize = function() {
11759                 if (!this.options.alwaysVisible) {
11760                     $scrollbar.css('opacity', 0);
11761                 }
11762                 self.update();
11763                 setEvents();
11764                 return self;
11765             };
11766             this.setSizeData = function() {
11767                 this.viewportSize = $viewport.prop('offset' + sizeLabelCap) || 1;
11768                 this.contentSize = $overview.prop('scroll' + sizeLabelCap) || 1;
11769                 this.contentRatio = this.viewportSize / this.contentSize;
11770                 this.trackSize = this.options.trackSize || this.viewportSize;
11771                 this.thumbSize = Math.min(this.trackSize, Math.max(0, (this.options.thumbSize || (this.trackSize * this.contentRatio))));
11772                 this.trackRatio = this.options.thumbSize ? (this.contentSize - this.viewportSize) / (this.trackSize - this.thumbSize) : (this.contentSize / this.trackSize);
11773             };
11774             this.update = function(scrollTo) {
11775                 self.setSizeData();
11776                 mousePosition = $scrollbar.prop('offsetTop');
11777
11778                 $scrollbar.toggleClass('disable', this.contentRatio >= 1 || isNaN(this.contentRatio));
11779
11780                 if (!this.options.alwaysVisible && this.contentRatio < 1 && this.viewportSize > 0) {
11781                     //flash the scrollbar when update happens
11782                     $animate.addClass($scrollbar, 'visible').then(function() {
11783                         $animate.removeClass($scrollbar, 'visible');
11784                         $scope.$digest();
11785                     });
11786                 }
11787                 if (scrollTo !== null) {
11788                 if (scrollTo==='bottom') {
11789                      this.contentPosition = this.contentSize - this.viewportSize;
11790                  }else{
11791                      this.contentPosition = parseInt(scrollTo, 10) || 0;
11792                      }
11793                  }
11794                  ensureContentPosition();
11795                 $thumb.css(posiLabel, self.contentPosition / self.trackRatio + 'px');
11796                 $scrollbar.css(sizeLabel, self.trackSize + 'px');
11797                 $thumb.css(sizeLabel, self.thumbSize + 'px');
11798                 $overview.css(posiLabel, -self.contentPosition + 'px');
11799
11800                 return this;
11801             };
11802             fireEvent = function(obj, evt) {
11803                 var fireOnThis = obj;
11804                 var evtObj;
11805                 if (document.createEvent) {
11806                     evtObj = document.createEvent('HTMLEvents');
11807                     evtObj.initEvent(evt, true, false);
11808                     fireOnThis.dispatchEvent(evtObj);
11809                 }
11810                 else if (document.createEventObject) {
11811                     evtObj = document.createEventObject();
11812                     fireOnThis.fireEvent('on' + evt, evtObj);
11813                 }
11814             };
11815             function ensureContentPosition() {
11816                 // if scrollbar is on, ensure the bottom of the content does not go above the bottom of the viewport
11817                 if (self.contentRatio <= 1 && self.contentPosition > self.contentSize - self.viewportSize) {
11818                     self.contentPosition = self.contentSize - self.viewportSize;
11819                 }
11820                 // if scrollbar is off, ensure the top of the content does not go below the top of the viewport
11821                 else if (self.contentRatio > 1 && self.contentPosition > 0) {
11822                     self.contentPosition = 0;
11823                 }
11824             }
11825
11826             function setEvents() {
11827
11828                 if (hasTouchEvents) {
11829                     $viewport.on('touchstart', touchstart);
11830                     $thumb.on('touchstart', touchstart);
11831                 }
11832                 else {
11833                     $thumb.on('mousedown', start);
11834                     $scrollbar.on('mousedown', drag);
11835                 }
11836
11837                 angular.element($window).on('resize', resize);
11838
11839                 if (self.options.wheel) {
11840                     $element.on(wheelEvent, wheel);
11841                 }
11842             }
11843
11844             function resize() {
11845                 self.update();
11846             }
11847
11848             function touchstart(event) {
11849                 if (1 === event.touches.length) {
11850                     event.stopPropagation();
11851                     start(event.touches[0]);
11852                 }
11853             }
11854
11855             function start(event) {
11856                 $body.addClass('scroll-no-select');
11857                 $element.addClass('scroll-no-select');
11858
11859                 if (!self.options.alwaysVisible) {
11860                     $scrollbar.addClass('visible');
11861                 }
11862                 mousePosition = isHorizontal ? event.clientX : event.clientY;
11863                 self.thumbPosition = parseInt($thumb.css(posiLabel), 10) || 0;
11864                 if (hasTouchEvents) {
11865                     documnetscrolltouch=false;
11866                     thumbscrolltouch=false;
11867                     $viewport.on('touchmove', touchdrag);
11868                     $thumb.on('touchmove',touchdragthumb);
11869                     $thumb.on('touchend', end);
11870                 } else {
11871                     $document.on('mousemove', drag);
11872                     $document.on('mouseup', end);
11873                     $thumb.on('mouseup', end);
11874                 }
11875             }
11876
11877             function wheel(event) {
11878
11879                 if (self.contentRatio >= 1) {
11880                     return;
11881                 }
11882
11883                 if (!self.options.alwaysVisible) {
11884                     //cancel removing visibility if wheel event is triggered before the timeout
11885                     if (restoreVisibilityAfterWheel) {
11886                         $timeout.cancel(restoreVisibilityAfterWheel);
11887                     }
11888                     $scrollbar.addClass('visible');
11889
11890                     restoreVisibilityAfterWheel = $timeout(function() {
11891                         $scrollbar.removeClass('visible');
11892                     }, 100);
11893                 }
11894
11895
11896                 var evntObj = (event && event.originalEvent) || event || $window.event,
11897                         deltaDir = self.options.axis.toUpperCase(),
11898                         delta = {
11899                             X: evntObj.deltaX,
11900                             Y: evntObj.deltaY
11901                         },
11902                 wheelSpeed = evntObj.deltaMode === 0 ? self.options.wheelSpeed : 1;
11903
11904                 if (self.options.scrollInvert) {
11905                     wheelSpeed *= -1;
11906                 }
11907
11908                 if (wheelEvent === 'mousewheel') {
11909                     delta.Y = -1 * evntObj.wheelDelta / 40;
11910                     if(evntObj.wheelDeltaX){
11911                    delta.X = -1 * evntObj.wheelDeltaX / 40;
11912                }
11913                 }
11914                 delta.X *= -1 / wheelSpeed;
11915                 delta.Y *= -1 / wheelSpeed;
11916
11917                 var wheelSpeedDelta = delta[deltaDir];
11918
11919                 self.contentPosition -= wheelSpeedDelta * self.options.wheelSpeed;
11920                 self.contentPosition = Math.min((self.contentSize - self.viewportSize), Math.max(0, self.contentPosition));
11921                 fireEvent($element[0], 'move');
11922
11923                 ensureContentPosition();
11924                 $thumb.css(posiLabel, self.contentPosition / self.trackRatio + 'px');
11925                 $overview.css(posiLabel, -self.contentPosition + 'px');
11926
11927                 if (self.options.wheelLock || (self.contentPosition !== (self.contentSize - self.viewportSize) && self.contentPosition !== 0)) {
11928                     evntObj.preventDefault();
11929                 }
11930             }
11931
11932             function touchdrag(event) {
11933                 event.preventDefault();
11934                 documnetscrolltouch=true;
11935                 drag(event.touches[0]);
11936             }
11937             function touchdragthumb(event){
11938                 event.preventDefault();
11939                 thumbscrolltouch=true;
11940                 drag(event.touches[0]);
11941             }
11942
11943             function drag(event) {
11944
11945                 if (self.contentRatio >= 1) {
11946                     return;
11947                 }
11948                 var mousePositionNew = isHorizontal ? event.clientX : event.clientY,
11949                         thumbPositionDelta = mousePositionNew - mousePosition;
11950
11951                 if ((self.options.scrollInvert && !hasTouchEvents) ||
11952                         (hasTouchEvents && !self.options.scrollInvert))
11953                 {
11954                     thumbPositionDelta = mousePosition - mousePositionNew;
11955                 }
11956                 if(documnetscrolltouch && hasTouchEvents){
11957                         thumbPositionDelta = mousePosition - mousePositionNew;
11958                 }
11959                 if(thumbscrolltouch && hasTouchEvents){
11960                     thumbPositionDelta = mousePositionNew - mousePosition;
11961                 }
11962                 var thumbPositionNew = Math.min((self.trackSize - self.thumbSize), Math.max(0, self.thumbPosition + thumbPositionDelta));
11963                 self.contentPosition = thumbPositionNew * self.trackRatio;
11964                 fireEvent($element[0], 'move');
11965
11966                 ensureContentPosition();
11967                 $thumb.css(posiLabel, thumbPositionNew + 'px');
11968                 $overview.css(posiLabel, -self.contentPosition + 'px');
11969             }
11970
11971             function end() {
11972
11973                 $body.removeClass('scroll-no-select');
11974                 $element.removeClass('scroll-no-select');
11975                 if (!self.options.alwaysVisible) {
11976                     $scrollbar.removeClass('visible');
11977                 }
11978                 $document.off('mousemove', drag);
11979                 $document.off('mouseup', end);
11980                 $thumb.off('mouseup', end);
11981                 $document.off('touchmove', touchdrag);
11982                 $document.off('ontouchend', end);
11983                 $thumb.off('touchmove',touchdragthumb);
11984                 $thumb.off('touchend', end);
11985             }
11986             this.cleanup = function() {
11987                 $viewport.off('touchstart', touchstart);
11988                 $thumb.off('mousedown', start);
11989                 $scrollbar.off('mousedown', drag);
11990                 $thumb.off('touchmove',touchdragthumb);
11991                 $thumb.off('touchend', end);
11992                 angular.element($window).off('resize', resize);
11993                 $element.off(wheelEvent, wheel);
11994                 //ensure scrollbar isn't activated
11995                 self.options.alwaysVisible = true;
11996                 end();
11997             };
11998
11999         }],
12000         link: function(scope, iElement, iAttrs, controller) {
12001             var position = iElement.css('position');
12002             if (position !== 'relative' && position !== 'absolute') {
12003                 iElement.css('position', 'relative');
12004             }
12005             scope.$watch(function() {
12006                 $timeout(function() {
12007                     var $overview = angular.element(iElement[0].querySelectorAll('.scroll-overview')[0]);
12008                     var newValue = $overview.prop('scrollHeight');
12009                     var oldValue = scope.oldValue;
12010                     if (newValue !== oldValue) {
12011                         scope.oldValue = newValue;
12012                         controller.update();
12013                     }
12014                 }, 100, false);
12015             });
12016             controller.initialize();
12017             iElement.on('$destroy', function() {
12018                 controller.cleanup();
12019             });
12020         }
12021     };
12022 }]);
12023 angular.module('att.abs.search', ['att.abs.utilities', 'att.abs.position', 'att.abs.utilities'])
12024 .directive('attSearch', ["$document", "$filter", "$isElement", '$documentBind', "$timeout", "keymap", function($document,$filter,$isElement,$documentBind,$timeout,keymap){
12025     return{
12026         restrict: 'A',
12027         scope:{cName: '=attSearch'},
12028         transclude: false,
12029         replace: false,
12030         require:'ngModel',
12031         templateUrl: 'app/scripts/ng_js_att_tpls/search/search.html',
12032         link: function(scope, element, attr, ctrl) {
12033             scope.selectedIndex = -1;
12034             scope.selectedOption = attr.placeholder;
12035             scope.isDisabled = false;
12036             scope.className = "select2-match";
12037             scope.showSearch = false;
12038             scope.showlist = false;
12039             if(attr.placeholderAsOption === "false")
12040             {
12041                 scope.selectMsg = "";
12042             }
12043             else
12044             {
12045                 scope.selectMsg = attr.placeholder;
12046             }
12047             if (attr.startsWithFilter === "true" || attr.startsWithFilter) {
12048                 scope.startsWithFilter = true;
12049             }
12050             if(attr.showInputFilter === "true"){
12051                 scope.showSearch = true;
12052             }
12053             scope.showDropdown = function(){
12054                 if(!(attr.disabled)){
12055                     scope.showlist = !scope.showlist;
12056                     scope.setSelectTop();
12057                 }
12058             };
12059             element.bind("keydown", function(e){
12060                 if (keymap.isAllowedKey(e.keyCode) || keymap.isControl(e) || keymap.isFunctionKey(e))
12061                 {
12062                     e.preventDefault();
12063                     e.stopPropagation();
12064
12065                     switch (e.keyCode) {
12066                         case keymap.KEY.DOWN:
12067                             scope.selectNext();
12068                             break;
12069                         case keymap.KEY.UP:
12070                             scope.selectPrev();
12071                             break;
12072                         case keymap.KEY.ENTER:
12073                             scope.selectCurrent();
12074                             break;
12075                         case keymap.KEY.BACKSPACE:
12076                             scope.title = "";
12077                             scope.$apply();
12078                             break;
12079                         case keymap.KEY.SPACE:
12080                             scope.title += " ";
12081                             scope.$apply();
12082                             break;
12083                         case keymap.KEY.ESC:
12084                             if(scope.title === "")
12085                             {
12086                                 scope.showlist = false;
12087                                 scope.$apply();
12088                             }
12089                             else
12090                             {
12091                                 scope.title = "";
12092                                 scope.$apply();
12093                             }
12094                             break;
12095                         default:;
12096                     }
12097                 }
12098                 else
12099                 {
12100                     if(typeof scope.showSearch === 'boolean' && !scope.showSearch && e.keyCode !== 9)
12101                     {
12102                         scope.showlist = true;
12103                         scope.title = scope.title ? scope.title + String.fromCharCode(e.keyCode):String.fromCharCode(e.keyCode);
12104                         scope.$apply();
12105                     }
12106                     else if(e.keyCode === 9)
12107                     {
12108                         scope.showlist = false;
12109                         scope.title = "";
12110                         scope.$apply();
12111                     }
12112                 }
12113             });
12114             scope.selectOption = function(sTitle,sIndex,keepOpen)
12115             {
12116                 if(sIndex === -1 || sIndex === '-1'){
12117                    scope.selCategory = "";
12118                    scope.selectedIndex = -1;
12119                    ctrl.$setViewValue("");
12120                    scope.selectedOption = scope.selectMsg;
12121                 }
12122                 else
12123                 {
12124                     scope.selCategory = scope.cName[sIndex];
12125                     scope.selectedIndex = sIndex;
12126                     ctrl.$setViewValue(scope.selCategory);
12127                     scope.selectedOption = scope.selCategory.title;
12128                 }
12129                 scope.title = "";
12130                 if(!keepOpen)
12131                 {
12132                     scope.showlist = false;
12133                 }
12134             };
12135             if(attr.disabled)
12136             {
12137                scope.isDisabled = true;
12138             }
12139             scope.selectCurrent = function()
12140             {
12141                 if(scope.showlist)
12142                 {
12143                     scope.selectOption(scope.selectMsg,scope.selectedIndex ,false);
12144                     scope.$apply();
12145                 }
12146                 else
12147                 {
12148                     scope.showlist = true;
12149                     scope.setSelectTop();
12150                     scope.$apply();
12151                 }
12152             };
12153             scope.hoverIn = function(cItem)
12154             {
12155                 scope.selectedIndex = cItem;
12156             };
12157             scope.setSelectTop = function()
12158             {
12159                 $timeout(function ()
12160                 {
12161                     if(scope.showlist)
12162                     {
12163                         var containerUL = angular.element(element)[0].querySelector(".select2-results");
12164                         var selectedElemTopPos = angular.element(containerUL.querySelector('.select2-result-current'))[0].offsetTop;
12165                         angular.element(containerUL)[0].scrollTop = selectedElemTopPos;
12166                     }
12167                 });
12168             };
12169             scope.setCurrentTop = function()
12170             {
12171                 $timeout(function ()
12172                 {
12173                     if(scope.showlist)
12174                     {
12175                         var containerUL = angular.element(element)[0].querySelector(".select2-results");
12176                         var selectedElemTopPos = angular.element(containerUL.querySelector('.hovstyle'))[0].offsetTop;
12177                         if(selectedElemTopPos < (angular.element(containerUL)[0].scrollTop) )
12178                         {
12179                             angular.element(containerUL)[0].scrollTop -= 30;
12180                         }
12181                         else if((selectedElemTopPos + 30) > (angular.element(containerUL)[0].clientHeight))
12182                         {
12183                             angular.element(containerUL)[0].scrollTop += 30;
12184                         }
12185
12186                     }
12187                 });
12188             };
12189             scope.selectNext = function()
12190             {
12191                 if((scope.selectedIndex + 1) <= (scope.cName.length-1))
12192                 {
12193                     scope.selectedIndex += 1;
12194                     if(!scope.showlist)
12195                     {
12196                         scope.selectOption(scope.selectMsg,scope.selectedIndex ,false);
12197                     }
12198                     scope.$apply();
12199                 }
12200                 scope.setCurrentTop();
12201             };
12202             scope.selectPrev = function()
12203             {
12204                 if((scope.selectedIndex - 1) >= 0)
12205                 {
12206                     scope.selectedIndex -= 1;
12207                     if(!scope.showlist)
12208                     {
12209                         scope.selectOption(scope.selectMsg,scope.selectedIndex ,false);
12210                     }
12211                     scope.$apply();
12212                 }
12213                 else if(scope.selectedIndex -1 < 0)
12214                 {
12215                     scope.selectedIndex = -1;
12216                     if(!scope.showlist)
12217                     {
12218                         scope.selectOption(scope.selectMsg,scope.selectedIndex ,false);
12219                     }
12220                     scope.$apply();
12221                 }
12222                 scope.setCurrentTop();
12223
12224             };
12225             scope.updateSelection = function(sItem)
12226             {
12227                 scope.selectedOption = sItem.title;
12228                 scope.title = "";
12229             };
12230             scope.$watch('selCategory',function(value)
12231             {
12232                 if(value){
12233                     scope.updateSelection(value);
12234                 };
12235             });
12236             ctrl.$viewChangeListeners.push(function(){
12237                 scope.$eval(attr.ngChange);
12238             });
12239             ctrl.$render = function(){
12240                 scope.selCategory = ctrl.$viewValue;
12241             };
12242             var outsideClick = function(e){
12243                 var isElement = $isElement(angular.element(e.target), element, $document);
12244                 if(!isElement) {
12245                     scope.showlist = false;
12246                     scope.$apply();
12247                 }
12248             };
12249             $documentBind.click('showlist', outsideClick, scope);
12250         }
12251     };
12252 }]);
12253
12254 angular.module('att.abs.select', ['att.abs.utilities', 'att.abs.position', 'att.abs.utilities'])
12255 .directive('attSelect', ["$document", "$filter", "$isElement", '$documentBind', "$timeout", "keymap", function($document,$filter,$isElement,$documentBind,$timeout,keymap){
12256     return{
12257         restrict: 'A',
12258         scope:{cName: '=attSelect'},
12259         transclude: false,
12260         replace: false,
12261         require:'ngModel',
12262         templateUrl: 'app/scripts/ng_js_att_tpls/select/select.html',
12263         link: function(scope, element, attr, ctrl) {
12264             scope.selectedIndex = -1;
12265             scope.selectedOption = attr.placeholder;
12266             scope.isDisabled = false;
12267             scope.className = "select2-match";
12268             scope.showSearch = false;
12269             scope.showlist = false;
12270             if(attr.placeholderAsOption === "false")
12271             {
12272                 scope.selectMsg = "";
12273             }
12274             else
12275             {
12276                 scope.selectMsg = attr.placeholder;
12277             }
12278             if (attr.startsWithFilter === "true" || attr.startsWithFilter) {
12279                 scope.startsWithFilter = true;
12280             }
12281             if(attr.showInputFilter === "true"){
12282                 scope.showSearch = true;
12283             }
12284             scope.showDropdown = function(){
12285                 if(!(attr.disabled)){
12286                     scope.showlist = !scope.showlist;
12287                     scope.setSelectTop();
12288                 }
12289             };
12290             element.bind("keydown", function(e){
12291                 if (keymap.isAllowedKey(e.keyCode) || keymap.isControl(e) || keymap.isFunctionKey(e))
12292                 {
12293                     e.preventDefault();
12294                     e.stopPropagation();
12295
12296                     switch (e.keyCode) {
12297                         case keymap.KEY.DOWN:
12298                             scope.selectNext();
12299                             break;
12300                         case keymap.KEY.UP:
12301                             scope.selectPrev();
12302                             break;
12303                         case keymap.KEY.ENTER:
12304                             scope.selectCurrent();
12305                             break;
12306                         case keymap.KEY.BACKSPACE:
12307                             scope.title = "";
12308                             scope.$apply();
12309                             break;
12310                         case keymap.KEY.SPACE:
12311                             scope.title += " ";
12312                             scope.$apply();
12313                             break;
12314                         case keymap.KEY.ESC:
12315                             if(scope.title === "")
12316                             {
12317                                 scope.showlist = false;
12318                                 scope.$apply();
12319                             }
12320                             else
12321                             {
12322                                 scope.title = "";
12323                                 scope.$apply();
12324                             }
12325                             break;
12326                         default:;
12327                     }
12328                 }
12329                 else
12330                 {
12331                     if(typeof scope.showSearch === 'boolean' && !scope.showSearch && e.keyCode !== 9)
12332                     {
12333                         scope.showlist = true;
12334                         scope.title = scope.title ? scope.title + String.fromCharCode(e.keyCode):String.fromCharCode(e.keyCode);
12335                         scope.$apply();
12336                     }
12337                     else if(e.keyCode === 9)
12338                     {
12339                         scope.showlist = false;
12340                         scope.title = "";
12341                         scope.$apply();
12342                     }
12343                 }
12344             });            
12345             scope.selectOption = function(sTitle,sIndex,keepOpen)
12346             {
12347                 if(sIndex === -1 || sIndex === '-1'){
12348                    scope.selCategory = "";
12349                    scope.selectedIndex = -1;
12350                    ctrl.$setViewValue("");
12351                    scope.selectedOption = scope.selectMsg;
12352                 }
12353                 else
12354                 {
12355                     scope.selCategory = scope.cName[sIndex];
12356                     scope.selectedIndex = sIndex;
12357                     ctrl.$setViewValue(scope.selCategory);
12358                     scope.selectedOption = scope.selCategory.title;
12359                 }
12360                 scope.title = "";
12361                 if(!keepOpen)
12362                 {
12363                     scope.showlist = false;
12364                 }
12365             };
12366             if(attr.disabled)
12367             {
12368                scope.isDisabled = true;
12369             }
12370             scope.selectCurrent = function()
12371             {
12372                 if(scope.showlist)
12373                 {
12374                     scope.selectOption(scope.selectMsg,scope.selectedIndex ,false);
12375                     scope.$apply();
12376                 }
12377                 else
12378                 {
12379                     scope.showlist = true;
12380                     scope.setSelectTop();
12381                     scope.$apply();
12382                 }
12383             };
12384             scope.hoverIn = function(cItem)
12385             {
12386                 scope.selectedIndex = cItem;
12387             };
12388             scope.setSelectTop = function()
12389             {
12390                 $timeout(function ()
12391                 {
12392                     if(scope.showlist)
12393                     {
12394                         var containerUL = angular.element(element)[0].querySelector(".select2-results");
12395                         var selectedElemTopPos = angular.element(containerUL.querySelector('.select2-result-current'))[0].offsetTop;
12396                         angular.element(containerUL)[0].scrollTop = selectedElemTopPos;
12397                     }
12398                 });
12399             };
12400             scope.setCurrentTop = function()
12401             {
12402                 $timeout(function ()
12403                 {
12404                     if(scope.showlist)
12405                     {
12406                         var containerUL = angular.element(element)[0].querySelector(".select2-results");
12407                         var selectedElemTopPos = angular.element(containerUL.querySelector('.hovstyle'))[0].offsetTop;
12408                         if(selectedElemTopPos < (angular.element(containerUL)[0].scrollTop) )
12409                         {
12410                             angular.element(containerUL)[0].scrollTop -= 30;
12411                         }
12412                         else if((selectedElemTopPos + 30) > (angular.element(containerUL)[0].clientHeight))
12413                         {
12414                             angular.element(containerUL)[0].scrollTop += 30;
12415                         }
12416
12417                     }
12418                 });
12419             };
12420             scope.selectNext = function()
12421             {
12422                 if((scope.selectedIndex + 1) <= (scope.cName.length-1))
12423                 {
12424                     scope.selectedIndex += 1;
12425                     if(!scope.showlist)
12426                     {
12427                         scope.selectOption(scope.selectMsg,scope.selectedIndex ,false);
12428                     }
12429                     scope.$apply();
12430                 }
12431                 scope.setCurrentTop();
12432             };
12433             scope.selectPrev = function()
12434             {
12435                 if((scope.selectedIndex - 1) >= 0)
12436                 {
12437                     scope.selectedIndex -= 1;
12438                     if(!scope.showlist)
12439                     {
12440                         scope.selectOption(scope.selectMsg,scope.selectedIndex ,false);
12441                     }
12442                     scope.$apply();
12443                 }
12444                 else if(scope.selectedIndex -1 < 0)
12445                 {
12446                     scope.selectedIndex = -1;
12447                     if(!scope.showlist)
12448                     {
12449                         scope.selectOption(scope.selectMsg,scope.selectedIndex ,false);
12450                     }
12451                     scope.$apply();
12452                 }
12453                 scope.setCurrentTop();
12454
12455             };
12456             scope.updateSelection = function(sItem)
12457             {
12458                 scope.selectedOption = sItem.title;
12459                 scope.title = "";
12460             };
12461
12462             scope.$watch('selCategory',function(value)
12463             {
12464                 if(value){
12465                     scope.updateSelection(value);
12466                 };
12467             });
12468             ctrl.$viewChangeListeners.push(function(){
12469                 scope.$eval(attr.ngChange);
12470             });
12471             ctrl.$render = function(){
12472                 scope.selCategory = ctrl.$viewValue;
12473             };
12474             var outsideClick = function(e){
12475                 var isElement = $isElement(angular.element(e.target), element, $document);
12476                 if(!isElement) {
12477                     scope.showlist = false;
12478                     scope.$apply();
12479                 }
12480             };
12481             $documentBind.click('showlist', outsideClick, scope);
12482         }
12483     };
12484 }])
12485
12486 .directive('textDropdown', ['$document', '$isElement', '$documentBind', "keymap", function($document,$isElement,$documentBind,keymap) {
12487     return {
12488         restrict: 'EA',
12489         replace: true,
12490         scope: {
12491             actions: '=actions',
12492             defaultAction: '=defaultAction',
12493             onActionClicked: '=?'
12494         },
12495         templateUrl : 'app/scripts/ng_js_att_tpls/select/textDropdown.html',
12496
12497         link: function(scope, element, attr) {
12498             scope.selectedIndex = 0;
12499             scope.selectedOption = attr.placeholder;
12500             scope.isDisabled = false;
12501             scope.isActionsShown = false;
12502
12503             if(typeof scope.defaultAction === 'undefined')
12504             {
12505                 scope.currentAction = scope.actions[0];
12506                 scope.selectedIndex = 0;
12507             } else if (typeof scope.defaultAction !== 'undefined' || scope.defaultAction !== '') {
12508                 for (var act in scope.actions)
12509                 {
12510                     if (scope.actions[act] === scope.defaultAction)
12511                     {
12512                         scope.currentAction = scope.actions[act];
12513                         scope.selectedIndex = scope.actions.indexOf(act);
12514                         scope.isActionsShown = false;
12515
12516                     break;
12517                     }
12518                 }
12519
12520             } else {
12521                 scope.currentAction = scope.actions[0];
12522             }
12523
12524             scope.toggle = function() {
12525                 scope.isActionsShown = !scope.isActionsShown;
12526             };
12527
12528             scope.chooseAction = function($event, action){
12529
12530                 if ($event != null) {
12531                     scope.currentAction = action;
12532                     scope.selectedIndex = scope.actions.indexOf(action);
12533                 }
12534                 else {
12535                     scope.currentAction = scope.actions[scope.selectedIndex];
12536                 }
12537
12538                 if (angular.isFunction(scope.onActionClicked))
12539                 {
12540                     scope.onActionClicked(scope.currentAction);
12541                 }
12542
12543                 scope.toggle();
12544             };
12545
12546             scope.isCurrentAction = function(action) {
12547                 return (action === scope.currentAction);
12548             };
12549
12550             // cato
12551             element.bind("keydown", function(e){
12552                 if (keymap.isAllowedKey(e.keyCode) || keymap.isControl(e) || keymap.isFunctionKey(e))
12553                 {
12554                     e.preventDefault();
12555                     e.stopPropagation();
12556                     switch (e.keyCode) {
12557                         case keymap.KEY.DOWN:
12558                             scope.selectNext();
12559                             break;
12560                         case keymap.KEY.UP:
12561                             scope.selectPrev();
12562                             break;
12563                         case keymap.KEY.ENTER:
12564                             scope.selectCurrent();
12565                             break;
12566                         case keymap.KEY.ESC:
12567                             scope.isActionsShown = false;
12568                             scope.$apply();
12569                             break;
12570                         default:;
12571                     }
12572                     scope.$apply();
12573                     return;
12574                 }
12575             });
12576
12577             if(attr.disabled)
12578             {
12579                scope.isDisabled = true;
12580             }
12581
12582
12583             scope.selectCurrent = function()
12584             {
12585                 if (scope.selectedIndex < 0)
12586                 {
12587                     scope.selectedIndex = 0;
12588                 }
12589
12590
12591                 if(!scope.isActionsShown) {
12592                     scope.toggle();
12593                 }
12594                 else {
12595                     scope.chooseAction(null, scope.currentAction);
12596                 }
12597             };
12598
12599             scope.selectNext = function()
12600             {
12601                 if(scope.isActionsShown)
12602                 {
12603                     if((scope.selectedIndex + 1) < scope.actions.length)
12604                     {
12605                         scope.selectedIndex += 1;
12606                         scope.$apply();
12607
12608                     }
12609                     else{
12610                         scope.selectedIndex = (scope.actions.length - 1);
12611                         scope.$apply();
12612
12613                     }
12614                 }
12615             };
12616
12617             scope.selectPrev = function()
12618             {
12619                 if(scope.isActionsShown)
12620                 {
12621                     if((scope.selectedIndex - 1) >= 0)
12622                     {
12623                         scope.selectedIndex -= 1;
12624                         scope.$apply();
12625                     }
12626                     else if(scope.selectedIndex - 1 < 0)
12627                     {
12628                         scope.selectedIndex = 0;
12629                         scope.$apply();
12630                     }
12631                 }
12632             };
12633
12634             scope.hoverIn = function(cItem)
12635             {
12636                 scope.selectedIndex = cItem;
12637             };
12638
12639
12640             //end cato
12641
12642             var outsideClick = function(e) {
12643                 var isElement = $isElement(angular.element(e.target), element, $document);
12644
12645                 if(!isElement) {
12646                     scope.toggle();
12647                     scope.$apply();
12648                 }
12649
12650             };
12651
12652             $documentBind.click('isActionsShown', outsideClick, scope);
12653
12654         }
12655     };
12656 }]);
12657
12658 angular.module('att.abs.slider', ['att.abs.position'])
12659         .constant('sliderDefaultOptions', {
12660             width: 300,
12661             step: 1,
12662             precision: 0,
12663             disabledWidth: 116
12664         })
12665         .directive('attSlider', ['sliderDefaultOptions','$position', function(sliderDefaultOptions,$position)
12666             {
12667                 return {
12668                     restrict: 'EA',
12669                     replace: true,
12670                     transclude: true,
12671                     scope: {
12672                         floor: "=",
12673                         ceiling: "=",
12674                         step: "@",
12675                         precision: "@",
12676                         width: "@",
12677                         textDisplay: "=",
12678                         value: "=",
12679                         ngModelSingle: '=?',
12680                         ngModelLow: '=?',
12681                         ngModelHigh: '=?',
12682                         ngModelDisabled: '=?'
12683                     },
12684                     templateUrl: 'app/scripts/ng_js_att_tpls/slider/slider.html',
12685                     link: function(scope, elem, attr)
12686                     {
12687                         var minOffset, maxOffset, newOffset, offsetRange, valueRange, start_x = 0, disabledRange, disabled, evFlag = false, minValue, maxValue, range, refLow, refHigh, maxPtr, minPtr, singlePtr, getHandles;
12688                         scope.minPtrOffset = 0;
12689                         scope.maxPtrOffset = 0;
12690                         var disableWidth = sliderDefaultOptions.disabledWidth;
12691                         //Get handles
12692                         var obj = elem.children();
12693                         disabledRange = obj[0].children;
12694                         disabledRange = angular.element(disabledRange[0]);
12695                         getHandles = obj[1].children;
12696                         singlePtr = angular.element(getHandles[0]);
12697                         minPtr = angular.element(getHandles[1]);
12698                         maxPtr = angular.element(getHandles[2]);
12699                         disabled = ((attr.ngModelSingle == null) && (attr.ngModelLow == null) && (attr.ngModelHigh == null)) && (attr.ngModelDisabled != null);
12700                         range = (attr.ngModelSingle == null) && ((attr.ngModelLow != null) && (attr.ngModelHigh != null));
12701                         refLow = 'ngModelLow';
12702                         refHigh = 'ngModelHigh';
12703                         if (!range) {
12704                             minPtr.remove();
12705                             maxPtr.remove();
12706                         }
12707                         else {
12708                             singlePtr.remove();
12709                         }
12710                         if (!disabled) {
12711                             disabledRange.remove();
12712                         }
12713                         else {
12714                             scope.disabledStyle = {width: disableWidth + 'px', zIndex: 1};
12715                             scope.handleStyle = {left: disableWidth + 'px'};
12716                         }
12717                         minValue = parseFloat(scope.floor);
12718                         maxValue = parseFloat(scope.ceiling);
12719                         valueRange = maxValue - minValue;
12720                         minOffset = 0;
12721                         if (attr.width !== undefined) {
12722                             maxOffset = attr.width;
12723                         }
12724                         else {
12725                             if (elem[0].clientWidth !== 0) {
12726                                 maxOffset = elem[0].clientWidth;
12727                             }
12728                             else {
12729                                 maxOffset = sliderDefaultOptions.width;
12730                             }
12731                         }
12732                         offsetRange = maxOffset - minOffset;
12733                         //Key Down Event
12734                         scope.keyDown = function(ev){
12735                                if(ev.keyCode === 39){
12736                                     var elemLeft = $position.position(elem).left;
12737                                     if (newOffset){
12738                                     newOffset = sliderDefaultOptions.step + newOffset;
12739                                 }
12740                                 else{newOffset = sliderDefaultOptions.step + elemLeft;}
12741                             }
12742                             else if(ev.keyCode === 37){
12743                                 var ptrLeft = $position.position(singlePtr).left;
12744                                 if(newOffset){
12745                                    if (newOffset!==0){
12746                                     newOffset = newOffset - sliderDefaultOptions.step ;
12747                                    }
12748                                 }
12749                                 else{
12750                                     newOffset = ptrLeft - sliderDefaultOptions.step ;}
12751                             }
12752                             if(newOffset>=0){
12753                                 scope.ptrOffset(newOffset);
12754                             }
12755                         };
12756                         //Mouse Down Event
12757                         scope.mouseDown = function(e, ref) {
12758                             scope.ref = ref;
12759                             evFlag = true;
12760                             if (!range){
12761                                 if (newOffset)
12762                                 {
12763                                     start_x = e.clientX - newOffset;
12764                                 }
12765                                 else {
12766                                     start_x = e.clientX;
12767                                 }
12768                             } else {
12769                                 if (scope.ref === refLow) {
12770                                     start_x = e.clientX - scope.minPtrOffset;
12771                                 }
12772                                 else {
12773                                     start_x = e.clientX - scope.maxPtrOffset;
12774                                 }
12775                             }
12776                             if (disabled) {
12777                                 scope.ref= 'ngModelDisabled';
12778                                 scope.disabledStyle = {width: disableWidth + 'px', zIndex: 1};
12779                             }
12780                         };
12781                         // Mouse Move Event
12782                         scope.moveElem = function(ev) {
12783                             if (evFlag) {
12784                                 var eventX;
12785                                 eventX = ev.clientX;
12786                                 newOffset = eventX - start_x;
12787                                 scope.ptrOffset(newOffset);
12788                             }
12789                         };
12790                         // Mouse Up Event
12791                         scope.mouseUp = function(ev) {
12792                             evFlag = false;
12793                             minPtr.removeClass('dragging');
12794                             maxPtr.removeClass('dragging');
12795                             singlePtr.removeClass('dragging');
12796                             $(document).off('mousemove');
12797                         };
12798                         //Function to calculate the current PositionValue
12799                         scope.calStep = function(value, precision, step, floor) {
12800                             var decimals, remainder, roundedValue, steppedValue;
12801                             if (floor === null) {
12802                                 floor = 0;
12803                             }
12804                             if (step === null) {
12805                                 step = 1 / Math.pow(10, precision);
12806                             }
12807                             remainder = (value - floor) % step;
12808                             steppedValue = remainder > (step / 2) ? value + step - remainder : value - remainder;
12809                             decimals = Math.pow(10, precision);
12810                             roundedValue = steppedValue * decimals / decimals;
12811                             return roundedValue.toFixed(precision);
12812                         };
12813                         //Function to calculate Offset Percent
12814                         scope.percentOffset = function(offset) {
12815                             return ((offset - minOffset) / offsetRange) * 100;
12816                         };
12817                         //Function to calculate Offset position
12818                         scope.ptrOffset = function(newOffset){
12819                             var newPercent, newValue;
12820                                 newOffset = Math.max(Math.min(newOffset, maxOffset), minOffset);
12821                                 newPercent = scope.percentOffset(newOffset);
12822                                 newValue = minValue + (valueRange * newPercent / 100.0);
12823                                 if (range) {
12824                                     var rangeSliderWidth;
12825                                     if (scope.ref === refLow) {
12826                                         scope.minHandleStyle = {left: newOffset + "px"};
12827                                         scope.minNewVal = newValue;
12828                                         scope.minPtrOffset = newOffset;
12829                                         minPtr.addClass('dragging');
12830                                         if (newValue > scope.maxNewVal) {
12831                                             scope.ref = refHigh;
12832                                             scope.maxNewVal = newValue;
12833                                             scope.maxPtrOffset = newOffset;
12834                                             maxPtr.addClass('dragging');
12835                                             minPtr.removeClass('dragging');
12836                                             scope.maxHandleStyle = {left: newOffset + "px"};
12837                                         }
12838                                     }
12839                                     else {
12840                                         scope.maxHandleStyle = {left: newOffset + "px"};
12841                                         scope.maxNewVal = newValue;
12842                                         scope.maxPtrOffset = newOffset;
12843                                         maxPtr.addClass('dragging');
12844                                         if (newValue < scope.minNewVal) {
12845                                             scope.ref = refLow;
12846                                             scope.minVal = newValue;
12847                                             scope.minPtrOffset = newOffset;
12848                                             minPtr.addClass('dragging');
12849                                             maxPtr.removeClass('dragging');
12850                                             scope.minHandleStyle = {left: newOffset + "px"};
12851                                         }
12852                                     }
12853                                     rangeSliderWidth = parseInt(scope.maxPtrOffset) - parseInt(scope.minPtrOffset);
12854                                     scope.rangeStyle = {width: rangeSliderWidth + "px", left: scope.minPtrOffset + "px"};
12855                                 }
12856                                 else {
12857                                     if (disabled && newOffset > disableWidth) {
12858                                         scope.rangeStyle = {width: newOffset + "px", zIndex: 0};
12859                                     }
12860                                     else {
12861                                         singlePtr.addClass('dragging');
12862                                         scope.rangeStyle = {width: newOffset + "px"};
12863                                     }
12864                                     scope.handleStyle = {left: newOffset + "px"};
12865                                 }
12866                                 if ((scope.precision === undefined) || (scope.step === undefined)) {
12867                                     scope.precision = sliderDefaultOptions.precision;
12868                                     scope.step = sliderDefaultOptions.step;
12869                                 }
12870                                 newValue = scope.calStep(newValue, parseInt(scope.precision), parseFloat(scope.step), parseFloat(scope.floor));
12871                                 scope[scope.ref] = newValue;
12872                         };
12873                     }
12874                 };
12875             }
12876         ]).directive('attSliderMin',[function()
12877             {
12878              return{
12879                  require: '^attSlider',
12880                  restrict: 'EA',
12881                  replace: true,
12882                  transclude: true,
12883                  templateUrl: 'app/scripts/ng_js_att_tpls/slider/minContent.html'
12884                };
12885          }
12886     ]).directive('attSliderMax',[function()
12887             {
12888              return{
12889                  require: '^attSlider',
12890                  restrict: 'EA',
12891                  replace: true,
12892                  transclude: true,
12893                  templateUrl: 'app/scripts/ng_js_att_tpls/slider/maxContent.html'
12894              };
12895          }
12896     ]);
12897 angular.module('att.abs.splitButtonDropdown', ['att.abs.utilities'])
12898         .directive('attButtonDropdown', ['$document', '$parse', '$documentBind', function($document, $parse, $documentBind) {
12899                 return {
12900                     restrict: 'EA',
12901                     replace: true,
12902                     transclude: true,
12903                     templateUrl: 'app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdown.html',
12904                     scope: {
12905                         btnText: "@",
12906                         btnType: "@",
12907                         btnLink: "@",
12908                         btnClick: "&"
12909                     },
12910                     link: function(scope, element, attr) {
12911                         scope.isSmall = false;
12912                         scope.isDropDownOpen = false;
12913                         scope.isActionDropdown = false;
12914
12915                         if (attr.small === "") {
12916                             scope.isSmall = true;
12917                         }
12918
12919                         if (!(scope.btnText)) {
12920                             scope.isActionDropdown = true;
12921                         }
12922
12923                         scope.clickFxn = function() {
12924                             if(typeof scope.btnClick === "function" && !scope.btnLink){
12925                                 scope.btnClick = $parse(scope.btnClick);
12926                                 scope.btnClick();
12927                             }
12928                         };
12929
12930                         scope.toggleDropdown = function() {
12931                             if (!(scope.btnType === 'disabled')) {
12932                                 scope.isDropDownOpen = !scope.isDropDownOpen;
12933                             }
12934                         };
12935
12936                         scope.hideDropdown = function() {
12937                             if (!(scope.btnType === 'disabled')) {
12938                                 scope.isDropDownOpen = false;
12939                             }
12940                         };
12941
12942                         var outsideClick = function() {
12943                             scope.$apply(function() {
12944                                 scope.isDropDownOpen = false;
12945                             });
12946                         };
12947
12948                         $documentBind.click('isDropDownOpen', outsideClick, scope);
12949
12950                         attr.$observe('btnType', function(val) {
12951                             scope.btnType = val;
12952                         });
12953                     }
12954                 };
12955
12956             }]);
12957 angular.module('att.abs.splitIconButton', ['att.abs.utilities'])
12958 .constant('iconStateConstants', {
12959     MIDDLE: 'middle',
12960     LEFT: 'left',
12961     RIGHT: 'right',
12962     NEXT_TO_DROPDOWN:'next-to-dropdown',
12963     LEFT_NEXT_TO_DROPDOWN:'left-next-to-dropdown',
12964     DIR_TYPE: {
12965         LEFT: 'left',
12966         RIGHT:  'right',
12967         BUTTON: 'button'
12968     },
12969     KEYBOARD: {
12970         UP: 38,
12971         DOWN:40,
12972         ENTER: 13,
12973         ESC: 27
12974     },
12975     SPLIT_ICON_BTN_EVENT_EMITTER_KEY: 'splitIconButtonTap'
12976 })
12977 .directive('expandableLine', ['$document',function($document){
12978     return {
12979         restrict: 'EA',
12980         replace: true,
12981         priority: 300,
12982         require: ['^attSplitIconButton', 'expandableLine'],
12983         controller: ['$scope', function($scope){
12984             $scope.isActive = false;
12985             this.setActiveState = function(isActive){
12986                 $scope.isActive = isActive;
12987             }
12988
12989             this.isActive = $scope.isActive;
12990             this.dirType = $scope.dirType;
12991         }],
12992         template: '<div ng-class="{\'expand-line-container\': !isActive, \'expand-line-container-active\': isActive}"> <div ng-class="{\'hovered-line\':isActive, \'vertical-line\':!isActive}"> </div></div>',
12993         scope:{
12994             dirType: '@'
12995         },
12996         link: function(scope,element,attr,ctrls){
12997             var attSplitIconButtonCtrl = ctrls[0];
12998             var expandableLineCtrl = ctrls[1];
12999             attSplitIconButtonCtrl.addSubCtrl(expandableLineCtrl);
13000         }
13001     }
13002 }])
13003 .controller('AttSplitIconCtrl', ['$scope', function($scope){
13004     this.setType = function(type){
13005         $scope.type = type;
13006     };
13007     
13008     this.isDropdown = function(isDropdown){
13009          $scope.isDropdown = isDropdown;
13010     };
13011
13012     this.dropDownClicked = function(){
13013         if($scope.dropDownClicked)
13014             $scope.dropDownClicked();
13015     }
13016
13017     this.dirType = $scope.dirType;
13018
13019 }])
13020 .directive('attSplitIcon', ['$document', '$timeout','iconStateConstants','$documentBind','events',
13021  function($document,$timeout,iconStateConstants,$documentBind, events){
13022     return {
13023         restrict: 'EA',
13024         replace: true,
13025         priority: 200,
13026         transclude: true,
13027         require: ['^attSplitIconButton','attSplitIcon'],
13028         templateUrl: 'app/scripts/ng_js_att_tpls/splitIconButton/splitIcon.html',
13029         scope:{
13030             icon: '@',
13031             hoverWatch: '=',
13032             dropDownWatch: '=',
13033             dirType: '@'
13034         },
13035         controller:'AttSplitIconCtrl',
13036         link: function(scope,element,attr,ctrls){
13037
13038             var attSplitIconButtonCtrl = ctrls[0];
13039             var attSplitIconCtrl = ctrls[1];
13040             attSplitIconButtonCtrl.addSubCtrl(attSplitIconCtrl);
13041
13042             scope.iconStateConstants = iconStateConstants;
13043
13044             var currentIndex = 0;
13045             var isMyElement = false;
13046             var listElements;
13047
13048             scope.isDropdown = false;
13049             scope.isDropdownOpen = false;
13050
13051
13052             scope.$on(iconStateConstants.SPLIT_ICON_BTN_EVENT_EMITTER_KEY, function(evnt, data){
13053                 if(typeof data == 'boolean' && data){
13054                     scope.dropDownClicked();    
13055                     
13056                     /*
13057                         Check if the dropdown is open and if we are selecting one
13058                         of the items, so that when pressing enter it will trigger it.
13059                     */
13060                     if(scope.isDropDownOpen){
13061                         listElements[currentIndex].eq(0).find('a')[0].click();
13062                     }
13063                 }
13064                 else{
13065                     var e = data;
13066                     //Only trigger the keyboard event if the icon button is a dropdown type
13067                     if(scope.isDropdown)
13068                         triggerKeyboardEvents(e);   
13069                 }
13070
13071                 function triggerKeyboardEvents(e){
13072                     if(e.which == iconStateConstants.KEYBOARD.ESC){
13073                         outsideClick();
13074                     }
13075                     if( e.which == iconStateConstants.KEYBOARD.UP ||  
13076                         e.which == iconStateConstants.KEYBOARD.DOWN){
13077
13078                         e.preventDefault();
13079                         events.stopPropagation(e);
13080                         //e.stopPropagation();
13081
13082                         if(e.which == iconStateConstants.KEYBOARD.DOWN){
13083                             //Dropdown is open and the user taps down again
13084
13085                             if(scope.isDropDownOpen){
13086                                 //Now we need to go through the rows in the dropdown
13087                                 scope.nextItemInDropdown();
13088                             }
13089                             //Dropdown is not open
13090                             else{
13091                                 isMyElement = true;
13092                                 outsideClick();
13093                                 listElementsInit();
13094                             }
13095                         }
13096                         else if(e.which  == iconStateConstants.KEYBOARD.UP){
13097                             if(scope.isDropDownOpen){
13098                                 scope.previousItemInDropdown();
13099                             }else{
13100                             }
13101                         }
13102                         
13103                         else{
13104                             isMyElement = false;
13105                             outsideClick();
13106                         }
13107                     }else if(e.which == iconStateConstants.KEYBOARD.ENTER){
13108                         if(scope.isDropDownOpen){
13109                             listElementsInit();
13110                         }else{
13111                         }
13112                     }
13113                 }
13114
13115                 function listElementsInit(){
13116                     if(listElements == undefined){
13117                         listElements = [];
13118                         var liTemps = element.find('li');
13119                         for(var i = 0; i < liTemps.length; i++){
13120                             listElements.push(liTemps.eq(i));
13121                         }
13122                         listElements[currentIndex].children().eq(0).addClass('selected-item');
13123                     }
13124                 }
13125             
13126             });
13127         
13128             scope.nextItemInDropdown = function(){
13129                 if(listElements && currentIndex < listElements.length - 1){
13130                     currentIndex++;
13131                     listElements[currentIndex - 1].children().eq(0).removeClass('selected-item');
13132                     listElements[currentIndex].children().eq(0).addClass('selected-item');
13133                 }
13134             };
13135
13136             scope.previousItemInDropdown = function(){
13137                 if(currentIndex > 0){
13138                     currentIndex--;
13139                     listElements[currentIndex].children().eq(0).addClass('selected-item');
13140
13141                     if(currentIndex + 1 < listElements.length)
13142                         listElements[currentIndex + 1].children().eq(0).removeClass('selected-item');
13143                 }
13144             };
13145
13146             scope.$watch('isIconHovered', function(val){
13147                 scope.hoverWatch = val;
13148             });
13149
13150             scope.$watch('type', function(val){
13151
13152                 function toggleValues(isMiddle,isNextToDropDown,isRight,isLeft,isLeftNextDropdown){
13153                     scope['isMiddle']  = isMiddle;
13154                     scope['isNextToDropDown'] = isNextToDropDown;
13155                     scope['isRight']  = isRight;
13156                     scope['isLeft'] = isLeft;
13157                     scope['isLeftNextDropdown'] = isLeftNextDropdown;
13158                 };
13159
13160                 if(val == scope.iconStateConstants.MIDDLE){
13161                     toggleValues(true,false,false,true,false);
13162                 }
13163                 else if(val ==  scope.iconStateConstants.LEFT){
13164                     toggleValues(false,false,false,true,false);
13165                 }
13166                 else if(val == scope.iconStateConstants.RIGHT){
13167                     toggleValues(false,false,true,false,false);
13168                 }else if(val == scope.iconStateConstants.NEXT_TO_DROPDOWN){
13169                     toggleValues(false,true,true,true,false);
13170                 }else  if(val == scope.iconStateConstants.LEFT_NEXT_TO_DROPDOWN){
13171                     toggleValues(false,false,false,true,true);
13172                 }
13173             });
13174
13175             if(attr.dropDownId && attr.dropDownId != ''){
13176                 scope.dropDownId = attr.dropDownId;
13177                 scope.isDropdown = true;
13178             }
13179
13180             scope.dropDownClicked = function(){
13181                 isMyElement = true;
13182             };
13183
13184             scope.toggleDropdown = function(val) {
13185                 if(val != undefined)
13186                     scope.isDropDownOpen=val;
13187                 else
13188                     scope.isDropDownOpen = !scope.isDropDownOpen; 
13189
13190                 scope.dropDownWatch = scope.isDropDownOpen;
13191             };
13192
13193             var outsideClick = function(e) {
13194                 if(scope.isDropdown){
13195                     if (isMyElement) {
13196                         isMyElement = false;
13197                         scope.toggleDropdown();
13198                     }else{
13199                         scope.toggleDropdown(false);
13200                     }
13201                     scope.$apply();
13202                 }
13203             };
13204
13205             $documentBind.click('isDropdown', outsideClick, scope);
13206         }
13207     }
13208 }])
13209 .controller('AttSplitIconButtonCtrl',['$scope', 'iconStateConstants',function($scope,iconStateConstants){
13210
13211     this.subCtrls = [];
13212
13213     $scope.isLeftLineShown=true;
13214     $scope.isRightLineShown=true;
13215     $scope.childrenScopes = [];
13216
13217     var origLeftLineShown = $scope.isLeftLineShown;
13218     var origRightLineShown = $scope.isRightLineShown;
13219
13220     var that = this;
13221
13222     function getDirIndex(dirType){
13223         var index = -1;
13224         for(var c in that.subCtrls){
13225             var ctrl = that.subCtrls[c];
13226             if(ctrl.dirType==dirType){
13227                 index = c;
13228                 break;
13229             }
13230         }
13231         return index;
13232     }
13233
13234     this.addSubCtrl =  function(sub){
13235         this.subCtrls.push(sub);
13236     };
13237
13238     this.isLeftLineShown = function(isShown){
13239         if(isShown == undefined)
13240             return $scope.isLeftLineShown;
13241         else
13242             $scope.isLeftLineShown = isShown;
13243     };
13244
13245     this.isRightLineShown = function(isShown){
13246         if(isShown == undefined)
13247             return $scope.isRightLineShown;
13248         else
13249             $scope.isRightLineShown = isShown;
13250     };
13251
13252     this.setLeftLineHover = function(isHovered){
13253         var leftLineIndex = getDirIndex(iconStateConstants.DIR_TYPE.LEFT);
13254
13255         if($scope.isLeftLineShown){
13256             if(this.subCtrls[leftLineIndex] && this.subCtrls[leftLineIndex].setActiveState){
13257                 this.subCtrls[leftLineIndex].setActiveState(isHovered);
13258             }
13259         }
13260     };
13261
13262     this.setRightLineHover = function(isHovered){
13263         var rightLineIndex = getDirIndex(iconStateConstants.DIR_TYPE.RIGHT);
13264         if($scope.isRightLineShown){
13265             if(this.subCtrls[rightLineIndex]  && this.subCtrls[rightLineIndex].setActiveState){
13266                 this.subCtrls[rightLineIndex].setActiveState(isHovered);
13267             }
13268         }
13269     };
13270
13271     this.toggleLines = function(isHovered,buttonGroupCtrl,buttonCtrl,isDropDownOpen){  
13272
13273         var subIconButtons = buttonGroupCtrl.subIconButtons;
13274         var subIconButtonsLength = subIconButtons.length;
13275
13276         var leftLineIndex =  getDirIndex(iconStateConstants.DIR_TYPE.LEFT);
13277         var rightLineIndex =  getDirIndex(iconStateConstants.DIR_TYPE.RIGHT);
13278
13279         function noVerticalLineToggle(){
13280             for(var i =0; i < subIconButtonsLength; i++){
13281                 if(subIconButtons[i] == buttonCtrl){
13282                     if(i + 1 <= subIconButtonsLength - 1){
13283                         if(subIconButtons[i+1].isLeftLineShown() && subIconButtons[i+1].subCtrls[leftLineIndex] 
13284                             && subIconButtons[i+1].subCtrls[leftLineIndex].setActiveState)
13285                             subIconButtons[i+1].subCtrls[leftLineIndex].setActiveState(isHovered);
13286                     }
13287                     if(i - 1 >= 0){
13288                         if(subIconButtons[i-1].isRightLineShown() && subIconButtons[i-1].subCtrls[rightLineIndex] 
13289                             && subIconButtons[i-1].subCtrls[rightLineIndex].setActiveState)
13290                             subIconButtons[i-1].subCtrls[rightLineIndex].setActiveState(isHovered);
13291                     }
13292                     break;
13293                 }
13294             }
13295         }   
13296
13297         if(isDropDownOpen){
13298             /*
13299               If the button is next to the dropdown button then just keep the 
13300               buttons left line or its left neighbors right line toggled on
13301               If the button is the dropdown button don't do anything
13302               else do things normally witht the button
13303             */
13304             if(subIconButtons[subIconButtonsLength-1] == buttonCtrl){
13305
13306             }
13307             else if(subIconButtons[subIconButtonsLength-2]==buttonCtrl){
13308                 if(subIconButtons[subIconButtonsLength-2].isLeftLineShown())
13309                     subIconButtons[subIconButtonsLength-2].subCtrls[leftLineIndex].setActiveState(isHovered);
13310                 else if(subIconButtonsLength  - 3 >= 0){
13311                     if(subIconButtons[subIconButtonsLength-3].isRightLineShown())
13312                         subIconButtons[subIconButtonsLength-3].subCtrls[rightLineIndex].setActiveState(isHovered);
13313                 }
13314             }else{
13315                
13316                 noVerticalLineToggle();
13317
13318                 if($scope.isLeftLineShown){
13319                     this.subCtrls[leftLineIndex].setActiveState(isHovered);
13320                 }
13321
13322                 if($scope.isRightLineShown){
13323                     this.subCtrls[rightLineIndex].setActiveState(isHovered);
13324                 }
13325             }
13326         }
13327         else{
13328             //Handle Special cases where they aren't showing any vertical lines
13329             //and the dropdown isn't down
13330             if(!$scope.isLeftLineShown && !$scope.isRightLineShown){
13331                 noVerticalLineToggle();
13332             }   
13333
13334             if($scope.isLeftLineShown){
13335                 if(this.subCtrls[leftLineIndex].setActiveState)
13336                 this.subCtrls[leftLineIndex].setActiveState(isHovered);
13337             }
13338
13339             if($scope.isRightLineShown){
13340                 if(this.subCtrls[rightLineIndex].setActiveState)
13341                 this.subCtrls[rightLineIndex].setActiveState(isHovered);
13342             }
13343         }
13344     };
13345   
13346     this.setButtonType = function(type){
13347         var buttonIndex = getDirIndex(iconStateConstants.DIR_TYPE.BUTTON);
13348         if(this.subCtrls[buttonIndex] && this.subCtrls[buttonIndex].setType)
13349             this.subCtrls[buttonIndex].setType(type);
13350     };
13351
13352 }])
13353 .directive('attSplitIconButton', ['$document', 'iconStateConstants',
13354     function($document,iconStateConstants){
13355     return {
13356         restrict: 'EA',
13357         replace: true,
13358         priority: 100,
13359         transclude: true,
13360         require: ['^attSplitIconButtonGroup', 'attSplitIconButton'],
13361         controller: 'AttSplitIconButtonCtrl',
13362         templateUrl: 'app/scripts/ng_js_att_tpls/splitIconButton/splitIconButton.html',
13363         scope:{
13364             icon: '@',
13365             dropDownId: '@'
13366         },
13367         link: function(scope,element,attr,ctrls){
13368
13369           
13370             var attSplitButtonGroupCtrl = ctrls[0];
13371             var attSplitIconButtonCtrl = ctrls[1];
13372
13373             attSplitButtonGroupCtrl.addIconButton(attSplitIconButtonCtrl);
13374
13375             element.bind('keydown', function(e){
13376                 //Check if the key is the up or down key
13377                 //if()
13378                 if(e.which == iconStateConstants.KEYBOARD.UP ||
13379                     e.which == iconStateConstants.KEYBOARD.DOWN ||
13380                     e.which == iconStateConstants.KEYBOARD.ENTER ||
13381                     e.which == iconStateConstants.KEYBOARD.ESC ) {
13382
13383                     scope.clickHandler();
13384                     scope.$broadcast(iconStateConstants.SPLIT_ICON_BTN_EVENT_EMITTER_KEY, e);
13385                 }
13386             });
13387
13388             scope.dropDownWatch = false;
13389
13390             scope.iconStateConstants = iconStateConstants;
13391
13392             scope.clickHandler = function(){
13393                 attSplitButtonGroupCtrl.hideLeftLineRightButton(attSplitIconButtonCtrl);
13394             };
13395             
13396             scope.$watch('isHovered', function(val){
13397                 if(val){
13398                     attSplitIconButtonCtrl.toggleLines(val,attSplitButtonGroupCtrl,attSplitIconButtonCtrl,attSplitButtonGroupCtrl.isDropDownOpen);
13399                 }else{
13400                     attSplitIconButtonCtrl.toggleLines(val,attSplitButtonGroupCtrl,attSplitIconButtonCtrl,attSplitButtonGroupCtrl.isDropDownOpen);
13401                 }
13402             });
13403
13404             scope.$watch('dropDownWatch', function(val){
13405                 attSplitButtonGroupCtrl.isDropDownOpen = val;
13406                 attSplitButtonGroupCtrl.toggleDropdownState(val);
13407             });
13408         }
13409     }
13410 }])
13411 .controller('AttSplitIconButtonGroupCtrl',   ['$scope','iconStateConstants',function($scope,iconStateConstants){
13412     
13413     this.subIconButtons = [];
13414     this.addIconButton = function(iconButton){
13415        this.subIconButtons.push(iconButton);
13416     };
13417
13418     this.isDropDownOpen = false;
13419
13420     this.hideLeftLineRightButton = function(btn){
13421         var numButtons = this.subIconButtons.length;
13422         var buttonLeftOfRightMost = this.subIconButtons[numButtons - 2];
13423         var rightMostButton = this.subIconButtons[numButtons -1];
13424
13425         if (btn != buttonLeftOfRightMost && btn != rightMostButton ){
13426             rightMostButton.setLeftLineHover(false);
13427         }
13428     };
13429
13430     this.toggleDropdownState = function(isDropDownOpen){
13431
13432         var numButtons = this.subIconButtons.length;
13433    
13434         if(numButtons > 2){
13435         
13436             if(isDropDownOpen){
13437
13438                 if(this.subIconButtons[numButtons - 2].isRightLineShown())
13439                     this.subIconButtons[numButtons - 2].setRightLineHover(true);
13440                 else
13441                     this.subIconButtons[numButtons - 1].setLeftLineHover(true);
13442
13443                 this.subIconButtons[numButtons - 2].setButtonType(iconStateConstants.NEXT_TO_DROPDOWN);
13444             }else{
13445                 
13446                 this.subIconButtons[numButtons - 1].setLeftLineHover(false);
13447                 this.subIconButtons[numButtons - 2].setButtonType(iconStateConstants.MIDDLE);
13448             }
13449
13450         }else{
13451
13452             if(isDropDownOpen){
13453                 this.subIconButtons[0].setRightLineHover(true);
13454                 this.subIconButtons[0].setButtonType(iconStateConstants.LEFT_NEXT_TO_DROPDOWN);
13455             }else{
13456                 this.subIconButtons[0].setButtonType(iconStateConstants.LEFT);
13457             }
13458         }
13459
13460     };
13461
13462 }])
13463 .directive('attSplitIconButtonGroup', ['$document', '$timeout',  'iconStateConstants' ,function($document,$timeout,iconStateConstants){
13464     return {
13465         restrict: 'EA',
13466         replace: true,
13467         priority: 50,
13468         transclude: true,
13469         require: 'attSplitIconButtonGroup',
13470         controller: 'AttSplitIconButtonGroupCtrl',
13471         templateUrl: 'app/scripts/ng_js_att_tpls/splitIconButton/splitIconButtonGroup.html',
13472         scope:{},
13473         link: function(scope,element,attr,ctrls){
13474
13475             $timeout(initialize,100);
13476          
13477             function initialize(){
13478
13479                 var subIconButtonCtrls = ctrls.subIconButtons;
13480                 var leftMostButtonIndex = 0;
13481                 var rightMostButtonIndex =subIconButtonCtrls.length-1;
13482
13483                 //left most button config
13484                 subIconButtonCtrls[leftMostButtonIndex].setButtonType(iconStateConstants.LEFT);
13485                 subIconButtonCtrls[leftMostButtonIndex].isLeftLineShown(false);
13486                 subIconButtonCtrls[leftMostButtonIndex].isRightLineShown(true);
13487
13488                 //right most button config
13489                 subIconButtonCtrls[rightMostButtonIndex].setButtonType(iconStateConstants.RIGHT);
13490                 subIconButtonCtrls[rightMostButtonIndex].isRightLineShown(false);
13491                 subIconButtonCtrls[rightMostButtonIndex].isLeftLineShown(false);
13492
13493                 //middle buttons config
13494                 if(rightMostButtonIndex >= 2){
13495                     var index = 1;
13496                     while(index < rightMostButtonIndex){
13497                         subIconButtonCtrls[index].setButtonType(iconStateConstants.MIDDLE);
13498                         subIconButtonCtrls[index].isRightLineShown(false);
13499                         subIconButtonCtrls[index].isLeftLineShown(false);
13500                         index++;
13501                     }
13502
13503                     var skipIndex = 2;
13504                     while(skipIndex <= rightMostButtonIndex){
13505                         if(skipIndex == rightMostButtonIndex){
13506                             subIconButtonCtrls[skipIndex].isLeftLineShown(true);
13507                         }else{
13508                             subIconButtonCtrls[skipIndex].isRightLineShown(true);
13509                             subIconButtonCtrls[skipIndex].isLeftLineShown(true); 
13510                         } 
13511                         skipIndex = skipIndex + 2;
13512                     }
13513                 }
13514
13515                 //reposition the dropdown
13516                 var ulElem = element.find('ul');
13517                 if(ulElem.length > 0){
13518                     var numButtons = rightMostButtonIndex+1;
13519                     if(numButtons > 2){
13520                         var offset = (numButtons)*34-70+(numButtons/1.5) + 0.5;
13521                         var offSetStr = offset+'px';
13522                         angular.element(ulElem).css('left',offSetStr);
13523                         angular.element(ulElem).css('border-top-left-radius','0px');
13524                     }else{
13525                         angular.element(ulElem).css('left','0px');
13526                     }
13527                 }
13528             }
13529         }
13530     }
13531 }]);
13532
13533 angular.module('att.abs.stepSlider', ['att.abs.position'])
13534         .constant('sliderConstants', {
13535             /*
13536              The MIT License (MIT)
13537              Copyright (c) 2013 Julien Valéry
13538              */
13539             SLIDER: {
13540                 settings: {
13541                     from: 1,
13542                     to: 40,
13543                     step: 1,
13544                     smooth: true,
13545                     limits: true,
13546                     value: "3",
13547                     dimension: "",
13548                     vertical: false
13549                 },
13550                 className: "jslider",
13551                 selector: ".jslider-"
13552             },
13553             EVENTS: {
13554             },
13555             COLORS: {
13556                 GREEN: 'green',
13557                 BLUE_HIGHLIGHT: 'blue',
13558                 MAGENTA: 'magenta',
13559                 GOLD: 'gold',
13560                 PURPLE: 'purple',
13561                 DARK_BLUE: 'dark-blue',
13562                 REGULAR: 'regular',
13563                 WHITE: 'white'
13564             }
13565         })
13566         .factory('utils', function () {
13567             /*
13568              The MIT License (MIT)
13569              Copyright (c) 2013 Julien Valéry
13570              */
13571             return {
13572                 offset: function (elm) {
13573                     var rawDom = elm[0];
13574                     var _x = 0;
13575                     var _y = 0;
13576                     var body = document.documentElement || document.body;
13577                     var scrollX = window.pageXOffset || body.scrollLeft;
13578                     var scrollY = window.pageYOffset || body.scrollTop;
13579                     _x = rawDom.getBoundingClientRect().left + scrollX;
13580                     _y = rawDom.getBoundingClientRect().top + scrollY;
13581                     return {left: _x, top: _y};
13582                 },
13583                 roundUpToScale: function (mousePrc, scale, cutOffWidth, cutOffIndex) {
13584                     var lowerVal;
13585                     var higherVal;
13586                     var newMousePrc;
13587                     var middle;
13588
13589                     for (var index = 1; index < scale.length; index++) {
13590                         lowerVal = scale[index - 1];
13591                         higherVal = scale[index];
13592                         middle = ((higherVal - lowerVal) * .5) + lowerVal;
13593                         /*
13594                          Handles a situation where the user clicks close to the start point of
13595                          the slider but the pointer doesn't move
13596                          */
13597                         if ((lowerVal === 0 && mousePrc <= middle) || checkEquality(lowerVal, mousePrc)) {
13598                             newMousePrc = lowerVal;
13599                             break;
13600                         }
13601                         else if (lowerVal < mousePrc && (mousePrc < higherVal ||
13602                                 checkEquality(mousePrc, higherVal)))
13603                         {
13604                             newMousePrc = higherVal;
13605                             break;
13606                         }
13607                     }
13608                     //Check if the newMousePrc is <= the cuttOffPoint
13609                     if (cutOffWidth && newMousePrc < cutOffWidth) {
13610                         return scale[cutOffIndex];
13611                     }
13612                     else {
13613                         return newMousePrc;
13614                     }
13615                     /*
13616                      Checks to see if 2 points are so close that they are
13617                      basically equal.
13618                      */
13619                     function checkEquality(point1, point2) {
13620                         var precision = 0.1;
13621                         if (Math.abs(point2 - point1) <= precision) {
13622                             return true;
13623                         }
13624                         return false;
13625                     }
13626                 },
13627                 valueForDifferentScale: function (from, to, prc, prcToValueMapper) {
13628                     var decimalPrc = prc / 100;
13629                     if (decimalPrc === 0) {
13630                         return from;
13631                     }
13632                     return prcToValueMapper[prc];
13633                 },
13634                 getConversionFactorValue: function (value, conversion, firstDimension) {
13635                     /*
13636                      Loop through the conversion array and keep checking the
13637                      startVal
13638                      */
13639                     if (value <= conversion[0].startVal) {
13640                         return{
13641                             scaledVal: value,
13642                             scaledDimension: firstDimension
13643                         };
13644                     }
13645                     var endIndex = 0;
13646                     for (var index in conversion) {
13647                         var c = conversion[index];
13648                         if (value > c.startVal) {
13649                             endIndex = index;
13650                         }
13651                     }
13652                     var scaleFactor = conversion[endIndex].scaleFactor;
13653                     var scaledVal = value / scaleFactor;
13654                     var scaledDimension = conversion[endIndex].dimension;
13655                     return {
13656                         scaledVal: scaledVal,
13657                         scaledDimension: scaledDimension
13658                     };
13659                 }
13660             };
13661         })
13662         .factory('sliderDraggable', ['utils', function (utils) {
13663                 /*
13664                  The MIT License (MIT)
13665                  Copyright (c) 2013 Julien Valéry
13666                  */
13667                 function Draggable() {
13668                     this._init.apply(this, arguments);
13669                 }
13670                 Draggable.prototype.oninit = function () {
13671                 };
13672                 Draggable.prototype.events = function () {
13673                 };
13674                 Draggable.prototype.onmousedown = function () {
13675                     this.ptr.css({position: "absolute"});
13676                 };
13677                 Draggable.prototype.onmousemove = function (evt, x, y) {
13678                     this.ptr.css({left: x, top: y});
13679                 };
13680                 Draggable.prototype.onmouseup = function () {
13681                 };
13682                 Draggable.prototype.isDefault = {
13683                     drag: false,
13684                     clicked: false,
13685                     toclick: true,
13686                     mouseup: false
13687                 };
13688                 Draggable.prototype._init = function () {
13689                     if (arguments.length > 0) {
13690                         this.ptr = arguments[0];
13691                         this.parent = arguments[2];
13692                         if (!this.ptr) {
13693                             return;
13694                         }
13695                         this.is = {};
13696                         angular.extend(this.is, this.isDefault);
13697                         var offset = utils.offset(this.ptr);
13698                         this.d = {
13699                             left: offset.left,
13700                             top: offset.top,
13701                             width: this.ptr[0].clientWidth,
13702                             height: this.ptr[0].clientHeight
13703                         };
13704                         this.oninit.apply(this, arguments);
13705                         this._events();
13706                     }
13707                 };
13708                 Draggable.prototype._getPageCoords = function (event) {
13709                     var value = {};
13710                     if (event.targetTouches && event.targetTouches[0]) {
13711                         value = {x: event.targetTouches[0].pageX, y: event.targetTouches[0].pageY};
13712                     } else {
13713                         value = {x: event.pageX, y: event.pageY};
13714                     }
13715                     return value;
13716                 };
13717                 Draggable.prototype._bindEvent = function (ptr, eventType, handler) {
13718                     if (this.supportTouches_) {
13719                         ptr[0].attachEvent(this.events_[ eventType ], handler);
13720                     }
13721                     else {
13722                         if (ptr.bind) {
13723                             ptr.bind(this.events_[ eventType ], handler);
13724                         }
13725                     }
13726                 };
13727                 Draggable.prototype._events = function () {
13728                     var self = this;
13729                     this.supportTouches_ = 'ontouchend' in document;
13730                     this.events_ = {
13731                         "click": this.supportTouches_ ? "touchstart" : "click",
13732                         "down": this.supportTouches_ ? "touchstart" : "mousedown",
13733                         "move": this.supportTouches_ ? "touchmove" : "mousemove",
13734                         "up": this.supportTouches_ ? "touchend" : "mouseup",
13735                         "mousedown": this.supportTouches_ ? "mousedown" : "mousedown"
13736                     };
13737                     var documentElt = angular.element(window.document);
13738                     this._bindEvent(documentElt, "move", function (event) {
13739                         if (self.is.drag) {
13740                             event.stopPropagation();
13741                             event.preventDefault();
13742                             if (!self.parent.disabled) {
13743                                 self._mousemove(event);
13744                             }
13745                         }
13746                     });
13747                     this._bindEvent(documentElt, "down", function (event) {
13748                         if (self.is.drag) {
13749                             event.stopPropagation();
13750                             event.preventDefault();
13751                         }
13752                     });
13753                     this._bindEvent(documentElt, "up", function (event) {
13754                         self._mouseup(event);
13755                     });
13756                     this._bindEvent(this.ptr, "down", function (event) {
13757                         self._mousedown(event);
13758                         return false;
13759                     });
13760                     this._bindEvent(this.ptr, "up", function (event) {
13761                         self._mouseup(event);
13762                     });
13763                     this.events();
13764                 };
13765                 Draggable.prototype._mousedown = function (evt) {
13766                     this.is.drag = true;
13767                     this.is.clicked = false;
13768                     this.is.mouseup = false;
13769                     var coords = this._getPageCoords(evt);
13770                     this.cx = coords.x - this.ptr[0].offsetLeft;
13771                     this.cy = coords.y - this.ptr[0].offsetTop;
13772                     angular.extend(this.d, {
13773                         left: this.ptr[0].offsetLeft,
13774                         top: this.ptr[0].offsetTop,
13775                         width: this.ptr[0].clientWidth,
13776                         height: this.ptr[0].clientHeight
13777                     });
13778                     if (this.outer && this.outer.get(0)) {
13779                         this.outer.css({height: Math.max(this.outer.height(), $(document.body).height()), overflow: "hidden"});
13780                     }
13781                     this.onmousedown(evt);
13782                 };
13783                 Draggable.prototype._mousemove = function (evt) {
13784                     if (this.uid === 0) {
13785                         return;
13786                     }
13787                     this.is.toclick = false;
13788                     var coords = this._getPageCoords(evt);
13789                     this.onmousemove(evt, coords.x - this.cx, coords.y - this.cy);
13790                 };
13791                 Draggable.prototype._mouseup = function (evt) {
13792                     if (this.is.drag) {
13793                         this.is.drag = false;
13794                         if (this.outer && this.outer.get(0)) {
13795                             if ($.browser.mozilla) {
13796                                 this.outer.css({overflow: "hidden"});
13797                             } else {
13798                                 this.outer.css({overflow: "visible"});
13799                             }
13800                             if ($.browser.msie && $.browser.version === '6.0') {
13801                                 this.outer.css({height: "100%"});
13802                             } else {
13803                                 this.outer.css({height: "auto"});
13804                             }
13805                         }
13806                         this.onmouseup(evt);
13807                     }
13808                 };
13809                 return Draggable;
13810             }])
13811         .factory('sliderPointer', ['sliderDraggable', 'utils', function (Draggable, utils) {
13812                 /*
13813                  The MIT License (MIT)
13814                  Copyright (c) 2013 Julien Valéry
13815                  */
13816                 function SliderPointer() {
13817                     Draggable.apply(this, arguments);
13818                 }
13819                 SliderPointer.prototype = new Draggable();
13820                 SliderPointer.prototype.oninit = function (ptr, id, _constructor) {
13821                     this.uid = id;
13822                     this.parent = _constructor;
13823                     this.value = {};
13824                     this.settings = angular.copy(_constructor.settings);
13825                 };
13826                 SliderPointer.prototype.onmousedown = function (evt) {
13827                     var off = utils.offset(this.parent.domNode);
13828                     var offset = {
13829                         left: off.left,
13830                         top: off.top,
13831                         width: this.parent.domNode[0].clientWidth,
13832                         height: this.parent.domNode[0].clientHeight
13833                     };
13834                     this._parent = {
13835                         offset: offset,
13836                         width: offset.width,
13837                         height: offset.height
13838                     };
13839                     this.ptr.addClass("jslider-pointer-hover");
13840                     this.setIndexOver();
13841                 };
13842                 SliderPointer.prototype.onmousemove = function (evt, x, y) {
13843                     var coords = this._getPageCoords(evt);
13844                     //val is the percent where the slider pointer is located
13845                     var val = this.calc(coords.x);
13846                     if (!this.parent.settings.smooth) {
13847                         val = utils.roundUpToScale(val,
13848                                 this.parent.settings.scale,
13849                                 this.parent.settings.cutOffWidth,
13850                                 this.parent.settings.cutOffIndex);
13851                     }
13852                     var cutOffWidth = this.parent.settings.cutOffWidth;
13853                     if (cutOffWidth && val < cutOffWidth) {
13854                         val = cutOffWidth;
13855                     }
13856                     this._set(val);
13857                 };
13858                 SliderPointer.prototype.onmouseup = function (evt) {
13859                     if (this.settings.callback && angular.isFunction(this.settings.callback)) {
13860                         var val = this.parent.getValue();
13861                         this.settings.callback.call(this.parent, val);
13862                     }
13863                     this.ptr.removeClass("jslider-pointer-hover");
13864                 };
13865                 SliderPointer.prototype.setIndexOver = function () {
13866                     this.parent.setPointersIndex(1);
13867                     this.index(2);
13868                 };
13869                 SliderPointer.prototype.index = function (i) {
13870                 };
13871                 SliderPointer.prototype.limits = function (x) {
13872                     return this.parent.limits(x, this);
13873                 };
13874                 SliderPointer.prototype.calc = function (coords) {
13875                     var diff = coords - this._parent.offset.left;
13876                     var val = this.limits((diff * 100) / this._parent.width);
13877                     return val;
13878                 };
13879                 SliderPointer.prototype.set = function (value, opt_origin) {
13880                     this.value.origin = this.parent.round(value);
13881                     this._set(this.parent.valueToPrc(value, this), opt_origin);
13882                 };
13883                 SliderPointer.prototype._set = function (prc, opt_origin) {
13884                     if (!opt_origin) {
13885                         this.value.origin = this.parent.prcToValue(prc);
13886                     }
13887                     this.value.prc = prc;
13888                     //Sets the location of the SliderPointer
13889                     this.ptr.css({left: prc + '%'});
13890                     this.parent.redraw(this);
13891                 };
13892                 return SliderPointer;
13893             }])
13894         .factory('slider', ['sliderPointer', 'sliderConstants', 'utils', function (SliderPointer, sliderConstants, utils) {
13895                 /*
13896                  The MIT License (MIT)
13897                  Copyright (c) 2013 Julien Valéry
13898                  */
13899                 var cutOffDom;
13900                 function Slider() {
13901                     return this.init.apply(this, arguments);
13902                 }
13903                 function changeCutOffWidth(width) {
13904                     cutOffDom.css('width', width);
13905                 }
13906                 ;
13907                 Slider.prototype.changeCutOffWidth = changeCutOffWidth;
13908                 Slider.prototype.init = function (inputNode, templateNode, settings) {
13909                     this.settings = sliderConstants.SLIDER.settings;
13910                     angular.extend(this.settings, angular.copy(settings));
13911                     this.inputNode = inputNode;
13912                     this.inputNode.addClass("ng-hide");
13913                     this.settings.interval = this.settings.to - this.settings.from;
13914                     if (this.settings.calculate && $.isFunction(this.settings.calculate)) {
13915                         this.nice = this.settings.calculate;
13916                     }
13917                     if (this.settings.onstatechange && $.isFunction(this.settings.onstatechange)) {
13918                         this.onstatechange = this.settings.onstatechange;
13919                     }
13920                     this.is = {init: false};
13921                     this.o = {};
13922                     this.create(templateNode);
13923                 };
13924                 Slider.prototype.create = function (templateNode) {
13925                     var $this = this;
13926                     this.domNode = templateNode;
13927                     var off = utils.offset(this.domNode);
13928                     var offset = {
13929                         left: off.left,
13930                         top: off.top,
13931                         width: this.domNode[0].clientWidth,
13932                         height: this.domNode[0].clientHeight
13933                     };
13934                     this.sizes = {domWidth: this.domNode[0].clientWidth, domOffset: offset};
13935                     angular.extend(this.o, {
13936                         pointers: {},
13937                         labels: {
13938                             0: {
13939                                 o: angular.element(this.domNode.find('div')[5])
13940                             },
13941                             1: {
13942                                 o: angular.element(this.domNode.find('div')[6])
13943                             }
13944                         },
13945                         limits: {
13946                             0: angular.element(this.domNode.find('div')[3]),
13947                             1: angular.element(this.domNode.find('div')[5])
13948                         }
13949                     });
13950                     angular.extend(this.o.labels[0], {
13951                         value: this.o.labels[0].o.find("span")
13952                     });
13953                     angular.extend(this.o.labels[1], {
13954                         value: this.o.labels[1].o.find("span")
13955                     });
13956                     if (!$this.settings.value.split(";")[1]) {
13957                         this.settings.single = true;
13958                     }
13959                     var domNodeDivs = this.domNode.find('div');
13960                     cutOffDom = angular.element(domNodeDivs[8]);
13961                     if (cutOffDom && cutOffDom.css) {
13962                         cutOffDom.css('width', '0%');
13963                     }
13964                     var pointers = [angular.element(domNodeDivs[1]), angular.element(domNodeDivs[2])];
13965                     angular.forEach(pointers, function (pointer, key) {
13966                         $this.settings = angular.copy($this.settings);
13967                         var value = $this.settings.value.split(';')[key];
13968                         if (value) {
13969                             $this.o.pointers[key] = new SliderPointer(pointer, key, $this);
13970                             var prev = $this.settings.value.split(';')[key - 1];
13971                             if (prev && parseInt(value, 10) < parseInt(prev, 10)) {
13972                                 value = prev;
13973                             }
13974                             var value1 = value < $this.settings.from ? $this.settings.from : value;
13975                             value1 = value > $this.settings.to ? $this.settings.to : value;
13976                             $this.o.pointers[key].set(value1, true);
13977                             if (key === 0) {
13978                                 $this.domNode.bind('mousedown', $this.clickHandler.apply($this));
13979                             }
13980                         }
13981                     });
13982                     this.o.value = angular.element(this.domNode.find("i")[2]);
13983                     this.is.init = true;
13984                     angular.forEach(this.o.pointers, function (pointer) {
13985                         $this.redraw(pointer);
13986                     });
13987                 };
13988                 Slider.prototype.clickHandler = function () {
13989                     var self = this;
13990                     return function (evt) {
13991                         if (self.disabled) {
13992                             return;
13993                         }
13994                         var className = evt.target.className;
13995                         var targetIdx = 0;
13996                         if (className.indexOf('jslider-pointer-to') > 0) {
13997                             targetIdx = 1;
13998                         }
13999                         var _off = utils.offset(self.domNode);
14000                         var offset = {
14001                             left: _off.left,
14002                             top: _off.top,
14003                             width: self.domNode[0].clientWidth,
14004                             height: self.domNode[0].clientHeight
14005                         };
14006                         targetIdx = 1;
14007                         var targetPtr = self.o.pointers[targetIdx];
14008                         targetPtr._parent = {offset: offset, width: offset.width, height: offset.height};
14009                         targetPtr._mousemove(evt);
14010                         targetPtr.onmouseup();
14011                         return false;
14012                     };
14013                 };
14014                 Slider.prototype.disable = function (bool) {
14015                     this.disabled = bool;
14016                 };
14017                 Slider.prototype.nice = function (value) {
14018                     return value;
14019                 };
14020                 Slider.prototype.onstatechange = function () {
14021                 };
14022                 Slider.prototype.limits = function (x, pointer) {
14023                     if (!this.settings.smooth) {
14024                         var step = this.settings.step * 100 / (this.settings.interval);
14025                         x = Math.round(x / step) * step;
14026                     }
14027                     var another = this.o.pointers[1 - pointer.uid];
14028                     if (another && pointer.uid && x < another.value.prc) {
14029                         x = another.value.prc;
14030                     }
14031                     if (another && !pointer.uid && x > another.value.prc) {
14032                         x = another.value.prc;
14033                     }
14034                     if (x < 0) {
14035                         x = 0;
14036                     }
14037                     if (x > 100) {
14038                         x = 100;
14039                     }
14040                     var val = Math.round(x * 10) / 10;
14041                     return val;
14042                 };
14043                 Slider.prototype.setPointersIndex = function (i) {
14044                     angular.forEach(this.getPointers(), function (pointer, i) {
14045                         pointer.index(i);
14046                     });
14047                 };
14048                 Slider.prototype.getPointers = function () {
14049                     return this.o.pointers;
14050                 };
14051                 Slider.prototype.onresize = function () {
14052                     var self = this;
14053                     this.sizes = {
14054                         domWidth: this.domNode[0].clientWidth,
14055                         domHeight: this.domNode[0].clientHeight,
14056                         domOffset: {
14057                             left: this.domNode[0].offsetLeft,
14058                             top: this.domNode[0].offsetTop,
14059                             width: this.domNode[0].clientWidth,
14060                             height: this.domNode[0].clientHeight
14061                         }
14062                     };
14063                     angular.forEach(this.o.pointers, function (ptr, key) {
14064                         self.redraw(ptr);
14065                     });
14066                 };
14067                 Slider.prototype.update = function () {
14068                     this.onresize();
14069                     this.drawScale();
14070                 };
14071                 Slider.prototype.drawScale = function () {
14072                 };
14073                 Slider.prototype.redraw = function (pointer) {
14074                     if (!this.settings.smooth) {
14075                         var newMousePrc = utils.roundUpToScale(pointer.value.prc,
14076                                 this.settings.scale,
14077                                 this.settings.cutOffWidth,
14078                                 this.settings.cutOffIndex);
14079                         pointer.value.origin = newMousePrc;
14080                         pointer.value.prc = newMousePrc;
14081                     }
14082
14083                     if (!this.is.init) {
14084                         return false;
14085                     }
14086                     this.setValue();
14087                     var width = this.o.pointers[1].value.prc;
14088                     var newPos = {left: '0%', width: width + '%'};
14089                     this.o.value.css(newPos);
14090                     var htmlValue = this.nice(pointer.value.origin);
14091                     var scaledDimension = this.settings.firstDimension;
14092                     if (this.settings.stepWithDifferentScale && !this.settings.smooth) {
14093                         htmlValue = utils.valueForDifferentScale(this.settings.from,
14094                                 this.settings.to, htmlValue, this.settings.prcToValueMapper);
14095                     }
14096                     //This is the base value before the conversion
14097                     if (this.settings.realtimeCallback && angular.isFunction(this.settings.realtimeCallback)
14098                             && this.settings.cutOffVal !== undefined && pointer.uid === 1) {
14099                         this.settings.realtimeCallback(htmlValue);
14100                     }
14101                     //Need to change this to the correct value for the scale
14102                     if (this.settings.conversion) {
14103                         var conversionObj = utils.getConversionFactorValue(parseInt(htmlValue),
14104                                 this.settings.conversion,
14105                                 this.settings.firstDimension);
14106                         htmlValue = conversionObj.scaledVal;
14107                         scaledDimension = conversionObj.scaledDimension;
14108                     }
14109                     //Check if we need to round the decimal places
14110                     if (this.settings.decimalPlaces || this.settings.decimalPlaces === 0) {
14111                         if (typeof htmlValue === 'number') {
14112                             htmlValue = htmlValue.toFixed(this.settings.decimalPlaces);
14113                         }
14114                     }
14115                     this.o.labels[pointer.uid].value.html(htmlValue + ' ' + scaledDimension);
14116                     //Top tooltip label
14117                     this.redrawLabels(pointer);
14118                 };
14119                 Slider.prototype.redrawLabels = function (pointer) {
14120                     function setPosition(label, sizes, prc) {
14121                         sizes.margin = -sizes.label / 2;
14122                         var domSize = self.sizes.domWidth;
14123                         var label_left = sizes.border + sizes.margin;
14124                         if (label_left < 0) {
14125                             sizes.margin -= label_left;
14126                         }
14127                         if (sizes.border + sizes.label / 2 > domSize) {
14128                             sizes.margin = 0;
14129                             sizes.right = true;
14130                         } else
14131                             sizes.right = false;
14132                         //Adjust the tooltip location
14133                         sizes.margin = -((label.o[0].clientWidth / 2) - label.o[0].clientWidth / 20);
14134                         label.o.css({left: prc + "%", marginLeft: sizes.margin, right: "auto"});
14135                         if (sizes.right)
14136                             label.o.css({left: "auto", right: 0});
14137                         return sizes;
14138                     }
14139                     var self = this;
14140                     var label = this.o.labels[pointer.uid];
14141                     var prc = pointer.value.prc;
14142                     var sizes = {
14143                         label: label.o[0].offsetWidth,
14144                         right: false,
14145                         border: (prc * domSize) / 100
14146                     };
14147                     var another_label = null;
14148                     var another = null;
14149                     if (!this.settings.single) {
14150                         another = this.o.pointers[1 - pointer.uid];
14151                         another_label = this.o.labels[another.uid];
14152                         switch (pointer.uid) {
14153                             case 0:
14154                                 if (sizes.border + sizes.label / 2 > another_label.o[0].offsetLeft - this.sizes.domOffset.left) {
14155                                     another_label.o.css({visibility: "hidden"});
14156                                     another_label.value.html(this.nice(another.value.origin));
14157                                     label.o.css({visibility: "hidden"});
14158                                     prc = (another.value.prc - prc) / 2 + prc;
14159                                     if (another.value.prc !== pointer.value.prc) {
14160                                         label.value.html(this.nice(pointer.value.origin) + "&nbsp;&ndash;&nbsp;" + this.nice(another.value.origin));
14161                                         sizes.label = label.o[0].clientWidth;
14162                                         sizes.border = (prc * domSize) / 100;
14163                                     }
14164                                 } else {
14165                                     another_label.o.css({visibility: "visible"});
14166                                 }
14167                                 break;
14168                             case 1:
14169                                 if (sizes.border - sizes.label / 2 < another_label.o[0].offsetLeft - this.sizes.domOffset.left + another_label.o[0].clientWidth) {
14170                                     another_label.o.css({visibility: "hidden"});
14171                                     another_label.value.html(this.nice(another.value.origin));
14172                                     label.o.css({visibility: "visible"});
14173                                     prc = (prc - another.value.prc) / 2 + another.value.prc;
14174                                     if (another.value.prc !== pointer.value.prc) {
14175                                         label.value.html(this.nice(another.value.origin) + "&nbsp;&ndash;&nbsp;" + this.nice(pointer.value.origin));
14176                                         sizes.label = label.o[0].clientWidth;
14177                                         sizes.border = (prc * domSize) / 100;
14178                                     }
14179                                 } else {
14180                                     another_label.o.css({visibility: "visible"});
14181                                 }
14182                                 break;
14183                         }
14184                     }
14185                     sizes = setPosition(label, sizes, prc);
14186                     var domSize = self.sizes.domWidth;
14187                     //This is the 0th pointer
14188                     if (another_label) {
14189                         sizes = {
14190                             label: another_label.o[0].clientWidth,
14191                             right: false,
14192                             border: (another.value.prc * this.sizes.domWidth) / 100
14193                         };
14194                         sizes = setPosition(another_label, sizes, another.value.prc);
14195                     }
14196                 };
14197                 Slider.prototype.redrawLimits = function () {
14198                     if (this.settings.limits) {
14199                         var limits = [true, true];
14200                         for (var key in this.o.pointers) {
14201                             if (!this.settings.single || key === 0) {
14202                                 var pointer = this.o.pointers[key];
14203                                 var label = this.o.labels[pointer.uid];
14204                                 var label_left = label.o[0].offsetLeft - this.sizes.domOffset.left;
14205                                 var limit = this.o.limits[0];
14206                                 if (label_left < limit[0].clientWidth)
14207                                     limits[0] = false;
14208                                 limit = this.o.limits[1];
14209                                 if (label_left + label.o[0].clientWidth > this.sizes.domWidth - limit[0].clientWidth)
14210                                     limits[1] = false;
14211                             }
14212                         }
14213                         for (var i = 0; i < limits.length; i++) {
14214                             if (limits[i]){
14215                                 angular.element(this.o.limits[i]).addClass("animate-show");}
14216                             else{
14217                                 angular.element(this.o.limits[i]).addClass("animate-hidde");}
14218                         }
14219                     }
14220                 };
14221                 Slider.prototype.setValue = function () {
14222                     var value = this.getValue();
14223                     this.inputNode.attr("value", value);
14224                     this.onstatechange.call(this, value, this.inputNode);
14225                 };
14226                 Slider.prototype.getValue = function () {
14227                     if (!this.is.init){
14228                         return false;}
14229                     var $this = this;
14230                     var value = "";
14231                     angular.forEach(this.o.pointers, function (pointer, key) {
14232                         if (pointer.value.prc !== undefined && !isNaN(pointer.value.prc)) {
14233                             var pointerPrc = pointer.value.prc;
14234                             var myValue = $this.prcToValue(pointerPrc);
14235                             if (!$this.settings.smooth) {
14236                                 var myValue = utils.valueForDifferentScale($this.settings.from,
14237                                         $this.settings.to,
14238                                         pointerPrc,
14239                                         $this.settings.prcToValueMapper);
14240                             }
14241                             value += (key > 0 ? ";" : "") + myValue;
14242                         }
14243                     });
14244                     return value;
14245                 };
14246                 Slider.prototype.getPrcValue = function () {
14247                     if (!this.is.init)
14248                         return false;
14249                     var value = "";
14250                     $.each(this.o.pointers, function (i) {
14251                         if (this.value.prc !== undefined && !isNaN(this.value.prc))
14252                             value += (i > 0 ? ";" : "") + this.value.prc;
14253                     });
14254                     return value;
14255                 };
14256                 Slider.prototype.prcToValue = function (prc) {
14257                     var value;
14258                     if (this.settings.heterogeneity && this.settings.heterogeneity.length > 0) {
14259                         var h = this.settings.heterogeneity;
14260                         var _start = 0;
14261                         var _from = this.settings.from;
14262                         for (var i = 0; i <= h.length; i++) {
14263                             var v;
14264                             if (h[i]){
14265                                 v = h[i].split("/");}
14266                             else{
14267                                 v = [100, this.settings.to];}
14268                             if (prc >= _start && prc <= v[0]) {
14269                                 value = _from + ((prc - _start) * (v[1] - _from)) / (v[0] - _start);
14270                             }
14271                             _start = v[0];
14272                             _from = v[1];
14273                         }
14274                     }
14275                     else {
14276                         value = this.settings.from + (prc * this.settings.interval) / 100;
14277                     }
14278                     var roundedValue = this.round(value);
14279                     return roundedValue;
14280                 };
14281                 Slider.prototype.valueToPrc = function (value, pointer) {
14282                     var prc;
14283                     if (this.settings.heterogeneity && this.settings.heterogeneity.length > 0) {
14284                         var h = this.settings.heterogeneity;
14285                         var _start = 0;
14286                         var _from = this.settings.from;
14287                         for (var i = 0; i <= h.length; i++) {
14288                             var v;
14289                             if (h[i])
14290                                 v = h[i].split("/");
14291                             else
14292                                 v = [100, this.settings.to];
14293                             if (value >= _from && value <= v[1]) {
14294                                 prc = pointer.limits(_start + (value - _from) * (v[0] - _start) / (v[1] - _from));
14295                             }
14296                             _start = v[0];
14297                             _from = v[1];
14298                         }
14299                     } else {
14300                         prc = pointer.limits((value - this.settings.from) * 100 / this.settings.interval);
14301                     }
14302                     return prc;
14303                 };
14304                 Slider.prototype.round = function (value) {
14305                     value = Math.round(value / this.settings.step) * this.settings.step;
14306                     if (this.settings.round){
14307                         value = Math.round(value * Math.pow(10, this.settings.round)) / Math.pow(10, this.settings.round);}
14308                     else{
14309                         value = Math.round(value);}
14310                     return value;
14311                 };
14312                 return Slider;
14313             }])
14314         .directive('attStepSlider', [
14315             '$compile', '$templateCache', '$timeout', '$window', 'slider', 'sliderConstants', 'utils',
14316             function (compile, templateCache, timeout, win, Slider, sliderConstants, utils) {
14317                 /*
14318                  The MIT License (MIT)
14319                  Copyright (c) 2013 Julien Valéry
14320                  */
14321                 var templateUrl = 'app/scripts/ng_js_att_tpls/stepSlider/attStepSlider.html';
14322                 return {
14323                     restrict: 'AE',
14324                     require: '?ngModel',
14325                     scope: {
14326                         options: '=',
14327                         cutOff: '='
14328                     },
14329                     priority: 1,
14330                     templateUrl: templateUrl,
14331                     link: function (scope, element, attrs, ngModel) {
14332                         if (!ngModel)
14333                             return;
14334                         scope.mainSliderClass = 'step-slider';
14335                         element.after(compile(templateCache.get(templateUrl))(scope, function (clonedElement, scope) {
14336                             scope.tmplElt = clonedElement;
14337                         }));
14338                         ngModel.$render = function () {
14339                             if (ngModel.$viewValue.split && ngModel.$viewValue.split(";").length === 1) {
14340                                 ngModel.$viewValue = '0;' + ngModel.$viewValue;
14341                             } else if (typeof (ngModel.$viewValue) === 'number') {
14342                                 ngModel.$viewValue = '0;' + ngModel.$viewValue;
14343                             }
14344                             if (!ngModel.$viewValue && ngModel.$viewValue !== 0) {
14345                                 return;
14346                             }
14347                             if (typeof (ngModel.$viewValue) === 'number') {
14348                                 ngModel.$viewValue = '' + ngModel.$viewValue;
14349                             }
14350                             if (scope.slider) {
14351                                 var firstPointer = '0';
14352                                 scope.slider.getPointers()[0].set(firstPointer, true);
14353                                 if (ngModel.$viewValue.split(";")[1]) {
14354                                     var value = ngModel.$viewValue.split(";")[1];
14355                                     if (value.length >= 4) {
14356                                         value = value.substring(0, 2);
14357                                     }
14358                                     if (!scope.options.realtime)
14359                                         scope.options.callback(parseFloat(ngModel.$viewValue.split(";")[1]));
14360                                     scope.slider.getPointers()[1].set(ngModel.$viewValue.split(";")[1], true);
14361                                 }
14362                             }
14363                         };
14364                         var init = function () {
14365                             scope.from = '' + scope.options.from;
14366                             scope.to = '' + scope.options.to;
14367                             if (scope.options.calculate && typeof scope.options.calculate === 'function') {
14368                                 scope.from = scope.options.calculate(scope.from);
14369                                 scope.to = scope.options.calculate(scope.to);
14370                             }
14371                             scope.showDividers = scope.options.showDividers;
14372                             scope.COLORS = sliderConstants.COLORS;
14373                             scope.sliderColor = scope.options.sliderColor;
14374                             if (!scope.sliderColor)
14375                                 scope.sliderColor = sliderConstants.COLORS.REGULAR;
14376                             var scaleArray = scope.options.scale;
14377                             //Make a copy of the scaleArray before converting it to percentage for the bars
14378                             var nonPercentScaleArray = [];
14379                             //Create Mapper for the percentage to value
14380                             var prcToValueMapper = {};
14381                             for (var i in scaleArray) {
14382                                 var s = scaleArray[i];
14383                                 nonPercentScaleArray.push(s);
14384                             }
14385                             function addScaleArrayStartAndEnd() {
14386                                 if (scaleArray[0] !== 0) {
14387                                     scaleArray.splice(0, 0, 0);
14388                                 }
14389                                 if (scaleArray[scaleArray.length - 1] !== 100) {
14390                                     scaleArray.splice(scaleArray.length, 0, 100);
14391                                 }
14392                             }
14393                             function convertScaleArrayToPercentage() {
14394                                 if (scaleArray[scaleArray.length - 1] !== scope.options.to) {
14395                                     scaleArray.splice(scaleArray.length, 0, scope.options.to);
14396                                 }
14397                                 for (var i in scaleArray) {
14398                                     var fromValueCheck = (scaleArray[i] / scope.options.from);
14399                                     var toValueCheck = (scaleArray[i] / scope.options.to);
14400                                     var prcValue = ((scaleArray[i] - scope.options.from) / (scope.options.to - scope.options.from)) * 100;
14401                                     var realValue = scaleArray[i];
14402                                     if (toValueCheck === 1) {
14403                                         prcValue = 100;
14404                                     }
14405                                     else if (fromValueCheck === 1) {
14406                                         prcValue = 0;
14407                                     }
14408                                     scaleArray[i] = prcValue;
14409                                     prcToValueMapper['' + prcValue] = realValue;
14410                                 }
14411                             }
14412                             if ((scope.options.from !== 0 || scope.options.to !== 100)
14413                                     && scope.options.smooth) {
14414                                 /*
14415                                  scale array is in real values.
14416                                  */
14417                                 addScaleArrayStartAndEnd();
14418                                 scope.options.stepWithDifferentScale = true;
14419                             }
14420                             else if ((scope.options.from !== 0 || scope.options.to !== 100)
14421                                     && !scope.options.smooth) {
14422                                 /*
14423                                  Case for different from and to values other than 0 and 100
14424                                  so we have to do some different calculations
14425                                  */
14426                                 scope.options.stepWithDifferentScale = true;
14427                                 convertScaleArrayToPercentage();
14428                                 addScaleArrayStartAndEnd();
14429                             }
14430                             else {
14431                                 /*
14432                                  This is the normal case where the from and to values are 0 and
14433                                  100 respectively.        
14434                                  */
14435                                 //Check that the scale starts at 0 and 100
14436                                 convertScaleArrayToPercentage();
14437                                 addScaleArrayStartAndEnd();
14438                             }
14439                             var decimalPlaces = 0;
14440                             if (scope.options.decimalPlaces) {
14441                                 decimalPlaces = scope.options.decimalPlaces;
14442                             }
14443                             //Modify the endDimension based on whether converison was passed in
14444                             //Also change the toStr value to scale to the last factor
14445                             scope.endDimension = scope.options.dimension;
14446                             if (scope.options.conversion) {
14447                                 //Get the dimension of the last conversion
14448                                 var lastIndex = scope.options.conversion.length - 1;
14449                                 var lastDimension = scope.options.conversion[lastIndex].dimension;
14450                                 var lastScaleFactor = scope.options.conversion[lastIndex].scaleFactor;
14451                                 scope.endDimension = " " + lastDimension;
14452
14453                                 var toVal = (scope.to / lastScaleFactor).toFixed(decimalPlaces);
14454                                 scope.toStr = toVal;
14455                             } else {
14456                                 scope.toStr = scope.options.to;
14457                             }
14458                             var OPTIONS = {
14459                                 from: scope.options.from,
14460                                 to: scope.options.to,
14461                                 step: scope.options.step,
14462                                 smooth: scope.options.smooth,
14463                                 limits: true,
14464                                 stepWithDifferentScale: scope.options.stepWithDifferentScale,
14465                                 round: scope.options.round || false,
14466                                 value: ngModel.$viewValue,
14467                                 scale: scope.options.scale,
14468                                 nonPercentScaleArray: nonPercentScaleArray,
14469                                 prcToValueMapper: prcToValueMapper,
14470                                 firstDimension: scope.options.dimension,
14471                                 decimalPlaces: decimalPlaces,
14472                                 conversion: scope.options.conversion
14473                             };
14474                             if (angular.isFunction(scope.options.realtime)) {
14475                                 OPTIONS.realtimeCallback = function (value) {
14476                                     ngModel.$setViewValue(value);
14477                                     scope.options.callback(value);
14478                                 };
14479                             }
14480                             else {
14481                                 OPTIONS.callback = forceApply;
14482                             }
14483                             OPTIONS.calculate = scope.options.calculate || undefined;
14484                             OPTIONS.onstatechange = scope.options.onstatechange || undefined;
14485                             timeout(function () {
14486                                 var scaleDiv = scope.tmplElt.find('div')[7];
14487                                 if (!OPTIONS.conversion) {
14488                                     scope.tmplElt.find('div').eq(6).find('span').eq(0).css('padding-left', '10px');
14489                                     scope.tmplElt.find('div').eq(6).find('span').eq(0).css('padding-right', '15px');
14490                                 }
14491                                 scope.slider = angular.element.slider(element, scope.tmplElt, OPTIONS);
14492                                 angular.element(scaleDiv).html(scope.generateScale());
14493                                 scope.drawScale(scaleDiv);
14494                                 initListener();
14495                                 scope.$watch('options.disable', function (val) {
14496                                     if (scope.slider) {
14497                                         scope.tmplElt.toggleClass('disabled', val);
14498                                         scope.slider.disable(val);
14499                                     }
14500                                 });
14501                                 scope.$watch('cutOff', function (cutOffVal) {
14502                                     if (cutOffVal && cutOffVal > 0) {
14503                                         var cutOffPrc = (cutOffVal - scope.slider.settings.from) / (scope.slider.settings.to -
14504                                                 scope.slider.settings.from);
14505                                         cutOffPrc = cutOffPrc * 100;
14506                                         scope.isCutOffSlider = true;
14507                                         scope.slider.settings.cutOffWidth = cutOffPrc;
14508                                         //cutOffVal is the actual value of the cutoff point
14509                                         scope.cutOffVal = cutOffVal;
14510                                         if (scope.options.conversion) {
14511                                             var convertedVal = utils.getConversionFactorValue(cutOffVal, scope.options.conversion, scope.options.dimension);
14512                                             convertedVal.scaledVal = parseFloat(convertedVal.scaledVal).toFixed(scope.options.decimalPlaces);
14513                                             scope.cutOffVal = convertedVal.scaledVal + ' ' + convertedVal.scaledDimension;
14514                                         }
14515                                         scope.slider.settings.cutOffVal = cutOffVal;
14516                                         //Calculate the cutOff percentage
14517                                         scope.slider.changeCutOffWidth(cutOffPrc + '%');
14518                                         var scale = scope.slider.settings.nonPercentScaleArray;
14519                                         //Calculate where the cutOff point in relation to the scale array
14520                                         for (var i in scale) {
14521                                             if (i >= 1) {
14522                                                 var lowerVal = scale[i - 1];
14523                                                 var higherVal = scale[i];
14524                                                 if (cutOffVal > lowerVal && cutOffVal <= higherVal) {
14525                                                     scope.slider.settings.cutOffIndex = i;
14526                                                 }
14527                                             }
14528                                         }
14529                                     } else {
14530                                         scope.slider.settings.cutOffVal = 0;
14531                                     }
14532                                 });
14533                             });
14534                         };
14535                         function initListener() {
14536                             angular.element(win).bind('resize', function (event) {
14537                                 scope.slider.onresize();
14538                             });
14539                         }
14540                         scope.generateScale = function () {
14541                             if (scope.options.scale && scope.options.scale.length > 0) {
14542                                 var str = "";
14543                                 var s = scope.options.scale;
14544                                 var position = 'left';
14545                                 for (var i = 0; i < s.length; i++) {
14546                                     if (i !== 0 && i !== s.length - 1) {
14547                                         var scaledPosition = ((s[i] - scope.from) / (scope.to - scope.from)) * 100;
14548                                         if (scope.options.stepWithDifferentScale && !scope.options.smooth) {
14549                                             scaledPosition = s[i];
14550                                         }
14551                                         str += '<span style="' + position + ': ' + scaledPosition + '%"></span>';
14552                                     }
14553                                 }
14554                                 return str;
14555                             } else
14556                                 return "";
14557                             return "";
14558                         };
14559                         scope.drawScale = function (scaleDiv) {
14560                             angular.forEach(angular.element(scaleDiv).find('ins'), function (scaleLabel, key) {
14561                                 scaleLabel.style.marginLeft = -scaleLabel.clientWidth / 2;
14562                             });
14563                         };
14564                         var forceApply = function (value) {
14565                             var val = value.split(";")[1];
14566                             scope.$apply(function () {
14567                                 ngModel.$setViewValue(parseInt(val));
14568                             });
14569                             if (scope.options.callback) {
14570                                 scope.options.callback(parseInt(val));
14571                             }
14572                         };
14573                         scope.$watch('options', function (value) {
14574                             init();
14575                         });
14576                         angular.element.slider = function (inputElement, element, settings) {
14577                             if (!element.data('jslider'))
14578                                 element.data('jslider', new Slider(inputElement, element, settings));
14579                             var sliderObj = element.data('jslider');
14580                             return sliderObj;
14581                         };
14582                     }
14583                 };
14584             }]);
14585 angular.module('att.abs.steptracker', ['att.abs.transition'])
14586         .directive('steptracker', ['$timeout', function ($timeout) {
14587                 return {
14588                     // This allows dev's clickHandler to cancel an operation
14589                     priority: 100,
14590                     scope: {
14591                         sdata: "=sdata",
14592                         cstep: "=currentStep",
14593                         clickHandler: '=?',
14594                         disableClick: '=?'
14595                     },
14596                     restrict: 'EA',
14597                     replace: true,
14598                     templateUrl: 'app/scripts/ng_js_att_tpls/steptracker/step-tracker.html',
14599                     link: function (scope, elem) {
14600                         if (scope.disableClick === undefined) {
14601                             scope.disableClick = false;
14602                         }
14603                         $timeout(function () {
14604                             if (scope.cstep < 1) {
14605                                 scope.cstep = 1;
14606                             }
14607                             else if (scope.cstep > scope.sdata.length) {
14608                                 scope.cstep = scope.sdata.length;
14609                             }
14610                             var divs = elem.find('div');
14611                             var slidertracks = [];
14612                             for (var i in divs) {
14613                                 if (divs.eq(i)[0]) {
14614                                     var el = divs.eq(i)[0].className;
14615                                     if (el.indexOf('track ng-scope') > -1) {
14616                                         slidertracks.push(divs.eq(i));
14617                                     }
14618                                 }
14619                             }
14620                             var currentPage,totalPage,currentTrack = updateCurrentTrack(scope.cstep);
14621                             function updateCurrentTrack(step) {
14622                                 // Always return the step-1 because array starts at 0
14623                                 return angular.element(slidertracks[step - 1]);
14624                             }
14625                             function updateTrackWidth() {
14626                                 if (scope.cstep > 0 && scope.cstep <= scope.sdata.length - 1 && currentPage > 0) {
14627                                     var newWidth = ((currentPage / totalPage) * 100) + "%";
14628                                     currentTrack = updateCurrentTrack(scope.cstep);
14629                                     currentTrack.css('width', newWidth);
14630                                 }
14631                             }
14632                             function updatePages() {
14633                                 if (scope.cstep <= scope.sdata.length) {
14634                                     currentPage = scope.sdata[scope.cstep - 1]['currentPage'];
14635                                     totalPage = scope.sdata[scope.cstep - 1]['totalPages'];
14636                                 }
14637                             }
14638                             // dynamically add width for steps, depending on the number of steps.
14639                             scope.set_width = function (indexval) {
14640                                 var setwidth = (100 / (scope.sdata.length - 1)) + "%";
14641                                 // skip last element and add width for all other element
14642                                 if ((scope.sdata.length - 1) > indexval) {
14643                                     return {'width': setwidth};
14644                                 }
14645                             };
14646                             scope.$watch('sdata', function () {
14647                                 updatePages();
14648                                 var prevStep = scope.cstep;
14649                                 // Before anything, ensure currentPage is never below 1
14650                                 if (currentPage < 1) {
14651                                     currentPage = 1;
14652                                     if (scope.cstep !== 1) {
14653                                         // Decrease step, current track width is 0%, new step width updates
14654                                         scope.cstep--;
14655                                         updatePages();
14656                                     }
14657                                 }
14658                                 // Move to next step, reset currentPage, totalPage, and ensure previous steps are completed
14659                                 if (currentPage > totalPage) {
14660                                     if (scope.cstep > scope.sdata.length - 1) {
14661                                         scope.cstep++;
14662                                         return;
14663                                     } else {
14664                                         currentPage = totalPage;
14665                                         updateTrackWidth();
14666                                         scope.cstep++;
14667                                         updatePages();
14668                                         updateTrackWidth();
14669                                     }
14670                                 }
14671                                 if (currentPage < 1 && prevStep === scope.cstep) {
14672                                     currentPage = 1;
14673                                     if (scope.cstep > 1) {
14674                                         scope.cstep--;
14675                                         scope.sdata[scope.cstep - 1]['currentPage'] = scope.sdata[scope.cstep - 1]['totalPages'];
14676                                         scope.sdata[scope.cstep]['currentPage'] = 1;
14677                                     }
14678                                 }
14679                                 updateTrackWidth();
14680                             }, true);
14681                             //add the active class for current step
14682                             scope.activestep = function (index) {
14683                                 return (index === scope.cstep - 1);
14684                             };
14685                             //add the done class for finished step
14686                             scope.donesteps = function (index) {
14687                                 return (index < scope.cstep - 1);
14688                             };
14689                             //add the last class for final step
14690                             scope.laststep = function (index) {
14691                                 return (index === scope.sdata.length - 1);
14692                             };
14693                             scope.isIncomplete = function (index) {
14694                                 if (index === scope.cstep - 1) {
14695                                     return false;
14696                                 }
14697                                 if (index >= 0 && index < scope.sdata.length - 1) {
14698                                     var step = scope.sdata[index];
14699                                     return (step['currentPage'] <= step['totalPages']);
14700                                 }
14701                             };
14702                             //click event
14703                             scope.stepclick = function ($event, steps) {
14704                                 // If we are decreasing steps, reset all currentPage counts to 1
14705                                 if (steps < scope.cstep) {
14706                                     for (var i = scope.cstep - 1; i > steps; i--) {
14707                                         scope.sdata[i]['currentPage'] = 1;
14708                                     }
14709                                     scope.sdata[steps]['currentPage']--;
14710                                 }
14711                                 if (angular.isFunction(scope.clickHandler)) {
14712                                     scope.clickHandler($event, steps);
14713                                 }
14714                                 scope.cstep = steps + 1;
14715                                 // In the case we decremented previously from this step, we need to reset currentpage to default
14716                                 if (scope.cstep <= scope.sdata.length && scope.sdata[scope.cstep]['currentPage'] < 1) {
14717                                     scope.sdata[scope.cstep]['currentPage'] = 1;
14718                                 }
14719                                 updatePages();
14720                                 updateTrackWidth();
14721                             };
14722                         }, 100);
14723                     }
14724                 };
14725             }
14726         ])
14727         .constant('timelineConstants', {
14728             STEP_TYPE: {
14729                 ALERT: 'alert',
14730                 COMPLETED: 'completed',
14731                 CANCELLED: 'cancelled'
14732             }
14733         })
14734         .controller('AttTimelineCtrl', ['$scope', '$timeout', function ($scope, $timeout) {
14735                 var timelineBarCtrls = [];
14736                 var timelineDotCtrls = [];
14737                 this.numSteps = 0;
14738                 this.isAlternate = function () {
14739                     return $scope.alternate;
14740                 };
14741                 this.addTimelineBarCtrls = function (t) {
14742                     timelineBarCtrls.push(t);
14743                 };
14744                 this.addTimelineDotCtrls = function (b) {
14745                     timelineDotCtrls.push(b);
14746                 };
14747                 $timeout(init, 200);
14748                 function init() {
14749                     function compare(a, b) {
14750                         if (a.order < b.order) {
14751                             return -1;
14752                         }
14753                         if (a.order > b.order) {
14754                             return 1;
14755                         }
14756                         return 0;
14757                     }
14758                     timelineDotCtrls.sort(compare);
14759                     timelineBarCtrls.sort(compare);
14760                     if ($scope.$parent.animate) {
14761                         animateSequence();
14762                     }
14763                     $scope.$watch('trigger', function (val) {
14764                         if (val) {
14765                             $scope.resetTimeline();
14766                         } else {
14767                             $scope.$parent.animate = false;
14768                         }
14769                     });
14770                 }
14771                 function animateSequence() {
14772                     var dotsDuration = .25;
14773                     var timelineBarProgressDuration = .25;
14774                     if (typeof $scope.barAnimateDuration === 'number') {
14775                         timelineBarProgressDuration = $scope.barAnimateDuration;
14776                     }
14777                     var start = createAnimation(0, timelineBarProgressDuration);
14778                     function setToInactiveStates() {
14779                         for (var i in timelineDotCtrls) {
14780                             var dotCtrl = timelineDotCtrls[i];
14781                             if (i % 2 === 0) {
14782                                 dotCtrl.unhoveredStateForBelow(.25);
14783                             } else {
14784                                 dotCtrl.unhoveredStateForAbove(.25);
14785                             }
14786                             if (dotCtrl.isStop()) {
14787                                 break;
14788                             }
14789                         }
14790                     }
14791                     function createAnimation(i, duration) {
14792                         if (i === 0) {
14793                             return function () {
14794                                 if (timelineDotCtrls[i + 1].isStop() && timelineDotCtrls[i + 1].isCancelled()) {
14795                                     timelineBarCtrls[i].isCancelled(true);
14796                                 }
14797                                 timelineBarCtrls[i].animate(createAnimation(i + 1, duration), duration);
14798                             };
14799                         } else if (i === timelineBarCtrls.length - 1) {
14800                             return function () {
14801                                 //Removes the bolded text from the start
14802                                 if (timelineDotCtrls[0].isCurrentStep()) {
14803                                     timelineDotCtrls[0].isCurrentStep(false);
14804                                 }
14805                                 if (timelineDotCtrls[i].isStop()) {
14806                                     timelineDotCtrls[i - 1].shrinkAnimate(dotsDuration);
14807                                     timelineDotCtrls[i].isCurrentStep(true);
14808                                 } else {
14809                                     timelineDotCtrls[i - 1].shrinkAnimate(dotsDuration);
14810                                     timelineBarCtrls[i].animate(createAnimation(i + 1, duration), duration);
14811                                 }
14812                                 timelineDotCtrls[i].expandedAnimate(dotsDuration);
14813                                 $timeout(function () {
14814                                     setToInactiveStates();
14815                                 }, 500);
14816                             };
14817                         }
14818                         //End Dot
14819                         else if (i === timelineBarCtrls.length) {
14820                             return function () {
14821                                 //Removes the bolded text from the start
14822                                 if (timelineDotCtrls[0].isCurrentStep()) {
14823                                     timelineDotCtrls[0].isCurrentStep(false);
14824                                 }
14825                                 timelineDotCtrls[i - 1].shrinkAnimate(dotsDuration);
14826                                 timelineDotCtrls[i].expandedAnimate(dotsDuration);
14827                                 timelineDotCtrls[i].isCurrentStep(true);
14828                                 $timeout(function () {
14829                                     setToInactiveStates();
14830                                 }, 500);
14831                             };
14832                         }
14833                         else {
14834                             return function () {
14835                                 //Removes the bolded text from the start
14836                                 if (timelineDotCtrls[0].isCurrentStep()) {
14837                                     timelineDotCtrls[0].isCurrentStep(false);
14838                                 }
14839                                 if (timelineDotCtrls[i].isStop()) {
14840                                     timelineDotCtrls[i - 1].shrinkAnimate(dotsDuration);
14841                                     timelineDotCtrls[i].expandedAnimate(dotsDuration);
14842                                     timelineDotCtrls[i].isCurrentStep(true);
14843                                     $timeout(function () {
14844                                         setToInactiveStates();
14845                                     }, 500);
14846                                 } else {
14847                                     if (timelineDotCtrls[i + 1].isStop() && timelineDotCtrls[i + 1].isCancelled()) {
14848                                         timelineBarCtrls[i].isCancelled(true);
14849                                     }
14850                                     timelineDotCtrls[i - 1].shrinkAnimate(dotsDuration);
14851                                     timelineBarCtrls[i].animate(createAnimation(i + 1, duration), duration);
14852                                     timelineDotCtrls[i].expandedAnimate(dotsDuration);
14853                                 }
14854                             };
14855                         }
14856                     }
14857                     start();
14858                 }
14859             }])
14860         .directive('attTimeline', ['$timeout', '$compile', function ($timeout, $compile) {
14861                 return {
14862                     restrict: 'EA',
14863                     replace: true,
14864                     scope: {
14865                         steps: '=',
14866                         trigger: '=',
14867                         alternate: '=',
14868                         barAnimateDuration: '='
14869                     },
14870                     templateUrl: 'app/scripts/ng_js_att_tpls/steptracker/timeline.html',
14871                     controller: 'AttTimelineCtrl',
14872                     link: function (scope, element, attrs, ctrl) {
14873                         var init = function () {
14874                             var steps = scope.steps;
14875                             var middleSteps = [];
14876                             for (var i = 1; i < steps.length; i++) {
14877                                 var aStep = steps[i];
14878                                 middleSteps.push(aStep);
14879                             }
14880                             scope.middleSteps = middleSteps;
14881                             //Used in calculating the width of the loading bars
14882                             ctrl.numSteps = steps.length - 1;
14883                         };
14884                         init();
14885                         //Recompile in case of scope changes
14886                         scope.resetTimeline = function () {
14887                             scope.animate = true;
14888                             $compile(element)(scope);
14889                         };
14890                     }
14891                 };
14892             }])
14893         .controller('TimelineBarCtrl', ['$scope', function ($scope) {
14894                 this.type = 'timelinebar';
14895                 this.order = parseInt($scope.order);
14896                 this.animate = function (callback, duration) {
14897                     $scope.loadingAnimation(callback, duration);
14898                 };
14899                 this.isCancelled = function (isCancelled) {
14900                     $scope.isCancelled = isCancelled;
14901                 };
14902             }])
14903         .directive('timelineBar', ['animation', '$progressBar', function (animation, $progressBar) {
14904                 return {
14905                     restrict: 'EA',
14906                     replace: true,
14907                     templateUrl: 'app/scripts/ng_js_att_tpls/steptracker/timelineBar.html',
14908                     scope: {
14909                         order: '@'
14910                     },
14911                     require: ['^attTimeline', 'timelineBar'],
14912                     controller: 'TimelineBarCtrl',
14913                     link: function (scope, element, attrs, ctrls) {
14914                         var attTimelineCtrl = ctrls[0];
14915                         var timelineBarCtrl = ctrls[1];
14916                         attTimelineCtrl.addTimelineBarCtrls(timelineBarCtrl);
14917                         scope.isCompleted = true;
14918                         var widthPerc = (100 / attTimelineCtrl.numSteps) - 3;
14919                         element.css('width', widthPerc + '%');
14920                         var elem = element.find('div').eq(0);
14921                         animation.set(elem, {opacity: 0.0});
14922                         var updateCallback = function (selfElement) {
14923                             animation.set(elem, {opacity: 1.0});
14924                             animation.set(elem, {
14925                                 scaleX: selfElement.progress(),
14926                                 transformOrigin: "left"
14927                             });
14928                         };
14929                         scope.loadingAnimation = $progressBar(updateCallback);
14930                     }
14931                 };
14932             }])
14933         .controller('TimelineDotCtrl', ['$scope', '$timeout', 'timelineConstants', function ($scope, $timeout, timelineConstants) {
14934                 this.type = 'dot';
14935                 this.order = parseInt($scope.order);
14936                 var self = this;
14937                 $timeout(function () {
14938                     if (self.order !== 0) {
14939                         if (self.order % 2 !== 0) {
14940                             $scope.initializeAboveForAnimation();
14941                         }
14942                         else {
14943                             $scope.initializeBelowForAnimation();
14944                         }
14945                     }
14946                 });
14947                 this.expandedAnimate = function (duration) {
14948                     $scope.setColor();
14949                     $scope.expandedAnimate(duration);
14950                     if (self.order !== 0 && !$scope.isStepsLessThanFive()) {
14951                         if (self.order % 2 !== 0) {
14952                             $scope.expandContentForAbove(duration);
14953                         } else {
14954                             $scope.expandContentForBelow(duration);
14955                         }
14956                     }
14957                 };
14958                 this.unhoveredStateForAbove = function (duration) {
14959                     $scope.unhoveredStateForAbove(duration);
14960                 };
14961                 this.unhoveredStateForBelow = function (duration) {
14962                     $scope.unhoveredStateForBelow(duration);
14963                 };
14964                 this.shrinkAnimate = function (duration) {
14965                     $scope.shrinkAnimate(duration);
14966                 };
14967                 this.setExpanded = function () {
14968                     $scope.setSize(3);
14969                 };
14970                 this.isStop = function () {
14971                     return $scope.isStop;
14972                 };
14973                 this.isCancelled = function () {
14974                     return ($scope.type === timelineConstants.STEP_TYPE.CANCELLED);
14975                 };
14976                 this.isAlert = function () {
14977                     return ($scope.type === timelineConstants.STEP_TYPE.ALERT);
14978                 };
14979                 //Sets the bolded text
14980                 this.isCurrentStep = function (isCurrentStep) {
14981                     if (isCurrentStep !== undefined) {
14982                         $scope.isCurrentStep = isCurrentStep;
14983                     }
14984                     return $scope.isCurrentStep;
14985                 };
14986             }])
14987         .directive('timelineDot', ['animation', 'timelineConstants',
14988             function (animation, timelineConstants) {
14989                 return {
14990                     restrict: 'EA',
14991                     replace: true,
14992                     scope: {
14993                         order: '@',
14994                         title: '@',
14995                         description: '@',
14996                         by: '@',
14997                         date: '@',
14998                         type: '@'
14999                     },
15000                     templateUrl: 'app/scripts/ng_js_att_tpls/steptracker/timelineDot.html',
15001                     require: ['^attTimeline', 'timelineDot'],
15002                     controller: 'TimelineDotCtrl',
15003                     link: function (scope, element, attrs, ctrls) {
15004                         var attTimelineCtrl = ctrls[0];
15005                         var timelineDotCtrl = ctrls[1];
15006                         attTimelineCtrl.addTimelineDotCtrls(timelineDotCtrl);
15007                         scope.numSteps = attTimelineCtrl.numSteps + 1;
15008                         scope.isCurrentStep = false;
15009                         scope.isCompleted = false;
15010                         scope.isStop = false;
15011                         if (scope.type === timelineConstants.STEP_TYPE.ALERT || scope.type === timelineConstants.STEP_TYPE.CANCELLED) {
15012                             scope.isStop = true;
15013                         }
15014                         scope.isInactive = true;
15015                         var divs = element.find('div');
15016                         var biggerCircleElem = divs.eq(0);
15017                         var expandableCircleElem = divs.eq(2);
15018                         var infoboxElem = divs.eq(3);
15019                         var titleElem = divs.eq(5);
15020                         var contentElem = divs.eq(6);
15021                         var dateElem = divs.eq(9);
15022                         function isEmptyStep() {
15023                             if (!scope.description && !scope.by && !scope.date) {
15024                                 return true;
15025                             }
15026                             return false;
15027                         }
15028                         scope.isStepsLessThanFive = function () {
15029                             if (scope.numSteps < 5) {
15030                                 return true;
15031                             }
15032                             return false;
15033                         };
15034                         scope.titleMouseover = function (num) {
15035                             if (!scope.isStepsLessThanFive() && !isEmptyStep()) {
15036                                 if (num === 1 && scope.order % 2 === 0) {
15037                                     scope.expandContentForBelow(.25);
15038                                 }
15039                                 if (num === 2 && scope.order % 2 !== 0) {
15040                                     scope.expandContentForAbove(.25);
15041                                 }
15042                             }
15043                         };
15044                         scope.titleMouseleave = function () {
15045                             if (scope.order % 2 === 0) {
15046                                 scope.unhoveredStateForBelow(.25);
15047                             }
15048                             else {
15049                                 scope.unhoveredStateForAbove(.25);
15050                             }
15051                         };
15052                         scope.initializeAboveForAnimation = function () {
15053                             if (!scope.isStepsLessThanFive() && attTimelineCtrl.isAlternate()) {
15054                                 animation.set(contentElem, {opacity: 0});
15055                                 animation.set(dateElem, {opacity: 0});
15056                                 if (!isEmptyStep()) {
15057                                     var yOffset = contentElem[0].offsetHeight + dateElem[0].offsetHeight;
15058                                     animation.set(titleElem, {'top': yOffset});
15059                                 }
15060                             }
15061                         };
15062                         scope.expandContentForAbove = function (duration) {
15063                             if (!scope.isStepsLessThanFive() && attTimelineCtrl.isAlternate()) {
15064                                 animation.to(titleElem, duration, {'top': 0});
15065                                 animation.to(contentElem, duration, {opacity: 1});
15066                                 animation.to(dateElem, duration, {opacity: 1});
15067                             }
15068                         };
15069                         scope.unhoveredStateForAbove = function (duration) {
15070                             if (!scope.isStepsLessThanFive() && attTimelineCtrl.isAlternate()) {
15071                                 animation.set(contentElem, {opacity: 0});
15072                                 animation.set(dateElem, {opacity: 1});
15073                                 var yOffset = contentElem[0].offsetHeight;
15074                                 animation.to(titleElem, duration, {'top': yOffset});
15075                             }
15076                         };
15077                         scope.initializeBelowForAnimation = function () {
15078                             if (!scope.isStepsLessThanFive() && attTimelineCtrl.isAlternate()) {
15079                                 animation.set(contentElem, {height: '0%', opacity: 0, top: '-20px'});
15080                                 animation.set(dateElem, {opacity: 0});
15081                             }
15082                         };
15083                         scope.expandContentForBelow = function (duration) {
15084                             if (!scope.isStepsLessThanFive() && attTimelineCtrl.isAlternate()) {
15085                                 animation.set(dateElem, {opacity: 1});
15086                                 animation.to(contentElem, duration, {height: 'auto', opacity: 1, top: '0px'});
15087                             }
15088                         };
15089                         scope.unhoveredStateForBelow = function (duration) {
15090                             if (!scope.isStepsLessThanFive() && attTimelineCtrl.isAlternate()) {
15091                                 animation.to(contentElem, duration, {height: '0%', opacity: 0, top: '-20px', position: 'relative'});
15092                                 animation.set(dateElem, {opacity: 1});
15093                             }
15094                         };
15095                         /*Default Initializaztion*/
15096                         //If the info box is above and the description and date and by are empty then we have do reset its position
15097                         if (isEmptyStep() && (scope.order % 2 !== 0 && attTimelineCtrl.isAlternate())) {
15098                             infoboxElem.css('top', '-47px');
15099                         }
15100                         //Check if the order is odd and set the appropiate above or below and other effects
15101                         if (scope.order % 2 === 0 || !attTimelineCtrl.isAlternate()) {
15102                             scope.isBelowInfoBoxShown = true;
15103                         }
15104                         else {
15105                             scope.isBelowInfoBoxShown = false;
15106                         }
15107                         //modify some css for steps less than 5 and not alternating
15108                         if (scope.isStepsLessThanFive() && !attTimelineCtrl.isAlternate()) {
15109                             animation.set(dateElem, {marginTop: 10});
15110                         }
15111                         //For IE 8 fix
15112                         animation.set(biggerCircleElem, {opacity: '.5'});
15113                         //shrink the expandableCircle to we can expand it later
15114                         animation.set(expandableCircleElem, {opacity: '0.0'});
15115                         animation.set(expandableCircleElem, {scale: .10});
15116                         if (scope.order === 0) {
15117                             animation.set(expandableCircleElem, {opacity: '1.0'});
15118                             animation.set(expandableCircleElem, {scale: 1});
15119                             animation.set(biggerCircleElem, {scale: 3});
15120                             scope.isCurrentStep = true;
15121                             scope.isInactive = false;
15122                             scope.isCompleted = true;
15123                         }
15124                         scope.setColor = function () {
15125                             scope.isInactive = false;
15126                             if (scope.type === timelineConstants.STEP_TYPE.CANCELLED) {
15127                                 scope.isCancelled = true;
15128                             }
15129                             else if (scope.type === timelineConstants.STEP_TYPE.ALERT) {
15130                                 scope.isAlert = true;
15131                             }
15132                             else {
15133                                 scope.isCompleted = true;
15134                             }
15135                             if (!scope.$phase) {
15136                                 scope.$apply();
15137                             }
15138                         };
15139                         scope.setSize = function (size) {
15140                             animation.set(biggerCircle, {scale: size});
15141                         };
15142                         scope.setExpandedCircle = function () {
15143                             animation.set(expandableCircleElem, {opacity: '1.0'});
15144                             animation.set(expandableCircleElem, {scale: 1});
15145                         };
15146                         scope.expandedAnimate = function (duration) {
15147                             animation.to(biggerCircleElem, duration, {scale: 3});
15148                             animation.set(expandableCircleElem, {opacity: '1.0'});
15149                             animation.to(expandableCircleElem, duration, {scale: 1});
15150                         };
15151                         scope.shrinkAnimate = function (duration) {
15152                             animation.to(biggerCircleElem, duration, {scale: 1});
15153                         };
15154                     }
15155                 };
15156             }]);
15157 angular.module('att.abs.table', ['att.abs.utilities'])
15158 .constant('tableConfig', {
15159     //true for descending & false for ascending
15160     defaultSortPattern: false,
15161     highlightSearchStringClass: 'tablesorter-search-highlight'
15162 })
15163
15164 .directive('attTable', ['$filter', function($filter) {
15165     return {
15166         restrict: 'EA',
15167         replace: true,
15168         transclude: true,
15169         scope: {
15170             tableData: "=",
15171             viewPerPage: "=",
15172             currentPage: "=",
15173             totalPage: "=",
15174             searchCategory: "=",
15175             searchString: "="
15176         },
15177         require: 'attTable',
15178         templateUrl: 'app/scripts/ng_js_att_tpls/table/attTable.html',
15179         controller: ['$scope', function($scope) {
15180             this.headers = [];
15181             this.currentSortIndex = null;
15182             this.setIndex = function(headerScope) {
15183                 this.headers.push(headerScope);
15184             };
15185             this.getIndex = function(headerName) {
15186                 for (var i = 0; i < this.headers.length; i++) {
15187                     if (this.headers[i].headerName === headerName) {
15188                         return this.headers[i].index;
15189                     }
15190                 }
15191                 return null;
15192             };
15193             this.sortData = function(columnIndex, reverse) {
15194                 $scope.$parent.columnIndex = columnIndex;
15195                 $scope.$parent.reverse = reverse;
15196                 this.currentSortIndex = columnIndex;
15197                 $scope.currentPage = 1;
15198                 this.resetSortPattern();
15199             };
15200             this.getSearchString = function() {
15201                 return $scope.searchString;
15202             };
15203             this.resetSortPattern = function() {
15204                 for(var i = 0; i < this.headers.length; i++) {
15205                     var currentScope = this.headers[i];
15206                     if(currentScope.index !== this.currentSortIndex) {
15207                         currentScope.resetSortPattern();
15208                     }
15209                 }
15210             };
15211         }],
15212         link: function(scope, elem, attr, ctrl) {
15213             scope.searchCriteria = {};
15214             scope.$watchCollection('tableData', function(value) {
15215                 if(value && !isNaN(value.length)) {
15216                     scope.totalRows = value.length;
15217                 }
15218             });
15219             scope.$watch('currentPage', function(val) {
15220                 scope.$parent.currentPage = val;
15221             });
15222             scope.$watch('viewPerPage', function(val) {
15223                 scope.$parent.viewPerPage = val;
15224             });
15225             scope.$watch(function() {
15226                 return scope.totalRows / scope.viewPerPage;
15227             }, function(value) {
15228                 if(!isNaN(value)) {
15229                     scope.totalPage = Math.ceil(value);
15230                     scope.currentPage = 1;
15231                 }
15232             });
15233             var searchValCheck = function(val){
15234                 if(angular.isDefined(val) && val !== null && val !== ""){
15235                     return true;
15236                 }
15237             };
15238             var setSearchCriteria = function(v1,v2){
15239                 if(searchValCheck(v1) && searchValCheck(v2)){
15240                     var index = ctrl.getIndex(v2);
15241                     scope.searchCriteria = {};
15242                     if (index !== null) {
15243                         scope.searchCriteria[index] = v1;
15244                     }
15245                 }else if(searchValCheck(v1) && (!angular.isDefined(v2) || v2 === null || v2 === "")){
15246                     scope.searchCriteria = {
15247                         $: v1
15248                     };
15249                 }else {
15250                     scope.searchCriteria = {};
15251                 }
15252             };
15253             scope.$watch('searchCategory', function(newVal,oldVal) {
15254                 if(newVal !== oldVal){
15255                     setSearchCriteria(scope.searchString,newVal);
15256                 }
15257             });
15258             scope.$watch('searchString', function (newVal,oldVal) {
15259                 if(newVal !== oldVal){
15260                     setSearchCriteria(newVal,scope.searchCategory);
15261                 }
15262             });
15263             scope.$watchCollection('searchCriteria', function(val) {
15264                 scope.$parent.searchCriteria = val;
15265                 scope.totalRows = ($filter('filter')(scope.tableData, val, false)).length;
15266                 scope.currentPage = 1;
15267             });
15268         }
15269     };
15270 }])
15271
15272 .directive('attTableRow', [function() {
15273     return {
15274         restrict: 'EA',
15275         compile: function (elem, attr) {
15276             if (attr.type === 'header') {
15277                 elem.find('tr').eq(0).addClass('tablesorter-headerRow');
15278             } else if (attr.type === 'body') {
15279                 var html = elem.children();
15280                 if(attr.rowRepeat){
15281                     html.attr('ng-repeat', attr.rowRepeat.concat(" | orderBy : columnIndex : reverse | filter : searchCriteria : false | attLimitTo : viewPerPage : viewPerPage*(currentPage-1)"));
15282                 }
15283                 html.attr('ng-class', "{'alt-row': $even,'normal-row': $odd}");
15284                 elem.append(html);
15285             }
15286         }
15287     };
15288 }])
15289
15290 .directive('attTableHeader', ['tableConfig', function(tableConfig) {
15291     return {
15292         restrict: 'EA',
15293         replace: true,
15294         transclude: true,
15295         scope: {
15296             sortable: '@',
15297             defaultSort: '@',
15298             index: '@key',
15299             arrowDirection: '=',
15300             clickFunc: '&'
15301         },
15302         require: '^attTable',
15303         templateUrl: 'app/scripts/ng_js_att_tpls/table/attTableHeader.html',
15304         link: function(scope, elem, attr, ctrl) {
15305             var reverse = tableConfig.defaultSortPattern;
15306             scope.headerName = elem.text();
15307             scope.sortPattern = null;
15308             ctrl.setIndex(scope);
15309
15310             scope.$watch('arrowDirection', function(val){
15311                 if(val){
15312                     scope.sortPattern = 'asc';}
15313                 else{
15314                     scope.sortPattern = 'desc';}
15315             });
15316
15317             scope.$watch(function() {
15318                 return elem.text();
15319             }, function(value) {
15320                 scope.headerName = value;
15321             });
15322             scope.sort = function(sortType) {
15323                 if(typeof sortType === 'boolean') {
15324                     reverse = sortType;
15325                 }
15326                 ctrl.sortData(scope.index, reverse);
15327                 scope.sortPattern = reverse ? 'desc' : 'asc';
15328                 reverse = !reverse;
15329             };
15330             scope.$watch(function() {
15331                 return ctrl.currentSortIndex;
15332             }, function(value) {
15333                 if (value !== scope.index) {
15334                     scope.sortPattern = null;
15335                 }
15336             });
15337             if(scope.sortable !== 'false') {
15338                 if(scope.defaultSort === 'A' || scope.defaultSort === 'a') {
15339                     scope.sort(false);
15340                 } else if(scope.defaultSort === 'D' || scope.defaultSort === 'd') {
15341                     scope.sort(true);
15342                 }
15343             }
15344             scope.resetSortPattern = function() {
15345                 reverse = tableConfig.defaultSortPattern;
15346             };
15347         }
15348     };
15349 }])
15350
15351 .directive('attTableBody', ['$filter', '$timeout', 'tableConfig', function($filter, $timeout, tableConfig) {
15352     return {
15353         restrict: 'EA',
15354         require: '^attTable',
15355         replace: true,
15356         transclude: true,
15357         templateUrl: 'app/scripts/ng_js_att_tpls/table/attTableBody.html',
15358         link: function (scope, elem, attr, ctrl) {
15359             var highlightSearchStringClass = tableConfig.highlightSearchStringClass;
15360             var searchString = "";
15361             var wrapElement = function (elem) {
15362                 var text = elem.text();
15363                 elem.html('');
15364                 elem.append($filter('highlight')(text, searchString, highlightSearchStringClass));
15365             };
15366             var traverse = function (elem) {
15367                 var innerHtml = elem.children();
15368                 if (innerHtml.length > 0) {
15369                     for (var i = 0; i < innerHtml.length; i++) {
15370                         traverse(innerHtml.eq(i));
15371                     }
15372                 } else {
15373                     wrapElement(elem);
15374                     return;
15375                 }
15376             };
15377             var clearWrap = function (elem) {
15378                 var elems = elem.find('*');
15379                 for (var i = 0; i < elems.length; i++) {
15380                     if (elems.eq(i).attr('class') && elems.eq(i).attr('class').indexOf(highlightSearchStringClass) !== -1) {
15381                         var text = elems.eq(i).text();
15382                         elems.eq(i).replaceWith(text);
15383                     }
15384                 }
15385             };
15386             $timeout(function () {
15387                 var actualHtml = elem.children();
15388                 scope.$watch(function () {
15389                     return ctrl.getSearchString();
15390                 }, function (val) {
15391                     searchString = val;
15392                     clearWrap(elem);
15393                     if (actualHtml.length > 0) {
15394                         traverse(elem);
15395                     } else {
15396                         wrapElement(elem);
15397                     }
15398                 });
15399             }, 50);
15400         }
15401     };
15402 }]);
15403
15404 angular.module('att.abs.tabs', [])
15405         .directive('attTabs', function () {
15406             return{
15407                 restrict: 'EA',
15408                 transclude: false,
15409                 replace: true,
15410                 scope: {
15411                     tabs: "=title"
15412                 },
15413                 controller: ['$scope', function ($scope) {
15414                         this.getData = function () {
15415                             return $scope.tabs;
15416                         };
15417                         this.onClickTab = function (tab) {
15418                             $scope.currentTab = tab.url;
15419                             return $scope.currentTab;
15420                         };
15421                         this.isActiveTab = function (tab) {
15422                             return (tab === $scope.currentTab);
15423                         };
15424                     }],
15425                 link: function (scope) {
15426                     for (var i = 0; i < scope.tabs.length; i++) {
15427                         if ((scope.tabs[i].selected) && (scope.tabs[i].url)) {
15428                             scope.currentTab = scope.tabs[i].url;
15429                         }
15430                     }
15431                 }
15432             };
15433         })
15434         .directive('floatingTabs', function () {
15435             return {
15436                 require: '^attTabs',
15437                 restrict: 'EA',
15438                 transclude: false,
15439                 replace: true,
15440                 scope: {
15441                     size: "@"
15442                 },
15443                 templateUrl: 'app/scripts/ng_js_att_tpls/tabs/floatingTabs.html',
15444                 link: function (scope, elem, attr, attTabsCtrl) {
15445                     scope.tabs = attTabsCtrl.getData();
15446                     scope.onClickTab = attTabsCtrl.onClickTab;
15447                     scope.isActiveTab = attTabsCtrl.isActiveTab;
15448                 }
15449             };
15450         })
15451         .directive('simplifiedTabs', function () {
15452             return {
15453                 require: '^attTabs',
15454                 restrict: 'EA',
15455                 transclude: false,
15456                 replace: true,
15457                 scope: {
15458                     ctab: "=ngModel"
15459                 },
15460                 templateUrl: 'app/scripts/ng_js_att_tpls/tabs/simplifiedTabs.html',
15461                 link: function (scope, elem, attr, attTabsCtrl) {
15462                     scope.tabs = attTabsCtrl.getData();
15463                     scope.clickTab = function (tab) {
15464                         scope.ctab = tab.id;
15465                         return scope.ctab;
15466                     };
15467                     scope.isActive = function (tab) {
15468                         return (tab === scope.ctab);
15469                     };
15470                 }
15471             };
15472         })
15473         .directive('genericTabs', function () {
15474             return {
15475                 require: '^attTabs',
15476                 restrict: 'EA',
15477                 transclude: false,
15478                 replace: true,
15479                 scope: {
15480                     ctab: "=ngModel"
15481                 },
15482                 templateUrl: 'app/scripts/ng_js_att_tpls/tabs/genericTabs.html',
15483                 link: function (scope, elem, attr, attTabsCtrl) {
15484                     scope.tabs = attTabsCtrl.getData();
15485                     scope.clickTab = function (tab) {
15486                         scope.ctab = tab.id;
15487                         return scope.ctab;
15488                     };
15489                     scope.isActive = function (tab) {
15490                         return (tab === scope.ctab);
15491                     };
15492                 }
15493             };
15494         })
15495         .directive('parentTab', [function () {
15496                 return {
15497                     restrict: 'EA',
15498                     scope: {
15499                         menuItems: '=',
15500                         activeSubMenu: '=',
15501                         activeMenu: '='
15502                     },
15503                     controller: ['$scope', function ($scope) {
15504                             $scope.megaMenu = $scope.menuItems;
15505                             $scope.megaMenuTab;
15506                             $scope.megaMenuHoverTab;
15507                             this.setMenu = function () {
15508                                 $scope.menuItems = $scope.megaMenu;
15509                                 for (var i = 0; i < $scope.menuItems.length; i++) {
15510                                     if ($scope.menuItems[i].active) {
15511                                         $scope.activeMenu = $scope.menuItems[i];
15512                                     }
15513                                 }
15514                                 this.setSubMenuStatus(false);
15515                                 $scope.$apply();
15516                             };
15517                             this.setActiveMenu = function () {
15518                                 if (!($scope.megaMenuTab === "undefined" || $scope.megaMenuTab === null)) {
15519                                     $scope.menuItems = [$scope.megaMenuTab];
15520                                     $scope.activeMenu = {};
15521                                     $scope.activeSubMenu = $scope.megaMenuTab;
15522                                     this.setSubMenuStatus(true);
15523                                 }
15524                                 else {
15525                                     setMenuItems();
15526                                 }
15527                                 $scope.$apply();
15528                             };
15529                             this.setMenuItems = function(){
15530                                 for (var i = 0; i < $scope.menuItems.length; i++) {
15531                                         $scope.menuItems[i].active = false;
15532                                         if ($scope.menuItems[i].subItems){
15533                                             for (var j = 0; j < $scope.menuItems[i].subItems.length; j++) {
15534                                                 $scope.menuItems[i].subItems[j].active = false;
15535                                             }
15536                                         }
15537                                     }
15538                                     $scope.menuItems = $scope.megaMenu;
15539                             };
15540                             var checkSubMenuStatus = false;
15541                             this.setSubMenuStatus = function (value) {
15542                                 checkSubMenuStatus = value;
15543                             };
15544                             this.getSubMenuStatus = function () {
15545                                 return checkSubMenuStatus;
15546                             };
15547                             this.setActiveMenuTab = function (tab) {
15548                                 $scope.megaMenuTab = tab;
15549                             };
15550                             this.setActiveMenuHoverTab = function (tab) {
15551                                 $scope.megaMenuHoverTab = tab;
15552                             };
15553                             this.setActiveSubMenuTab = function () {
15554                                 $scope.megaMenuTab = $scope.megaMenuHoverTab;
15555                             };
15556                             this.resetMenuTab = function () {
15557                                 $scope.megaMenuTab = 'undefined';
15558                             };
15559                         }]
15560                 };
15561             }])
15562         .directive('parentmenuTabs', [function () {
15563                 return {
15564                     restrict: 'EA',
15565                     transclude: true,
15566                     replace: true,
15567                     scope: {
15568                         megaMenu: '@',
15569                         menuItems: '='
15570                     },
15571                     controller: ['$scope', function ($scope) {
15572                             this.getMenu = function () {
15573                                 return $scope.menuItems;
15574                             };
15575                             this.setMenu = function (menuItem) {
15576                                 $scope.menuItems = menuItem;
15577                             };
15578                         }],
15579                     templateUrl: 'app/scripts/ng_js_att_tpls/tabs/parentmenuTab.html'
15580                 };
15581             }])
15582         .directive('menuTabs', ["$window", "$document", function (win, $document) {
15583                 return {
15584                     restrict: 'EA',
15585                     transclude: true,
15586                     replace: true,
15587                     require: ['^parentTab', '^?parentmenuTabs'],
15588                     scope: {
15589                         activeMenu: "=",
15590                         menuItem: "=",
15591                         subMenu: "@",
15592                         subItemActive: "@"
15593                     },
15594                     templateUrl: function (element, attrs) {
15595                         if (attrs.megaMenu) {
15596                             return 'app/scripts/ng_js_att_tpls/tabs/menuTab.html';
15597                         }
15598                         else {
15599                             return 'app/scripts/ng_js_att_tpls/tabs/submenuTab.html';
15600                         }
15601                     },
15602                     link: function (scope, elem, attr, ctrl) {
15603                         var parentCtrl = ctrl[0];
15604                         var parentmenuCtrl = ctrl[1];
15605                         scope.clickInactive = true;
15606                         scope.showHoverChild = function (e) {
15607                             scope.clickInactive = false;
15608                             scope.hoverChild = ctrl[0].getSubMenuStatus();
15609                             if (e.type === "mouseover" && ctrl[0].getSubMenuStatus())
15610                             {
15611                                 scope.showChildren(e);
15612                             }
15613                         };
15614                         scope.showChildren = function (e) {
15615                             scope.parentMenuItems = parentmenuCtrl.getMenu();
15616                             for (var i = 0; i < scope.parentMenuItems.length; i++) {
15617                                 scope.parentMenuItems[i].active = false;
15618                                 if (scope.parentMenuItems[i].subItems) {
15619                                     for (var j = 0; j < scope.parentMenuItems[i].subItems.length; j++) {
15620                                         scope.parentMenuItems[i].subItems[j].active = false;
15621                                     }
15622                                 }
15623                                 scope.clickInactive = true;
15624                             }
15625                             scope.menuItem.active = true;
15626                             scope.activeMenu = scope.menuItem;
15627                             e.stopPropagation();
15628                         };
15629                         scope.$watch("subItemActive", function (value) {
15630                             if (value === "true" && scope.subMenu === 'true') {
15631                                 parentCtrl.setActiveMenuHoverTab(scope.menuItem);
15632                             }
15633                         });
15634                         scope.showMenuClick = function () {
15635                             parentCtrl.setActiveMenuTab(scope.menuItem);
15636                         };
15637                         scope.showSubMenuClick = function () {
15638                             parentCtrl.setActiveSubMenuTab();
15639                         };
15640                         scope.resetMenu = function () {
15641                             parentCtrl.resetMenuTab();
15642                         };
15643                         function debounce(method, delay) {
15644                             clearTimeout(method._tId);
15645                             method._tId = setTimeout(function () {
15646                                 parentCtrl.setMenu();
15647                             }, delay);
15648                         }
15649                         function debounce1(method, delay) {
15650                             clearTimeout(method._tId);
15651                             method._tId = setTimeout(function () {
15652                                 parentCtrl.setActiveMenu();
15653                             }, delay);
15654                         }
15655                         $document.bind('scroll', function () {
15656                             if (win.pageYOffset === 0) {
15657                                 debounce(parentCtrl.setMenu, 100);
15658                             }
15659                             else if (win.pageYOffset > 1 && win.pageYOffset < 1500) {
15660                                 debounce1(parentCtrl.setActiveMenu, 100);
15661                             }
15662                         });
15663                     }
15664                 };
15665             }]);
15666 angular.module('att.abs.tagBadges', [])
15667         .directive('tagBadges', ['$parse', '$timeout', function($parse, $timeout) {
15668                 return {
15669                     restrict: 'EA',
15670                     replace: false,
15671                     transclude: true,
15672                     templateUrl: 'app/scripts/ng_js_att_tpls/tagBadges/tagBadges.html',
15673                     scope: {
15674                         styleType: "@",
15675                         onClose: "&"
15676                     },
15677                     link: function(scope, elem, attr) {
15678                         scope.isSmall = false;
15679                         scope.isIcon = false;
15680                         scope.isColor = false;
15681                         scope.display = true;
15682                         scope.isClosable = false;
15683                         scope.isHighlight = false;
15684                         scope.customColor = false;
15685
15686                         if (attr.small === "") {
15687                             scope.isSmall = true;
15688                         }
15689                         if (scope.styleType === "icon") {
15690                             scope.isIcon = true;
15691                         }
15692                         else if (scope.styleType === "color") {
15693                             scope.isColor = true;
15694                             if(attr.color !== undefined && attr.color !== "") {
15695                                 scope.customColor = true;
15696                                 attr.$observe("color", function(val) {
15697                                     scope.border_type_borderColor = val;
15698                                     scope.background_type_backgroundColor = val;
15699                                     scope.background_type_borderColor = val;
15700                                 });
15701                             }
15702                         }
15703                         scope.activeHighlight = function(state){
15704                             if(scope.customColor){
15705                                 if(state){
15706                                     scope.isHighlight = true;
15707                                 }
15708                                 else{
15709                                     scope.isHighlight = false;
15710                                 }
15711                             }
15712                         };
15713                         if (attr.closable === "") {
15714                             scope.isClosable = true;
15715                             scope.closeMe = function() {
15716                                 scope.display = false;
15717                                 $timeout(function(){
15718                                     elem.attr("tabindex", "0");
15719                                     elem[0].focus();
15720                                     elem.bind('blur', function(){
15721                                         elem.remove();
15722                                     });
15723                                 });
15724                                 if(attr['onClose']){
15725                                     scope.onClose = $parse(scope.onClose);
15726                                     scope.onClose();
15727                                 }
15728                             };
15729                         }
15730                     }
15731                 };
15732             }]);
15733 angular.module('att.abs.textOverflow', [])
15734         .constant('textDefaultOptions', {
15735             width: '50%'
15736         })
15737 .directive('attTextOverflow', ['textDefaultOptions','$compile',function(textDefaultOptions,$compile)
15738 {
15739     return {
15740         restrict: 'A',
15741         link: function(scope, elem, attrs)
15742         {
15743             var tooltipText = elem.text();
15744             elem.addClass('text-ellipsis');
15745             attrs.$observe('attTextOverflow', function(val){
15746                 if(val){
15747                     elem.css({"width":val});
15748                 }
15749                 else{
15750                     elem.css({"width":textDefaultOptions.width});
15751                 }
15752             });
15753             if(!(elem.attr('tooltip'))){
15754                 elem.attr("tooltip", tooltipText);
15755                 elem.attr("tooltip-placement", 'above');
15756                 var newElem =  angular.element(elem);
15757                 $compile(newElem)(scope);
15758             }
15759         }
15760     };
15761 }]);
15762
15763 angular.module('att.abs.toggle', ['angular-gestures', 'att.abs.position'])
15764         .directive('attToggleTemplate', ['$compile', '$log', '$position',  function($compile, $log, $position)
15765             {
15766                 return{
15767                     restrict: 'A',
15768                     require: 'ngModel',
15769                     transclude: true,
15770                     scope: {
15771                         modelVal: "=ngModel"
15772                     },
15773                     templateUrl: 'app/scripts/ng_js_att_tpls/toggle/demoToggle.html',
15774                     link: function(scope, element, attr) {
15775                         scope.initialDragPosition = 0;
15776                         var dragStatus = 0;
15777                         var switchMovementPath = ($position.offset(element.children().eq(1).children().eq(0)).width -1);
15778                          var updateModelVal = function() {
15779                              if (scope.attrValue === attr.ngTrueValue || scope.attrValue)
15780                             {
15781                                 scope.modelVal = false;
15782                             }
15783                             else
15784                             {
15785                                 scope.modelVal = true;
15786                             }
15787                         };
15788                         scope.updateModel = function(env){
15789                            {
15790                             if (dragStatus !== 1) {
15791                                 updateModelVal();
15792                                 dragStatus = 0;
15793                             }
15794                             }
15795                             env.preventDefault();
15796                         };
15797                         scope.drag = function(e) {
15798                             dragStatus = 1;
15799                             if (e.type === 'dragstart') {
15800                                 scope.initialDragPosition = $position.position(element.children().eq(1)).left;
15801
15802                                 element.children().eq(1).addClass('dragging');
15803                             } else if (e.type === 'drag') {
15804                                 var left = Math.min(0, Math.max(scope.initialDragPosition + e.gesture.deltaX, -switchMovementPath));
15805                                 element.children().eq(1).css({
15806                                     left: left + 'px'
15807                                 });
15808                             } else if (e.type === 'dragend') {
15809                                 var isOn = $position.position(element.children().eq(1)).left > (switchMovementPath*-1)/2;
15810                                 element.children().eq(1).removeClass('dragging');
15811                                 TweenMax.to(element.children().eq(1), .1, {left: isOn ? 0 : (switchMovementPath*-1), ease: Power4.easeOut,
15812                                     onComplete: function(){element.children().eq(1).css({left: ''});
15813                                     }});
15814                                 if(isOn || (!isOn && e.gesture.direction === "left")){
15815                                 updateModelVal();
15816                             }
15817                             dragStatus = 0;
15818                             }
15819
15820                             return false;
15821                         };
15822
15823                         scope.directiveValue = attr.attToggleTemplate;
15824                         scope.on = attr.trueValue;
15825                         scope.off = attr.falseValue;
15826                         var switchMovementPathPixels = ((switchMovementPath)*-1) + 'px';
15827                         scope.$watch('modelVal', function(newVal) {
15828                             scope.attrValue = newVal;
15829                             if (newVal === attr.ngTrueValue || newVal) {
15830                                 element.children().eq(1).css({
15831                                     left : '0px'
15832                                 });
15833                                 element.addClass('att-checkbox--on');
15834                                 element.attr("aria-checked", true);
15835                                 dragStatus = 0;
15836                             } else {
15837                                 element.children().eq(1).css({
15838                                     left : switchMovementPathPixels
15839                                 });
15840                                 element.removeClass('att-checkbox--on');
15841                                 element.attr("aria-checked", false);
15842                                 dragStatus = 0;
15843                             }
15844                             element.children().eq(1).css({
15845                                     left : ''
15846                                 });
15847                             });
15848                         }
15849                     };
15850                 }
15851             ])
15852
15853         .directive('attToggleMain', ['$compile', function($compile)
15854             {
15855                 return{
15856                     restrict: 'A',
15857                     require: 'ngModel',
15858                     transclude: true,
15859                     replace: true,
15860                     scope: {
15861                         modelValue: "=ngModel",
15862                         trueValue: "=ngTrueValue",
15863                         falseValue: "=ngFalseValue"
15864                     },
15865                     link: function(scope, element, attr) {
15866                         var html = "";
15867                         var attrVal = "";
15868                         element.removeAttr('att-toggle-main');
15869                         scope.on = attr.ngTrueValue;
15870                         scope.off = attr.ngFalseValue;
15871                         scope.largeValue = attr.attToggleMain;
15872                         if (angular.isDefined(attr.ngTrueValue)) {
15873                             html += ' true-value="{{on}}" false-value="{{off}}"';
15874                         }
15875                         if (scope.largeValue !== undefined)
15876                         {
15877                             attrVal += ' ="{{largeValue}}"';
15878                         }
15879
15880                         element.css({display:'none'});
15881                         var elm = angular.element('<div role="checkbox" class="att-switch att-switch-alt"  ng-class="{\'large\' : largeValue == \'large\'}" ng-model="modelValue"' + html + ' att-toggle-template' + attrVal + '>' + element.prop('outerHTML') + '</div>');
15882                         elm = $compile(elm)(scope);
15883                         element.replaceWith(elm);
15884                     }
15885                 };
15886             }]
15887                 );
15888 angular.module('att.abs.tooltip', ['att.abs.position', 'att.abs.utilities', 'ngSanitize'])
15889         // The default options tooltip and popover.
15890         .constant('tooltipDefaultOptions', {
15891             placement: 'above',
15892             animation: false,
15893             popupDelay: 0,
15894             stylett: 'dark',
15895             appendToBody: true
15896         })
15897
15898         /**
15899          * The $tooltip service creates tooltip- and popover-like directives as well as
15900          * houses global options for them.
15901          */
15902         .provider('$tooltip', ['tooltipDefaultOptions', function(tooltipDefaultOptions) {
15903
15904             // Default hide triggers for each show trigger
15905             var triggerMap = {
15906                 'mouseenter': 'mouseleave',
15907                 'click': 'click',
15908                 'focus': 'blur',
15909                 'mouseover':'mouseout'
15910             };
15911
15912             // The options specified to the provider globally.
15913             var globalOptions = {};
15914
15915             this.options = function(value) {
15916                 angular.extend(globalOptions, value);
15917             };
15918
15919             /**
15920              * This allows you to extend the set of trigger mappings available. E.g.:
15921              *
15922              *   $tooltipProvider.setTriggers( 'openTrigger': 'closeTrigger' );
15923              */
15924             this.setTriggers = function(triggers) {
15925                 angular.extend(triggerMap, triggers);
15926             };
15927
15928             /**
15929              * This is a helper function for translating camel-case to snake-case.
15930              */
15931             function snakeCase(name) {
15932                 var regexp = /[A-Z]/g;
15933                 var separator = '-';
15934                 return name.replace(regexp, function(letter, pos) {
15935                     return (pos ? separator : '') + letter.toLowerCase();
15936                 });
15937             }
15938
15939             /**
15940              * Returns the actual instance of the $tooltip service.
15941              */
15942             this.$get = ['$window', '$compile', '$timeout', '$parse', '$document', '$position', '$interpolate', function($window, $compile, $timeout, $parse, $document, $position, $interpolate) {
15943                     return function (type, prefix, defaultTriggerShow) {
15944                         var options = angular.extend({}, tooltipDefaultOptions, globalOptions);
15945                         /**
15946                          * Returns an object of show and hide triggers.
15947                          *
15948                          * If a trigger is supplied,
15949                          * it is used to show the tooltip; otherwise, it will use the `trigger`
15950                          * option passed to the `$tooltipProvider.options` method; else it will
15951                          * default to the trigger supplied to this directive factory.
15952                          *
15953                          * The hide trigger is based on the show trigger. If the `trigger` option
15954                          * was passed to the `$tooltipProvider.options` method, it will use the
15955                          * mapped trigger from `triggerMap` or the passed trigger if the map is
15956                          * undefined; otherwise, it uses the `triggerMap` value of the show
15957                          * trigger; else it will just use the show trigger.
15958                          */
15959                         function getTriggers(trigger) {
15960                             var show = trigger || options.trigger || defaultTriggerShow;
15961                             var hide = triggerMap[show] || show;
15962                             return {
15963                                 show: show,
15964                                 hide: hide
15965                             };
15966                         }
15967
15968                         var directiveName = snakeCase(type);
15969
15970                         var startSym = $interpolate.startSymbol();
15971                         var endSym = $interpolate.endSymbol();
15972                         var template =
15973                                 '<div ' + directiveName + '-popup ' +
15974                                 'title="' + startSym + 'tt_title' + endSym + '" ' +
15975                                 'content="' + startSym + 'tt_content' + endSym + '" ' +
15976                                 'placement="' + startSym + 'tt_placement' + endSym + '" ' +
15977                                 'animation="tt_animation()" ' +
15978                                 'is-open="tt_isOpen" ' +
15979                                 'stylett="' + startSym + 'tt_style' + endSym + '" ' +
15980                                 '>' +
15981                                 '</div>';
15982                         return {
15983                             restrict: 'EA',
15984                             scope: true,
15985                             link: function (scope, element, attrs) {
15986                                 element.attr("tabindex", "0");
15987                                 element.bind('mouseenter', function(){
15988                                     element.removeAttr("title");
15989                                 });
15990                                 element.bind('mouseleave', function(){
15991                                     element.attr("title", scope.tt_content);
15992                                 });
15993                                 var tooltip = $compile(template)(scope);
15994                                 var transitionTimeout;
15995                                 var popupTimeout;
15996                                 var $body;
15997                                 var appendToBody = angular.isDefined(options.appendToBody) ? options.appendToBody : false;
15998                                 var triggers = getTriggers(undefined);
15999                                 var hasRegisteredTriggers = false;
16000                                 var hasEnableExp = angular.isDefined(attrs[prefix + 'Enable']);
16001
16002                                 // By default, the tooltip is not open.
16003                                 // add ability to start tooltip opened
16004                                 scope.tt_isOpen = false;
16005
16006                                 //Adding a scope watch, to remove the created popup from DOM, incase it is updated outside the provider code.
16007                                 scope.$watch('tt_isOpen', function(newVal, oldVal){
16008                                     if(newVal !== oldVal && !newVal){
16009                                         tooltip.remove();
16010                                     }
16011                                 });
16012
16013                                 function toggleTooltipBind() {
16014                                     if (!scope.tt_isOpen) {
16015                                         showTooltipBind();
16016                                     } else {
16017                                         hideTooltipBind();
16018                                     }
16019                                 }
16020
16021                                 // Show the tooltip with delay if specified, otherwise show it immediately
16022                                 function showTooltipBind() {
16023                                     tooltip = $compile(template)(scope);
16024                                     scope.$digest();
16025                                     if (hasEnableExp && !scope.$eval(attrs[prefix + 'Enable'])) {
16026                                         return;
16027                                     }
16028                                     if (scope.tt_popupDelay) {
16029                                         popupTimeout = $timeout(show, scope.tt_popupDelay);
16030                                     } else {
16031                                         scope.$apply(show);
16032                                     }
16033                                 }
16034
16035                                 function hideTooltipBind() {
16036                                     scope.$apply(function() {
16037                                         hide();
16038                                     });
16039                                 }
16040
16041                                 // Show the tooltip popup element.
16042                                 function show() {
16043                                     var position,
16044                                             ttWidth,
16045                                             ttHeight,
16046                                             ttPosition;
16047
16048                                     // Don't show empty tooltips.
16049                                     if (!scope.tt_content) {
16050                                         return;
16051                                     }
16052
16053                                     // If there is a pending remove transition, we must cancel it, lest the
16054                                     // tooltip be mysteriously removed.
16055                                     if (transitionTimeout) {
16056                                         $timeout.cancel(transitionTimeout);
16057                                     }
16058
16059                                     // Set the initial positioning.
16060                                     tooltip.css({top: 0, left: 0, display: 'block', 'z-index': 9999});
16061
16062                                     // Now we add it to the DOM because need some info about it. But it's not
16063                                     // visible yet anyway.
16064                                     if (appendToBody) {
16065                                         $body = $body || $document.find('body');
16066                                         $body.append(tooltip);
16067                                     } else {
16068                                         element.after(tooltip);
16069                                     }
16070
16071                                     // Get the position of the directive element.
16072                                     position = appendToBody ? $position.offset(element) : $position.position(element);
16073
16074                                     // Get the height and width of the tooltip so we can center it.
16075                                     ttWidth = tooltip.prop('offsetWidth');
16076                                     ttHeight = tooltip.prop('offsetHeight');
16077
16078                                     // Calculate the tooltip's top and left coordinates to center it with
16079                                     // this directive.
16080                                     var ttArrowOffset = 10;
16081                                     switch (scope.tt_placement) {
16082                                         case 'right':
16083                                             if(appendToBody){
16084                                                 ttPosition = {
16085                                                     top: position.top + position.height / 2 - ttHeight / 2,
16086                                                     left: position.left + position.width
16087                                                 };
16088                                             }else{
16089                                                 ttPosition = {
16090                                                     top: position.top + position.height / 2 - ttHeight / 2,
16091                                                     left: position.left + position.width + ttArrowOffset
16092                                                 };
16093                                             }
16094                                             break;
16095                                         case 'below':
16096                                             if(appendToBody){
16097                                                 ttPosition = {
16098                                                     top: position.top + position.height,
16099                                                     left: position.left + position.width / 2 - ttWidth / 2
16100                                                 };
16101                                             }else{
16102                                                 ttPosition = {
16103                                                     top: position.top + position.height + ttArrowOffset,
16104                                                     left: position.left + position.width / 2 - ttWidth / 2
16105                                                 };
16106                                             }
16107                                             break;
16108                                         case 'left':
16109                                             if(appendToBody){
16110                                                 ttPosition = {
16111                                                     top: position.top + position.height / 2 - ttHeight / 2,
16112                                                     left: position.left - ttWidth
16113                                                 };
16114                                             }else{
16115                                                 ttPosition = {
16116                                                     top: position.top + position.height / 2 - ttHeight / 2,
16117                                                     left: position.left - ttWidth - ttArrowOffset
16118                                                 };
16119                                             }
16120                                             break;
16121                                         default:
16122                                             if(appendToBody){
16123                                                 ttPosition = {
16124                                                     top: position.top - ttHeight,
16125                                                     left: position.left + position.width / 2 - ttWidth / 2
16126                                                 };
16127                                             }else{
16128                                                 ttPosition = {
16129                                                     top: position.top - ttHeight - ttArrowOffset,
16130                                                     left: position.left + position.width / 2 - ttWidth / 2
16131                                                 };
16132                                             }
16133                                             break;
16134                                     }
16135
16136                                     ttPosition.top += 'px';
16137                                     ttPosition.left += 'px';
16138
16139                                     // Now set the calculated positioning.
16140                                     tooltip.css(ttPosition);
16141
16142                                     // And show the tooltip.
16143                                     scope.tt_isOpen = true;
16144                                 }
16145
16146                                 // Hide the tooltip popup element.
16147                                 function hide() {
16148                                     // First things first: we don't show it anymore.
16149                                     scope.tt_isOpen = false;
16150
16151                                     //if tooltip is going to be shown after delay, we must cancel this
16152                                     $timeout.cancel(popupTimeout);
16153
16154                                     // And now we remove it from the DOM. However, if we have animation, we
16155                                     // need to wait for it to expire beforehand.
16156                                     // This is a placeholder for a port of the transitions library.
16157                                     if (angular.isDefined(scope.tt_animation) && scope.tt_animation()) {
16158                                         transitionTimeout = $timeout(function() {
16159                                             tooltip.remove();
16160                                         }, 500);
16161                                     } else {
16162                                         tooltip.remove();
16163                                     }
16164                                 }
16165
16166                                 /**
16167                                  * Observe the relevant attributes.
16168                                  */
16169                                 attrs.$observe(type, function(val) {
16170                                     if (val) {
16171                                         scope.tt_content = val;
16172                                         element.attr('title',val);
16173                                     } else {
16174                                         if (scope.tt_isOpen) {
16175                                             hide();
16176                                         }
16177                                     }
16178                                 });
16179
16180                                 attrs.$observe(prefix + 'Title', function(val) {
16181                                     scope.tt_title = val;
16182                                 });
16183
16184                                 attrs.$observe(prefix + 'Placement', function(val) {
16185                                     scope.tt_placement = angular.isDefined(val) ? val : options.placement;
16186                                 });
16187
16188                                 attrs.$observe(prefix + 'Style', function(val) {
16189                                     scope.tt_style = angular.isDefined(val) ? val : options.stylett;
16190                                 });
16191
16192                                 attrs.$observe(prefix + 'Animation', function(val) {
16193                                     scope.tt_animation = angular.isDefined(val) ? $parse(val) : function() {
16194                                         return options.animation;
16195                                     };
16196                                 });
16197
16198                                 attrs.$observe(prefix + 'PopupDelay', function(val) {
16199                                     var delay = parseInt(val, 10);
16200                                     scope.tt_popupDelay = !isNaN(delay) ? delay : options.popupDelay;
16201                                 });
16202
16203                                 attrs.$observe(prefix + 'Trigger', function(val) {
16204
16205                                     if (hasRegisteredTriggers) {
16206                                         element.unbind(triggers.show, showTooltipBind);
16207                                         element.unbind(triggers.hide, hideTooltipBind);
16208                                     }
16209
16210                                     triggers = getTriggers(val);
16211
16212                                     if (triggers.show === triggers.hide) {
16213                                         element.bind(triggers.show, toggleTooltipBind);
16214                                     } else {
16215                                         element.bind(triggers.show, showTooltipBind);
16216                                         element.bind(triggers.hide, hideTooltipBind);
16217                                     }
16218
16219                                     hasRegisteredTriggers = true;
16220                                 });
16221
16222                                 attrs.$observe(prefix + 'AppendToBody', function(val) {
16223                                     appendToBody = angular.isDefined(val) ? $parse(val)(scope) : appendToBody;
16224                                 });
16225
16226                                 // if a tooltip is attached to <body> we need to remove it on
16227                                 // location change as its parent scope will probably not be destroyed
16228                                 // by the change.
16229                                 if (appendToBody) {
16230                                     scope.$on('$locationChangeSuccess', function() {
16231                                         if (scope.tt_isOpen) {
16232                                             hide();
16233                                         }
16234                                     });
16235                                 }
16236
16237                                 // Make sure tooltip is destroyed and removed.
16238                                 scope.$on('$destroy', function() {
16239                                     if (scope.tt_isOpen) {
16240                                         hide();
16241                                     } else {
16242                                         tooltip.remove();
16243                                     }
16244                                 });
16245                             }
16246                         };
16247                     };
16248                 }];
16249         }])
16250
16251         .directive('tooltipPopup', ['$document', '$documentBind', function($document, $documentBind) {
16252             return {
16253                 restrict: 'EA',
16254                 replace: true,
16255                 transclude: true,
16256                 scope: {content: '@', placement: '@', animation: '&', isOpen: '=', stylett: '@'},
16257                 templateUrl: 'app/scripts/ng_js_att_tpls/tooltip/tooltip-popup.html',
16258                 link: function(scope, elem) {
16259                     var flag = false;
16260                     scope.$watch("isOpen", function() {
16261                         flag = scope.isOpen;
16262                     });
16263                     elem.bind('click', function (e) {
16264                         e.stopPropagation();
16265                     });
16266                     var outsideClick = function() {
16267                         if (!flag) {
16268                             scope.$apply(function() {
16269                                 scope.isOpen = false;
16270                             });
16271                         }
16272                         flag = false;
16273                     };
16274
16275                     $documentBind.click('isOpen', outsideClick, scope);
16276                 }
16277             };
16278         }])
16279
16280         .directive('tooltip', ['$tooltip', function($tooltip) {
16281             return $tooltip('tooltip', 'tooltip', 'mouseenter');
16282         }])
16283
16284         .directive('tooltipCondition', [ '$timeout',function($timeout) {
16285                 return  {
16286                     restrict: 'EA',
16287                     replace: true,
16288                     scope:{
16289                         tooltipCondition:"@?"
16290                     },
16291                     template:'<p><span tooltip=\"{{tooltipCondition}}\" ng-if=\"showpop\">{{tooltipCondition}}</span><span id=\"innerElement\" ng-hide=\"showpop\">{{tooltipCondition}}</span></p>',
16292                     link: function(scope, elem, attr){
16293                         scope.showpop=false;
16294                         if(attr.height==='true'){
16295                             $timeout(function () {
16296                                 var maxHeight=(elem[0].offsetHeight);
16297                                var elemHeight=elem.children(0)[0].offsetHeight;
16298                                if(elemHeight > maxHeight){
16299                                    scope.showpop=true;
16300                                }
16301                             },1000);
16302                         }
16303                         else if(scope.tooltipCondition.length>=25){
16304                         scope.showpop=true;
16305                         }
16306                     }
16307                 };
16308         }]);
16309 angular.module('att.abs.treeview', [])
16310         .directive('treeView', function() {
16311             return{
16312                 restrict: 'A',
16313                 link: function(scope, elem) {
16314                     var el = elem.children('ul li');
16315                     var list = TweenMax.from(el, .2, {display: 'none', paused: true, reversed: true});
16316                     elem.attr("tabindex","0");
16317                     function toggleBranch() {
16318                         if (list.reversed())
16319                         {
16320                             list.play();
16321                         } else
16322                         {
16323                             list.reverse();
16324                         }
16325                     };
16326                     function toggleTree(e) {
16327                         e.stopPropagation();
16328                         if ($(e.target).attr("tree-view") !== undefined)
16329                         {
16330                             if (elem.hasClass('minus'))
16331                             {
16332                                 elem.removeClass('minus');
16333                             }
16334                             else
16335                             {
16336                                 elem.addClass('minus');
16337                             }
16338                             toggleBranch();
16339                         }
16340                     }
16341                     elem.on('click', function(e) {
16342                         toggleTree(e);
16343                     });
16344                     elem.on('keypress', function (e) {
16345                         var activeCode = e.keyCode ? e.keyCode : e.charCode;
16346                         var keyCode = [13,32];
16347                         if (keyCode.length > 0 && ((activeCode && keyCode.indexOf(activeCode) > -1))) {
16348                             toggleTree(e);
16349                             e.preventDefault();
16350                         }
16351                     });
16352                 }
16353             };
16354         });
16355
16356 angular.module('att.abs.typeAhead', ['att.abs.tagBadges'])
16357
16358         .directive('focusMe',['$timeout', '$parse', function($timeout, $parse) {
16359             return {
16360                 link: function(scope, element, attrs) {
16361                     var model = $parse(attrs.focusMe);
16362                     scope.$watch(model, function(value) {
16363                         if (value) {
16364                             $timeout(function() {
16365                                 element[0].focus();
16366                                 scope.inputActive=true;
16367                             });
16368                         }
16369                     });
16370                     element.bind('blur', function() {
16371                         scope.$apply(model.assign(scope, false));
16372                              scope.inputActive=false;
16373                     });
16374                 }
16375             };
16376         }])
16377
16378         .directive('typeAhead', ['$timeout', function($timeout) {
16379                 return {
16380                     restrict: 'EA',
16381                     templateUrl: 'app/scripts/ng_js_att_tpls/typeAhead/typeAhead.html',
16382                     replace: true,
16383                     scope: {
16384                         items: '=',
16385                         title: '@',
16386                         subtitle: '@',
16387                         model: '=',
16388                         emailIdList:'=',
16389                         emailMessage:'='
16390                     },
16391                     link: function(scope, elem) {
16392                         scope.lineItems = [];
16393                         scope.filteredListLength = -1;
16394                         scope.filteredList = [];
16395                         scope.inputfocus = false;
16396
16397                         scope.setFocus = function() {
16398                             scope.clickFocus = true;
16399                         };
16400                         scope.handleSelection = function(selectedItem,emailItem) {
16401                             scope.lineItems.push(selectedItem);
16402                             scope.emailIdList.push(emailItem);
16403                             scope.model = "";
16404                             scope.current = 0;
16405                             scope.selected = true;
16406                             scope.clickFocus = true;
16407                         };
16408                         scope.theMethodToBeCalled = function(index) {
16409                             var tempArr = scope.lineItems.slice();
16410                             scope.emailIdList.splice(index, 1);
16411                             tempArr.splice(index, 1);
16412                             $timeout(function() {
16413                                 scope.lineItems = [];
16414                                 scope.$apply();
16415                                 scope.lineItems = scope.lineItems.concat(tempArr);
16416                             });
16417                         };
16418
16419                         scope.current = 0;
16420                         scope.selected = true;
16421
16422                         scope.isCurrent = function(index, itemName,itemEmail,dropdownLength) {
16423                             if (scope.current === index) {
16424                                 scope.itemName = itemName;
16425                                 scope.itemEmail = itemEmail;
16426                             }
16427                             scope.dropdownLength=dropdownLength;
16428                             return scope.current === index;
16429                         };
16430
16431                         scope.setCurrent = function(index) {
16432                             scope.current = index;
16433                         };
16434
16435                         scope.selectionIndex = function(evt) {
16436                             if (evt.keyCode === 38 && scope.current > 0) {
16437                                evt.preventDefault();
16438                                 scope.current = scope.current - 1;
16439                                 scope.isCurrent(scope.current);
16440                             } else if (evt.keyCode === 9) {
16441                                 scope.selected = true;
16442                             } else if (evt.keyCode === 13 && scope.dropdownLength!==scope.items.length) {
16443                                 scope.handleSelection(scope.itemName,scope.itemEmail);
16444                             } else if ((evt.keyCode === 8 && scope.model.length === 0) || evt.keyCode === 46) {
16445                                 scope.theMethodToBeCalled(scope.lineItems.length - 1);
16446                             } else if (evt.keyCode === 40 && scope.current < scope.dropdownLength-1) {
16447                                 evt.preventDefault();
16448                                 scope.current = scope.current + 1;
16449                                 scope.isCurrent(scope.current);
16450                             }
16451                             elem[0].querySelector('.list-scrollable').scrollTop = (scope.current - 1) * 35;
16452                         };
16453                     }
16454                 };
16455             }]);
16456 angular.module('att.abs.userMessages', [])
16457     .constant('messageConstants', {
16458             TABLE_MESSAGE_TYPES: {
16459                 noMatching: 1,
16460                 errorLoading: 2,
16461                 magnifySearch: 3,
16462                 isLoading: 4},
16463         USER_MESSAGE_TYPES: {
16464             success: 1,
16465             error: 0
16466             }
16467         })
16468         .directive('attTableMessage', ['messageConstants', function(messageConstants) {
16469                 return {
16470                     restrict: 'AE',
16471                     replace: true,
16472                     transclude: true,
16473                     scope: {
16474                         msgType: '=',
16475                         onRefreshClick: '&'
16476                     },
16477                     templateUrl: 'app/scripts/ng_js_att_tpls/userMessages/attTableMessage.html',
16478                     link: function(scope) {
16479                         scope.messageConstants = messageConstants;
16480                         scope.refreshAction = function(evt) {
16481                             scope.onRefreshClick(evt);
16482                         };
16483                     }
16484                 };
16485             }]).directive('attUserMessage', ['messageConstants', function(messageConstants) {
16486         return{
16487             restrict: 'AE',
16488             replace: true,
16489             transclude: true,
16490             scope: {
16491                 thetitle: '=',
16492                 type: '=',
16493                 message: '=',
16494                 trigger: '='
16495             },
16496             templateUrl: 'app/scripts/ng_js_att_tpls/userMessages/attUserMessage.html',
16497             link: function(scope) {
16498                 scope.messageConstants = messageConstants;
16499             }
16500         };
16501     }]);
16502 angular.module('att.abs.verticalSteptracker', ['ngSanitize'])
16503     .directive('verticalSteptracker', [ function(){
16504         return {
16505             restrict: 'EA',
16506             transclude: true,
16507             replace: false,
16508             scope: {},
16509             template: '<div class="vertical-nav"><ul ng-transclude class="tickets-list-height"></ul></div>',
16510             link: function () {}
16511         };
16512     }])
16513     .directive('verticalSteptrackerStep',[ function(){
16514         return {
16515             restrict: 'EA',
16516             transclude: true,
16517             replace: false,
16518             scope: {
16519                 type: "=type",
16520                 id: "=id"
16521             },
16522             templateUrl: 'app/scripts/ng_js_att_tpls/verticalSteptracker/vertical-step-tracker.html',
16523             link: function(){}
16524          };
16525     }])
16526     .directive('attAbsLink',[ function(){
16527         return{
16528             restrict: 'EA',
16529             transclude: true,
16530             replace: false,
16531             template: '<span ng-transclude class="view-log"></span>'
16532         };
16533     }]);
16534 angular.module('att.abs.videoControls', [])
16535         .config(['$compileProvider' , function ($compileProvider) {
16536                 $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|javascript):/);
16537             }])
16538         .directive('videoControls', [function() {
16539                 return {
16540                     restrict: 'EA',
16541                     replace: true,
16542                     transclude: true,
16543                     templateUrl: 'app/scripts/ng_js_att_tpls/videoControls/videoControls.html'
16544                 };
16545             }])
16546         .directive('photoControls', [function() {
16547                 return {
16548                     restrict: 'EA',
16549                     replace: true,
16550                     transclude: true,
16551                     templateUrl: 'app/scripts/ng_js_att_tpls/videoControls/photoControls.html',
16552                     scope: {
16553                         prevLink: "@",
16554                         nextLink: "@"
16555                     },
16556                     link: function(scope, elem, attr) {
16557                         if(!attr['prevLink']){
16558                             scope.prevLink = 'javascript:void(0)';
16559                         }
16560                         if(!attr['nextLink']){
16561                             scope.nextLink = 'javascript:void(0)';
16562                         }
16563                         scope.links = {
16564                             prevLink : scope.prevLink,
16565                             nextLink : scope.nextLink
16566                         };
16567                     }
16568                 };
16569             }]);
16570 angular.module("app/scripts/ng_js_att_tpls/accordion/accordion.html", []).run(["$templateCache", function($templateCache) {
16571   $templateCache.put("app/scripts/ng_js_att_tpls/accordion/accordion.html",
16572     "<div class=\"att-accordion__group tabpanel\" ng-class=\"{'att-accordion__group att-accordion__group--open':isOpen,'att-accordion__group':!isOpen }\">\n" +
16573     "    <a ng-show=\"showico\" id=\"tab{{index}}\" class=\"toggle-header att-accordion__heading att-accordion__toggle noafter\" aria-selected=\"{{focused}}\" aria-controls=\"panel{{index}}\" ng-class=\"{focus: focused, selected: focused}\" aria-expanded=\"{{isOpen}}\" role=\"tab\" ng-click=\"toggle()\" accordion-transclude=\"heading\" style=\"cursor:pointer; text-decoration:none\">\n" +
16574     "        <span>{{heading}}</span>\n" +
16575     "        <i ng-class=\"{'icon-chevron-down':!isOpen,'icon-chevron-up':isOpen }\" class=\"pull-right\"></i>\n" +
16576     "    </a>\n" +
16577     "    <div ng-show=\"!showico\" ng-class=\"{focus: focused, selected: focused}\" id=\"tab{{index}}\" style=\"text-decoration:none\" accordion-transclude=\"heading\" aria-expanded=\"{{isOpen}}\" role=\"tab\"  aria-selected=\"{{focused}}\" aria-controls=\"panel{{index}}\" class=\"toggle-header att-accordion__heading att-accordion__toggle noafter\"><span>{{heading}}</span></div>    \n" +
16578     "    <div id=\"panel{{index}}\" aria-labelledby=\"tab{{index}}\" aria-hidden=\"{{!isOpen}}\" role=\"tabpanel\" collapse=\"!isOpen\" class=\"att-accordion__body\" ng-transclude>\n" +
16579     "    </div>\n" +
16580     "    <div class=\"att-accordion__bottom--border\"></div>    \n" +
16581     "</div> ");
16582 }]);
16583
16584 angular.module("app/scripts/ng_js_att_tpls/accordion/accordion_alt.html", []).run(["$templateCache", function($templateCache) {
16585   $templateCache.put("app/scripts/ng_js_att_tpls/accordion/accordion_alt.html",
16586     "<div class=\"att-accordion__group tabpanel\" ng-class=\"{'att-accordion__group att-accordion__group--open':isOpen,'att-accordion__group':!isOpen }\">\n" +
16587     "    <a id=\"tab{{index}}\" class=\"toggle-header att-accordion__heading att-accordion__toggle\" aria-selected=\"{{focused}}\" aria-controls=\"panel{{index}}\" ng-class=\"{focus: focused, selected: focused}\" aria-expanded=\"{{isOpen}}\" role=\"tab\" ng-click=\"toggle()\" accordion-transclude=\"heading\">        \n" +
16588     "    </a>\n" +
16589     "    <span>{{heading}}</span>\n" +
16590     "    <div id<span>{{heading}}</span>=\"panel{{index}}\" aria-labelledby=\"tab{{index}}\" aria-hidden=\"{{!isOpen}}\" role=\"tabpanel\" collapse=\"!isOpen\" class=\"att-accordion__body\" ng-transclude>\n" +
16591     "    </div>\n" +
16592     "</div> ");
16593 }]);
16594
16595 angular.module("app/scripts/ng_js_att_tpls/accordion/attAccord.html", []).run(["$templateCache", function($templateCache) {
16596   $templateCache.put("app/scripts/ng_js_att_tpls/accordion/attAccord.html",
16597     "<div ng-transclude></div>");
16598 }]);
16599
16600 angular.module("app/scripts/ng_js_att_tpls/accordion/attAccordBody.html", []).run(["$templateCache", function($templateCache) {
16601   $templateCache.put("app/scripts/ng_js_att_tpls/accordion/attAccordBody.html",
16602     "<div ng-transclude></div>");
16603 }]);
16604
16605 angular.module("app/scripts/ng_js_att_tpls/accordion/attAccordHeader.html", []).run(["$templateCache", function($templateCache) {
16606   $templateCache.put("app/scripts/ng_js_att_tpls/accordion/attAccordHeader.html",
16607     "<div ng-click=\"clickFunc()\">\n" +
16608     "   <div ng-transclude>\n" +
16609     "           <i class=\"icon-chevron-down\"></i>\n" +
16610     "   </div>\n" +
16611     "</div>");
16612 }]);
16613
16614 angular.module("app/scripts/ng_js_att_tpls/alert/alert.html", []).run(["$templateCache", function($templateCache) {
16615   $templateCache.put("app/scripts/ng_js_att_tpls/alert/alert.html",
16616     "<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" +
16617     "    <div class=\"container\">\n" +
16618     "        <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" +
16619     "        <span ng-transclude> </span>\n" +
16620     "    </div>\n" +
16621     "</div>");
16622 }]);
16623
16624 angular.module("app/scripts/ng_js_att_tpls/colorselector/colorselector.html", []).run(["$templateCache", function($templateCache) {
16625   $templateCache.put("app/scripts/ng_js_att_tpls/colorselector/colorselector.html",
16626     "<div class=\"att-radio att-color-selector__item\"  \n" +
16627     "     ng-class=\"{'att-radio--on': (iconColor === selected)}\">\n" +
16628     "    <div class=\"att-radio__indicator\"  tabindex=\"0\" att-accessibility-click=\"32,13\"ng-click=\"selectedcolor(iconColor)\" \n" +
16629     "         ng-style=\"applycolor\" ng-transclude></div>\n" +
16630     "</div>");
16631 }]);
16632
16633 angular.module("app/scripts/ng_js_att_tpls/datepicker/dateFilter.html", []).run(["$templateCache", function($templateCache) {
16634   $templateCache.put("app/scripts/ng_js_att_tpls/datepicker/dateFilter.html",
16635     "<div class=\"calendar\" ng-class=\"{'monthpicker':mode === 1}\">\n" +
16636     "    <div class=\"select2-container\" ng-class=\"{'select2-container-active select2-dropdown-open': showDropdownList}\" style=\"width: 100%; z-index:0\">\n" +
16637     "        <a tabindex=\"0\" 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" +
16638     "            <span class=\"select2-chosen\" ng-show=\"!showCalendar\">{{selectedOption}}</span>\n" +
16639     "            <input type=\"text\" ng-show=\"showCalendar\" ng-blur=\"untrackInputChange($event)\" att-input-deny=\"[^0-9\\/-]\" maxlength=\"{{maxLength}}\" ng-model=\"selectedOption\" ng-change=\"getDropdownText()\" />\n" +
16640     "            <abbr class=\"select2-search-choice-close\"></abbr>\n" +
16641     "            <span ng-class=\"{'select2-arrow': mode !== 1, 'calendar-icon': mode === 1}\"><b></b></span>\n" +
16642     "        </a>\n" +
16643     "        <a class=\"select2-choice\" href=\"javascript:void(0)\" ng-show=\"showCalendar\">\n" +
16644     "            <span class=\"select2-chosen\" ng-show=\"!showCalendar\">{{selectedOption}}</span>\n" +
16645     "            <input type=\"text\" ng-show=\"showCalendar\" ng-blur=\"untrackInputChange($event)\" att-input-deny=\"[^0-9\\/-]\" maxlength=\"{{maxLength}}\" ng-model=\"selectedOption\" ng-change=\"getDropdownText()\" />\n" +
16646     "            <abbr class=\"select2-search-choice-close\"></abbr>\n" +
16647     "            <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" +
16648     "        </a>\n" +
16649     "    </div>\n" +
16650     "    <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" +
16651     "        <div  id=\"dateFilterList\" att-scrollbar ><ul class=\"select2-results options\" ng-transclude></ul></div>\n" +
16652     "           <ul class=\"select2-results sttings\" style=\"margin-top:0px\">\n" +
16653     "                   <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" +
16654     "                <div class=\"select2-result-label\" ng-if=\"mode !== 1\">Custom Single Date...</div>\n" +
16655     "                           <div class=\"select2-result-label\" ng-if=\"mode === 1\">Custom single month...</div>\n" +
16656     "            </li>\n" +
16657     "            <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" +
16658     "                <div class=\"select2-result-label\" ng-if=\"mode !== 1\">Custom Range...</div>\n" +
16659     "                           <div class=\"select2-result-label\" ng-if=\"mode === 1\">Custom month range...</div>\n" +
16660     "            </li>\n" +
16661     "            <li class=\"select2-result select2-highlighted btnContainer\" ng-style=\"{display: (showCalendar && 'block') || 'none'}\">\n" +
16662     "                <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" +
16663     "                <button tabindex=\"0\" att-button=\"\" btn-type=\"secondary\" size=\"small\" att-accessibility-click=\"13,32\" ng-click=\"cancel()\">Cancel</button>\n" +
16664     "                <div>\n" +
16665     "                    <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" +
16666     "                    <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" +
16667     "                </div>\n" +
16668     "            </li>\n" +
16669     "           </ul>\n" +
16670     "    </div>\n" +
16671     "    <div class=\"datepicker-wrapper show-right\" ng-style=\"{display: (showCalendar && 'block') || 'none'}\">\n" +
16672     "        <span datepicker ng-blur=\"resetFocus($event)\" att-element-focus=\"focusSingleDateCalendar\" ng-show=\"checkCurrentSelection('Custom Single Date')\"></span>\n" +
16673     "        <span datepicker ng-blur=\"resetFocus($event)\" att-element-focus=\"focusRangeCalendar\" ng-show=\"checkCurrentSelection('Custom Range')\"></span>\n" +
16674     "    </div>\n" +
16675     "</div>\n" +
16676     "");
16677 }]);
16678
16679 angular.module("app/scripts/ng_js_att_tpls/datepicker/dateFilterList.html", []).run(["$templateCache", function($templateCache) {
16680   $templateCache.put("app/scripts/ng_js_att_tpls/datepicker/dateFilterList.html",
16681     "<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" +
16682     "                <div class=\"select2-result-label\" ng-class=\"{'disabled':disabled}\" ng-transclude></div>\n" +
16683     "</li>");
16684 }]);
16685
16686 angular.module("app/scripts/ng_js_att_tpls/datepicker/datepicker.html", []).run(["$templateCache", function($templateCache) {
16687   $templateCache.put("app/scripts/ng_js_att_tpls/datepicker/datepicker.html",
16688     "<ul id=\"datepicker\" class=\"datepicker\" ng-class=\"{'monthpicker': mode === 1}\" aria-hidden=\"false\" role=\"dialog\" tabindex=\"-1\">\n" +
16689     "    <div class=\"datepicker-days\" style=\"display: block;\">\n" +
16690     "        <table class=\"table-condensed\">\n" +
16691     "            <thead>\n" +
16692     "                <tr>\n" +
16693     "                    <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" +
16694     "                    <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" +
16695     "                        <div class=\"icons-list\" data-size=\"medium\"><i class=\"icon-arrow-left-circle\" ng-class=\"{'disabled': disablePrev}\"></i>\n" +
16696     "                        </div><span class=\"hidden-spoken\">Previous Month</span>\n" +
16697     "                    </th>\n" +
16698     "                    <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" +
16699     "                        <div class=\"icons-list\" data-size=\"medium\"><i class=\"icon-arrow-right-circle\" ng-class=\"{'disabled': disableNext}\"></i>\n" +
16700     "                        </div><span class=\"hidden-spoken\">Next Month</span>\n" +
16701     "                    </th>\n" +
16702     "                </tr>\n" +
16703     "                <tr ng-if=\"labels.length > 0\">\n" +
16704     "                    <th id=\"{{label.post}}\" tabindex=\"-1\" class=\"dow weekday\" ng-repeat=\"label in labels\"><span>{{label.pre}}</span><span class=\"hidden-spoken\">{{label.post}}</span></th>\n" +
16705     "                </tr>\n" +
16706     "            </thead>\n" +
16707     "            <tbody>\n" +
16708     "                <tr>\n" +
16709     "                    <td id=\"datepickerBody\" att-scrollbar colspan=\"{{currentRows[0].length}}\" style=\"padding: 0px;\">\n" +
16710     "                        <table ng-class=\"{'table-condensed': mode === 0, 'monthtable-condensed': mode === 1}\" style=\"padding: 0px;\">\n" +
16711     "                                                   <thead class=\"hidden-spoken\">\n" +
16712     "                                                            <tr ng-show=\"labels.length > 0\">\n" +
16713     "                                                                   <th id=\"{{label.post}}\" tabindex=\"-1\" class=\"dow weekday\" ng-repeat=\"label in labels\"><span>{{label.post}}</span></th>\n" +
16714     "                                                           </tr>\n" +
16715     "                                                   </thead>\n" +
16716     "                            <tbody>\n" +
16717     "                                <tr ng-repeat=\"row in currentRows\">\n" +
16718     "                                    <td headers=\"{{dt.header}}\" 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\"><span aria-label=\"{{dt.label}}\"  class=\"day\">{{dt.label}}</span></td>\n" +
16719     "                                </tr>\n" +
16720     "                                                           <tr ng-if=\"mode === 1\" class=\"divider\"><td colspan=\"{{nextRows[0].length}}\"><hr></td></tr>\n" +
16721     "                                <tr>\n" +
16722     "                                    <th id=\"month\" tabindex=\"0\" class=\"datepicker-switch internal\" colspan=\"{{nextRows[0].length}}\" style=\"text-align:left\">{{nextTitle}}</th>\n" +
16723     "                                </tr>\n" +
16724     "                                <tr ng-repeat=\"row in nextRows\">\n" +
16725     "                                    <td headers=\"{{dt.header}}\" 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\"><span aria-label=\"{{dt.label}}\" class=\"day\">{{dt.label}}</span></td>\n" +
16726     "                                </tr>\n" +
16727     "                            </tbody>\n" +
16728     "                        </table>\n" +
16729     "                    </td>\n" +
16730     "                </tr>\n" +
16731     "            </tbody>\n" +
16732     "        </table>\n" +
16733     "    </div>\n" +
16734     "</ul>\n" +
16735     "");
16736 }]);
16737
16738 angular.module("app/scripts/ng_js_att_tpls/datepicker/datepickerPopup.html", []).run(["$templateCache", function($templateCache) {
16739   $templateCache.put("app/scripts/ng_js_att_tpls/datepicker/datepickerPopup.html",
16740     "<div class=\"calendar\">\n" +
16741     "    <div class=\"box\" ng-class=\"{'active': isOpen}\">\n" +
16742     "        <span ng-transclude></span>\n" +
16743     "        <i class=\"calendar-icon\" tabindex=\"0\" att-accessibility-click=\"13,32\" ng-click=\"toggle()\"></i>\n" +
16744     "    </div>\n" +
16745     "    <div class=\"datepicker-wrapper datepicker-wrapper-display-none\" ng-style=\"{display: (isOpen && 'block') || 'none'}\" aria-hidden=\"false\" role=\"dialog\" tabindex=\"-1\">\n" +
16746     "        <span datepicker></span>\n" +
16747     "    </div>\n" +
16748     "</div>\n" +
16749     "");
16750 }]);
16751
16752 angular.module("app/scripts/ng_js_att_tpls/dividerLines/dividerLines.html", []).run(["$templateCache", function($templateCache) {
16753   $templateCache.put("app/scripts/ng_js_att_tpls/dividerLines/dividerLines.html",
16754     "<div class=\"divider-container\" ng-class=\"{'divider-container-light': lightContainer}\">\n" +
16755     "    <hr ng-class=\"{'divider-light': lightContainer}\">\n" +
16756     "</div>\n" +
16757     "\n" +
16758     "");
16759 }]);
16760
16761 angular.module("app/scripts/ng_js_att_tpls/dragdrop/fileUpload.html", []).run(["$templateCache", function($templateCache) {
16762   $templateCache.put("app/scripts/ng_js_att_tpls/dragdrop/fileUpload.html",
16763     "<label class=\"fileContainer\"><span ng-transclude></span><input type=\"file\" att-file-change></label>");
16764 }]);
16765
16766 angular.module("app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlert.html", []).run(["$templateCache", function($templateCache) {
16767   $templateCache.put("app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlert.html",
16768     "<div class=\"form-field\" ng-class=\"{'error': errorMessage, 'warning': warningMessage}\">\n" +
16769     "    <label class=\"form-field__label\" ng-class=\"{'form-field__label--show': showLabel, 'form-field__label--hide': hideLabel}\"></label>\n" +
16770     "    <div class=\"form-field-input-container\" ng-transclude></div>\n" +
16771     "</div>");
16772 }]);
16773
16774 angular.module("app/scripts/ng_js_att_tpls/hourpicker/hourpicker.html", []).run(["$templateCache", function($templateCache) {
16775   $templateCache.put("app/scripts/ng_js_att_tpls/hourpicker/hourpicker.html",
16776     "<div class=\"hourpicker\">\n" +
16777     "    <div class=\"dropdown-width\">\n" +
16778     "        <div ng-model=\"showlist\" class=\"select2-container topDropDownWidth\" ng-class=\"{'select2-dropdown-open select2-container-active': showlist}\" >\n" +
16779     "            <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" +
16780     "                <span class=\"select2-chosen\">{{selectedOption}}</span>\n" +
16781     "                <span class=\"select2-arrow\"><b></b></span>\n" +
16782     "            </a>\n" +
16783     "        </div>             \n" +
16784     "        <div class=\"select2-display-none select2-with-searchbox select2-drop-active show-search resultTopWidth\" ng-show=\"showlist\">       \n" +
16785     "        <ul class=\"select2-results resultTopMargin\" >                       \n" +
16786     "            <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" +
16787     "        </ul>\n" +
16788     "        </div>\n" +
16789     "    </div>\n" +
16790     "    <div ng-show=\"showDaysSelector\" class=\"customdays-width\">\n" +
16791     "        <div att-divider-lines class=\"divider-margin-f\"></div>  \n" +
16792     "        <div class=\"col-md-3 fromto-margin\">\n" +
16793     "            <div>From</div> <br>\n" +
16794     "            <div>To</div>\n" +
16795     "        </div>\n" +
16796     "        <div ng-repeat=\"day in days\">\n" +
16797     "            <div class=\"col-md-3 col-md-days\">\n" +
16798     "                <div  class=\"col-md-1 daysselect-margin\">\n" +
16799     "                    <input type=\"checkbox\" ng-model=\"daysList[day]\" title=\"Day selection\" att-checkbox ng-change=\"addSelectedValue(day)\">    \n" +
16800     "                </div>\n" +
16801     "                <span>{{day}}</span><br>\n" +
16802     "                \n" +
16803     "                <div class=\"dropDownMarginBottom\">\n" +
16804     "                    <div class=\"select2-container topDropDownWidth\" ng-class=\"{'select2-dropdown-open select2-container-active': FrtimeListDay[day]}\" >\n" +
16805     "                        <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" +
16806     "                            <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" +
16807     "                        </a>\n" +
16808     "                    </div>             \n" +
16809     "                    \n" +
16810     "                    <div class=\"select2-display-none select2-with-searchbox select2-drop-active show-search resultFromDropDown\"  ng-show=\"FrtimeListDay[day]\">       \n" +
16811     "                    <ul class=\"select2-results resultTopMargin\" >                       \n" +
16812     "                        <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" +
16813     "                    </ul>\n" +
16814     "                    </div>\n" +
16815     "                </div>\n" +
16816     "                \n" +
16817     "                <div class=\"dropDownMarginBottom\">\n" +
16818     "                    <div class=\"select2-container topDropDownWidth\" ng-class=\"{'select2-dropdown-open select2-container-active': TotimeListDay[day]}\" >\n" +
16819     "                        <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]}\"  ng-keydown=\"daysList[day] && selectToDayOption(day , selectPrevNextValue($event,totime,selectedToOption[day]));daysList[day] && addSelectedValue(day);\">\n" +
16820     "                            <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" +
16821     "                        </a>\n" +
16822     "                    </div>\n" +
16823     "                    \n" +
16824     "                    <div class=\"select2-display-none select2-with-searchbox select2-drop-active show-search resultToDropDown\" ng-show=\"TotimeListDay[day]\">       \n" +
16825     "                    <ul class=\"select2-results resultTopMargin\" >                       \n" +
16826     "                        <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" +
16827     "                    </ul>\n" +
16828     "                    </div>\n" +
16829     "                </div>\n" +
16830     "            </div>  \n" +
16831     "        </div>    \n" +
16832     "        <div att-divider-lines class=\"divider-margin-s\"></div>    \n" +
16833     "    </div>\n" +
16834     "    <div ng-transclude></div>\n" +
16835     "</div>");
16836 }]);
16837
16838 angular.module("app/scripts/ng_js_att_tpls/links/readMore.html", []).run(["$templateCache", function($templateCache) {
16839   $templateCache.put("app/scripts/ng_js_att_tpls/links/readMore.html",
16840     "<div>\n" +
16841     "    <div ng-bind-html=\"textToDisplay\" ng-class=\"{'att--readMore': readFlag, 'att--readLess': !readFlag}\" ng-style=\"readLinkStyle\"></div>\n" +
16842     "    <span class=\"att--readmore__link\" ng-show=\"readMoreLink\">… <a href=\"#\" ng-click=\"readMore()\" att-accessbility-click=\"32,13\">Read More</a>\n" +
16843     "    </span>\n" +
16844     "</div>\n" +
16845     "<span class=\"att--readless__link\" ng-show=\"readLessLink\">\n" +
16846     "    <a href=\"#\" ng-click=\"readLess()\" att-accessbility-click=\"32,13\">Read Less</a>\n" +
16847     "</span>");
16848 }]);
16849
16850 angular.module("app/scripts/ng_js_att_tpls/loading/loading.html", []).run(["$templateCache", function($templateCache) {
16851   $templateCache.put("app/scripts/ng_js_att_tpls/loading/loading.html",
16852     "<div data-progress=\"{{progressStatus}}\" class=\"{{colorClass}}\" ng-class=\"{'att-loading-count':icon == 'count','loading--small':icon == 'small','loading': icon != 'count'}\">\n" +
16853     "   <div class=\"att-loading-circle\" ng-if=\"icon == 'count'\">\n" +
16854     "           <div class=\"att-loading-circle__mask att-loading-circle__full\">\n" +
16855     "                   <div class=\"att-loading-circle__fill\"></div>\n" +
16856     "           </div>\n" +
16857     "           <div class=\"att-loading-circle__mask att-loading-circle__half\">\n" +
16858     "                   <div class=\"att-loading-circle__fill\"></div>\n" +
16859     "                   <div class=\"att-loading-circle__fill att-loading-circle__fix\"></div>\n" +
16860     "           </div>\n" +
16861     "   </div>\n" +
16862     "   <div ng-class=\"{'att-loading-inset':icon == 'count','loading__inside':icon != 'count'}\"><div class=\"att-loading-inset__percentage\" ng-if=\"icon == 'count'\"></div></div>\n" +
16863     "</div>\n" +
16864     "\n" +
16865     "");
16866 }]);
16867
16868 angular.module("app/scripts/ng_js_att_tpls/modal/backdrop.html", []).run(["$templateCache", function($templateCache) {
16869   $templateCache.put("app/scripts/ng_js_att_tpls/modal/backdrop.html",
16870     "<div class=\"overlayed\" ng-class=\"{show: animate}\" \n" +
16871     "     ng-style=\"{'z-index': 2000 + index*10,'overflow':'scroll'}\">         \n" +
16872     "</div>");
16873 }]);
16874
16875 angular.module("app/scripts/ng_js_att_tpls/modal/window.html", []).run(["$templateCache", function($templateCache) {
16876   $templateCache.put("app/scripts/ng_js_att_tpls/modal/window.html",
16877     "<div tabindex=\"-1\" role=\"dialog\" att-element-focus=\"focusModalFlag\" class=\"modals {{ windowClass }}\" ng-class=\"{show: animate}\" \n" +
16878     "     ng-style=\"{'z-index': 2010 + index*10}\"  ng-click=\"close($event)\" ng-transclude>         \n" +
16879     "</div>\n" +
16880     "");
16881 }]);
16882
16883 angular.module("app/scripts/ng_js_att_tpls/pagination/pagination.html", []).run(["$templateCache", function($templateCache) {
16884   $templateCache.put("app/scripts/ng_js_att_tpls/pagination/pagination.html",
16885     "<div class=\"pager\">\n" +
16886     "    <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" +
16887     "    <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" +
16888     "    <span class=\"pager__item\" ng-if=\"totalPages > 7 && currentPage > 3\">...</span>\n" +
16889     "    <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" +
16890     "    <span class=\"pager__item\" ng-if=\"totalPages > 7 && currentPage < totalPages - 2 && showInput !== true\">...</span>\n" +
16891     "    <span ng-show=\"totalPages > 7 && showInput === true\"><input class=\"pager__item--input\" type=\"text\" placeholder=\"...\" maxlength=\"2\" ng-model=\"currentPage\"/></span>\n" +
16892     "    <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" +
16893     "    <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" +
16894     "</div>");
16895 }]);
16896
16897 angular.module("app/scripts/ng_js_att_tpls/paneSelector/innerPane.html", []).run(["$templateCache", function($templateCache) {
16898   $templateCache.put("app/scripts/ng_js_att_tpls/paneSelector/innerPane.html",
16899     "<div class='inner-pane'>\n" +
16900     "   <div ng-transclude>\n" +
16901     "   </div>\n" +
16902     "</div>");
16903 }]);
16904
16905 angular.module("app/scripts/ng_js_att_tpls/paneSelector/paneGroup.html", []).run(["$templateCache", function($templateCache) {
16906   $templateCache.put("app/scripts/ng_js_att_tpls/paneSelector/paneGroup.html",
16907     "<div class='pane-group'>\n" +
16908     "   <div ng-transclude>\n" +
16909     "   </div>\n" +
16910     "</div>");
16911 }]);
16912
16913 angular.module("app/scripts/ng_js_att_tpls/paneSelector/sidePane.html", []).run(["$templateCache", function($templateCache) {
16914   $templateCache.put("app/scripts/ng_js_att_tpls/paneSelector/sidePane.html",
16915     "<div class='side-pane'>    \n" +
16916     "   <div ng-transclude>\n" +
16917     "   </div>\n" +
16918     "</div>");
16919 }]);
16920
16921 angular.module("app/scripts/ng_js_att_tpls/profileCard/addUser.html", []).run(["$templateCache", function($templateCache) {
16922   $templateCache.put("app/scripts/ng_js_att_tpls/profileCard/addUser.html",
16923     "<div  class=\"col-md-9 profile-card add-user\">\n" +
16924     "    <div class=\"atcenter\">\n" +
16925     "        <div><i class=\"icon-add\"></i></div>\n" +
16926     "        <span>add User</span>\n" +
16927     "    </div>\n" +
16928     "</div>");
16929 }]);
16930
16931 angular.module("app/scripts/ng_js_att_tpls/profileCard/profileCard.html", []).run(["$templateCache", function($templateCache) {
16932   $templateCache.put("app/scripts/ng_js_att_tpls/profileCard/profileCard.html",
16933     " <div class=\"col-md-9 profile-card\">\n" +
16934     "    <div class=\"top-block\">\n" +
16935     "       <div class=\"profile-image\">\n" +
16936     "            <img ng-if=\"image\" profile-name=\"{{profile.name}}\" ng-src=\"{{profile.img}}\" alt=\"{{profile.name}}\">\n" +
16937     "            <span ng-hide=\"image\" class=\"default-img\">{{initials}}</span>\n" +
16938     "            <p class=\"name\" tooltip-condition=\"{{profile.name}}\" height=\"true\"></p>\n" +
16939     "            <p class=\"status\">\n" +
16940     "                <span class=\"status-icon\" ng-class=\"{'icon-green':colorIcon==='green','icon-red':colorIcon==='red','icon-blue':colorIcon==='blue','icon-yellow':colorIcon==='yellow'}\">   \n" +
16941     "                </span>\n" +
16942     "                <span>{{profile.state}}<span ng-if=\"badge\" class=\"status-badge\">Admin</span></span>\n" +
16943     "            </p>\n" +
16944     "        </div>\n" +
16945     "    </div>\n" +
16946     "    <div class=\"bottom-block\">\n" +
16947     "         <div class=\"profile-details\">\n" +
16948     "            <label>Username</label>\n" +
16949     "            <p att-text-overflow=\"92%\" tooltip-condition=\"{{profile.userName}}\">{{profile.userName}}</p>\n" +
16950     "            <label>Email</label>\n" +
16951     "            <p att-text-overflow=\"92%\" tooltip-condition=\"{{profile.email}}\">{{profile.email}}</p>\n" +
16952     "            <label>Role</label>\n" +
16953     "            <p att-text-overflow=\"92%\" tooltip-condition=\"{{profile.role}}\">{{profile.role}}</p>\n" +
16954     "            <label>Last Login</label>\n" +
16955     "            <p att-text-overflow=\"92%\" tooltip-condition=\"{{profile.lastLogin}}\">{{profile.lastLogin}}</p>\n" +
16956     "         </div>\n" +
16957     "    </div>\n" +
16958     "</div>");
16959 }]);
16960
16961 angular.module("app/scripts/ng_js_att_tpls/progressBars/progressBars.html", []).run(["$templateCache", function($templateCache) {
16962   $templateCache.put("app/scripts/ng_js_att_tpls/progressBars/progressBars.html",
16963     "<div class=\"att-progress\">\n" +
16964     "    <div class=\"att-progress-value\">&nbsp;</div>\n" +
16965     "</div>");
16966 }]);
16967
16968 angular.module("app/scripts/ng_js_att_tpls/scrollbar/scrollbar.html", []).run(["$templateCache", function($templateCache) {
16969   $templateCache.put("app/scripts/ng_js_att_tpls/scrollbar/scrollbar.html",
16970     "<div class=\"scroll-bar\">\n" +
16971     "   <div class=\"scroll-thumb\"></div>\n" +
16972     "</div>\n" +
16973     "<div class=\"scroll-viewport\">\n" +
16974     "   <div class=\"scroll-overview\" ng-transclude></div>\n" +
16975     "</div>");
16976 }]);
16977
16978 angular.module("app/scripts/ng_js_att_tpls/search/search.html", []).run(["$templateCache", function($templateCache) {
16979   $templateCache.put("app/scripts/ng_js_att_tpls/search/search.html",
16980     "<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" +
16981     "   <a href=\"javascript:void(0)\" class=\"select2-choice needsclick\" tabindex=\"0\" ng-click=\"showDropdown()\" ng-class=\"{'select2-chosen-disabled':isDisabled}\" ng-focus=\"isact=true;\" ng-blur=\"isact=false;\">\n" +
16982     "           <span class=\"select2-chosen needsclick\">{{selectedOption}}</span>\n" +
16983     "           <abbr class=\"select2-search-choice-close needsclick\"></abbr>\n" +
16984     "           <span class=\"select2-arrow needsclick\" role=\"presentation\">\n" +
16985     "                   <b role=\"presentation\" class=\"needsclick\"></b>\n" +
16986     "           </span>\n" +
16987     "        </a>\n" +
16988     "   <label class=\"select2-offscreen\"></label>\n" +
16989     "        <input class=\"select2-focusser select2-offscreen\" tabindex=\"-1\" type=\"text\" aria-haspopup=\"true\" role=\"button\">\n" +
16990     "</div>\n" +
16991     "<div class=\"select2-drop select2-with-searchbox select2-drop-auto-width select2-drop-active\" ng-class=\"{'select2-display-none':(!showlist || isDisabled),'show-search':showSearch}\" style=\"width:100%;z-index: 10\">\n" +
16992     "   <div class=\"select2-search\">\n" +
16993     "           <label class=\"select2-offscreen\"></label>\n" +
16994     "           <input ng-model=\"title\" typeahead=\"c.title for c in cName | filter:$viewValue:startsWith\" type=\"text\" autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"off\" spellcheck=\"false\" class=\"select2-input\" role=\"combobox\" aria-\n" +
16995     "expanded=\"true\" aria-autocomplete=\"list\" placeholder=\"\">\n" +
16996     "   </div>\n" +
16997     "   <ul class=\"select2-results\" role=\"listbox\">\n" +
16998     "                <li ng-show=\"filteredName.length === 0\" class=\"select2-no-results\">No matches found</li>\n" +
16999     "           <li class=\"select2-results-dept-0 select2-result select2-result-selectable\" role=\"presentation\"\n" +
17000     "                    ng-model=\"ListType\" ng-show=\"selectMsg && filteredName.length > 0\"\n" +
17001     "                    ng-click=\"selectOption(selectMsg, '-1')\"\n" +
17002     "                    ng-class=\"{'select2-result-current': selectedOption === selectMsg, 'hovstyle': selectedIndex === -1}\"\n" +
17003     "                    ng-mouseover=\"hoverIn(-1)\">\n" +
17004     "                    <div ng-if=\"startsWithFilter\" class=\"select2-result-label\"  ng-bind-html=\"selectMsg | unsafe\" role=\"option\">\n" +
17005     "                                    <span class=\"select2-match\" ></span>\n" +
17006     "                    </div>\n" +
17007     "                    <div ng-if=\"!startsWithFilter\" class=\"select2-result-label\"  ng-bind-html=\"selectMsg | highlight:title:className | unsafe\" role=\"option\">\n" +
17008     "                        <span class=\"select2-match\" ></span>\n" +
17009     "                    </div>\n" +
17010     "           </li>\n" +
17011     "           <li ng-if=\"startsWithFilter\" class=\"select2-results-dept-0 select2-result select2-result-selectable\" role=\"presentation\"\n" +
17012     "                    ng-model=\"ListType\" ng-repeat=\"(fIndex, item) in filteredName = (cName | startsWith:title:item)\"\n" +
17013     "                    ng-class=\"{'select2-result-current': selectedOption === item.title,'hovstyle': selectedIndex === item.index}\"\n" +
17014     "                    ng-click=\"selectOption(item.title,item.index)\"\n" +
17015     "                    ng-mouseover=\"hoverIn(item.index)\">\n" +
17016     "                    <div class=\"select2-result-label\" ng-bind-html=\"item.title | unsafe\" role=\"option\">\n" +
17017     "                            <span class=\"select2-match\" ></span>\n" +
17018     "                    </div>\n" +
17019     "           </li>\n" +
17020     "\n" +
17021     "                <li ng-if=\"!startsWithFilter\" class=\"select2-results-dept-0 select2-result select2-result-selectable\" role=\"presentation\"\n" +
17022     "                    ng-model=\"ListType\" ng-repeat=\"(fIndex, item) in filteredName = (cName | filter:title)\"\n" +
17023     "                    ng-class=\"{'select2-result-current': selectedOption === item.title,'hovstyle': selectedIndex === item.index}\"\n" +
17024     "                    ng-click=\"selectOption(item.title,item.index)\"\n" +
17025     "                    ng-mouseover=\"hoverIn(item.index)\"\n" +
17026     "                    >\n" +
17027     "                    <div class=\"select2-result-label\" ng-bind-html=\"item.title | highlight:title:className | unsafe\" role=\"option\">\n" +
17028     "                        <span class=\"select2-match\" ></span>\n" +
17029     "                    </div>\n" +
17030     "                </li>\n" +
17031     "\n" +
17032     "   </ul>\n" +
17033     "</div>\n" +
17034     "");
17035 }]);
17036
17037 angular.module("app/scripts/ng_js_att_tpls/search/search_2.html", []).run(["$templateCache", function($templateCache) {
17038   $templateCache.put("app/scripts/ng_js_att_tpls/search/search_2.html",
17039     "<div ng-model=\"showlist\" class=\"select2-container\" ng-class=\"{'select2-dropdown-open select2-container-active': showlist}\" style=\"width: 100%; z-index:0\">\n" +
17040     "    <a tabindex=\"-1\" class=\"select2-choice\" href=\"javascript:void(0)\" ng-click=\"showDropdown()\">\n" +
17041     "        <span class=\"select2-chosen\">{{selectedOption}}</span>\n" +
17042     "        <abbr class=\"select2-search-choice-close\"></abbr>\n" +
17043     "        <span class=\"select2-arrow\"><b></b></span>\n" +
17044     "    </a>\n" +
17045     "    <input type=\"text\" class=\"select2-focusser select2-offscreen\">\n" +
17046     "</div>\n" +
17047     "<select ng-model=\"value\" ng-options=\"c.title for c in cName\" class=\"select2-offscreen\"></select>\n" +
17048     "<div class=\"select2-drop select2-display-none select2-with-searchbox select2-drop-active show-search\" style=\"display: block; width: 100%;\" ng-show=\"showlist\">\n" +
17049     "    <div ng-show=\"showSearch\" class=\"select2-search\">\n" +
17050     "        <input ng-model=\"title\" typeahead=\"c.title for c in cName | filter:$viewValue:startsWith\" type=\"text\" class=\"select2-input\" spellcheck=\"false\" autocapitalize=\"off\" autocorrect=\"off\" autocomplete=\"off\">\n" +
17051     "    </div>\n" +
17052     "    <ul class=\"select2-results\" style=\"margin-top:0px;max-height:205px\">\n" +
17053     "        <li ng-model=\"ListType\" ng-repeat=\"(fIndex, country) in cName | filter:title\" ng-class=\"{'select2-result-current': selectedOption === country.title}\" ng-click=\"selectOption(country.title,country.index)\" class=\"select2-results-dept-0 select2-result select2-result-selectable select2-highlighted\">\n" +
17054     "            <div class=\"select2-result-label\" ng-bind-html=\"country.title | highlight:title:className\"><span class=\"select2-match\"></span>\n" +
17055     "            </div>\n" +
17056     "        </li>\n" +
17057     "    </ul>\n" +
17058     "</div>\n" +
17059     "");
17060 }]);
17061
17062 angular.module("app/scripts/ng_js_att_tpls/select/select.html", []).run(["$templateCache", function($templateCache) {
17063   $templateCache.put("app/scripts/ng_js_att_tpls/select/select.html",
17064     "<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" +
17065     "   <a href=\"javascript:void(0)\" class=\"select2-choice needsclick\" tabindex=\"0\" ng-click=\"showDropdown()\" ng-class=\"{'select2-chosen-disabled':isDisabled}\" ng-focus=\"isact=true;\" ng-blur=\"isact=false;\">\n" +
17066     "           <span class=\"select2-chosen needsclick\">{{selectedOption}}</span>\n" +
17067     "           <abbr class=\"select2-search-choice-close needsclick\"></abbr>\n" +
17068     "           <span class=\"select2-arrow needsclick\" role=\"presentation\">\n" +
17069     "                   <b role=\"presentation\" class=\"needsclick\"></b>\n" +
17070     "           </span>\n" +
17071     "        </a>\n" +
17072     "   <label class=\"select2-offscreen\"></label>\n" +
17073     "        <input class=\"select2-focusser select2-offscreen\" tabindex=\"-1\" type=\"text\" aria-haspopup=\"true\" role=\"button\">\n" +
17074     "</div>\n" +
17075     "<div class=\"select2-drop select2-with-searchbox select2-drop-auto-width select2-drop-active\" ng-class=\"{'select2-display-none':(!showlist || isDisabled),'show-search':showSearch}\" style=\"width:100%;z-index: 10\">\n" +
17076     "   <div class=\"select2-search\">\n" +
17077     "           <label class=\"select2-offscreen\"></label>\n" +
17078     "           <input ng-model=\"title\" typeahead=\"c.title for c in cName | filter:$viewValue:startsWith\" type=\"text\" autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"off\" spellcheck=\"false\" class=\"select2-input\" role=\"combobox\" aria-\n" +
17079     "expanded=\"true\" aria-autocomplete=\"list\" placeholder=\"\">\n" +
17080     "   </div>\n" +
17081     "   <ul class=\"select2-results\" role=\"listbox\">\n" +
17082     "                <li ng-show=\"filteredName.length === 0\" class=\"select2-no-results\">No matches found</li>\n" +
17083     "           <li class=\"select2-results-dept-0 select2-result select2-result-selectable\" role=\"presentation\"\n" +
17084     "                    ng-model=\"ListType\" ng-show=\"selectMsg && filteredName.length > 0\"\n" +
17085     "                    ng-click=\"selectOption(selectMsg, '-1')\"\n" +
17086     "                    ng-class=\"{'select2-result-current': selectedOption === selectMsg, 'hovstyle': selectedIndex === -1}\"\n" +
17087     "                    ng-mouseover=\"hoverIn(-1)\">\n" +
17088     "                    <div ng-if=\"startsWithFilter\" class=\"select2-result-label\"  ng-bind-html=\"selectMsg | unsafe\" role=\"option\">\n" +
17089     "                                    <span class=\"select2-match\" ></span>\n" +
17090     "                    </div>\n" +
17091     "                    <div ng-if=\"!startsWithFilter\" class=\"select2-result-label\"  ng-bind-html=\"selectMsg | highlight:title:className | unsafe\" role=\"option\">\n" +
17092     "                        <span class=\"select2-match\" ></span>\n" +
17093     "                    </div>\n" +
17094     "           </li>\n" +
17095     "           <li ng-if=\"startsWithFilter\" class=\"select2-results-dept-0 select2-result select2-result-selectable\" role=\"presentation\"\n" +
17096     "                    ng-model=\"ListType\" ng-repeat=\"(fIndex, item) in filteredName = (cName | startsWith:title:item)\"\n" +
17097     "                    ng-class=\"{'select2-result-current': selectedOption === item.title,'hovstyle': selectedIndex === item.index}\"\n" +
17098     "                    ng-click=\"selectOption(item.title,item.index)\"\n" +
17099     "                    ng-mouseover=\"hoverIn(item.index)\">\n" +
17100     "                    <div class=\"select2-result-label\" ng-bind-html=\"item.title | unsafe\" role=\"option\">\n" +
17101     "                            <span class=\"select2-match\" ></span>\n" +
17102     "                    </div>\n" +
17103     "           </li>\n" +
17104     "\n" +
17105     "                <li ng-if=\"!startsWithFilter\" class=\"select2-results-dept-0 select2-result select2-result-selectable\" role=\"presentation\"\n" +
17106     "                    ng-model=\"ListType\" ng-repeat=\"(fIndex, item) in filteredName = (cName | filter:title)\"\n" +
17107     "                    ng-class=\"{'select2-result-current': selectedOption === item.title,'hovstyle': selectedIndex === item.index}\"\n" +
17108     "                    ng-click=\"selectOption(item.title,item.index)\"\n" +
17109     "                    ng-mouseover=\"hoverIn(item.index)\"\n" +
17110     "                    >\n" +
17111     "                    <div class=\"select2-result-label\" ng-bind-html=\"item.title | highlight:title:className | unsafe\" role=\"option\">\n" +
17112     "                        <span class=\"select2-match\" ></span>\n" +
17113     "                    </div>\n" +
17114     "                </li>\n" +
17115     "\n" +
17116     "   </ul>\n" +
17117     "</div>\n" +
17118     "");
17119 }]);
17120
17121 angular.module("app/scripts/ng_js_att_tpls/select/textDropdown.html", []).run(["$templateCache", function($templateCache) {
17122   $templateCache.put("app/scripts/ng_js_att_tpls/select/textDropdown.html",
17123     "<div tabindex=\"0\" class=\"text-dropdown\">\n" +
17124     "   <div class=\"dropdown\" ng-class=\"{'not-visible': isActionsShown}\" ng-click=\"toggle()\" >\n" +
17125     "           <span class=\"action--selected\" ng-bind=\"currentAction\"></span>\n" +
17126     "           <i ng-class=\"isActionsShown ? 'icon-dropdown-up' : 'icon-dropdown-down'\"></i>\n" +
17127     "   </div>\n" +
17128     "\n" +
17129     "   <ul ng-class=\"isActionsShown ? 'actionsOpened' : 'actionsClosed'\" ng-show=\"isActionsShown\">\n" +
17130     "           <li ng-class=\"{'highlight': selectedIndex==$index}\" ng-repeat=\"action in actions track by $index\" ng-click=\"chooseAction($event, action)\" ng-mouseover=\"hoverIn($index)\">{{action}}<i ng-class=\"{'icon-included-checkmark': isCurrentAction(action)}\"></i></li>\n" +
17131     "   </ul>\n" +
17132     "\n" +
17133     "</div>");
17134 }]);
17135
17136 angular.module("app/scripts/ng_js_att_tpls/slider/maxContent.html", []).run(["$templateCache", function($templateCache) {
17137   $templateCache.put("app/scripts/ng_js_att_tpls/slider/maxContent.html",
17138     "<div class=\"att-slider__label att-slider__label--max att-slider__label--below\" ng-transclude></div>");
17139 }]);
17140
17141 angular.module("app/scripts/ng_js_att_tpls/slider/minContent.html", []).run(["$templateCache", function($templateCache) {
17142   $templateCache.put("app/scripts/ng_js_att_tpls/slider/minContent.html",
17143     " <div class=\"att-slider__label att-slider__label--min att-slider__label--below\" ng-transclude></div>");
17144 }]);
17145
17146 angular.module("app/scripts/ng_js_att_tpls/slider/slider.html", []).run(["$templateCache", function($templateCache) {
17147   $templateCache.put("app/scripts/ng_js_att_tpls/slider/slider.html",
17148     "<div class=\"att-slider\" ng-mousemove=\"moveElem($event)\" ng-mouseup=\"mouseUp($event)\">\n" +
17149     "    <div class=\"att-slider__track\">\n" +
17150     "        <div class=\"att-slider__range att-slider__range--disabled\" ng-style=\"disabledStyle\"></div>\n" +
17151     "        <div class=\"att-slider__range\" ng-style=\"rangeStyle\"></div>\n" +
17152     "    </div>\n" +
17153     "    <div class=\"att-slider__handles-container\">\n" +
17154     "       <div 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" +
17155     "       <div class=\"att-slider__handle\"  ng-style=\"minHandleStyle\" ng-mousedown=\"mouseDown($event,'ngModelLow')\" ng-mousemove=\"moveElem($event)\" ng-mouseup=\"mouseUp($event)\" tabindex=\"0\" ng-keydown=\"keyDown($event,'ngModelLow')\"></div>\n" +
17156     "       <div class=\"att-slider__handle\" ng-style=\"maxHandleStyle\" ng-mousedown=\"mouseDown($event,'ngModelHigh')\" ng-mousemove=\"moveElem($event)\" ng-mouseup=\"mouseUp($event)\" tabindex=\"0\" ng-keydown=\"keyDown($event,'ngModelHigh')\"></div>\n" +
17157     "    </div>\n" +
17158     "    <div ng-transclude></div>\n" +
17159     "</div>");
17160 }]);
17161
17162 angular.module("app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdown.html", []).run(["$templateCache", function($templateCache) {
17163   $templateCache.put("app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdown.html",
17164     "<div class=\" btn-group\" \n" +
17165     "     ng-class=\"{'buttons-dropdown--large':!isSmall, \n" +
17166     "                 'buttons-dropdown--small':isSmall, \n" +
17167     "                 'action-dropdown':isActionDropdown, \n" +
17168     "                 'open':isDropDownOpen}\">\n" +
17169     "    <a tabindex=\"0\" href=\"javascript:void(0)\" class=\"button btn buttons-dropdown__split\" \n" +
17170     "       ng-class=\"{'button--primary':(btnType==undefined || btnType=='primary'), \n" +
17171     "                   'button--secondary':btnType=='secondary', \n" +
17172     "                   'button--disabled':btnType=='disabled', \n" +
17173     "                   'button--small':isSmall}\" \n" +
17174     "       ng-if=\"!isActionDropdown\"\n" +
17175     "       ng-click=\"btnType==='disabled'?undefined:clickFxn()\" att-accessibility-click=\"13,32\">{{btnText}}</a>\n" +
17176     "    <a tabindex=\"0\" href=\"javascript:void(0)\" role=\"button\" aria-label=\"Toggle Dropdown\" class=\"button buttons-dropdown__drop dropdown-toggle\" \n" +
17177     "       ng-class=\"{'button--primary':(btnType==undefined || btnType=='primary'), \n" +
17178     "               'button--secondary':btnType=='secondary', \n" +
17179     "               'button--disabled':btnType=='disabled', \n" +
17180     "               'button--small':isSmall}\" ng-click=\"toggleDropdown()\" att-accessibility-click=\"13,32\"></a>\n" +
17181     "    <ul class=\"dropdown-menu\" ng-click=\"hideDropdown()\" ng-transclude></ul>\n" +
17182     "</div>");
17183 }]);
17184
17185 angular.module("app/scripts/ng_js_att_tpls/splitIconButton/splitIcon.html", []).run(["$templateCache", function($templateCache) {
17186   $templateCache.put("app/scripts/ng_js_att_tpls/splitIconButton/splitIcon.html",
17187     "<div class='split-icon-button-container'>\n" +
17188     "\n" +
17189     "   <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" +
17190     "           <a class='{{icon}}' aria-label='{{icon}}' role='button' tabindex=\"0\"></a>\n" +
17191     "           <i ng-if=\"isRight && !isMiddle && !isLeftNextDropdown && !isNextToDropDown\" \n" +
17192     "                   ng-class=\"isDropDownOpen ? 'icon-dropdown-up' : 'icon-dropdown-down'\"> </i>\n" +
17193     "   </div> \n" +
17194     "\n" +
17195     "    <ul ng-if='isDropdown' class='dropdown-menu {{dropDownId}}' ng-show='\n" +
17196     "    isDropDownOpen' ng-click='toggleDropdown(false)' ng-transclude>\n" +
17197     "    </ul>\n" +
17198     "\n" +
17199     "</div>");
17200 }]);
17201
17202 angular.module("app/scripts/ng_js_att_tpls/splitIconButton/splitIconButton.html", []).run(["$templateCache", function($templateCache) {
17203   $templateCache.put("app/scripts/ng_js_att_tpls/splitIconButton/splitIconButton.html",
17204     "<div>\n" +
17205     "   <div ng-if='isLeftLineShown' dir-type='{{iconStateConstants.DIR_TYPE.LEFT}}' expandable-line></div>\n" +
17206     "   <div ng-click='clickHandler()' att-split-icon icon='{{icon}}' dir-type='{{iconStateConstants.DIR_TYPE.BUTTON}}' hover-watch='isHovered' drop-down-watch='dropDownWatch' drop-down-id='{{dropDownId}}'>\n" +
17207     "           <div ng-transclude>\n" +
17208     "           </div>\n" +
17209     "   </div>\n" +
17210     "   <div ng-if='isRightLineShown' dir-type='{{iconStateConstants.DIR_TYPE.RIGHT}}' expandable-line></div>\n" +
17211     "</div>");
17212 }]);
17213
17214 angular.module("app/scripts/ng_js_att_tpls/splitIconButton/splitIconButtonGroup.html", []).run(["$templateCache", function($templateCache) {
17215   $templateCache.put("app/scripts/ng_js_att_tpls/splitIconButton/splitIconButtonGroup.html",
17216     "<div ng-transclude>\n" +
17217     "</div>");
17218 }]);
17219
17220 angular.module("app/scripts/ng_js_att_tpls/stepSlider/attStepSlider.html", []).run(["$templateCache", function($templateCache) {
17221   $templateCache.put("app/scripts/ng_js_att_tpls/stepSlider/attStepSlider.html",
17222     "<span ng-class=\"mainSliderClass\">\n" +
17223     "    <table>\n" +
17224     "        <tr>\n" +
17225     "            <td>\n" +
17226     "                <div class=\"jslider-bg\">\n" +
17227     "                    <i class=\"l\"></i>\n" +
17228     "                    <i class=\"r\"></i>\n" +
17229     "                    <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" +
17230     "                </div>\n" +
17231     "                <div class=\"jslider-pointer\" id=\"left-pointer\"></div>\n" +
17232     "                <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" +
17233     "                <div class=\"jslider-label\"><span ng-bind=\"from\"></span><span ng-bind=\"options.dimension\"></span></div>\n" +
17234     "                <div class=\"jslider-label jslider-label-to\"><span ng-bind=\"toStr\"></span><span ng-bind=\"endDimension\"></span></div>\n" +
17235     "                <div class=\"jslider-value\" id=\"jslider-value-left\"><span></span>{{options.dimension}}</div>\n" +
17236     "                <div class=\"jslider-value jslider-value-to\"><span></span>{{toolTipDimension}}</div>\n" +
17237     "                <div class=\"jslider-scale\" ng-class=\"{'show-dividers': showDividers, 'cutoff-slider-dividers':isCutOffSlider}\">\n" +
17238     "                </div>\n" +
17239     "                <div class=\"jslider-cutoff\">\n" +
17240     "                    <div class=\"jslider-label jslider-label-cutoff\">\n" +
17241     "                        <span ng-bind=\"cutOffVal\"></span>\n" +
17242     "                    </div>\n" +
17243     "                </div>\n" +
17244     "            </td>\n" +
17245     "        </tr>\n" +
17246     "    </table>\n" +
17247     "</span>\n" +
17248     "");
17249 }]);
17250
17251 angular.module("app/scripts/ng_js_att_tpls/steptracker/step-tracker.html", []).run(["$templateCache", function($templateCache) {
17252   $templateCache.put("app/scripts/ng_js_att_tpls/steptracker/step-tracker.html",
17253     "<div class=\"steptracker1\">\n" +
17254     "    <div class=\"steptracker-bg\">\n" +
17255     "        <div class=\"steptracker-track size-onethird\" ng-repeat=\"step in sdata\"\n" +
17256     "             ng-style=\"set_width($index)\"\n" +
17257     "             ng-class=\"{'last':laststep($index),'done':donesteps($index),'active':activestep($index), 'incomplete': isIncomplete($index), 'disabled': disableClick}\">\n" +
17258     "            <div class=\"circle\" tabindex=\"0\"\n" +
17259     "                 ng-click=\"stepclick($event, $index);\"\n" +
17260     "                 att-accessibility-click=\"13,23\">{{($index) + 1}}<span>{{step.title}}</span></div>\n" +
17261     "            <div ng-if=\"!laststep($index)\" class=\"track\"></div>\n" +
17262     "        </div>\n" +
17263     "    </div>\n" +
17264     "</div>\n" +
17265     "");
17266 }]);
17267
17268 angular.module("app/scripts/ng_js_att_tpls/steptracker/step.html", []).run(["$templateCache", function($templateCache) {
17269   $templateCache.put("app/scripts/ng_js_att_tpls/steptracker/step.html",
17270     "<div class=\"steptracker1\">\n" +
17271     "    <div class=\"steptracker-bg\">\n" +
17272     "        <div class=\"steptracker-track size-onethird\" \n" +
17273     "             ng-class=\"{'last':laststep($index),'done':donesteps($index),'active':activestep($index)}\">\n" +
17274     "            <div class=\"circle\" tabindex=\"0\" \n" +
17275     "                 ng-click=\"stepclick($event, $index);\" \n" +
17276     "                 att-accessibility-click=\"13,23\">{{($index) + 1}}<span>{{step.title}}</span></div>\n" +
17277     "            <div ng-if=\"!laststep($index)\" class=\"track\"></div>\n" +
17278     "        </div>\n" +
17279     "    </div>\n" +
17280     "</div>\n" +
17281     "");
17282 }]);
17283
17284 angular.module("app/scripts/ng_js_att_tpls/steptracker/timeline.html", []).run(["$templateCache", function($templateCache) {
17285   $templateCache.put("app/scripts/ng_js_att_tpls/steptracker/timeline.html",
17286     "<div class='att-timeline'>\n" +
17287     "   <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" +
17288     "\n" +
17289     "   <div ng-repeat=\"m in middleSteps track by $index\">\n" +
17290     "           <div timeline-bar order='{{$index}}'></div>\n" +
17291     "           <div timeline-dot order='{{$index + 1}}' title='{{m.title}}' description='{{m.description}}' by='{{m.by}}' date='{{m.date}}' type='{{m.type}}'>\n" +
17292     "           </div>\n" +
17293     "   </div>\n" +
17294     "\n" +
17295     "</div>");
17296 }]);
17297
17298 angular.module("app/scripts/ng_js_att_tpls/steptracker/timelineBar.html", []).run(["$templateCache", function($templateCache) {
17299   $templateCache.put("app/scripts/ng_js_att_tpls/steptracker/timelineBar.html",
17300     "<div class='timeline-bar'>\n" +
17301     "   <div class='progress-bar' ng-class=\"{'completed-color':isCompleted,'cancelled-color':isCancelled,'alert-color':isAlert}\">\n" +
17302     "   </div>\n" +
17303     "   <hr></hr>\n" +
17304     "</div>");
17305 }]);
17306
17307 angular.module("app/scripts/ng_js_att_tpls/steptracker/timelineDot.html", []).run(["$templateCache", function($templateCache) {
17308   $templateCache.put("app/scripts/ng_js_att_tpls/steptracker/timelineDot.html",
17309     "<div class='timeline-dot'>\n" +
17310     "\n" +
17311     "   <div class='bigger-circle' ng-class=\"{'completed-color':isCompleted,'cancelled-color':isCancelled,'alert-color':isAlert}\">\n" +
17312     "   </div>\n" +
17313     "\n" +
17314     "   <div class='inactive-circle'>\n" +
17315     "   </div>\n" +
17316     "\n" +
17317     "   <div class='expandable-circle' ng-class=\"{'completed-color':isCompleted,'cancelled-color':isCancelled,'alert-color':isAlert}\">\n" +
17318     "   </div>\n" +
17319     "\n" +
17320     "   <div ng-class=\"{'below-info-box':isBelowInfoBoxShown, 'above-info-box': !isBelowInfoBoxShown}\">\n" +
17321     "           \n" +
17322     "           <div ng-if='isBelowInfoBoxShown' class='vertical-line'>\n" +
17323     "           </div>\n" +
17324     "\n" +
17325     "           <div class='info-container' ng-init='isContentShown=false'>\n" +
17326     "                   <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" +
17327     "                   <div class='content'>\n" +
17328     "                           <div class='description' ng-bind='description'></div>\n" +
17329     "                           <div class='submitter' ng-bind='by'></div>\n" +
17330     "                   </div>\n" +
17331     "                   <div class='date' ng-mouseover='titleMouseover(2)' ng-mouseleave='titleMouseleave()' ng-bind='date'></div>\n" +
17332     "           </div>\n" +
17333     "\n" +
17334     "           <div ng-if='!isBelowInfoBoxShown' class='vertical-line'>\n" +
17335     "           </div>\n" +
17336     "   </div>\n" +
17337     "\n" +
17338     "</div>");
17339 }]);
17340
17341 angular.module("app/scripts/ng_js_att_tpls/table/attTable.html", []).run(["$templateCache", function($templateCache) {
17342   $templateCache.put("app/scripts/ng_js_att_tpls/table/attTable.html",
17343     "<table class=\"tablesorter tablesorter-default\" ng-transclude></table>\n" +
17344     "");
17345 }]);
17346
17347 angular.module("app/scripts/ng_js_att_tpls/table/attTableBody.html", []).run(["$templateCache", function($templateCache) {
17348   $templateCache.put("app/scripts/ng_js_att_tpls/table/attTableBody.html",
17349     "<td ng-transclude></td>\n" +
17350     "");
17351 }]);
17352
17353 angular.module("app/scripts/ng_js_att_tpls/table/attTableHeader.html", []).run(["$templateCache", function($templateCache) {
17354   $templateCache.put("app/scripts/ng_js_att_tpls/table/attTableHeader.html",
17355     "<th 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(); clickFunc && clickFunc()\"><div class=\"tablesorter-header-inner\" ng-transclude></div></th>\n" +
17356     "");
17357 }]);
17358
17359 angular.module("app/scripts/ng_js_att_tpls/tabs/floatingTabs.html", []).run(["$templateCache", function($templateCache) {
17360   $templateCache.put("app/scripts/ng_js_att_tpls/tabs/floatingTabs.html",
17361     "<ul ng-class=\"{'tabsbid': size === 'large', 'tabsbid--small': size === 'small'}\">\n" +
17362     " <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" +
17363     "        <a class=\"tabsbid__item-link\" href=\"{{tab.url}}\" tabindex=\"0\" att-accessibility-click=\"32,13\">{{tab.title}}</a>\n" +
17364     "  </li>\n" +
17365     "</ul>");
17366 }]);
17367
17368 angular.module("app/scripts/ng_js_att_tpls/tabs/genericTabs.html", []).run(["$templateCache", function($templateCache) {
17369   $templateCache.put("app/scripts/ng_js_att_tpls/tabs/genericTabs.html",
17370     "<ul ng-class=\"{'tabsbid': size === 'large', 'tabsbid--small': size === 'small'}\">\n" +
17371     "    <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" +
17372     "           <a class=\"tabsbid__item-link\" href=\"{{tab.url}}\" tabindex=\"0\" att-accessibility-click=\"32,13\">{{tab.title}}</a>\n" +
17373     "    </li>\n" +
17374     "</ul>\n" +
17375     "");
17376 }]);
17377
17378 angular.module("app/scripts/ng_js_att_tpls/tabs/menuTab.html", []).run(["$templateCache", function($templateCache) {
17379   $templateCache.put("app/scripts/ng_js_att_tpls/tabs/menuTab.html",
17380     "<li class=\"megamenu__item\" ng-mouseover=\"showHoverChild($event)\" ng-click=\"showChildren($event);!clickInactive||resetMenu()\"  ng-class=\"{'tabs__item--active': menuItem.active==true && !hoverChild==true}\" ng-transclude att-accessibility-click=\"13,32\" tabindex=\"0\"></li>");
17381 }]);
17382
17383 angular.module("app/scripts/ng_js_att_tpls/tabs/parentmenuTab.html", []).run(["$templateCache", function($templateCache) {
17384   $templateCache.put("app/scripts/ng_js_att_tpls/tabs/parentmenuTab.html",
17385     "<div ng-class=\"{'megamenu-tabs': megaMenu,'submenu-tabs': !megaMenu}\">\n" +
17386     "    <ul class=\"megamenu__items\" ng-transclude>\n" +
17387     "    </ul>\n" +
17388     "</div>");
17389 }]);
17390
17391 angular.module("app/scripts/ng_js_att_tpls/tabs/simplifiedTabs.html", []).run(["$templateCache", function($templateCache) {
17392   $templateCache.put("app/scripts/ng_js_att_tpls/tabs/simplifiedTabs.html",
17393     "<div class=\"simplified-tabs\">\n" +
17394     "<ul class=\"simplified-tabs__items\">\n" +
17395     "    <li ng-repeat=\"tab in tabs\" 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" +
17396     "    <li class=\"tabs__pointer\"></li>\n" +
17397     "</ul>\n" +
17398     "</div>");
17399 }]);
17400
17401 angular.module("app/scripts/ng_js_att_tpls/tabs/submenuTab.html", []).run(["$templateCache", function($templateCache) {
17402   $templateCache.put("app/scripts/ng_js_att_tpls/tabs/submenuTab.html",
17403     "<li class=\"tabsbid__item megamenu__item\" ng-class=\"{'subMenuHover': menuItem.active==true}\" ng-mouseover=\"!subMenu || showChildren($event)\" ng-focus=\"!subMenu ||showChildren($event)\" tabindex=\"{{subMenu=='true'?0:-1}}\" ng-click=\"!subMenu ||showMenuClick() ; subMenu ||showSubMenuClick()\" att-accessibility-click=\"13,32\" ng-transclude>\n" +
17404     "</li>");
17405 }]);
17406
17407 angular.module("app/scripts/ng_js_att_tpls/tagBadges/tagBadges.html", []).run(["$templateCache", function($templateCache) {
17408   $templateCache.put("app/scripts/ng_js_att_tpls/tagBadges/tagBadges.html",
17409     "<div class=\"tags__item\" \n" +
17410     "     ng-class=\"{'tags__item--small':isSmall, \n" +
17411     "                 'tags__item--color':isColor, \n" +
17412     "                 'tags__item--cloud':!isClosable && !isColor,'active':applyActiveClass}\"\n" +
17413     "     ng-if=\"display\" \n" +
17414     "     ng-style=\"{borderColor: border_type_borderColor, background: isHighlight?'#bbb':undefined, color: isHighlight?'#444':undefined }\"\n" +
17415     "     ng-mousedown=\"activeHighlight(true)\" ng-mouseup=\"activeHighlight(false)\">\n" +
17416     "    <i class=\"icon-filter tags__item--icon\" ng-if=\"isIcon\">&nbsp;</i>\n" +
17417     "    <i class=\"tags__item--color-icon\" ng-if=\"isColor\" ng-style=\"{backgroundColor: background_type_backgroundColor, borderColor: background_type_borderColor}\"></i>\n" +
17418     "    <span class=\"tags__item--title\" tabindex=0 aria-label ng-mousedown=\"activeHighlight(true)\" ng-mouseup=\"activeHighlight(false)\" ng-transclude></span>\n" +
17419     "    <a href=\"javascript:void(0)\" title=\"Dismiss Link\" class=\"tags__item--action\" ng-click=\"closeMe();$event.preventDefault()\" ng-if=\"isClosable\"\n" +
17420     "       ng-style=\"{color: (isHighlight && '#444') || '#888' , borderLeft: (isHighlight && '1px solid #444')|| '1px solid #888' }\">\n" +
17421     "        <i class=\"icon-erase\">&nbsp;</i>\n" +
17422     "    </a>\n" +
17423     "</div>");
17424 }]);
17425
17426 angular.module("app/scripts/ng_js_att_tpls/toggle/demoToggle.html", []).run(["$templateCache", function($templateCache) {
17427   $templateCache.put("app/scripts/ng_js_att_tpls/toggle/demoToggle.html",
17428     "<span ng-transclude></span>\n" +
17429     "<div tabindex=\"0\" 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" +
17430     "    <div class=\"att-switch-onText\" ng-style=\"\" ng-class=\"{'icon-included-checkmark ico' : on === undefined,'large' : directiveValue == 'large'}\">{{on}}<span class=\"hidden-spoken\">when checked.</span></div>\n" +
17431     "    <div class=\"att-switch-thumb\" tabindex=\"0\" ng-class=\"{'large' : directiveValue == 'large'}\"></div>\n" +
17432     "    <div class=\"att-switch-offText\" ng-class=\"{'icon-erase ico' : on === undefined,'large' : directiveValue == 'large'}\">{{off}}<span class=\"hidden-spoken\">when unchecked.</span></div>\n" +
17433     "</div>\n" +
17434     "");
17435 }]);
17436
17437 angular.module("app/scripts/ng_js_att_tpls/tooltip/tooltip-popup.html", []).run(["$templateCache", function($templateCache) {
17438   $templateCache.put("app/scripts/ng_js_att_tpls/tooltip/tooltip-popup.html",
17439     "<div class=\"att-tooltip \" \n" +
17440     "     ng-class=\"{ 'att-tooltip--on': isOpen, \n" +
17441     "                'att-tooltip--dark att-tooltip--dark--hover':stylett=='dark', \n" +
17442     "                'att-tooltip--light att-tooltip--light--hover':stylett=='light',\n" +
17443     "                'att-tooltip--left':placement=='left', \n" +
17444     "                'att-tooltip--above':placement=='above', \n" +
17445     "                'att-tooltip--right':placement=='right', \n" +
17446     "                'att-tooltip--below':placement=='below'}\" \n" +
17447     "    ng-bind-html=\"content\" ></div>");
17448 }]);
17449
17450 angular.module("app/scripts/ng_js_att_tpls/typeAhead/typeAhead.html", []).run(["$templateCache", function($templateCache) {
17451   $templateCache.put("app/scripts/ng_js_att_tpls/typeAhead/typeAhead.html",
17452     "<div class=\"typeahead mainContainerOuter\">\n" +
17453     "    <span class=\"message\">To</span> \n" +
17454     "    <div class='maincontainer' ng-click=\"setFocus()\" ng-class =\"{'typeahed_active':inputActive}\">\n" +
17455     "        <span tag-badges closable ng-repeat =\"lineItem in lineItems track by $index\" on-close=\"theMethodToBeCalled($index)\" >{{lineItem}}</span>\n" +
17456     "        <input type=\"text\"  focus-me=\"clickFocus\" id=\"inpute\" aria-label=\"model\" role=\"textfiled\" ng-model=\"model\" ng-keydown=\"selected = false; selectionIndex($event)\"/><br/> \n" +
17457     "    </div>\n" +
17458     "    <div ng-hide=\"!model.length || selected\">\n" +
17459     "        <div class=\"filtercontainer list-scrollable\" ng-show=\"( items | filter:model).length\">\n" +
17460     "            <div  class=\"item\" ng-repeat=\"item in items| filter:model track by $index\"  ng-click=\"handleSelection(item[title],item[subtitle])\" att-accessibility-click=\"13,32\" style=\"cursor:pointer\" ng-class=\"{active:isCurrent($index,item[title],item[subtitle],( items | filter:model).length)}\"  aria-label=\"item[title]\" ng-mouseenter=\"setCurrent($index)\">\n" +
17461     "                <span class=\"title\" >{{item[title]}}</span>\n" +
17462     "                <span class=\"subtitle\">{{item[subtitle]}}</span>\n" +
17463     "            </div>  \n" +
17464     "        </div>\n" +
17465     "    </div>\n" +
17466     "   \n" +
17467     "    <div class=\"textAreaEmailContentDiv\">\n" +
17468     "        <span class=\"message\">Message</span>\n" +
17469     "        <textarea rows=\"4\" cols=\"50\" role=\"textarea\" class=\"textAreaEmailContent\" ng-model=\"emailMessage\">To send \n" +
17470     " a text, picture, or video message1 to an AT&T wireless device from your email:my message.</textarea>\n" +
17471     "        \n" +
17472     "    </div>\n" +
17473     "</div>\n" +
17474     "");
17475 }]);
17476
17477 angular.module("app/scripts/ng_js_att_tpls/userMessages/attTableMessage.html", []).run(["$templateCache", function($templateCache) {
17478   $templateCache.put("app/scripts/ng_js_att_tpls/userMessages/attTableMessage.html",
17479     "<div class=\"att-table-message\">\n" +
17480     "   <div class=\"message\" ng-if=\"msgType==messageConstants.TABLE_MESSAGE_TYPES.noMatching\">\n" +
17481     "      <div class=\"img-magnify-glass\"></div> \n" +
17482     "      <div>\n" +
17483     "         <div ng-transclude></div>\n" +
17484     "      </div>\n" +
17485     "   </div>\n" +
17486     "   <div class=\"message\" ng-if=\"msgType==messageConstants.TABLE_MESSAGE_TYPES.errorLoading\">\n" +
17487     "      <div class=\"img-oops-exclamation\"></div> \n" +
17488     "      <div>Oops!</div>\n" +
17489     "      <div>The information could not load at this time.</div>\n" +
17490     "      <div>Please <a href=\"javascript:void(0)\" ng-click=\"refreshAction($event)\">refresh the page</a>\n" +
17491     "      </div>\n" +
17492     "   </div>\n" +
17493     "   <div class=\"message\" ng-if=\"msgType==messageConstants.TABLE_MESSAGE_TYPES.magnifySearch\">\n" +
17494     "      <div class=\"img-magnify-glass\"></div>\n" +
17495     "      <div>\n" +
17496     "         <p class=\"title\">Please input values to <br/> begin your search.</p>\n" +
17497     "      </div>\n" +
17498     "   </div>\n" +
17499     "   <div class=\"message loading-message\" ng-if=\"msgType==messageConstants.TABLE_MESSAGE_TYPES.isLoading\">\n" +
17500     "      <div class=\"img-loading-dots\"></div>\n" +
17501     "      <div ng-transclude></div>\n" +
17502     "   </div>\n" +
17503     "</div>");
17504 }]);
17505
17506 angular.module("app/scripts/ng_js_att_tpls/userMessages/attUserMessage.html", []).run(["$templateCache", function($templateCache) {
17507   $templateCache.put("app/scripts/ng_js_att_tpls/userMessages/attUserMessage.html",
17508     "<div class=\"att-user-message\">\n" +
17509     "  <div ng-class=\"type==messageConstants.USER_MESSAGE_TYPES.error && trigger ? 'message-wrapper-error' : 'hidden'\">\n" +
17510     "      <div class=\"message-icon-error\"> <i class=\"icon-info-alert\"></i> </div>\n" +
17511     "\n" +
17512     "      <div class=\"message-body-wrapper\">\n" +
17513     "        <div class=\"message-title-error\" ng-if=\"thetitle && thetitle.length > 0\"> <span ng-bind=\"thetitle\"></span> </div>\n" +
17514     "        <div class=\"message-msg\" ng-bind=\"message\" ng-if=\"message && message.length > 0\"> </div>\n" +
17515     "        <div class=\"message-bottom\">\n" +
17516     "           <div ng-transclude></div>\n" +
17517     "        </div>\n" +
17518     "      </div>\n" +
17519     "\n" +
17520     "   </div>\n" +
17521     "  <div ng-class=\"type==messageConstants.USER_MESSAGE_TYPES.success && trigger ? 'message-wrapper-success' : 'hidden'\">\n" +
17522     "      <div class=\"message-icon-success\"> <i class=\"icon-included-checkmark\"></i> </div>\n" +
17523     "\n" +
17524     "      <div class=\"message-body-wrapper\">\n" +
17525     "        <div class=\"message-title-success\" ng-if=\"thetitle && thetitle.length > 0\"> <span ng-bind=\"thetitle\"></span> </div>\n" +
17526     "        <div class=\"message-msg\" ng-bind=\"message\" ng-if=\"message && message.length > 0\"> </div>\n" +
17527     "        <div class=\"message-bottom\">\n" +
17528     "           <div ng-transclude></div>\n" +
17529     "        </div>\n" +
17530     "      </div>\n" +
17531     "\n" +
17532     "   </div>\n" +
17533     "</div>\n" +
17534     "");
17535 }]);
17536
17537 angular.module("app/scripts/ng_js_att_tpls/verticalSteptracker/vertical-step-tracker.html", []).run(["$templateCache", function($templateCache) {
17538   $templateCache.put("app/scripts/ng_js_att_tpls/verticalSteptracker/vertical-step-tracker.html",
17539     "<li>\n" +
17540     "    <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" +
17541     "    <span ng-transclude></span>\n" +
17542     "</li>\n" +
17543     "        \n" +
17544     "");
17545 }]);
17546
17547 angular.module("app/scripts/ng_js_att_tpls/videoControls/photoControls.html", []).run(["$templateCache", function($templateCache) {
17548   $templateCache.put("app/scripts/ng_js_att_tpls/videoControls/photoControls.html",
17549     "<div>\n" +
17550     "    <a title=\"Previous Link\" ng-href=\"{{links.prevLink}}\"><i class=\"icon-arrow-left\">&nbsp;</i></a>\n" +
17551     "    <span ng-transclude></span>\n" +
17552     "    <a title=\"Next Link\" ng-href=\"{{links.nextLink}}\"><i class=\"icon-arrow-right\">&nbsp;</i></a>\n" +
17553     "</div>");
17554 }]);
17555
17556 angular.module("app/scripts/ng_js_att_tpls/videoControls/videoControls.html", []).run(["$templateCache", function($templateCache) {
17557   $templateCache.put("app/scripts/ng_js_att_tpls/videoControls/videoControls.html",
17558     "<div class=\"video-player\">\n" +
17559     "    <div class=\"video-player__control video-player__play-button\">\n" +
17560     "        <a class=\"video-player__button gigant-play\" data-toggle-buttons=\"icon-play, icon-pause\" data-target=\"i\"><i class=\"icon-play\"></i></a>\n" +
17561     "    </div>\n" +
17562     "    <div class=\"video-player__control video-player__track\">\n" +
17563     "\n" +
17564     "        <div class=\"video-player__track--inner\">\n" +
17565     "            <div class=\"video-player__track--loaded\" style=\"width: 75%\"></div>\n" +
17566     "            <div class=\"video-player__track--played\" style=\"width: 40%\">\n" +
17567     "                <div class=\"att-tooltip att-tooltip--on att-tooltip--dark att-tooltip--above video-player__track-tooltip\" ng-transclude></div>\n" +
17568     "                <div class=\"video-player__track-handle\"></div>\n" +
17569     "            </div>\n" +
17570     "        </div>\n" +
17571     "    </div>\n" +
17572     "    <a class=\"video-player__time\" ng-transclude></a>\n" +
17573     "    <div class=\"video-player__control video-player__volume_icon\">\n" +
17574     "        <a class=\"video-player__button\" data-toggle-buttons=\"icon-volume-mute, icon-volume-up\" data-target=\"i\"><i class=\"icon-volume-up\"></i></a>\n" +
17575     "    </div>\n" +
17576     "    <ul class=\"video-player__control video-player__volume\">\n" +
17577     "        <li class=\"video-player__volume-bar video-player__volume-bar--full\">&nbsp;</li>\n" +
17578     "        <li class=\"video-player__volume-bar video-player__volume-bar--full\">&nbsp;</li>\n" +
17579     "        <li class=\"video-player__volume-bar\">&nbsp;</li>\n" +
17580     "        <li class=\"video-player__volume-bar\">&nbsp;</li>\n" +
17581     "        <li class=\"video-player__volume-bar\">&nbsp;</li>\n" +
17582     "    </ul>\n" +
17583     "    <div class=\"video-player__control video-player__toggle-fullscreen-button\">\n" +
17584     "        <a class=\"video-player__button\" data-toggle-buttons=\"icon-full-screen, icon-normal-screen\" data-target=\"i\"><i class=\"icon-full-screen\">&nbsp;</i></a>\n" +
17585     "    </div>\n" +
17586     "</div>");
17587 }]);