nexus site path corrected
[portal.git] / ecomp-portal-BE / war / static / ebz / angular_js / att_abs_tpls.js
1 /*Sandbox version 1.2.51*/
2 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.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"]);
3 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/attStepSlider.html","app/scripts/ng_js_att_tpls/slider/maxContent.html","app/scripts/ng_js_att_tpls/slider/minContent.html","app/scripts/ng_js_att_tpls/slider/slider.html","app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdown.html","app/scripts/ng_js_att_tpls/splitButtonDropdown/splitIcon.html","app/scripts/ng_js_att_tpls/splitButtonDropdown/splitIconButton.html","app/scripts/ng_js_att_tpls/splitButtonDropdown/splitIconButtonGroup.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"]);
4 angular.module('att.abs.position', [])
5
6 .factory('$position', ['$document', '$window', function ($document, $window) {
7     function getStyle(el, cssprop) {
8         if (el.currentStyle) { //IE
9             return el.currentStyle[cssprop];
10         } else if ($window.getComputedStyle) {
11             return $window.getComputedStyle(el)[cssprop];
12         }
13         // finally try and get inline style
14         return el.style[cssprop];
15     }
16
17     /**
18      * Checks if a given element is statically positioned
19      * @param element - raw DOM element
20      */
21     function isStaticPositioned(element) {
22         return (getStyle(element, "position") || 'static') === 'static';
23     }
24
25     /**
26      * returns the closest, non-statically positioned parentOffset of a given element
27      * @param element
28      */
29     var parentOffsetEl = function (element) {
30         var docDomEl = $document[0];
31         var offsetParent = element.offsetParent || docDomEl;
32         while (offsetParent && offsetParent !== docDomEl && isStaticPositioned(offsetParent)) {
33             offsetParent = offsetParent.offsetParent;
34         }
35         return offsetParent || docDomEl;
36     };
37
38     return {
39         /**
40          * Provides read-only equivalent of jQuery's position function:
41          * http://api.jquery.com/position/
42          */
43         position: function (element) {
44             var elBCR = this.offset(element);
45             var offsetParentBCR = {
46                 top: 0,
47                 left: 0
48             };
49             var offsetParentEl = parentOffsetEl(element[0]);
50             if (offsetParentEl != $document[0]) {
51                 offsetParentBCR = this.offset(angular.element(offsetParentEl));
52                 offsetParentBCR.top += offsetParentEl.clientTop - offsetParentEl.scrollTop;
53                 offsetParentBCR.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft;
54             }
55
56             return {
57                 width: element.prop('offsetWidth'),
58                 height: element.prop('offsetHeight'),
59                 top: elBCR.top - offsetParentBCR.top,
60                 left: elBCR.left - offsetParentBCR.left
61             };
62         },
63
64         /**
65          * Provides read-only equivalent of jQuery's offset function:
66          * http://api.jquery.com/offset/
67          */
68         offset: function (element) {
69             var boundingClientRect = element[0].getBoundingClientRect();
70             return {
71                 width: element.prop('offsetWidth'),
72                 height: element.prop('offsetHeight'),
73                 top: boundingClientRect.top + ($window.pageYOffset || $document[0].body.scrollTop || $document[0].documentElement.scrollTop),
74                 left: boundingClientRect.left + ($window.pageXOffset || $document[0].body.scrollLeft || $document[0].documentElement.scrollLeft)
75             };
76         }
77     };
78 }])
79
80 .factory('$isElement', [function () {
81     var isElement = function (currentElem, targetElem, alternateElem) {
82         if (currentElem[0] === targetElem[0]) {
83             return true;
84         } else if (currentElem[0] === alternateElem[0]) {
85             return false;
86         } else {
87             return isElement((currentElem.parent()[0] && currentElem.parent()) || targetElem, targetElem, alternateElem);
88         }
89     };
90
91     return isElement;
92 }]);
93
94 /*!
95  * VERSION: 1.7.3
96  * DATE: 2014-01-14
97  * UPDATES AND DOCS AT: http://www.greensock.com
98  *
99  * @license Copyright (c) 2008-2014, GreenSock. All rights reserved.
100  * This work is subject to the terms at http://www.greensock.com/terms_of_use.html or for
101  * Club GreenSock members, the software agreement that was issued with your membership.
102  * 
103  * @author: Jack Doyle, jack@greensock.com
104  **/
105 (window._gsQueue || (window._gsQueue = [])).push( function() {
106
107         "use strict";
108
109         var _doc = document.documentElement,
110                 _window = window,
111                 _max = function(element, axis) {
112                         var dim = (axis === "x") ? "Width" : "Height",
113                                 scroll = "scroll" + dim,
114                                 client = "client" + dim,
115                                 body = document.body;
116                         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];
117                 },
118
119                 ScrollToPlugin = window._gsDefine.plugin({
120                         propName: "scrollTo",
121                         API: 2,
122                         version:"1.7.3",
123
124                         //called when the tween renders for the first time. This is where initial values should be recorded and any setup routines should run.
125                         init: function(target, value, tween) {
126                                 this._wdw = (target === _window);
127                                 this._target = target;
128                                 this._tween = tween;
129                                 if (typeof(value) !== "object") {
130                                         value = {y:value}; //if we don't receive an object as the parameter, assume the user intends "y".
131                                 }
132                                 this._autoKill = (value.autoKill !== false);
133                                 this.x = this.xPrev = this.getX();
134                                 this.y = this.yPrev = this.getY();
135                                 if (value.x != null) {
136                                         this._addTween(this, "x", this.x, (value.x === "max") ? _max(target, "x") : value.x, "scrollTo_x", true);
137                                         this._overwriteProps.push("scrollTo_x");
138                                 } else {
139                                         this.skipX = true;
140                                 }
141                                 if (value.y != null) {
142                                         this._addTween(this, "y", this.y, (value.y === "max") ? _max(target, "y") : value.y, "scrollTo_y", true);
143                                         this._overwriteProps.push("scrollTo_y");
144                                 } else {
145                                         this.skipY = true;
146                                 }
147                                 return true;
148                         },
149
150                         //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.)
151                         set: function(v) {
152                                 this._super.setRatio.call(this, v);
153
154                                 var x = (this._wdw || !this.skipX) ? this.getX() : this.xPrev,
155                                         y = (this._wdw || !this.skipY) ? this.getY() : this.yPrev,
156                                         yDif = y - this.yPrev,
157                                         xDif = x - this.xPrev;
158
159                                 if (this._autoKill) {
160                                         //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.
161                                         if (!this.skipX && (xDif > 7 || xDif < -7) && x < _max(this._target, "x")) {
162                                                 this.skipX = true; //if the user scrolls separately, we should stop tweening!
163                                         }
164                                         if (!this.skipY && (yDif > 7 || yDif < -7) && y < _max(this._target, "y")) {
165                                                 this.skipY = true; //if the user scrolls separately, we should stop tweening!
166                                         }
167                                         if (this.skipX && this.skipY) {
168                                                 this._tween.kill();
169                                         }
170                                 }
171                                 if (this._wdw) {
172                                         _window.scrollTo((!this.skipX) ? this.x : x, (!this.skipY) ? this.y : y);
173                                 } else {
174                                         if (!this.skipY) {
175                                                 this._target.scrollTop = this.y;
176                                         }
177                                         if (!this.skipX) {
178                                                 this._target.scrollLeft = this.x;
179                                         }
180                                 }
181                                 this.xPrev = this.x;
182                                 this.yPrev = this.y;
183                         }
184
185                 }),
186                 p = ScrollToPlugin.prototype;
187
188         ScrollToPlugin.max = _max;
189
190         p.getX = function() {
191                 return (!this._wdw) ? this._target.scrollLeft : (_window.pageXOffset != null) ? _window.pageXOffset : (_doc.scrollLeft != null) ? _doc.scrollLeft : document.body.scrollLeft;
192         };
193
194         p.getY = function() {
195                 return (!this._wdw) ? this._target.scrollTop : (_window.pageYOffset != null) ? _window.pageYOffset : (_doc.scrollTop != null) ? _doc.scrollTop : document.body.scrollTop;
196         };
197
198         p._kill = function(lookup) {
199                 if (lookup.scrollTo_x) {
200                         this.skipX = true;
201                 }
202                 if (lookup.scrollTo_y) {
203                         this.skipY = true;
204                 }
205                 return this._super._kill.call(this, lookup);
206         };
207
208 }); if (window._gsDefine) { window._gsQueue.pop()(); }
209 /*!
210  * VERSION: 1.12.1
211  * DATE: 2014-06-26
212  * UPDATES AND DOCS AT: http://www.greensock.com
213  * 
214  * Includes all of the following: TweenLite, TweenMax, TimelineLite, TimelineMax, EasePack, CSSPlugin, RoundPropsPlugin, BezierPlugin, AttrPlugin, DirectionalRotationPlugin
215  *
216  * @license Copyright (c) 2008-2014, GreenSock. All rights reserved.
217  * This work is subject to the terms at http://www.greensock.com/terms_of_use.html or for
218  * Club GreenSock members, the software agreement that was issued with your membership.
219  * 
220  * @author: Jack Doyle, jack@greensock.com
221  **/
222
223 (window._gsQueue || (window._gsQueue = [])).push( function() {
224
225         "use strict";
226
227         window._gsDefine("TweenMax", ["core.Animation","core.SimpleTimeline","TweenLite"], function(Animation, SimpleTimeline, TweenLite) {
228
229                 var _slice = [].slice,
230                         TweenMax = function(target, duration, vars) {
231                                 TweenLite.call(this, target, duration, vars);
232                                 this._cycle = 0;
233                                 this._yoyo = (this.vars.yoyo === true);
234                                 this._repeat = this.vars.repeat || 0;
235                                 this._repeatDelay = this.vars.repeatDelay || 0;
236                                 this._dirty = true; //ensures that if there is any repeat, the totalDuration will get recalculated to accurately report it.
237                                 this.render = TweenMax.prototype.render; //speed optimization (avoid prototype lookup on this "hot" method)
238                         },
239                         _tinyNum = 0.0000000001,
240                         TweenLiteInternals = TweenLite._internals,
241                         _isSelector = TweenLiteInternals.isSelector,
242                         _isArray = TweenLiteInternals.isArray,
243                         p = TweenMax.prototype = TweenLite.to({}, 0.1, {}),
244                         _blankArray = [];
245
246                 TweenMax.version = "1.12.1";
247                 p.constructor = TweenMax;
248                 p.kill()._gc = false;
249                 TweenMax.killTweensOf = TweenMax.killDelayedCallsTo = TweenLite.killTweensOf;
250                 TweenMax.getTweensOf = TweenLite.getTweensOf;
251                 TweenMax.lagSmoothing = TweenLite.lagSmoothing;
252                 TweenMax.ticker = TweenLite.ticker;
253                 TweenMax.render = TweenLite.render;
254
255                 p.invalidate = function() {
256                         this._yoyo = (this.vars.yoyo === true);
257                         this._repeat = this.vars.repeat || 0;
258                         this._repeatDelay = this.vars.repeatDelay || 0;
259                         this._uncache(true);
260                         return TweenLite.prototype.invalidate.call(this);
261                 };
262                 
263                 p.updateTo = function(vars, resetDuration) {
264                         var curRatio = this.ratio, p;
265                         if (resetDuration && this._startTime < this._timeline._time) {
266                                 this._startTime = this._timeline._time;
267                                 this._uncache(false);
268                                 if (this._gc) {
269                                         this._enabled(true, false);
270                                 } else {
271                                         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.
272                                 }
273                         }
274                         for (p in vars) {
275                                 this.vars[p] = vars[p];
276                         }
277                         if (this._initted) {
278                                 if (resetDuration) {
279                                         this._initted = false;
280                                 } else {
281                                         if (this._gc) {
282                                                 this._enabled(true, false);
283                                         }
284                                         if (this._notifyPluginsOfEnabled && this._firstPT) {
285                                                 TweenLite._onPluginEvent("_onDisable", this); //in case a plugin like MotionBlur must perform some cleanup tasks
286                                         }
287                                         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. 
288                                                 var prevTime = this._time;
289                                                 this.render(0, true, false);
290                                                 this._initted = false;
291                                                 this.render(prevTime, true, false);
292                                         } else if (this._time > 0) {
293                                                 this._initted = false;
294                                                 this._init();
295                                                 var inv = 1 / (1 - curRatio),
296                                                         pt = this._firstPT, endValue;
297                                                 while (pt) {
298                                                         endValue = pt.s + pt.c; 
299                                                         pt.c *= inv;
300                                                         pt.s = endValue - pt.c;
301                                                         pt = pt._next;
302                                                 }
303                                         }
304                                 }
305                         }
306                         return this;
307                 };
308                                 
309                 p.render = function(time, suppressEvents, force) {
310                         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.
311                                 this.invalidate();
312                         }
313                         var totalDur = (!this._dirty) ? this._totalDuration : this.totalDuration(),
314                                 prevTime = this._time,
315                                 prevTotalTime = this._totalTime, 
316                                 prevCycle = this._cycle,
317                                 duration = this._duration,
318                                 prevRawPrevTime = this._rawPrevTime,
319                                 isComplete, callback, pt, cycleDuration, r, type, pow, rawPrevTime, i;
320                         if (time >= totalDur) {
321                                 this._totalTime = totalDur;
322                                 this._cycle = this._repeat;
323                                 if (this._yoyo && (this._cycle & 1) !== 0) {
324                                         this._time = 0;
325                                         this.ratio = this._ease._calcEnd ? this._ease.getRatio(0) : 0;
326                                 } else {
327                                         this._time = duration;
328                                         this.ratio = this._ease._calcEnd ? this._ease.getRatio(1) : 1;
329                                 }
330                                 if (!this._reversed) {
331                                         isComplete = true;
332                                         callback = "onComplete";
333                                 }
334                                 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.
335                                         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.
336                                                 time = 0;
337                                         }
338                                         if (time === 0 || prevRawPrevTime < 0 || prevRawPrevTime === _tinyNum) if (prevRawPrevTime !== time) {
339                                                 force = true;
340                                                 if (prevRawPrevTime > _tinyNum) {
341                                                         callback = "onReverseComplete";
342                                                 }
343                                         }
344                                         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.
345                                 }
346                                 
347                         } else if (time < 0.0000001) { //to work around occasional floating point math artifacts, round super small values to 0.
348                                 this._totalTime = this._time = this._cycle = 0;
349                                 this.ratio = this._ease._calcEnd ? this._ease.getRatio(0) : 0;
350                                 if (prevTotalTime !== 0 || (duration === 0 && prevRawPrevTime > 0 && prevRawPrevTime !== _tinyNum)) {
351                                         callback = "onReverseComplete";
352                                         isComplete = this._reversed;
353                                 }
354                                 if (time < 0) {
355                                         this._active = false;
356                                         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.
357                                                 if (prevRawPrevTime >= 0) {
358                                                         force = true;
359                                                 }
360                                                 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.
361                                         }
362                                 } 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.
363                                         force = true;
364                                 }
365                         } else {
366                                 this._totalTime = this._time = time;
367                                 
368                                 if (this._repeat !== 0) {
369                                         cycleDuration = duration + this._repeatDelay;
370                                         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!)
371                                         if (this._cycle !== 0) if (this._cycle === this._totalTime / cycleDuration) {
372                                                 this._cycle--; //otherwise when rendered exactly at the end time, it will act as though it is repeating (at the beginning)
373                                         }
374                                         this._time = this._totalTime - (this._cycle * cycleDuration);
375                                         if (this._yoyo) if ((this._cycle & 1) !== 0) {
376                                                 this._time = duration - this._time;
377                                         }
378                                         if (this._time > duration) {
379                                                 this._time = duration;
380                                         } else if (this._time < 0) {
381                                                 this._time = 0;
382                                         }
383                                 }
384
385                                 if (this._easeType) {
386                                         r = this._time / duration;
387                                         type = this._easeType;
388                                         pow = this._easePower;
389                                         if (type === 1 || (type === 3 && r >= 0.5)) {
390                                                 r = 1 - r;
391                                         }
392                                         if (type === 3) {
393                                                 r *= 2;
394                                         }
395                                         if (pow === 1) {
396                                                 r *= r;
397                                         } else if (pow === 2) {
398                                                 r *= r * r;
399                                         } else if (pow === 3) {
400                                                 r *= r * r * r;
401                                         } else if (pow === 4) {
402                                                 r *= r * r * r * r;
403                                         }
404
405                                         if (type === 1) {
406                                                 this.ratio = 1 - r;
407                                         } else if (type === 2) {
408                                                 this.ratio = r;
409                                         } else if (this._time / duration < 0.5) {
410                                                 this.ratio = r / 2;
411                                         } else {
412                                                 this.ratio = 1 - (r / 2);
413                                         }
414
415                                 } else {
416                                         this.ratio = this._ease.getRatio(this._time / duration);
417                                 }
418                                 
419                         }
420                                 
421                         if (prevTime === this._time && !force && prevCycle === this._cycle) {
422                                 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.
423                                         this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray);
424                                 }
425                                 return;
426                         } else if (!this._initted) {
427                                 this._init();
428                                 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.
429                                         return;
430                                 } 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.
431                                         this._time = prevTime;
432                                         this._totalTime = prevTotalTime;
433                                         this._rawPrevTime = prevRawPrevTime;
434                                         this._cycle = prevCycle;
435                                         TweenLiteInternals.lazyTweens.push(this);
436                                         this._lazy = time;
437                                         return;
438                                 }
439                                 //_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.
440                                 if (this._time && !isComplete) {
441                                         this.ratio = this._ease.getRatio(this._time / duration);
442                                 } else if (isComplete && this._ease._calcEnd) {
443                                         this.ratio = this._ease.getRatio((this._time === 0) ? 0 : 1);
444                                 }
445                         }
446                         if (this._lazy !== false) {
447                                 this._lazy = false;
448                         }
449
450                         if (!this._active) if (!this._paused && this._time !== prevTime && time >= 0) {
451                                 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.
452                         }
453                         if (prevTotalTime === 0) {
454                                 if (this._initted === 2 && time > 0) {
455                                         //this.invalidate();
456                                         this._init(); //will just apply overwriting since _initted of (2) means it was a from() tween that had immediateRender:true
457                                 }
458                                 if (this._startAt) {
459                                         if (time >= 0) {
460                                                 this._startAt.render(time, suppressEvents, force);
461                                         } else if (!callback) {
462                                                 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.
463                                         }
464                                 }
465                                 if (this.vars.onStart) if (this._totalTime !== 0 || duration === 0) if (!suppressEvents) {
466                                         this.vars.onStart.apply(this.vars.onStartScope || this, this.vars.onStartParams || _blankArray);
467                                 }
468                         }
469                         
470                         pt = this._firstPT;
471                         while (pt) {
472                                 if (pt.f) {
473                                         pt.t[pt.p](pt.c * this.ratio + pt.s);
474                                 } else {
475                                         pt.t[pt.p] = pt.c * this.ratio + pt.s;
476                                 }
477                                 pt = pt._next;
478                         }
479                         
480                         if (this._onUpdate) {
481                                 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.
482                                         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.
483                                 }
484                                 if (!suppressEvents) if (this._totalTime !== prevTotalTime || isComplete) {
485                                         this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray);
486                                 }
487                         }
488                         if (this._cycle !== prevCycle) if (!suppressEvents) if (!this._gc) if (this.vars.onRepeat) {
489                                 this.vars.onRepeat.apply(this.vars.onRepeatScope || this, this.vars.onRepeatParams || _blankArray);
490                         }
491                         if (callback) if (!this._gc) { //check gc because there's a chance that kill() could be called in an onUpdate
492                                 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.
493                                         this._startAt.render(time, suppressEvents, force);
494                                 }
495                                 if (isComplete) {
496                                         if (this._timeline.autoRemoveChildren) {
497                                                 this._enabled(false, false);
498                                         }
499                                         this._active = false;
500                                 }
501                                 if (!suppressEvents && this.vars[callback]) {
502                                         this.vars[callback].apply(this.vars[callback + "Scope"] || this, this.vars[callback + "Params"] || _blankArray);
503                                 }
504                                 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.
505                                         this._rawPrevTime = 0;
506                                 }
507                         }
508                 };
509                 
510 //---- STATIC FUNCTIONS -----------------------------------------------------------------------------------------------------------
511                 
512                 TweenMax.to = function(target, duration, vars) {
513                         return new TweenMax(target, duration, vars);
514                 };
515                 
516                 TweenMax.from = function(target, duration, vars) {
517                         vars.runBackwards = true;
518                         vars.immediateRender = (vars.immediateRender != false);
519                         return new TweenMax(target, duration, vars);
520                 };
521                 
522                 TweenMax.fromTo = function(target, duration, fromVars, toVars) {
523                         toVars.startAt = fromVars;
524                         toVars.immediateRender = (toVars.immediateRender != false && fromVars.immediateRender != false);
525                         return new TweenMax(target, duration, toVars);
526                 };
527                 
528                 TweenMax.staggerTo = TweenMax.allTo = function(targets, duration, vars, stagger, onCompleteAll, onCompleteAllParams, onCompleteAllScope) {
529                         stagger = stagger || 0;
530                         var delay = vars.delay || 0,
531                                 a = [],
532                                 finalComplete = function() {
533                                         if (vars.onComplete) {
534                                                 vars.onComplete.apply(vars.onCompleteScope || this, arguments);
535                                         }
536                                         onCompleteAll.apply(onCompleteAllScope || this, onCompleteAllParams || _blankArray);
537                                 },
538                                 l, copy, i, p;
539                         if (!_isArray(targets)) {
540                                 if (typeof(targets) === "string") {
541                                         targets = TweenLite.selector(targets) || targets;
542                                 }
543                                 if (_isSelector(targets)) {
544                                         targets = _slice.call(targets, 0);
545                                 }
546                         }
547                         l = targets.length;
548                         for (i = 0; i < l; i++) {
549                                 copy = {};
550                                 for (p in vars) {
551                                         copy[p] = vars[p];
552                                 }
553                                 copy.delay = delay;
554                                 if (i === l - 1 && onCompleteAll) {
555                                         copy.onComplete = finalComplete;
556                                 }
557                                 a[i] = new TweenMax(targets[i], duration, copy);
558                                 delay += stagger;
559                         }
560                         return a;
561                 };
562                 
563                 TweenMax.staggerFrom = TweenMax.allFrom = function(targets, duration, vars, stagger, onCompleteAll, onCompleteAllParams, onCompleteAllScope) {
564                         vars.runBackwards = true;
565                         vars.immediateRender = (vars.immediateRender != false);
566                         return TweenMax.staggerTo(targets, duration, vars, stagger, onCompleteAll, onCompleteAllParams, onCompleteAllScope);
567                 };
568                 
569                 TweenMax.staggerFromTo = TweenMax.allFromTo = function(targets, duration, fromVars, toVars, stagger, onCompleteAll, onCompleteAllParams, onCompleteAllScope) {
570                         toVars.startAt = fromVars;
571                         toVars.immediateRender = (toVars.immediateRender != false && fromVars.immediateRender != false);
572                         return TweenMax.staggerTo(targets, duration, toVars, stagger, onCompleteAll, onCompleteAllParams, onCompleteAllScope);
573                 };
574                                 
575                 TweenMax.delayedCall = function(delay, callback, params, scope, useFrames) {
576                         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});
577                 };
578                 
579                 TweenMax.set = function(target, vars) {
580                         return new TweenMax(target, 0, vars);
581                 };
582                 
583                 TweenMax.isTweening = function(target) {
584                         return (TweenLite.getTweensOf(target, true).length > 0);
585                 };
586                 
587                 var _getChildrenOf = function(timeline, includeTimelines) {
588                                 var a = [],
589                                         cnt = 0,
590                                         tween = timeline._first;
591                                 while (tween) {
592                                         if (tween instanceof TweenLite) {
593                                                 a[cnt++] = tween;
594                                         } else {
595                                                 if (includeTimelines) {
596                                                         a[cnt++] = tween;
597                                                 }
598                                                 a = a.concat(_getChildrenOf(tween, includeTimelines));
599                                                 cnt = a.length;
600                                         }
601                                         tween = tween._next;
602                                 }
603                                 return a;
604                         }, 
605                         getAllTweens = TweenMax.getAllTweens = function(includeTimelines) {
606                                 return _getChildrenOf(Animation._rootTimeline, includeTimelines).concat( _getChildrenOf(Animation._rootFramesTimeline, includeTimelines) );
607                         };
608                 
609                 TweenMax.killAll = function(complete, tweens, delayedCalls, timelines) {
610                         if (tweens == null) {
611                                 tweens = true;
612                         }
613                         if (delayedCalls == null) {
614                                 delayedCalls = true;
615                         }
616                         var a = getAllTweens((timelines != false)),
617                                 l = a.length,
618                                 allTrue = (tweens && delayedCalls && timelines),
619                                 isDC, tween, i;
620                         for (i = 0; i < l; i++) {
621                                 tween = a[i];
622                                 if (allTrue || (tween instanceof SimpleTimeline) || ((isDC = (tween.target === tween.vars.onComplete)) && delayedCalls) || (tweens && !isDC)) {
623                                         if (complete) {
624                                                 tween.totalTime(tween._reversed ? 0 : tween.totalDuration());
625                                         } else {
626                                                 tween._enabled(false, false);
627                                         }
628                                 }
629                         }
630                 };
631                 
632                 TweenMax.killChildTweensOf = function(parent, complete) {
633                         if (parent == null) {
634                                 return;
635                         }
636                         var tl = TweenLiteInternals.tweenLookup,
637                                 a, curParent, p, i, l;
638                         if (typeof(parent) === "string") {
639                                 parent = TweenLite.selector(parent) || parent;
640                         }
641                         if (_isSelector(parent)) {
642                                 parent = _slice.call(parent, 0);
643                         }
644                         if (_isArray(parent)) {
645                                 i = parent.length;
646                                 while (--i > -1) {
647                                         TweenMax.killChildTweensOf(parent[i], complete);
648                                 }
649                                 return;
650                         }
651                         a = [];
652                         for (p in tl) {
653                                 curParent = tl[p].target.parentNode;
654                                 while (curParent) {
655                                         if (curParent === parent) {
656                                                 a = a.concat(tl[p].tweens);
657                                         }
658                                         curParent = curParent.parentNode;
659                                 }
660                         }
661                         l = a.length;
662                         for (i = 0; i < l; i++) {
663                                 if (complete) {
664                                         a[i].totalTime(a[i].totalDuration());
665                                 }
666                                 a[i]._enabled(false, false);
667                         }
668                 };
669
670                 var _changePause = function(pause, tweens, delayedCalls, timelines) {
671                         tweens = (tweens !== false);
672                         delayedCalls = (delayedCalls !== false);
673                         timelines = (timelines !== false);
674                         var a = getAllTweens(timelines),
675                                 allTrue = (tweens && delayedCalls && timelines),
676                                 i = a.length,
677                                 isDC, tween;
678                         while (--i > -1) {
679                                 tween = a[i];
680                                 if (allTrue || (tween instanceof SimpleTimeline) || ((isDC = (tween.target === tween.vars.onComplete)) && delayedCalls) || (tweens && !isDC)) {
681                                         tween.paused(pause);
682                                 }
683                         }
684                 };
685                 
686                 TweenMax.pauseAll = function(tweens, delayedCalls, timelines) {
687                         _changePause(true, tweens, delayedCalls, timelines);
688                 };
689                 
690                 TweenMax.resumeAll = function(tweens, delayedCalls, timelines) {
691                         _changePause(false, tweens, delayedCalls, timelines);
692                 };
693
694                 TweenMax.globalTimeScale = function(value) {
695                         var tl = Animation._rootTimeline,
696                                 t = TweenLite.ticker.time;
697                         if (!arguments.length) {
698                                 return tl._timeScale;
699                         }
700                         value = value || _tinyNum; //can't allow zero because it'll throw the math off
701                         tl._startTime = t - ((t - tl._startTime) * tl._timeScale / value);
702                         tl = Animation._rootFramesTimeline;
703                         t = TweenLite.ticker.frame;
704                         tl._startTime = t - ((t - tl._startTime) * tl._timeScale / value);
705                         tl._timeScale = Animation._rootTimeline._timeScale = value;
706                         return value;
707                 };
708                 
709         
710 //---- GETTERS / SETTERS ----------------------------------------------------------------------------------------------------------
711                 
712                 p.progress = function(value) {
713                         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);
714                 };
715                 
716                 p.totalProgress = function(value) {
717                         return (!arguments.length) ? this._totalTime / this.totalDuration() : this.totalTime( this.totalDuration() * value, false);
718                 };
719                 
720                 p.time = function(value, suppressEvents) {
721                         if (!arguments.length) {
722                                 return this._time;
723                         }
724                         if (this._dirty) {
725                                 this.totalDuration();
726                         }
727                         if (value > this._duration) {
728                                 value = this._duration;
729                         }
730                         if (this._yoyo && (this._cycle & 1) !== 0) {
731                                 value = (this._duration - value) + (this._cycle * (this._duration + this._repeatDelay));
732                         } else if (this._repeat !== 0) {
733                                 value += this._cycle * (this._duration + this._repeatDelay);
734                         }
735                         return this.totalTime(value, suppressEvents);
736                 };
737
738                 p.duration = function(value) {
739                         if (!arguments.length) {
740                                 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.
741                         }
742                         return Animation.prototype.duration.call(this, value);
743                 };
744
745                 p.totalDuration = function(value) {
746                         if (!arguments.length) {
747                                 if (this._dirty) {
748                                         //instead of Infinity, we use 999999999999 so that we can accommodate reverses
749                                         this._totalDuration = (this._repeat === -1) ? 999999999999 : this._duration * (this._repeat + 1) + (this._repeatDelay * this._repeat);
750                                         this._dirty = false;
751                                 }
752                                 return this._totalDuration;
753                         }
754                         return (this._repeat === -1) ? this : this.duration( (value - (this._repeat * this._repeatDelay)) / (this._repeat + 1) );
755                 };
756                 
757                 p.repeat = function(value) {
758                         if (!arguments.length) {
759                                 return this._repeat;
760                         }
761                         this._repeat = value;
762                         return this._uncache(true);
763                 };
764                 
765                 p.repeatDelay = function(value) {
766                         if (!arguments.length) {
767                                 return this._repeatDelay;
768                         }
769                         this._repeatDelay = value;
770                         return this._uncache(true);
771                 };
772                 
773                 p.yoyo = function(value) {
774                         if (!arguments.length) {
775                                 return this._yoyo;
776                         }
777                         this._yoyo = value;
778                         return this;
779                 };
780                 
781                 
782                 return TweenMax;
783                 
784         }, true);
785
786
787
788
789
790
791
792
793 /*
794  * ----------------------------------------------------------------
795  * TimelineLite
796  * ----------------------------------------------------------------
797  */
798         window._gsDefine("TimelineLite", ["core.Animation","core.SimpleTimeline","TweenLite"], function(Animation, SimpleTimeline, TweenLite) {
799
800                 var TimelineLite = function(vars) {
801                                 SimpleTimeline.call(this, vars);
802                                 this._labels = {};
803                                 this.autoRemoveChildren = (this.vars.autoRemoveChildren === true);
804                                 this.smoothChildTiming = (this.vars.smoothChildTiming === true);
805                                 this._sortChildren = true;
806                                 this._onUpdate = this.vars.onUpdate;
807                                 var v = this.vars,
808                                         val, p;
809                                 for (p in v) {
810                                         val = v[p];
811                                         if (_isArray(val)) if (val.join("").indexOf("{self}") !== -1) {
812                                                 v[p] = this._swapSelfInParams(val);
813                                         }
814                                 }
815                                 if (_isArray(v.tweens)) {
816                                         this.add(v.tweens, 0, v.align, v.stagger);
817                                 }
818                         },
819                         _tinyNum = 0.0000000001,
820                         _isSelector = TweenLite._internals.isSelector,
821                         _isArray = TweenLite._internals.isArray,
822                         _blankArray = [],
823                         _globals = window._gsDefine.globals,
824                         _copy = function(vars) {
825                                 var copy = {}, p;
826                                 for (p in vars) {
827                                         copy[p] = vars[p];
828                                 }
829                                 return copy;
830                         },
831                         _pauseCallback = function(tween, callback, params, scope) {
832                                 tween._timeline.pause(tween._startTime);
833                                 if (callback) {
834                                         callback.apply(scope || tween._timeline, params || _blankArray);
835                                 }
836                         },
837                         _slice = _blankArray.slice,
838                         p = TimelineLite.prototype = new SimpleTimeline();
839
840                 TimelineLite.version = "1.12.1";
841                 p.constructor = TimelineLite;
842                 p.kill()._gc = false;
843
844                 p.to = function(target, duration, vars, position) {
845                         var Engine = (vars.repeat && _globals.TweenMax) || TweenLite;
846                         return duration ? this.add( new Engine(target, duration, vars), position) : this.set(target, vars, position);
847                 };
848
849                 p.from = function(target, duration, vars, position) {
850                         return this.add( ((vars.repeat && _globals.TweenMax) || TweenLite).from(target, duration, vars), position);
851                 };
852
853                 p.fromTo = function(target, duration, fromVars, toVars, position) {
854                         var Engine = (toVars.repeat && _globals.TweenMax) || TweenLite;
855                         return duration ? this.add( Engine.fromTo(target, duration, fromVars, toVars), position) : this.set(target, toVars, position);
856                 };
857
858                 p.staggerTo = function(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope) {
859                         var tl = new TimelineLite({onComplete:onCompleteAll, onCompleteParams:onCompleteAllParams, onCompleteScope:onCompleteAllScope, smoothChildTiming:this.smoothChildTiming}),
860                                 i;
861                         if (typeof(targets) === "string") {
862                                 targets = TweenLite.selector(targets) || targets;
863                         }
864                         if (_isSelector(targets)) { //senses if the targets object is a selector. If it is, we should translate it into an array.
865                                 targets = _slice.call(targets, 0);
866                         }
867                         stagger = stagger || 0;
868                         for (i = 0; i < targets.length; i++) {
869                                 if (vars.startAt) {
870                                         vars.startAt = _copy(vars.startAt);
871                                 }
872                                 tl.to(targets[i], duration, _copy(vars), i * stagger);
873                         }
874                         return this.add(tl, position);
875                 };
876
877                 p.staggerFrom = function(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope) {
878                         vars.immediateRender = (vars.immediateRender != false);
879                         vars.runBackwards = true;
880                         return this.staggerTo(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope);
881                 };
882
883                 p.staggerFromTo = function(targets, duration, fromVars, toVars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope) {
884                         toVars.startAt = fromVars;
885                         toVars.immediateRender = (toVars.immediateRender != false && fromVars.immediateRender != false);
886                         return this.staggerTo(targets, duration, toVars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope);
887                 };
888
889                 p.call = function(callback, params, scope, position) {
890                         return this.add( TweenLite.delayedCall(0, callback, params, scope), position);
891                 };
892
893                 p.set = function(target, vars, position) {
894                         position = this._parseTimeOrLabel(position, 0, true);
895                         if (vars.immediateRender == null) {
896                                 vars.immediateRender = (position === this._time && !this._paused);
897                         }
898                         return this.add( new TweenLite(target, 0, vars), position);
899                 };
900
901                 TimelineLite.exportRoot = function(vars, ignoreDelayedCalls) {
902                         vars = vars || {};
903                         if (vars.smoothChildTiming == null) {
904                                 vars.smoothChildTiming = true;
905                         }
906                         var tl = new TimelineLite(vars),
907                                 root = tl._timeline,
908                                 tween, next;
909                         if (ignoreDelayedCalls == null) {
910                                 ignoreDelayedCalls = true;
911                         }
912                         root._remove(tl, true);
913                         tl._startTime = 0;
914                         tl._rawPrevTime = tl._time = tl._totalTime = root._time;
915                         tween = root._first;
916                         while (tween) {
917                                 next = tween._next;
918                                 if (!ignoreDelayedCalls || !(tween instanceof TweenLite && tween.target === tween.vars.onComplete)) {
919                                         tl.add(tween, tween._startTime - tween._delay);
920                                 }
921                                 tween = next;
922                         }
923                         root.add(tl, 0);
924                         return tl;
925                 };
926
927                 p.add = function(value, position, align, stagger) {
928                         var curTime, l, i, child, tl, beforeRawTime;
929                         if (typeof(position) !== "number") {
930                                 position = this._parseTimeOrLabel(position, 0, true, value);
931                         }
932                         if (!(value instanceof Animation)) {
933                                 if ((value instanceof Array) || (value && value.push && _isArray(value))) {
934                                         align = align || "normal";
935                                         stagger = stagger || 0;
936                                         curTime = position;
937                                         l = value.length;
938                                         for (i = 0; i < l; i++) {
939                                                 if (_isArray(child = value[i])) {
940                                                         child = new TimelineLite({tweens:child});
941                                                 }
942                                                 this.add(child, curTime);
943                                                 if (typeof(child) !== "string" && typeof(child) !== "function") {
944                                                         if (align === "sequence") {
945                                                                 curTime = child._startTime + (child.totalDuration() / child._timeScale);
946                                                         } else if (align === "start") {
947                                                                 child._startTime -= child.delay();
948                                                         }
949                                                 }
950                                                 curTime += stagger;
951                                         }
952                                         return this._uncache(true);
953                                 } else if (typeof(value) === "string") {
954                                         return this.addLabel(value, position);
955                                 } else if (typeof(value) === "function") {
956                                         value = TweenLite.delayedCall(0, value);
957                                 } else {
958                                         throw("Cannot add " + value + " into the timeline; it is not a tween, timeline, function, or string.");
959                                 }
960                         }
961
962                         SimpleTimeline.prototype.add.call(this, value, position);
963
964                         //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.
965                         if (this._gc || this._time === this._duration) if (!this._paused) if (this._duration < this.duration()) {
966                                 //in case any of the ancestors had completed but should now be enabled...
967                                 tl = this;
968                                 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.
969                                 while (tl._timeline) {
970                                         if (beforeRawTime && tl._timeline.smoothChildTiming) {
971                                                 tl.totalTime(tl._totalTime, true); //moves the timeline (shifts its startTime) if necessary, and also enables it.
972                                         } else if (tl._gc) {
973                                                 tl._enabled(true, false);
974                                         }
975                                         tl = tl._timeline;
976                                 }
977                         }
978
979                         return this;
980                 };
981
982                 p.remove = function(value) {
983                         if (value instanceof Animation) {
984                                 return this._remove(value, false);
985                         } else if (value instanceof Array || (value && value.push && _isArray(value))) {
986                                 var i = value.length;
987                                 while (--i > -1) {
988                                         this.remove(value[i]);
989                                 }
990                                 return this;
991                         } else if (typeof(value) === "string") {
992                                 return this.removeLabel(value);
993                         }
994                         return this.kill(null, value);
995                 };
996
997                 p._remove = function(tween, skipDisable) {
998                         SimpleTimeline.prototype._remove.call(this, tween, skipDisable);
999                         var last = this._last;
1000                         if (!last) {
1001                                 this._time = this._totalTime = this._duration = this._totalDuration = 0;
1002                         } else if (this._time > last._startTime + last._totalDuration / last._timeScale) {
1003                                 this._time = this.duration();
1004                                 this._totalTime = this._totalDuration;
1005                         }
1006                         return this;
1007                 };
1008
1009                 p.append = function(value, offsetOrLabel) {
1010                         return this.add(value, this._parseTimeOrLabel(null, offsetOrLabel, true, value));
1011                 };
1012
1013                 p.insert = p.insertMultiple = function(value, position, align, stagger) {
1014                         return this.add(value, position || 0, align, stagger);
1015                 };
1016
1017                 p.appendMultiple = function(tweens, offsetOrLabel, align, stagger) {
1018                         return this.add(tweens, this._parseTimeOrLabel(null, offsetOrLabel, true, tweens), align, stagger);
1019                 };
1020
1021                 p.addLabel = function(label, position) {
1022                         this._labels[label] = this._parseTimeOrLabel(position);
1023                         return this;
1024                 };
1025
1026                 p.addPause = function(position, callback, params, scope) {
1027                         return this.call(_pauseCallback, ["{self}", callback, params, scope], this, position);
1028                 };
1029
1030                 p.removeLabel = function(label) {
1031                         delete this._labels[label];
1032                         return this;
1033                 };
1034
1035                 p.getLabelTime = function(label) {
1036                         return (this._labels[label] != null) ? this._labels[label] : -1;
1037                 };
1038
1039                 p._parseTimeOrLabel = function(timeOrLabel, offsetOrLabel, appendIfAbsent, ignore) {
1040                         var i;
1041                         //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().
1042                         if (ignore instanceof Animation && ignore.timeline === this) {
1043                                 this.remove(ignore);
1044                         } else if (ignore && ((ignore instanceof Array) || (ignore.push && _isArray(ignore)))) {
1045                                 i = ignore.length;
1046                                 while (--i > -1) {
1047                                         if (ignore[i] instanceof Animation && ignore[i].timeline === this) {
1048                                                 this.remove(ignore[i]);
1049                                         }
1050                                 }
1051                         }
1052                         if (typeof(offsetOrLabel) === "string") {
1053                                 return this._parseTimeOrLabel(offsetOrLabel, (appendIfAbsent && typeof(timeOrLabel) === "number" && this._labels[offsetOrLabel] == null) ? timeOrLabel - this.duration() : 0, appendIfAbsent);
1054                         }
1055                         offsetOrLabel = offsetOrLabel || 0;
1056                         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).
1057                                 i = timeOrLabel.indexOf("=");
1058                                 if (i === -1) {
1059                                         if (this._labels[timeOrLabel] == null) {
1060                                                 return appendIfAbsent ? (this._labels[timeOrLabel] = this.duration() + offsetOrLabel) : offsetOrLabel;
1061                                         }
1062                                         return this._labels[timeOrLabel] + offsetOrLabel;
1063                                 }
1064                                 offsetOrLabel = parseInt(timeOrLabel.charAt(i-1) + "1", 10) * Number(timeOrLabel.substr(i+1));
1065                                 timeOrLabel = (i > 1) ? this._parseTimeOrLabel(timeOrLabel.substr(0, i-1), 0, appendIfAbsent) : this.duration();
1066                         } else if (timeOrLabel == null) {
1067                                 timeOrLabel = this.duration();
1068                         }
1069                         return Number(timeOrLabel) + offsetOrLabel;
1070                 };
1071
1072                 p.seek = function(position, suppressEvents) {
1073                         return this.totalTime((typeof(position) === "number") ? position : this._parseTimeOrLabel(position), (suppressEvents !== false));
1074                 };
1075
1076                 p.stop = function() {
1077                         return this.paused(true);
1078                 };
1079
1080                 p.gotoAndPlay = function(position, suppressEvents) {
1081                         return this.play(position, suppressEvents);
1082                 };
1083
1084                 p.gotoAndStop = function(position, suppressEvents) {
1085                         return this.pause(position, suppressEvents);
1086                 };
1087
1088                 p.render = function(time, suppressEvents, force) {
1089                         if (this._gc) {
1090                                 this._enabled(true, false);
1091                         }
1092                         var totalDur = (!this._dirty) ? this._totalDuration : this.totalDuration(),
1093                                 prevTime = this._time,
1094                                 prevStart = this._startTime,
1095                                 prevTimeScale = this._timeScale,
1096                                 prevPaused = this._paused,
1097                                 tween, isComplete, next, callback, internalForce;
1098                         if (time >= totalDur) {
1099                                 this._totalTime = this._time = totalDur;
1100                                 if (!this._reversed) if (!this._hasPausedChild()) {
1101                                         isComplete = true;
1102                                         callback = "onComplete";
1103                                         if (this._duration === 0) if (time === 0 || this._rawPrevTime < 0 || this._rawPrevTime === _tinyNum) if (this._rawPrevTime !== time && this._first) {
1104                                                 internalForce = true;
1105                                                 if (this._rawPrevTime > _tinyNum) {
1106                                                         callback = "onReverseComplete";
1107                                                 }
1108                                         }
1109                                 }
1110                                 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.
1111                                 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.
1112
1113                         } else if (time < 0.0000001) { //to work around occasional floating point math artifacts, round super small values to 0.
1114                                 this._totalTime = this._time = 0;
1115                                 if (prevTime !== 0 || (this._duration === 0 && this._rawPrevTime !== _tinyNum && (this._rawPrevTime > 0 || (time < 0 && this._rawPrevTime >= 0)))) {
1116                                         callback = "onReverseComplete";
1117                                         isComplete = this._reversed;
1118                                 }
1119                                 if (time < 0) {
1120                                         this._active = false;
1121                                         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.
1122                                                 internalForce = true;
1123                                         }
1124                                         this._rawPrevTime = time;
1125                                 } else {
1126                                         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.
1127
1128                                         time = 0; //to avoid occasional floating point rounding errors (could cause problems especially with zero-duration tweens at the very beginning of the timeline)
1129                                         if (!this._initted) {
1130                                                 internalForce = true;
1131                                         }
1132                                 }
1133
1134                         } else {
1135                                 this._totalTime = this._time = this._rawPrevTime = time;
1136                         }
1137                         if ((this._time === prevTime || !this._first) && !force && !internalForce) {
1138                                 return;
1139                         } else if (!this._initted) {
1140                                 this._initted = true;
1141                         }
1142
1143                         if (!this._active) if (!this._paused && this._time !== prevTime && time > 0) {
1144                                 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.
1145                         }
1146
1147                         if (prevTime === 0) if (this.vars.onStart) if (this._time !== 0) if (!suppressEvents) {
1148                                 this.vars.onStart.apply(this.vars.onStartScope || this, this.vars.onStartParams || _blankArray);
1149                         }
1150
1151                         if (this._time >= prevTime) {
1152                                 tween = this._first;
1153                                 while (tween) {
1154                                         next = tween._next; //record it here because the value could change after rendering...
1155                                         if (this._paused && !prevPaused) { //in case a tween pauses the timeline when rendering
1156                                                 break;
1157                                         } else if (tween._active || (tween._startTime <= this._time && !tween._paused && !tween._gc)) {
1158                                                 if (!tween._reversed) {
1159                                                         tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force);
1160                                                 } else {
1161                                                         tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force);
1162                                                 }
1163                                         }
1164                                         tween = next;
1165                                 }
1166                         } else {
1167                                 tween = this._last;
1168                                 while (tween) {
1169                                         next = tween._prev; //record it here because the value could change after rendering...
1170                                         if (this._paused && !prevPaused) { //in case a tween pauses the timeline when rendering
1171                                                 break;
1172                                         } else if (tween._active || (tween._startTime <= prevTime && !tween._paused && !tween._gc)) {
1173                                                 if (!tween._reversed) {
1174                                                         tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force);
1175                                                 } else {
1176                                                         tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force);
1177                                                 }
1178                                         }
1179                                         tween = next;
1180                                 }
1181                         }
1182
1183                         if (this._onUpdate) if (!suppressEvents) {
1184                                 this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray);
1185                         }
1186
1187                         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
1188                                 if (isComplete) {
1189                                         if (this._timeline.autoRemoveChildren) {
1190                                                 this._enabled(false, false);
1191                                         }
1192                                         this._active = false;
1193                                 }
1194                                 if (!suppressEvents && this.vars[callback]) {
1195                                         this.vars[callback].apply(this.vars[callback + "Scope"] || this, this.vars[callback + "Params"] || _blankArray);
1196                                 }
1197                         }
1198                 };
1199
1200                 p._hasPausedChild = function() {
1201                         var tween = this._first;
1202                         while (tween) {
1203                                 if (tween._paused || ((tween instanceof TimelineLite) && tween._hasPausedChild())) {
1204                                         return true;
1205                                 }
1206                                 tween = tween._next;
1207                         }
1208                         return false;
1209                 };
1210
1211                 p.getChildren = function(nested, tweens, timelines, ignoreBeforeTime) {
1212                         ignoreBeforeTime = ignoreBeforeTime || -9999999999;
1213                         var a = [],
1214                                 tween = this._first,
1215                                 cnt = 0;
1216                         while (tween) {
1217                                 if (tween._startTime < ignoreBeforeTime) {
1218                                         //do nothing
1219                                 } else if (tween instanceof TweenLite) {
1220                                         if (tweens !== false) {
1221                                                 a[cnt++] = tween;
1222                                         }
1223                                 } else {
1224                                         if (timelines !== false) {
1225                                                 a[cnt++] = tween;
1226                                         }
1227                                         if (nested !== false) {
1228                                                 a = a.concat(tween.getChildren(true, tweens, timelines));
1229                                                 cnt = a.length;
1230                                         }
1231                                 }
1232                                 tween = tween._next;
1233                         }
1234                         return a;
1235                 };
1236
1237                 p.getTweensOf = function(target, nested) {
1238                         var disabled = this._gc,
1239                                 a = [],
1240                                 cnt = 0,
1241                                 tweens, i;
1242                         if (disabled) {
1243                                 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.
1244                         }
1245                         tweens = TweenLite.getTweensOf(target);
1246                         i = tweens.length;
1247                         while (--i > -1) {
1248                                 if (tweens[i].timeline === this || (nested && this._contains(tweens[i]))) {
1249                                         a[cnt++] = tweens[i];
1250                                 }
1251                         }
1252                         if (disabled) {
1253                                 this._enabled(false, true);
1254                         }
1255                         return a;
1256                 };
1257
1258                 p._contains = function(tween) {
1259                         var tl = tween.timeline;
1260                         while (tl) {
1261                                 if (tl === this) {
1262                                         return true;
1263                                 }
1264                                 tl = tl.timeline;
1265                         }
1266                         return false;
1267                 };
1268
1269                 p.shiftChildren = function(amount, adjustLabels, ignoreBeforeTime) {
1270                         ignoreBeforeTime = ignoreBeforeTime || 0;
1271                         var tween = this._first,
1272                                 labels = this._labels,
1273                                 p;
1274                         while (tween) {
1275                                 if (tween._startTime >= ignoreBeforeTime) {
1276                                         tween._startTime += amount;
1277                                 }
1278                                 tween = tween._next;
1279                         }
1280                         if (adjustLabels) {
1281                                 for (p in labels) {
1282                                         if (labels[p] >= ignoreBeforeTime) {
1283                                                 labels[p] += amount;
1284                                         }
1285                                 }
1286                         }
1287                         return this._uncache(true);
1288                 };
1289
1290                 p._kill = function(vars, target) {
1291                         if (!vars && !target) {
1292                                 return this._enabled(false, false);
1293                         }
1294                         var tweens = (!target) ? this.getChildren(true, true, false) : this.getTweensOf(target),
1295                                 i = tweens.length,
1296                                 changed = false;
1297                         while (--i > -1) {
1298                                 if (tweens[i]._kill(vars, target)) {
1299                                         changed = true;
1300                                 }
1301                         }
1302                         return changed;
1303                 };
1304
1305                 p.clear = function(labels) {
1306                         var tweens = this.getChildren(false, true, true),
1307                                 i = tweens.length;
1308                         this._time = this._totalTime = 0;
1309                         while (--i > -1) {
1310                                 tweens[i]._enabled(false, false);
1311                         }
1312                         if (labels !== false) {
1313                                 this._labels = {};
1314                         }
1315                         return this._uncache(true);
1316                 };
1317
1318                 p.invalidate = function() {
1319                         var tween = this._first;
1320                         while (tween) {
1321                                 tween.invalidate();
1322                                 tween = tween._next;
1323                         }
1324                         return this;
1325                 };
1326
1327                 p._enabled = function(enabled, ignoreTimeline) {
1328                         if (enabled === this._gc) {
1329                                 var tween = this._first;
1330                                 while (tween) {
1331                                         tween._enabled(enabled, true);
1332                                         tween = tween._next;
1333                                 }
1334                         }
1335                         return SimpleTimeline.prototype._enabled.call(this, enabled, ignoreTimeline);
1336                 };
1337
1338                 p.duration = function(value) {
1339                         if (!arguments.length) {
1340                                 if (this._dirty) {
1341                                         this.totalDuration(); //just triggers recalculation
1342                                 }
1343                                 return this._duration;
1344                         }
1345                         if (this.duration() !== 0 && value !== 0) {
1346                                 this.timeScale(this._duration / value);
1347                         }
1348                         return this;
1349                 };
1350
1351                 p.totalDuration = function(value) {
1352                         if (!arguments.length) {
1353                                 if (this._dirty) {
1354                                         var max = 0,
1355                                                 tween = this._last,
1356                                                 prevStart = 999999999999,
1357                                                 prev, end;
1358                                         while (tween) {
1359                                                 prev = tween._prev; //record it here in case the tween changes position in the sequence...
1360                                                 if (tween._dirty) {
1361                                                         tween.totalDuration(); //could change the tween._startTime, so make sure the tween's cache is clean before analyzing it.
1362                                                 }
1363                                                 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
1364                                                         this.add(tween, tween._startTime - tween._delay);
1365                                                 } else {
1366                                                         prevStart = tween._startTime;
1367                                                 }
1368                                                 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.
1369                                                         max -= tween._startTime;
1370                                                         if (this._timeline.smoothChildTiming) {
1371                                                                 this._startTime += tween._startTime / this._timeScale;
1372                                                         }
1373                                                         this.shiftChildren(-tween._startTime, false, -9999999999);
1374                                                         prevStart = 0;
1375                                                 }
1376                                                 end = tween._startTime + (tween._totalDuration / tween._timeScale);
1377                                                 if (end > max) {
1378                                                         max = end;
1379                                                 }
1380                                                 tween = prev;
1381                                         }
1382                                         this._duration = this._totalDuration = max;
1383                                         this._dirty = false;
1384                                 }
1385                                 return this._totalDuration;
1386                         }
1387                         if (this.totalDuration() !== 0) if (value !== 0) {
1388                                 this.timeScale(this._totalDuration / value);
1389                         }
1390                         return this;
1391                 };
1392
1393                 p.usesFrames = function() {
1394                         var tl = this._timeline;
1395                         while (tl._timeline) {
1396                                 tl = tl._timeline;
1397                         }
1398                         return (tl === Animation._rootFramesTimeline);
1399                 };
1400
1401                 p.rawTime = function() {
1402                         return this._paused ? this._totalTime : (this._timeline.rawTime() - this._startTime) * this._timeScale;
1403                 };
1404
1405                 return TimelineLite;
1406
1407         }, true);
1408         
1409
1410
1411
1412
1413
1414
1415
1416         
1417         
1418         
1419         
1420         
1421 /*
1422  * ----------------------------------------------------------------
1423  * TimelineMax
1424  * ----------------------------------------------------------------
1425  */
1426         window._gsDefine("TimelineMax", ["TimelineLite","TweenLite","easing.Ease"], function(TimelineLite, TweenLite, Ease) {
1427
1428                 var TimelineMax = function(vars) {
1429                                 TimelineLite.call(this, vars);
1430                                 this._repeat = this.vars.repeat || 0;
1431                                 this._repeatDelay = this.vars.repeatDelay || 0;
1432                                 this._cycle = 0;
1433                                 this._yoyo = (this.vars.yoyo === true);
1434                                 this._dirty = true;
1435                         },
1436                         _tinyNum = 0.0000000001,
1437                         _blankArray = [],
1438                         _easeNone = new Ease(null, null, 1, 0),
1439                         p = TimelineMax.prototype = new TimelineLite();
1440
1441                 p.constructor = TimelineMax;
1442                 p.kill()._gc = false;
1443                 TimelineMax.version = "1.12.1";
1444
1445                 p.invalidate = function() {
1446                         this._yoyo = (this.vars.yoyo === true);
1447                         this._repeat = this.vars.repeat || 0;
1448                         this._repeatDelay = this.vars.repeatDelay || 0;
1449                         this._uncache(true);
1450                         return TimelineLite.prototype.invalidate.call(this);
1451                 };
1452
1453                 p.addCallback = function(callback, position, params, scope) {
1454                         return this.add( TweenLite.delayedCall(0, callback, params, scope), position);
1455                 };
1456
1457                 p.removeCallback = function(callback, position) {
1458                         if (callback) {
1459                                 if (position == null) {
1460                                         this._kill(null, callback);
1461                                 } else {
1462                                         var a = this.getTweensOf(callback, false),
1463                                                 i = a.length,
1464                                                 time = this._parseTimeOrLabel(position);
1465                                         while (--i > -1) {
1466                                                 if (a[i]._startTime === time) {
1467                                                         a[i]._enabled(false, false);
1468                                                 }
1469                                         }
1470                                 }
1471                         }
1472                         return this;
1473                 };
1474
1475                 p.tweenTo = function(position, vars) {
1476                         vars = vars || {};
1477                         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.
1478                                 duration, p, t;
1479                         for (p in vars) {
1480                                 copy[p] = vars[p];
1481                         }
1482                         copy.time = this._parseTimeOrLabel(position);
1483                         duration = (Math.abs(Number(copy.time) - this._time) / this._timeScale) || 0.001;
1484                         t = new TweenLite(this, duration, copy);
1485                         copy.onStart = function() {
1486                                 t.target.paused(true);
1487                                 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.
1488                                         t.duration( Math.abs( t.vars.time - t.target.time()) / t.target._timeScale );
1489                                 }
1490                                 if (vars.onStart) { //in case the user had an onStart in the vars - we don't want to overwrite it.
1491                                         vars.onStart.apply(vars.onStartScope || t, vars.onStartParams || _blankArray);
1492                                 }
1493                         };
1494                         return t;
1495                 };
1496
1497                 p.tweenFromTo = function(fromPosition, toPosition, vars) {
1498                         vars = vars || {};
1499                         fromPosition = this._parseTimeOrLabel(fromPosition);
1500                         vars.startAt = {onComplete:this.seek, onCompleteParams:[fromPosition], onCompleteScope:this};
1501                         vars.immediateRender = (vars.immediateRender !== false);
1502                         var t = this.tweenTo(toPosition, vars);
1503                         return t.duration((Math.abs( t.vars.time - fromPosition) / this._timeScale) || 0.001);
1504                 };
1505
1506                 p.render = function(time, suppressEvents, force) {
1507                         if (this._gc) {
1508                                 this._enabled(true, false);
1509                         }
1510                         var totalDur = (!this._dirty) ? this._totalDuration : this.totalDuration(),
1511                                 dur = this._duration,
1512                                 prevTime = this._time,
1513                                 prevTotalTime = this._totalTime,
1514                                 prevStart = this._startTime,
1515                                 prevTimeScale = this._timeScale,
1516                                 prevRawPrevTime = this._rawPrevTime,
1517                                 prevPaused = this._paused,
1518                                 prevCycle = this._cycle,
1519                                 tween, isComplete, next, callback, internalForce, cycleDuration;
1520                         if (time >= totalDur) {
1521                                 if (!this._locked) {
1522                                         this._totalTime = totalDur;
1523                                         this._cycle = this._repeat;
1524                                 }
1525                                 if (!this._reversed) if (!this._hasPausedChild()) {
1526                                         isComplete = true;
1527                                         callback = "onComplete";
1528                                         if (this._duration === 0) if (time === 0 || prevRawPrevTime < 0 || prevRawPrevTime === _tinyNum) if (prevRawPrevTime !== time && this._first) {
1529                                                 internalForce = true;
1530                                                 if (prevRawPrevTime > _tinyNum) {
1531                                                         callback = "onReverseComplete";
1532                                                 }
1533                                         }
1534                                 }
1535                                 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.
1536                                 if (this._yoyo && (this._cycle & 1) !== 0) {
1537                                         this._time = time = 0;
1538                                 } else {
1539                                         this._time = dur;
1540                                         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.
1541                                 }
1542
1543                         } else if (time < 0.0000001) { //to work around occasional floating point math artifacts, round super small values to 0.
1544                                 if (!this._locked) {
1545                                         this._totalTime = this._cycle = 0;
1546                                 }
1547                                 this._time = 0;
1548                                 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)
1549                                         callback = "onReverseComplete";
1550                                         isComplete = this._reversed;
1551                                 }
1552                                 if (time < 0) {
1553                                         this._active = false;
1554                                         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.
1555                                                 internalForce = true;
1556                                         }
1557                                         this._rawPrevTime = time;
1558                                 } else {
1559                                         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.
1560                                         time = 0; //to avoid occasional floating point rounding errors (could cause problems especially with zero-duration tweens at the very beginning of the timeline)
1561                                         if (!this._initted) {
1562                                                 internalForce = true;
1563                                         }
1564                                 }
1565
1566                         } else {
1567                                 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.
1568                                         internalForce = true;
1569                                 }
1570                                 this._time = this._rawPrevTime = time;
1571                                 if (!this._locked) {
1572                                         this._totalTime = time;
1573                                         if (this._repeat !== 0) {
1574                                                 cycleDuration = dur + this._repeatDelay;
1575                                                 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!)
1576                                                 if (this._cycle !== 0) if (this._cycle === this._totalTime / cycleDuration) {
1577                                                         this._cycle--; //otherwise when rendered exactly at the end time, it will act as though it is repeating (at the beginning)
1578                                                 }
1579                                                 this._time = this._totalTime - (this._cycle * cycleDuration);
1580                                                 if (this._yoyo) if ((this._cycle & 1) !== 0) {
1581                                                         this._time = dur - this._time;
1582                                                 }
1583                                                 if (this._time > dur) {
1584                                                         this._time = dur;
1585                                                         time = dur + 0.0001; //to avoid occasional floating point rounding error
1586                                                 } else if (this._time < 0) {
1587                                                         this._time = time = 0;
1588                                                 } else {
1589                                                         time = this._time;
1590                                                 }
1591                                         }
1592                                 }
1593                         }
1594
1595                         if (this._cycle !== prevCycle) if (!this._locked) {
1596                                 /*
1597                                 make sure children at the end/beginning of the timeline are rendered properly. If, for example,
1598                                 a 3-second long timeline rendered at 2.9 seconds previously, and now renders at 3.2 seconds (which
1599                                 would get transated to 2.8 seconds if the timeline yoyos or 0.2 seconds if it just repeats), there
1600                                 could be a callback or a short tween that's at 2.95 or 3 seconds in which wouldn't render. So
1601                                 we need to push the timeline to the end (and/or beginning depending on its yoyo value). Also we must
1602                                 ensure that zero-duration tweens at the very beginning or end of the TimelineMax work.
1603                                 */
1604                                 var backwards = (this._yoyo && (prevCycle & 1) !== 0),
1605                                         wrap = (backwards === (this._yoyo && (this._cycle & 1) !== 0)),
1606                                         recTotalTime = this._totalTime,
1607                                         recCycle = this._cycle,
1608                                         recRawPrevTime = this._rawPrevTime,
1609                                         recTime = this._time;
1610
1611                                 this._totalTime = prevCycle * dur;
1612                                 if (this._cycle < prevCycle) {
1613                                         backwards = !backwards;
1614                                 } else {
1615                                         this._totalTime += dur;
1616                                 }
1617                                 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.
1618
1619                                 this._rawPrevTime = (dur === 0) ? prevRawPrevTime - 0.0001 : prevRawPrevTime;
1620                                 this._cycle = prevCycle;
1621                                 this._locked = true; //prevents changes to totalTime and skips repeat/yoyo behavior when we recursively call render()
1622                                 prevTime = (backwards) ? 0 : dur;
1623                                 this.render(prevTime, suppressEvents, (dur === 0));
1624                                 if (!suppressEvents) if (!this._gc) {
1625                                         if (this.vars.onRepeat) {
1626                                                 this.vars.onRepeat.apply(this.vars.onRepeatScope || this, this.vars.onRepeatParams || _blankArray);
1627                                         }
1628                                 }
1629                                 if (wrap) {
1630                                         prevTime = (backwards) ? dur + 0.0001 : -0.0001;
1631                                         this.render(prevTime, true, false);
1632                                 }
1633                                 this._locked = false;
1634                                 if (this._paused && !prevPaused) { //if the render() triggered callback that paused this timeline, we should abort (very rare, but possible)
1635                                         return;
1636                                 }
1637                                 this._time = recTime;
1638                                 this._totalTime = recTotalTime;
1639                                 this._cycle = recCycle;
1640                                 this._rawPrevTime = recRawPrevTime;
1641                         }
1642
1643                         if ((this._time === prevTime || !this._first) && !force && !internalForce) {
1644                                 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.
1645                                         this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray);
1646                                 }
1647                                 return;
1648                         } else if (!this._initted) {
1649                                 this._initted = true;
1650                         }
1651
1652                         if (!this._active) if (!this._paused && this._totalTime !== prevTotalTime && time > 0) {
1653                                 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.
1654                         }
1655
1656                         if (prevTotalTime === 0) if (this.vars.onStart) if (this._totalTime !== 0) if (!suppressEvents) {
1657                                 this.vars.onStart.apply(this.vars.onStartScope || this, this.vars.onStartParams || _blankArray);
1658                         }
1659
1660                         if (this._time >= prevTime) {
1661                                 tween = this._first;
1662                                 while (tween) {
1663                                         next = tween._next; //record it here because the value could change after rendering...
1664                                         if (this._paused && !prevPaused) { //in case a tween pauses the timeline when rendering
1665                                                 break;
1666                                         } else if (tween._active || (tween._startTime <= this._time && !tween._paused && !tween._gc)) {
1667                                                 if (!tween._reversed) {
1668                                                         tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force);
1669                                                 } else {
1670                                                         tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force);
1671                                                 }
1672
1673                                         }
1674                                         tween = next;
1675                                 }
1676                         } else {
1677                                 tween = this._last;
1678                                 while (tween) {
1679                                         next = tween._prev; //record it here because the value could change after rendering...
1680                                         if (this._paused && !prevPaused) { //in case a tween pauses the timeline when rendering
1681                                                 break;
1682                                         } else if (tween._active || (tween._startTime <= prevTime && !tween._paused && !tween._gc)) {
1683                                                 if (!tween._reversed) {
1684                                                         tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force);
1685                                                 } else {
1686                                                         tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force);
1687                                                 }
1688                                         }
1689                                         tween = next;
1690                                 }
1691                         }
1692
1693                         if (this._onUpdate) if (!suppressEvents) {
1694                                 this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray);
1695                         }
1696                         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
1697                                 if (isComplete) {
1698                                         if (this._timeline.autoRemoveChildren) {
1699                                                 this._enabled(false, false);
1700                                         }
1701                                         this._active = false;
1702                                 }
1703                                 if (!suppressEvents && this.vars[callback]) {
1704                                         this.vars[callback].apply(this.vars[callback + "Scope"] || this, this.vars[callback + "Params"] || _blankArray);
1705                                 }
1706                         }
1707                 };
1708
1709                 p.getActive = function(nested, tweens, timelines) {
1710                         if (nested == null) {
1711                                 nested = true;
1712                         }
1713                         if (tweens == null) {
1714                                 tweens = true;
1715                         }
1716                         if (timelines == null) {
1717                                 timelines = false;
1718                         }
1719                         var a = [],
1720                                 all = this.getChildren(nested, tweens, timelines),
1721                                 cnt = 0,
1722                                 l = all.length,
1723                                 i, tween;
1724                         for (i = 0; i < l; i++) {
1725                                 tween = all[i];
1726                                 if (tween.isActive()) {
1727                                         a[cnt++] = tween;
1728                                 }
1729                         }
1730                         return a;
1731                 };
1732
1733
1734                 p.getLabelAfter = function(time) {
1735                         if (!time) if (time !== 0) { //faster than isNan()
1736                                 time = this._time;
1737                         }
1738                         var labels = this.getLabelsArray(),
1739                                 l = labels.length,
1740                                 i;
1741                         for (i = 0; i < l; i++) {
1742                                 if (labels[i].time > time) {
1743                                         return labels[i].name;
1744                                 }
1745                         }
1746                         return null;
1747                 };
1748
1749                 p.getLabelBefore = function(time) {
1750                         if (time == null) {
1751                                 time = this._time;
1752                         }
1753                         var labels = this.getLabelsArray(),
1754                                 i = labels.length;
1755                         while (--i > -1) {
1756                                 if (labels[i].time < time) {
1757                                         return labels[i].name;
1758                                 }
1759                         }
1760                         return null;
1761                 };
1762
1763                 p.getLabelsArray = function() {
1764                         var a = [],
1765                                 cnt = 0,
1766                                 p;
1767                         for (p in this._labels) {
1768                                 a[cnt++] = {time:this._labels[p], name:p};
1769                         }
1770                         a.sort(function(a,b) {
1771                                 return a.time - b.time;
1772                         });
1773                         return a;
1774                 };
1775
1776
1777 //---- GETTERS / SETTERS -------------------------------------------------------------------------------------------------------
1778
1779                 p.progress = function(value) {
1780                         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);
1781                 };
1782
1783                 p.totalProgress = function(value) {
1784                         return (!arguments.length) ? this._totalTime / this.totalDuration() : this.totalTime( this.totalDuration() * value, false);
1785                 };
1786
1787                 p.totalDuration = function(value) {
1788                         if (!arguments.length) {
1789                                 if (this._dirty) {
1790                                         TimelineLite.prototype.totalDuration.call(this); //just forces refresh
1791                                         //Instead of Infinity, we use 999999999999 so that we can accommodate reverses.
1792                                         this._totalDuration = (this._repeat === -1) ? 999999999999 : this._duration * (this._repeat + 1) + (this._repeatDelay * this._repeat);
1793                                 }
1794                                 return this._totalDuration;
1795                         }
1796                         return (this._repeat === -1) ? this : this.duration( (value - (this._repeat * this._repeatDelay)) / (this._repeat + 1) );
1797                 };
1798
1799                 p.time = function(value, suppressEvents) {
1800                         if (!arguments.length) {
1801                                 return this._time;
1802                         }
1803                         if (this._dirty) {
1804                                 this.totalDuration();
1805                         }
1806                         if (value > this._duration) {
1807                                 value = this._duration;
1808                         }
1809                         if (this._yoyo && (this._cycle & 1) !== 0) {
1810                                 value = (this._duration - value) + (this._cycle * (this._duration + this._repeatDelay));
1811                         } else if (this._repeat !== 0) {
1812                                 value += this._cycle * (this._duration + this._repeatDelay);
1813                         }
1814                         return this.totalTime(value, suppressEvents);
1815                 };
1816
1817                 p.repeat = function(value) {
1818                         if (!arguments.length) {
1819                                 return this._repeat;
1820                         }
1821                         this._repeat = value;
1822                         return this._uncache(true);
1823                 };
1824
1825                 p.repeatDelay = function(value) {
1826                         if (!arguments.length) {
1827                                 return this._repeatDelay;
1828                         }
1829                         this._repeatDelay = value;
1830                         return this._uncache(true);
1831                 };
1832
1833                 p.yoyo = function(value) {
1834                         if (!arguments.length) {
1835                                 return this._yoyo;
1836                         }
1837                         this._yoyo = value;
1838                         return this;
1839                 };
1840
1841                 p.currentLabel = function(value) {
1842                         if (!arguments.length) {
1843                                 return this.getLabelBefore(this._time + 0.00000001);
1844                         }
1845                         return this.seek(value, true);
1846                 };
1847
1848                 return TimelineMax;
1849
1850         }, true);
1851         
1852
1853
1854
1855
1856         
1857         
1858         
1859         
1860         
1861         
1862         
1863 /*
1864  * ----------------------------------------------------------------
1865  * BezierPlugin
1866  * ----------------------------------------------------------------
1867  */
1868         (function() {
1869
1870                 var _RAD2DEG = 180 / Math.PI,
1871                         _r1 = [],
1872                         _r2 = [],
1873                         _r3 = [],
1874                         _corProps = {},
1875                         Segment = function(a, b, c, d) {
1876                                 this.a = a;
1877                                 this.b = b;
1878                                 this.c = c;
1879                                 this.d = d;
1880                                 this.da = d - a;
1881                                 this.ca = c - a;
1882                                 this.ba = b - a;
1883                         },
1884                         _correlate = ",x,y,z,left,top,right,bottom,marginTop,marginLeft,marginRight,marginBottom,paddingLeft,paddingTop,paddingRight,paddingBottom,backgroundPosition,backgroundPosition_y,",
1885                         cubicToQuadratic = function(a, b, c, d) {
1886                                 var q1 = {a:a},
1887                                         q2 = {},
1888                                         q3 = {},
1889                                         q4 = {c:d},
1890                                         mab = (a + b) / 2,
1891                                         mbc = (b + c) / 2,
1892                                         mcd = (c + d) / 2,
1893                                         mabc = (mab + mbc) / 2,
1894                                         mbcd = (mbc + mcd) / 2,
1895                                         m8 = (mbcd - mabc) / 8;
1896                                 q1.b = mab + (a - mab) / 4;
1897                                 q2.b = mabc + m8;
1898                                 q1.c = q2.a = (q1.b + q2.b) / 2;
1899                                 q2.c = q3.a = (mabc + mbcd) / 2;
1900                                 q3.b = mbcd - m8;
1901                                 q4.b = mcd + (d - mcd) / 4;
1902                                 q3.c = q4.a = (q3.b + q4.b) / 2;
1903                                 return [q1, q2, q3, q4];
1904                         },
1905                         _calculateControlPoints = function(a, curviness, quad, basic, correlate) {
1906                                 var l = a.length - 1,
1907                                         ii = 0,
1908                                         cp1 = a[0].a,
1909                                         i, p1, p2, p3, seg, m1, m2, mm, cp2, qb, r1, r2, tl;
1910                                 for (i = 0; i < l; i++) {
1911                                         seg = a[ii];
1912                                         p1 = seg.a;
1913                                         p2 = seg.d;
1914                                         p3 = a[ii+1].d;
1915
1916                                         if (correlate) {
1917                                                 r1 = _r1[i];
1918                                                 r2 = _r2[i];
1919                                                 tl = ((r2 + r1) * curviness * 0.25) / (basic ? 0.5 : _r3[i] || 0.5);
1920                                                 m1 = p2 - (p2 - p1) * (basic ? curviness * 0.5 : (r1 !== 0 ? tl / r1 : 0));
1921                                                 m2 = p2 + (p3 - p2) * (basic ? curviness * 0.5 : (r2 !== 0 ? tl / r2 : 0));
1922                                                 mm = p2 - (m1 + (((m2 - m1) * ((r1 * 3 / (r1 + r2)) + 0.5) / 4) || 0));
1923                                         } else {
1924                                                 m1 = p2 - (p2 - p1) * curviness * 0.5;
1925                                                 m2 = p2 + (p3 - p2) * curviness * 0.5;
1926                                                 mm = p2 - (m1 + m2) / 2;
1927                                         }
1928                                         m1 += mm;
1929                                         m2 += mm;
1930
1931                                         seg.c = cp2 = m1;
1932                                         if (i !== 0) {
1933                                                 seg.b = cp1;
1934                                         } else {
1935                                                 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.
1936                                         }
1937
1938                                         seg.da = p2 - p1;
1939                                         seg.ca = cp2 - p1;
1940                                         seg.ba = cp1 - p1;
1941
1942                                         if (quad) {
1943                                                 qb = cubicToQuadratic(p1, cp1, cp2, p2);
1944                                                 a.splice(ii, 1, qb[0], qb[1], qb[2], qb[3]);
1945                                                 ii += 4;
1946                                         } else {
1947                                                 ii++;
1948                                         }
1949
1950                                         cp1 = m2;
1951                                 }
1952                                 seg = a[ii];
1953                                 seg.b = cp1;
1954                                 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.
1955                                 seg.da = seg.d - seg.a;
1956                                 seg.ca = seg.c - seg.a;
1957                                 seg.ba = cp1 - seg.a;
1958                                 if (quad) {
1959                                         qb = cubicToQuadratic(seg.a, cp1, seg.c, seg.d);
1960                                         a.splice(ii, 1, qb[0], qb[1], qb[2], qb[3]);
1961                                 }
1962                         },
1963                         _parseAnchors = function(values, p, correlate, prepend) {
1964                                 var a = [],
1965                                         l, i, p1, p2, p3, tmp;
1966                                 if (prepend) {
1967                                         values = [prepend].concat(values);
1968                                         i = values.length;
1969                                         while (--i > -1) {
1970                                                 if (typeof( (tmp = values[i][p]) ) === "string") if (tmp.charAt(1) === "=") {
1971                                                         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
1972                                                 }
1973                                         }
1974                                 }
1975                                 l = values.length - 2;
1976                                 if (l < 0) {
1977                                         a[0] = new Segment(values[0][p], 0, 0, values[(l < -1) ? 0 : 1][p]);
1978                                         return a;
1979                                 }
1980                                 for (i = 0; i < l; i++) {
1981                                         p1 = values[i][p];
1982                                         p2 = values[i+1][p];
1983                                         a[i] = new Segment(p1, 0, 0, p2);
1984                                         if (correlate) {
1985                                                 p3 = values[i+2][p];
1986                                                 _r1[i] = (_r1[i] || 0) + (p2 - p1) * (p2 - p1);
1987                                                 _r2[i] = (_r2[i] || 0) + (p3 - p2) * (p3 - p2);
1988                                         }
1989                                 }
1990                                 a[i] = new Segment(values[i][p], 0, 0, values[i+1][p]);
1991                                 return a;
1992                         },
1993                         bezierThrough = function(values, curviness, quadratic, basic, correlate, prepend) {
1994                                 var obj = {},
1995                                         props = [],
1996                                         first = prepend || values[0],
1997                                         i, p, a, j, r, l, seamless, last;
1998                                 correlate = (typeof(correlate) === "string") ? ","+correlate+"," : _correlate;
1999                                 if (curviness == null) {
2000                                         curviness = 1;
2001                                 }
2002                                 for (p in values[0]) {
2003                                         props.push(p);
2004                                 }
2005                                 //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)
2006                                 if (values.length > 1) {
2007                                         last = values[values.length - 1];
2008                                         seamless = true;
2009                                         i = props.length;
2010                                         while (--i > -1) {
2011                                                 p = props[i];
2012                                                 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
2013                                                         seamless = false;
2014                                                         break;
2015                                                 }
2016                                         }
2017                                         if (seamless) {
2018                                                 values = values.concat(); //duplicate the array to avoid contaminating the original which the user may be reusing for other tweens
2019                                                 if (prepend) {
2020                                                         values.unshift(prepend);
2021                                                 }
2022                                                 values.push(values[1]);
2023                                                 prepend = values[values.length - 3];
2024                                         }
2025                                 }
2026                                 _r1.length = _r2.length = _r3.length = 0;
2027                                 i = props.length;
2028                                 while (--i > -1) {
2029                                         p = props[i];
2030                                         _corProps[p] = (correlate.indexOf(","+p+",") !== -1);
2031                                         obj[p] = _parseAnchors(values, p, _corProps[p], prepend);
2032                                 }
2033                                 i = _r1.length;
2034                                 while (--i > -1) {
2035                                         _r1[i] = Math.sqrt(_r1[i]);
2036                                         _r2[i] = Math.sqrt(_r2[i]);
2037                                 }
2038                                 if (!basic) {
2039                                         i = props.length;
2040                                         while (--i > -1) {
2041                                                 if (_corProps[p]) {
2042                                                         a = obj[props[i]];
2043                                                         l = a.length - 1;
2044                                                         for (j = 0; j < l; j++) {
2045                                                                 r = a[j+1].da / _r2[j] + a[j].da / _r1[j];
2046                                                                 _r3[j] = (_r3[j] || 0) + r * r;
2047                                                         }
2048                                                 }
2049                                         }
2050                                         i = _r3.length;
2051                                         while (--i > -1) {
2052                                                 _r3[i] = Math.sqrt(_r3[i]);
2053                                         }
2054                                 }
2055                                 i = props.length;
2056                                 j = quadratic ? 4 : 1;
2057                                 while (--i > -1) {
2058                                         p = props[i];
2059                                         a = obj[p];
2060                                         _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
2061                                         if (seamless) {
2062                                                 a.splice(0, j);
2063                                                 a.splice(a.length - j, j);
2064                                         }
2065                                 }
2066                                 return obj;
2067                         },
2068                         _parseBezierData = function(values, type, prepend) {
2069                                 type = type || "soft";
2070                                 var obj = {},
2071                                         inc = (type === "cubic") ? 3 : 2,
2072                                         soft = (type === "soft"),
2073                                         props = [],
2074                                         a, b, c, d, cur, i, j, l, p, cnt, tmp;
2075                                 if (soft && prepend) {
2076                                         values = [prepend].concat(values);
2077                                 }
2078                                 if (values == null || values.length < inc + 1) { throw "invalid Bezier data"; }
2079                                 for (p in values[0]) {
2080                                         props.push(p);
2081                                 }
2082                                 i = props.length;
2083                                 while (--i > -1) {
2084                                         p = props[i];
2085                                         obj[p] = cur = [];
2086                                         cnt = 0;
2087                                         l = values.length;
2088                                         for (j = 0; j < l; j++) {
2089                                                 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);
2090                                                 if (soft) if (j > 1) if (j < l - 1) {
2091                                                         cur[cnt++] = (a + cur[cnt-2]) / 2;
2092                                                 }
2093                                                 cur[cnt++] = a;
2094                                         }
2095                                         l = cnt - inc + 1;
2096                                         cnt = 0;
2097                                         for (j = 0; j < l; j += inc) {
2098                                                 a = cur[j];
2099                                                 b = cur[j+1];
2100                                                 c = cur[j+2];
2101                                                 d = (inc === 2) ? 0 : cur[j+3];
2102                                                 cur[cnt++] = tmp = (inc === 3) ? new Segment(a, b, c, d) : new Segment(a, (2 * b + a) / 3, (2 * b + c) / 3, c);
2103                                         }
2104                                         cur.length = cnt;
2105                                 }
2106                                 return obj;
2107                         },
2108                         _addCubicLengths = function(a, steps, resolution) {
2109                                 var inc = 1 / resolution,
2110                                         j = a.length,
2111                                         d, d1, s, da, ca, ba, p, i, inv, bez, index;
2112                                 while (--j > -1) {
2113                                         bez = a[j];
2114                                         s = bez.a;
2115                                         da = bez.d - s;
2116                                         ca = bez.c - s;
2117                                         ba = bez.b - s;
2118                                         d = d1 = 0;
2119                                         for (i = 1; i <= resolution; i++) {
2120                                                 p = inc * i;
2121                                                 inv = 1 - p;
2122                                                 d = d1 - (d1 = (p * p * da + 3 * inv * (p * ca + inv * ba)) * p);
2123                                                 index = j * resolution + i - 1;
2124                                                 steps[index] = (steps[index] || 0) + d * d;
2125                                         }
2126                                 }
2127                         },
2128                         _parseLengthData = function(obj, resolution) {
2129                                 resolution = resolution >> 0 || 6;
2130                                 var a = [],
2131                                         lengths = [],
2132                                         d = 0,
2133                                         total = 0,
2134                                         threshold = resolution - 1,
2135                                         segments = [],
2136                                         curLS = [], //current length segments array
2137                                         p, i, l, index;
2138                                 for (p in obj) {
2139                                         _addCubicLengths(obj[p], a, resolution);
2140                                 }
2141                                 l = a.length;
2142                                 for (i = 0; i < l; i++) {
2143                                         d += Math.sqrt(a[i]);
2144                                         index = i % resolution;
2145                                         curLS[index] = d;
2146                                         if (index === threshold) {
2147                                                 total += d;
2148                                                 index = (i / resolution) >> 0;
2149                                                 segments[index] = curLS;
2150                                                 lengths[index] = total;
2151                                                 d = 0;
2152                                                 curLS = [];
2153                                         }
2154                                 }
2155                                 return {length:total, lengths:lengths, segments:segments};
2156                         },
2157
2158
2159
2160                         BezierPlugin = window._gsDefine.plugin({
2161                                         propName: "bezier",
2162                                         priority: -1,
2163                                         version: "1.3.2",
2164                                         API: 2,
2165                                         global:true,
2166
2167                                         //gets called when the tween renders for the first time. This is where initial values should be recorded and any setup routines should run.
2168                                         init: function(target, vars, tween) {
2169                                                 this._target = target;
2170                                                 if (vars instanceof Array) {
2171                                                         vars = {values:vars};
2172                                                 }
2173                                                 this._func = {};
2174                                                 this._round = {};
2175                                                 this._props = [];
2176                                                 this._timeRes = (vars.timeResolution == null) ? 6 : parseInt(vars.timeResolution, 10);
2177                                                 var values = vars.values || [],
2178                                                         first = {},
2179                                                         second = values[0],
2180                                                         autoRotate = vars.autoRotate || tween.vars.orientToBezier,
2181                                                         p, isFunc, i, j, prepend;
2182
2183                                                 this._autoRotate = autoRotate ? (autoRotate instanceof Array) ? autoRotate : [["x","y","rotation",((autoRotate === true) ? 0 : Number(autoRotate) || 0)]] : null;
2184                                                 for (p in second) {
2185                                                         this._props.push(p);
2186                                                 }
2187
2188                                                 i = this._props.length;
2189                                                 while (--i > -1) {
2190                                                         p = this._props[i];
2191
2192                                                         this._overwriteProps.push(p);
2193                                                         isFunc = this._func[p] = (typeof(target[p]) === "function");
2194                                                         first[p] = (!isFunc) ? parseFloat(target[p]) : target[ ((p.indexOf("set") || typeof(target["get" + p.substr(3)]) !== "function") ? p : "get" + p.substr(3)) ]();
2195                                                         if (!prepend) if (first[p] !== values[0][p]) {
2196                                                                 prepend = first;
2197                                                         }
2198                                                 }
2199                                                 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);
2200                                                 this._segCount = this._beziers[p].length;
2201
2202                                                 if (this._timeRes) {
2203                                                         var ld = _parseLengthData(this._beziers, this._timeRes);
2204                                                         this._length = ld.length;
2205                                                         this._lengths = ld.lengths;
2206                                                         this._segments = ld.segments;
2207                                                         this._l1 = this._li = this._s1 = this._si = 0;
2208                                                         this._l2 = this._lengths[0];
2209                                                         this._curSeg = this._segments[0];
2210                                                         this._s2 = this._curSeg[0];
2211                                                         this._prec = 1 / this._curSeg.length;
2212                                                 }
2213
2214                                                 if ((autoRotate = this._autoRotate)) {
2215                                                         this._initialRotations = [];
2216                                                         if (!(autoRotate[0] instanceof Array)) {
2217                                                                 this._autoRotate = autoRotate = [autoRotate];
2218                                                         }
2219                                                         i = autoRotate.length;
2220                                                         while (--i > -1) {
2221                                                                 for (j = 0; j < 3; j++) {
2222                                                                         p = autoRotate[i][j];
2223                                                                         this._func[p] = (typeof(target[p]) === "function") ? target[ ((p.indexOf("set") || typeof(target["get" + p.substr(3)]) !== "function") ? p : "get" + p.substr(3)) ] : false;
2224                                                                 }
2225                                                                 p = autoRotate[i][2];
2226                                                                 this._initialRotations[i] = this._func[p] ? this._func[p].call(this._target) : this._target[p];
2227                                                         }
2228                                                 }
2229                                                 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.
2230                                                 return true;
2231                                         },
2232
2233                                         //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.)
2234                                         set: function(v) {
2235                                                 var segments = this._segCount,
2236                                                         func = this._func,
2237                                                         target = this._target,
2238                                                         notStart = (v !== this._startRatio),
2239                                                         curIndex, inv, i, p, b, t, val, l, lengths, curSeg;
2240                                                 if (!this._timeRes) {
2241                                                         curIndex = (v < 0) ? 0 : (v >= 1) ? segments - 1 : (segments * v) >> 0;
2242                                                         t = (v - (curIndex * (1 / segments))) * segments;
2243                                                 } else {
2244                                                         lengths = this._lengths;
2245                                                         curSeg = this._curSeg;
2246                                                         v *= this._length;
2247                                                         i = this._li;
2248                                                         //find the appropriate segment (if the currently cached one isn't correct)
2249                                                         if (v > this._l2 && i < segments - 1) {
2250                                                                 l = segments - 1;
2251                                                                 while (i < l && (this._l2 = lengths[++i]) <= v) {       }
2252                                                                 this._l1 = lengths[i-1];
2253                                                                 this._li = i;
2254                                                                 this._curSeg = curSeg = this._segments[i];
2255                                                                 this._s2 = curSeg[(this._s1 = this._si = 0)];
2256                                                         } else if (v < this._l1 && i > 0) {
2257                                                                 while (i > 0 && (this._l1 = lengths[--i]) >= v) { }
2258                                                                 if (i === 0 && v < this._l1) {
2259                                                                         this._l1 = 0;
2260                                                                 } else {
2261                                                                         i++;
2262                                                                 }
2263                                                                 this._l2 = lengths[i];
2264                                                                 this._li = i;
2265                                                                 this._curSeg = curSeg = this._segments[i];
2266                                                                 this._s1 = curSeg[(this._si = curSeg.length - 1) - 1] || 0;
2267                                                                 this._s2 = curSeg[this._si];
2268                                                         }
2269                                                         curIndex = i;
2270                                                         //now find the appropriate sub-segment (we split it into the number of pieces that was defined by "precision" and measured each one)
2271                                                         v -= this._l1;
2272                                                         i = this._si;
2273                                                         if (v > this._s2 && i < curSeg.length - 1) {
2274                                                                 l = curSeg.length - 1;
2275                                                                 while (i < l && (this._s2 = curSeg[++i]) <= v) {        }
2276                                                                 this._s1 = curSeg[i-1];
2277                                                                 this._si = i;
2278                                                         } else if (v < this._s1 && i > 0) {
2279                                                                 while (i > 0 && (this._s1 = curSeg[--i]) >= v) {        }
2280                                                                 if (i === 0 && v < this._s1) {
2281                                                                         this._s1 = 0;
2282                                                                 } else {
2283                                                                         i++;
2284                                                                 }
2285                                                                 this._s2 = curSeg[i];
2286                                                                 this._si = i;
2287                                                         }
2288                                                         t = (i + (v - this._s1) / (this._s2 - this._s1)) * this._prec;
2289                                                 }
2290                                                 inv = 1 - t;
2291
2292                                                 i = this._props.length;
2293                                                 while (--i > -1) {
2294                                                         p = this._props[i];
2295                                                         b = this._beziers[p][curIndex];
2296                                                         val = (t * t * b.da + 3 * inv * (t * b.ca + inv * b.ba)) * t + b.a;
2297                                                         if (this._round[p]) {
2298                                                                 val = Math.round(val);
2299                                                         }
2300                                                         if (func[p]) {
2301                                                                 target[p](val);
2302                                                         } else {
2303                                                                 target[p] = val;
2304                                                         }
2305                                                 }
2306
2307                                                 if (this._autoRotate) {
2308                                                         var ar = this._autoRotate,
2309                                                                 b2, x1, y1, x2, y2, add, conv;
2310                                                         i = ar.length;
2311                                                         while (--i > -1) {
2312                                                                 p = ar[i][2];
2313                                                                 add = ar[i][3] || 0;
2314                                                                 conv = (ar[i][4] === true) ? 1 : _RAD2DEG;
2315                                                                 b = this._beziers[ar[i][0]];
2316                                                                 b2 = this._beziers[ar[i][1]];
2317
2318                                                                 if (b && b2) { //in case one of the properties got overwritten.
2319                                                                         b = b[curIndex];
2320                                                                         b2 = b2[curIndex];
2321
2322                                                                         x1 = b.a + (b.b - b.a) * t;
2323                                                                         x2 = b.b + (b.c - b.b) * t;
2324                                                                         x1 += (x2 - x1) * t;
2325                                                                         x2 += ((b.c + (b.d - b.c) * t) - x2) * t;
2326
2327                                                                         y1 = b2.a + (b2.b - b2.a) * t;
2328                                                                         y2 = b2.b + (b2.c - b2.b) * t;
2329                                                                         y1 += (y2 - y1) * t;
2330                                                                         y2 += ((b2.c + (b2.d - b2.c) * t) - y2) * t;
2331
2332                                                                         val = notStart ? Math.atan2(y2 - y1, x2 - x1) * conv + add : this._initialRotations[i];
2333
2334                                                                         if (func[p]) {
2335                                                                                 target[p](val);
2336                                                                         } else {
2337                                                                                 target[p] = val;
2338                                                                         }
2339                                                                 }
2340                                                         }
2341                                                 }
2342                                         }
2343                         }),
2344                         p = BezierPlugin.prototype;
2345
2346
2347                 BezierPlugin.bezierThrough = bezierThrough;
2348                 BezierPlugin.cubicToQuadratic = cubicToQuadratic;
2349                 BezierPlugin._autoCSS = true; //indicates that this plugin can be inserted into the "css" object using the autoCSS feature of TweenLite
2350                 BezierPlugin.quadraticToCubic = function(a, b, c) {
2351                         return new Segment(a, (2 * b + a) / 3, (2 * b + c) / 3, c);
2352                 };
2353
2354                 BezierPlugin._cssRegister = function() {
2355                         var CSSPlugin = window._gsDefine.globals.CSSPlugin;
2356                         if (!CSSPlugin) {
2357                                 return;
2358                         }
2359                         var _internals = CSSPlugin._internals,
2360                                 _parseToProxy = _internals._parseToProxy,
2361                                 _setPluginRatio = _internals._setPluginRatio,
2362                                 CSSPropTween = _internals.CSSPropTween;
2363                         _internals._registerComplexSpecialProp("bezier", {parser:function(t, e, prop, cssp, pt, plugin) {
2364                                 if (e instanceof Array) {
2365                                         e = {values:e};
2366                                 }
2367                                 plugin = new BezierPlugin();
2368                                 var values = e.values,
2369                                         l = values.length - 1,
2370                                         pluginValues = [],
2371                                         v = {},
2372                                         i, p, data;
2373                                 if (l < 0) {
2374                                         return pt;
2375                                 }
2376                                 for (i = 0; i <= l; i++) {
2377                                         data = _parseToProxy(t, values[i], cssp, pt, plugin, (l !== i));
2378                                         pluginValues[i] = data.end;
2379                                 }
2380                                 for (p in e) {
2381                                         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.
2382                                 }
2383                                 v.values = pluginValues;
2384                                 pt = new CSSPropTween(t, "bezier", 0, 0, data.pt, 2);
2385                                 pt.data = data;
2386                                 pt.plugin = plugin;
2387                                 pt.setRatio = _setPluginRatio;
2388                                 if (v.autoRotate === 0) {
2389                                         v.autoRotate = true;
2390                                 }
2391                                 if (v.autoRotate && !(v.autoRotate instanceof Array)) {
2392                                         i = (v.autoRotate === true) ? 0 : Number(v.autoRotate);
2393                                         v.autoRotate = (data.end.left != null) ? [["left","top","rotation",i,false]] : (data.end.x != null) ? [["x","y","rotation",i,false]] : false;
2394                                 }
2395                                 if (v.autoRotate) {
2396                                         if (!cssp._transform) {
2397                                                 cssp._enableTransforms(false);
2398                                         }
2399                                         data.autoRotate = cssp._target._gsTransform;
2400                                 }
2401                                 plugin._onInitTween(data.proxy, v, cssp._tween);
2402                                 return pt;
2403                         }});
2404                 };
2405
2406                 p._roundProps = function(lookup, value) {
2407                         var op = this._overwriteProps,
2408                                 i = op.length;
2409                         while (--i > -1) {
2410                                 if (lookup[op[i]] || lookup.bezier || lookup.bezierThrough) {
2411                                         this._round[op[i]] = value;
2412                                 }
2413                         }
2414                 };
2415
2416                 p._kill = function(lookup) {
2417                         var a = this._props,
2418                                 p, i;
2419                         for (p in this._beziers) {
2420                                 if (p in lookup) {
2421                                         delete this._beziers[p];
2422                                         delete this._func[p];
2423                                         i = a.length;
2424                                         while (--i > -1) {
2425                                                 if (a[i] === p) {
2426                                                         a.splice(i, 1);
2427                                                 }
2428                                         }
2429                                 }
2430                         }
2431                         return this._super._kill.call(this, lookup);
2432                 };
2433
2434         }());
2435
2436
2437
2438
2439
2440
2441         
2442         
2443         
2444         
2445         
2446         
2447         
2448         
2449 /*
2450  * ----------------------------------------------------------------
2451  * CSSPlugin
2452  * ----------------------------------------------------------------
2453  */
2454         window._gsDefine("plugins.CSSPlugin", ["plugins.TweenPlugin","TweenLite"], function(TweenPlugin, TweenLite) {
2455
2456                 /** @constructor **/
2457                 var CSSPlugin = function() {
2458                                 TweenPlugin.call(this, "css");
2459                                 this._overwriteProps.length = 0;
2460                                 this.setRatio = CSSPlugin.prototype.setRatio; //speed optimization (avoid prototype lookup on this "hot" method)
2461                         },
2462                         _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.
2463                         _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
2464                         _cs, //computed style (we store this in a shared variable to conserve memory and make minification tighter
2465                         _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.
2466                         _specialProps = {},
2467                         p = CSSPlugin.prototype = new TweenPlugin("css");
2468
2469                 p.constructor = CSSPlugin;
2470                 CSSPlugin.version = "1.12.1";
2471                 CSSPlugin.API = 2;
2472                 CSSPlugin.defaultTransformPerspective = 0;
2473                 CSSPlugin.defaultSkewType = "compensated";
2474                 p = "px"; //we'll reuse the "p" variable to keep file size down
2475                 CSSPlugin.suffixMap = {top:p, right:p, bottom:p, left:p, width:p, height:p, fontSize:p, padding:p, margin:p, perspective:p, lineHeight:""};
2476
2477
2478                 var _numExp = /(?:\d|\-\d|\.\d|\-\.\d)+/g,
2479                         _relNumExp = /(?:\d|\-\d|\.\d|\-\.\d|\+=\d|\-=\d|\+=.\d|\-=\.\d)+/g,
2480                         _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)"
2481                         _NaNExp = /[^\d\-\.]/g,
2482                         _suffixExp = /(?:\d|\-|\+|=|#|\.)*/g,
2483                         _opacityExp = /opacity *= *([^)]*)/i,
2484                         _opacityValExp = /opacity:([^;]*)/i,
2485                         _alphaFilterExp = /alpha\(opacity *=.+?\)/i,
2486                         _rgbhslExp = /^(rgb|hsl)/,
2487                         _capsExp = /([A-Z])/g,
2488                         _camelExp = /-([a-z])/gi,
2489                         _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)
2490                         _camelFunc = function(s, g) { return g.toUpperCase(); },
2491                         _horizExp = /(?:Left|Right|Width)/i,
2492                         _ieGetMatrixExp = /(M11|M12|M21|M22)=[\d\-\.e]+/gi,
2493                         _ieSetMatrixExp = /progid\:DXImageTransform\.Microsoft\.Matrix\(.+?\)/i,
2494                         _commasOutsideParenExp = /,(?=[^\)]*(?:\(|$))/gi, //finds any commas that are not within parenthesis
2495                         _DEG2RAD = Math.PI / 180,
2496                         _RAD2DEG = 180 / Math.PI,
2497                         _forcePT = {},
2498                         _doc = document,
2499                         _tempDiv = _doc.createElement("div"),
2500                         _tempImg = _doc.createElement("img"),
2501                         _internals = CSSPlugin._internals = {_specialProps:_specialProps}, //provides a hook to a few internal methods that we need to access from inside other plugins
2502                         _agent = navigator.userAgent,
2503                         _autoRound,
2504                         _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).
2505
2506                         _isSafari,
2507                         _isFirefox, //Firefox has a bug that causes 3D transformed elements to randomly disappear unless a repaint is forced after each update on each element.
2508                         _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!)
2509                         _ieVers,
2510                         _supportsOpacity = (function() { //we set _isSafari, _ieVers, _isFirefox, and _supportsOpacity all in one function here to reduce file size slightly, especially in the minified version.
2511                                 var i = _agent.indexOf("Android"),
2512                                         d = _doc.createElement("div"), a;
2513
2514                                 _isSafari = (_agent.indexOf("Safari") !== -1 && _agent.indexOf("Chrome") === -1 && (i === -1 || Number(_agent.substr(i+8, 1)) > 3));
2515                                 _isSafariLT6 = (_isSafari && (Number(_agent.substr(_agent.indexOf("Version/")+8, 1)) < 6));
2516                                 _isFirefox = (_agent.indexOf("Firefox") !== -1);
2517
2518                                 if ((/MSIE ([0-9]{1,}[\.0-9]{0,})/).exec(_agent)) {
2519                                         _ieVers = parseFloat( RegExp.$1 );
2520                                 }
2521
2522                                 d.innerHTML = "<a style='top:1px;opacity:.55;'>a</a>";
2523                                 a = d.getElementsByTagName("a")[0];
2524                                 return a ? /^0.55/.test(a.style.opacity) : false;
2525                         }()),
2526                         _getIEOpacity = function(v) {
2527                                 return (_opacityExp.test( ((typeof(v) === "string") ? v : (v.currentStyle ? v.currentStyle.filter : v.style.filter) || "") ) ? ( parseFloat( RegExp.$1 ) / 100 ) : 1);
2528                         },
2529                         _log = function(s) {//for logging messages, but in a way that won't throw errors in old versions of IE.
2530                                 if (window.console) {
2531                                         //console.log(s);
2532                                 }
2533                         },
2534                         _prefixCSS = "", //the non-camelCase vendor prefix like "-o-", "-moz-", "-ms-", or "-webkit-"
2535                         _prefix = "", //camelCase vendor prefix like "O", "ms", "Webkit", or "Moz".
2536
2537                         // @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)
2538                         _checkPropPrefix = function(p, e) {
2539                                 e = e || _tempDiv;
2540                                 var s = e.style,
2541                                         a, i;
2542                                 if (s[p] !== undefined) {
2543                                         return p;
2544                                 }
2545                                 p = p.charAt(0).toUpperCase() + p.substr(1);
2546                                 a = ["O","Moz","ms","Ms","Webkit"];
2547                                 i = 5;
2548                                 while (--i > -1 && s[a[i]+p] === undefined) { }
2549                                 if (i >= 0) {
2550                                         _prefix = (i === 3) ? "ms" : a[i];
2551                                         _prefixCSS = "-" + _prefix.toLowerCase() + "-";
2552                                         return _prefix + p;
2553                                 }
2554                                 return null;
2555                         },
2556
2557                         _getComputedStyle = _doc.defaultView ? _doc.defaultView.getComputedStyle : function() {},
2558
2559                         /**
2560                          * @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:
2561                          * var currentLeft = CSSPlugin.getStyle( document.getElementById("myElement"), "left");
2562                          *
2563                          * @param {!Object} t Target element whose style property you want to query
2564                          * @param {!string} p Property name (like "left" or "top" or "marginTop", etc.)
2565                          * @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.
2566                          * @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.
2567                          * @param {string=} dflt Default value that should be returned in the place of null, "none", "auto" or "auto auto".
2568                          * @return {?string} The current property value
2569                          */
2570                         _getStyle = CSSPlugin.getStyle = function(t, p, cs, calc, dflt) {
2571                                 var rv;
2572                                 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.
2573                                         return _getIEOpacity(t);
2574                                 }
2575                                 if (!calc && t.style[p]) {
2576                                         rv = t.style[p];
2577                                 } else if ((cs = cs || _getComputedStyle(t))) {
2578                                         rv = cs[p] || cs.getPropertyValue(p) || cs.getPropertyValue(p.replace(_capsExp, "-$1").toLowerCase());
2579                                 } else if (t.currentStyle) {
2580                                         rv = t.currentStyle[p];
2581                                 }
2582                                 return (dflt != null && (!rv || rv === "none" || rv === "auto" || rv === "auto auto")) ? dflt : rv;
2583                         },
2584
2585                         /**
2586                          * @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.
2587                          * @param {!Object} t Target element
2588                          * @param {!string} p Property name (like "left", "top", "marginLeft", etc.)
2589                          * @param {!number} v Value
2590                          * @param {string=} sfx Suffix (like "px" or "%" or "em")
2591                          * @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.
2592                          * @return {number} value in pixels
2593                          */
2594                         _convertToPixels = _internals.convertToPixels = function(t, p, v, sfx, recurse) {
2595                                 if (sfx === "px" || !sfx) { return v; }
2596                                 if (sfx === "auto" || !v) { return 0; }
2597                                 var horiz = _horizExp.test(p),
2598                                         node = t,
2599                                         style = _tempDiv.style,
2600                                         neg = (v < 0),
2601                                         pix, cache, time;
2602                                 if (neg) {
2603                                         v = -v;
2604                                 }
2605                                 if (sfx === "%" && p.indexOf("border") !== -1) {
2606                                         pix = (v / 100) * (horiz ? t.clientWidth : t.clientHeight);
2607                                 } else {
2608                                         style.cssText = "border:0 solid red;position:" + _getStyle(t, "position") + ";line-height:0;";
2609                                         if (sfx === "%" || !node.appendChild) {
2610                                                 node = t.parentNode || _doc.body;
2611                                                 cache = node._gsCache;
2612                                                 time = TweenLite.ticker.frame;
2613                                                 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)
2614                                                         return cache.width * v / 100;
2615                                                 }
2616                                                 style[(horiz ? "width" : "height")] = v + sfx;
2617                                         } else {
2618                                                 style[(horiz ? "borderLeftWidth" : "borderTopWidth")] = v + sfx;
2619                                         }
2620                                         node.appendChild(_tempDiv);
2621                                         pix = parseFloat(_tempDiv[(horiz ? "offsetWidth" : "offsetHeight")]);
2622                                         node.removeChild(_tempDiv);
2623                                         if (horiz && sfx === "%" && CSSPlugin.cacheWidths !== false) {
2624                                                 cache = node._gsCache = node._gsCache || {};
2625                                                 cache.time = time;
2626                                                 cache.width = pix / v * 100;
2627                                         }
2628                                         if (pix === 0 && !recurse) {
2629                                                 pix = _convertToPixels(t, p, v, sfx, true);
2630                                         }
2631                                 }
2632                                 return neg ? -pix : pix;
2633                         },
2634                         _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
2635                                 if (_getStyle(t, "position", cs) !== "absolute") { return 0; }
2636                                 var dim = ((p === "left") ? "Left" : "Top"),
2637                                         v = _getStyle(t, "margin" + dim, cs);
2638                                 return t["offset" + dim] - (_convertToPixels(t, p, parseFloat(v), v.replace(_suffixExp, "")) || 0);
2639                         },
2640
2641                         // @private returns at object containing ALL of the style properties in camelCase and their associated values.
2642                         _getAllStyles = function(t, cs) {
2643                                 var s = {},
2644                                         i, tr;
2645                                 if ((cs = cs || _getComputedStyle(t, null))) {
2646                                         if ((i = cs.length)) {
2647                                                 while (--i > -1) {
2648                                                         s[cs[i].replace(_camelExp, _camelFunc)] = cs.getPropertyValue(cs[i]);
2649                                                 }
2650                                         } else { //Opera behaves differently - cs.length is always 0, so we must do a for...in loop.
2651                                                 for (i in cs) {
2652                                                         s[i] = cs[i];
2653                                                 }
2654                                         }
2655                                 } else if ((cs = t.currentStyle || t.style)) {
2656                                         for (i in cs) {
2657                                                 if (typeof(i) === "string" && s[i] === undefined) {
2658                                                         s[i.replace(_camelExp, _camelFunc)] = cs[i];
2659                                                 }
2660                                         }
2661                                 }
2662                                 if (!_supportsOpacity) {
2663                                         s.opacity = _getIEOpacity(t);
2664                                 }
2665                                 tr = _getTransform(t, cs, false);
2666                                 s.rotation = tr.rotation;
2667                                 s.skewX = tr.skewX;
2668                                 s.scaleX = tr.scaleX;
2669                                 s.scaleY = tr.scaleY;
2670                                 s.x = tr.x;
2671                                 s.y = tr.y;
2672                                 if (_supports3D) {
2673                                         s.z = tr.z;
2674                                         s.rotationX = tr.rotationX;
2675                                         s.rotationY = tr.rotationY;
2676                                         s.scaleZ = tr.scaleZ;
2677                                 }
2678                                 if (s.filters) {
2679                                         delete s.filters;
2680                                 }
2681                                 return s;
2682                         },
2683
2684                         // @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.
2685                         _cssDif = function(t, s1, s2, vars, forceLookup) {
2686                                 var difs = {},
2687                                         style = t.style,
2688                                         val, p, mpt;
2689                                 for (p in s2) {
2690                                         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") {
2691                                                 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.
2692                                                 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.
2693                                                         mpt = new MiniPropTween(style, p, style[p], mpt);
2694                                                 }
2695                                         }
2696                                 }
2697                                 if (vars) {
2698                                         for (p in vars) { //copy properties (except className)
2699                                                 if (p !== "className") {
2700                                                         difs[p] = vars[p];
2701                                                 }
2702                                         }
2703                                 }
2704                                 return {difs:difs, firstMPT:mpt};
2705                         },
2706                         _dimensions = {width:["Left","Right"], height:["Top","Bottom"]},
2707                         _margins = ["marginLeft","marginRight","marginTop","marginBottom"],
2708
2709                         /**
2710                          * @private Gets the width or height of an element
2711                          * @param {!Object} t Target element
2712                          * @param {!string} p Property name ("width" or "height")
2713                          * @param {Object=} cs Computed style object (if one exists). Just a speed optimization.
2714                          * @return {number} Dimension (in pixels)
2715                          */
2716                         _getDimension = function(t, p, cs) {
2717                                 var v = parseFloat((p === "width") ? t.offsetWidth : t.offsetHeight),
2718                                         a = _dimensions[p],
2719                                         i = a.length;
2720                                 cs = cs || _getComputedStyle(t, null);
2721                                 while (--i > -1) {
2722                                         v -= parseFloat( _getStyle(t, "padding" + a[i], cs, true) ) || 0;
2723                                         v -= parseFloat( _getStyle(t, "border" + a[i] + "Width", cs, true) ) || 0;
2724                                 }
2725                                 return v;
2726                         },
2727
2728                         // @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)
2729                         _parsePosition = function(v, recObj) {
2730                                 if (v == null || v === "" || v === "auto" || v === "auto auto") { //note: Firefox uses "auto auto" as default whereas Chrome uses "auto".
2731                                         v = "0 0";
2732                                 }
2733                                 var a = v.split(" "),
2734                                         x = (v.indexOf("left") !== -1) ? "0%" : (v.indexOf("right") !== -1) ? "100%" : a[0],
2735                                         y = (v.indexOf("top") !== -1) ? "0%" : (v.indexOf("bottom") !== -1) ? "100%" : a[1];
2736                                 if (y == null) {
2737                                         y = "0";
2738                                 } else if (y === "center") {
2739                                         y = "50%";
2740                                 }
2741                                 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.
2742                                         x = "50%";
2743                                 }
2744                                 if (recObj) {
2745                                         recObj.oxp = (x.indexOf("%") !== -1);
2746                                         recObj.oyp = (y.indexOf("%") !== -1);
2747                                         recObj.oxr = (x.charAt(1) === "=");
2748                                         recObj.oyr = (y.charAt(1) === "=");
2749                                         recObj.ox = parseFloat(x.replace(_NaNExp, ""));
2750                                         recObj.oy = parseFloat(y.replace(_NaNExp, ""));
2751                                 }
2752                                 return x + " " + y + ((a.length > 2) ? " " + a[2] : "");
2753                         },
2754
2755                         /**
2756                          * @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!)
2757                          * @param {(number|string)} e End value which is typically a string, but could be a number
2758                          * @param {(number|string)} b Beginning value which is typically a string but could be a number
2759                          * @return {number} Amount of change between the beginning and ending values (relative values that have a "+=" or "-=" are recognized)
2760                          */
2761                         _parseChange = function(e, b) {
2762                                 return (typeof(e) === "string" && e.charAt(1) === "=") ? parseInt(e.charAt(0) + "1", 10) * parseFloat(e.substr(2)) : parseFloat(e) - parseFloat(b);
2763                         },
2764
2765                         /**
2766                          * @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.
2767                          * @param {Object} v Value to be parsed
2768                          * @param {!number} d Default value (which is also used for relative calculations if "+=" or "-=" is found in the first parameter)
2769                          * @return {number} Parsed value
2770                          */
2771                         _parseVal = function(v, d) {
2772                                 return (v == null) ? d : (typeof(v) === "string" && v.charAt(1) === "=") ? parseInt(v.charAt(0) + "1", 10) * Number(v.substr(2)) + d : parseFloat(v);
2773                         },
2774
2775                         /**
2776                          * @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.
2777                          * @param {Object} v Value to be parsed
2778                          * @param {!number} d Default value (which is also used for relative calculations if "+=" or "-=" is found in the first parameter)
2779                          * @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"
2780                          * @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.
2781                          * @return {number} parsed angle in radians
2782                          */
2783                         _parseAngle = function(v, d, p, directionalEnd) {
2784                                 var min = 0.000001,
2785                                         cap, split, dif, result;
2786                                 if (v == null) {
2787                                         result = d;
2788                                 } else if (typeof(v) === "number") {
2789                                         result = v;
2790                                 } else {
2791                                         cap = 360;
2792                                         split = v.split("_");
2793                                         dif = Number(split[0].replace(_NaNExp, "")) * ((v.indexOf("rad") === -1) ? 1 : _RAD2DEG) - ((v.charAt(1) === "=") ? 0 : d);
2794                                         if (split.length) {
2795                                                 if (directionalEnd) {
2796                                                         directionalEnd[p] = d + dif;
2797                                                 }
2798                                                 if (v.indexOf("short") !== -1) {
2799                                                         dif = dif % cap;
2800                                                         if (dif !== dif % (cap / 2)) {
2801                                                                 dif = (dif < 0) ? dif + cap : dif - cap;
2802                                                         }
2803                                                 }
2804                                                 if (v.indexOf("_cw") !== -1 && dif < 0) {
2805                                                         dif = ((dif + cap * 9999999999) % cap) - ((dif / cap) | 0) * cap;
2806                                                 } else if (v.indexOf("ccw") !== -1 && dif > 0) {
2807                                                         dif = ((dif - cap * 9999999999) % cap) - ((dif / cap) | 0) * cap;
2808                                                 }
2809                                         }
2810                                         result = d + dif;
2811                                 }
2812                                 if (result < min && result > -min) {
2813                                         result = 0;
2814                                 }
2815                                 return result;
2816                         },
2817
2818                         _colorLookup = {aqua:[0,255,255],
2819                                 lime:[0,255,0],
2820                                 silver:[192,192,192],
2821                                 black:[0,0,0],
2822                                 maroon:[128,0,0],
2823                                 teal:[0,128,128],
2824                                 blue:[0,0,255],
2825                                 navy:[0,0,128],
2826                                 white:[255,255,255],
2827                                 fuchsia:[255,0,255],
2828                                 olive:[128,128,0],
2829                                 yellow:[255,255,0],
2830                                 orange:[255,165,0],
2831                                 gray:[128,128,128],
2832                                 purple:[128,0,128],
2833                                 green:[0,128,0],
2834                                 red:[255,0,0],
2835                                 pink:[255,192,203],
2836                                 cyan:[0,255,255],
2837                                 transparent:[255,255,255,0]},
2838
2839                         _hue = function(h, m1, m2) {
2840                                 h = (h < 0) ? h + 1 : (h > 1) ? h - 1 : h;
2841                                 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;
2842                         },
2843
2844                         /**
2845                          * @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)
2846                          * @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.
2847                          * @return {Array.<number>} An array containing red, green, and blue (and optionally alpha) in that order.
2848                          */
2849                         _parseColor = function(v) {
2850                                 var c1, c2, c3, h, s, l;
2851                                 if (!v || v === "") {
2852                                         return _colorLookup.black;
2853                                 }
2854                                 if (typeof(v) === "number") {
2855                                         return [v >> 16, (v >> 8) & 255, v & 255];
2856                                 }
2857                                 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.
2858                                         v = v.substr(0, v.length - 1);
2859                                 }
2860                                 if (_colorLookup[v]) {
2861                                         return _colorLookup[v];
2862                                 }
2863                                 if (v.charAt(0) === "#") {
2864                                         if (v.length === 4) { //for shorthand like #9F0
2865                                                 c1 = v.charAt(1),
2866                                                 c2 = v.charAt(2),
2867                                                 c3 = v.charAt(3);
2868                                                 v = "#" + c1 + c1 + c2 + c2 + c3 + c3;
2869                                         }
2870                                         v = parseInt(v.substr(1), 16);
2871                                         return [v >> 16, (v >> 8) & 255, v & 255];
2872                                 }
2873                                 if (v.substr(0, 3) === "hsl") {
2874                                         v = v.match(_numExp);
2875                                         h = (Number(v[0]) % 360) / 360;
2876                                         s = Number(v[1]) / 100;
2877                                         l = Number(v[2]) / 100;
2878                                         c2 = (l <= 0.5) ? l * (s + 1) : l + s - l * s;
2879                                         c1 = l * 2 - c2;
2880                                         if (v.length > 3) {
2881                                                 v[3] = Number(v[3]);
2882                                         }
2883                                         v[0] = _hue(h + 1 / 3, c1, c2);
2884                                         v[1] = _hue(h, c1, c2);
2885                                         v[2] = _hue(h - 1 / 3, c1, c2);
2886                                         return v;
2887                                 }
2888                                 v = v.match(_numExp) || _colorLookup.transparent;
2889                                 v[0] = Number(v[0]);
2890                                 v[1] = Number(v[1]);
2891                                 v[2] = Number(v[2]);
2892                                 if (v.length > 3) {
2893                                         v[3] = Number(v[3]);
2894                                 }
2895                                 return v;
2896                         },
2897                         _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.
2898
2899                 for (p in _colorLookup) {
2900                         _colorExp += "|" + p + "\\b";
2901                 }
2902                 _colorExp = new RegExp(_colorExp+")", "gi");
2903
2904                 /**
2905                  * @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.
2906                  * @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.
2907                  * @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.
2908                  * @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.
2909                  * @return {Function} formatter function
2910                  */
2911                 var _getFormatter = function(dflt, clr, collapsible, multi) {
2912                                 if (dflt == null) {
2913                                         return function(v) {return v;};
2914                                 }
2915                                 var dColor = clr ? (dflt.match(_colorExp) || [""])[0] : "",
2916                                         dVals = dflt.split(dColor).join("").match(_valuesExp) || [],
2917                                         pfx = dflt.substr(0, dflt.indexOf(dVals[0])),
2918                                         sfx = (dflt.charAt(dflt.length - 1) === ")") ? ")" : "",
2919                                         delim = (dflt.indexOf(" ") !== -1) ? " " : ",",
2920                                         numVals = dVals.length,
2921                                         dSfx = (numVals > 0) ? dVals[0].replace(_numExp, "") : "",
2922                                         formatter;
2923                                 if (!numVals) {
2924                                         return function(v) {return v;};
2925                                 }
2926                                 if (clr) {
2927                                         formatter = function(v) {
2928                                                 var color, vals, i, a;
2929                                                 if (typeof(v) === "number") {
2930                                                         v += dSfx;
2931                                                 } else if (multi && _commasOutsideParenExp.test(v)) {
2932                                                         a = v.replace(_commasOutsideParenExp, "|").split("|");
2933                                                         for (i = 0; i < a.length; i++) {
2934                                                                 a[i] = formatter(a[i]);
2935                                                         }
2936                                                         return a.join(",");
2937                                                 }
2938                                                 color = (v.match(_colorExp) || [dColor])[0];
2939                                                 vals = v.split(color).join("").match(_valuesExp) || [];
2940                                                 i = vals.length;
2941                                                 if (numVals > i--) {
2942                                                         while (++i < numVals) {
2943                                                                 vals[i] = collapsible ? vals[(((i - 1) / 2) | 0)] : dVals[i];
2944                                                         }
2945                                                 }
2946                                                 return pfx + vals.join(delim) + delim + color + sfx + (v.indexOf("inset") !== -1 ? " inset" : "");
2947                                         };
2948                                         return formatter;
2949
2950                                 }
2951                                 formatter = function(v) {
2952                                         var vals, a, i;
2953                                         if (typeof(v) === "number") {
2954                                                 v += dSfx;
2955                                         } else if (multi && _commasOutsideParenExp.test(v)) {
2956                                                 a = v.replace(_commasOutsideParenExp, "|").split("|");
2957                                                 for (i = 0; i < a.length; i++) {
2958                                                         a[i] = formatter(a[i]);
2959                                                 }
2960                                                 return a.join(",");
2961                                         }
2962                                         vals = v.match(_valuesExp) || [];
2963                                         i = vals.length;
2964                                         if (numVals > i--) {
2965                                                 while (++i < numVals) {
2966                                                         vals[i] = collapsible ? vals[(((i - 1) / 2) | 0)] : dVals[i];
2967                                                 }
2968                                         }
2969                                         return pfx + vals.join(delim) + sfx;
2970                                 };
2971                                 return formatter;
2972                         },
2973
2974                         /**
2975                          * @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.
2976                          * @param {!string} props a comma-delimited list of property names in order from top to left, like "marginTop,marginRight,marginBottom,marginLeft"
2977                          * @return {Function} a formatter function
2978                          */
2979                         _getEdgeParser = function(props) {
2980                                 props = props.split(",");
2981                                 return function(t, e, p, cssp, pt, plugin, vars) {
2982                                         var a = (e + "").split(" "),
2983                                                 i;
2984                                         vars = {};
2985                                         for (i = 0; i < 4; i++) {
2986                                                 vars[props[i]] = a[i] = a[i] || a[(((i - 1) / 2) >> 0)];
2987                                         }
2988                                         return cssp.parse(t, vars, pt, plugin);
2989                                 };
2990                         },
2991
2992                         // @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.
2993                         _setPluginRatio = _internals._setPluginRatio = function(v) {
2994                                 this.plugin.setRatio(v);
2995                                 var d = this.data,
2996                                         proxy = d.proxy,
2997                                         mpt = d.firstMPT,
2998                                         min = 0.000001,
2999                                         val, pt, i, str;
3000                                 while (mpt) {
3001                                         val = proxy[mpt.v];
3002                                         if (mpt.r) {
3003                                                 val = Math.round(val);
3004                                         } else if (val < min && val > -min) {
3005                                                 val = 0;
3006                                         }
3007                                         mpt.t[mpt.p] = val;
3008                                         mpt = mpt._next;
3009                                 }
3010                                 if (d.autoRotate) {
3011                                         d.autoRotate.rotation = proxy.rotation;
3012                                 }
3013                                 //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.
3014                                 if (v === 1) {
3015                                         mpt = d.firstMPT;
3016                                         while (mpt) {
3017                                                 pt = mpt.t;
3018                                                 if (!pt.type) {
3019                                                         pt.e = pt.s + pt.xs0;
3020                                                 } else if (pt.type === 1) {
3021                                                         str = pt.xs0 + pt.s + pt.xs1;
3022                                                         for (i = 1; i < pt.l; i++) {
3023                                                                 str += pt["xn"+i] + pt["xs"+(i+1)];
3024                                                         }
3025                                                         pt.e = str;
3026                                                 }
3027                                                 mpt = mpt._next;
3028                                         }
3029                                 }
3030                         },
3031
3032                         /**
3033                          * @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.
3034                          * @param {!Object} t target object whose property we're tweening (often a CSSPropTween)
3035                          * @param {!string} p property name
3036                          * @param {(number|string|object)} v value
3037                          * @param {MiniPropTween=} next next MiniPropTween in the linked list
3038                          * @param {boolean=} r if true, the tweened value should be rounded to the nearest integer
3039                          */
3040                         MiniPropTween = function(t, p, v, next, r) {
3041                                 this.t = t;
3042                                 this.p = p;
3043                                 this.v = v;
3044                                 this.r = r;
3045                                 if (next) {
3046                                         next._prev = this;
3047                                         this._next = next;
3048                                 }
3049                         },
3050
3051                         /**
3052                          * @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.
3053                          * This method returns an object that has the following properties:
3054                          *  - 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
3055                          *  - 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
3056                          *  - firstMPT: the first MiniPropTween in the linked list
3057                          *  - 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.
3058                          * @param {!Object} t target object to be tweened
3059                          * @param {!(Object|string)} vars the object containing the information about the tweening values (typically the end/destination values) that should be parsed
3060                          * @param {!CSSPlugin} cssp The CSSPlugin instance
3061                          * @param {CSSPropTween=} pt the next CSSPropTween in the linked list
3062                          * @param {TweenPlugin=} plugin the external TweenPlugin instance that will be handling tweening the numeric values
3063                          * @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.
3064                          * @return An object containing the following properties: proxy, end, firstMPT, and pt (see above for descriptions)
3065                          */
3066                         _parseToProxy = _internals._parseToProxy = function(t, vars, cssp, pt, plugin, shallow) {
3067                                 var bpt = pt,
3068                                         start = {},
3069                                         end = {},
3070                                         transform = cssp._transform,
3071                                         oldForce = _forcePT,
3072                                         i, p, xp, mpt, firstPT;
3073                                 cssp._transform = null;
3074                                 _forcePT = vars;
3075                                 pt = firstPT = cssp.parse(t, vars, pt, plugin);
3076                                 _forcePT = oldForce;
3077                                 //break off from the linked list so the new ones are isolated.
3078                                 if (shallow) {
3079                                         cssp._transform = transform;
3080                                         if (bpt) {
3081                                                 bpt._prev = null;
3082                                                 if (bpt._prev) {
3083                                                         bpt._prev._next = null;
3084                                                 }
3085                                         }
3086                                 }
3087                                 while (pt && pt !== bpt) {
3088                                         if (pt.type <= 1) {
3089                                                 p = pt.p;
3090                                                 end[p] = pt.s + pt.c;
3091                                                 start[p] = pt.s;
3092                                                 if (!shallow) {
3093                                                         mpt = new MiniPropTween(pt, "s", p, mpt, pt.r);
3094                                                         pt.c = 0;
3095                                                 }
3096                                                 if (pt.type === 1) {
3097                                                         i = pt.l;
3098                                                         while (--i > 0) {
3099                                                                 xp = "xn" + i;
3100                                                                 p = pt.p + "_" + xp;
3101                                                                 end[p] = pt.data[xp];
3102                                                                 start[p] = pt[xp];
3103                                                                 if (!shallow) {
3104                                                                         mpt = new MiniPropTween(pt, xp, p, mpt, pt.rxp[xp]);
3105                                                                 }
3106                                                         }
3107                                                 }
3108                                         }
3109                                         pt = pt._next;
3110                                 }
3111                                 return {proxy:start, end:end, firstMPT:mpt, pt:firstPT};
3112                         },
3113
3114
3115
3116                         /**
3117                          * @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.
3118                          * CSSPropTweens have the following optional properties as well (not defined through the constructor):
3119                          *  - 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.
3120                          *  - 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)
3121                          *  - 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.
3122                          *  - 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.
3123                          *  - 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.
3124                          * @param {!Object} t Target object whose property will be tweened. Often a DOM element, but not always. It could be anything.
3125                          * @param {string} p Property to tween (name). For example, to tween element.width, p would be "width".
3126                          * @param {number} s Starting numeric value
3127                          * @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.
3128                          * @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.
3129                          * @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.
3130                          * @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"
3131                          * @param {boolean=} r If true, the value(s) should be rounded
3132                          * @param {number=} pr Priority in the linked list order. Higher priority CSSPropTweens will be updated before lower priority ones. The default priority is 0.
3133                          * @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.
3134                          * @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.
3135                          */
3136                         CSSPropTween = _internals.CSSPropTween = function(t, p, s, c, next, type, n, r, pr, b, e) {
3137                                 this.t = t; //target
3138                                 this.p = p; //property
3139                                 this.s = s; //starting value
3140                                 this.c = c; //change value
3141                                 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)
3142                                 if (!(t instanceof CSSPropTween)) {
3143                                         _overwriteProps.push(this.n);
3144                                 }
3145                                 this.r = r; //round (boolean)
3146                                 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
3147                                 if (pr) {
3148                                         this.pr = pr;
3149                                         _hasPriority = true;
3150                                 }
3151                                 this.b = (b === undefined) ? s : b;
3152                                 this.e = (e === undefined) ? s + c : e;
3153                                 if (next) {
3154                                         this._next = next;
3155                                         next._prev = this;
3156                                 }
3157                         },
3158
3159                         /**
3160                          * 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:
3161                          * 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);
3162                          * 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().
3163                          * 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.
3164                          *
3165                          * @param {!Object} t Target whose property will be tweened
3166                          * @param {!string} p Property that will be tweened (its name, like "left" or "backgroundColor" or "boxShadow")
3167                          * @param {string} b Beginning value
3168                          * @param {string} e Ending value
3169                          * @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)
3170                          * @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
3171                          * @param {?CSSPropTween} pt CSSPropTween instance that is the current head of the linked list (we'll prepend to this).
3172                          * @param {number=} pr Priority in the linked list order. Higher priority properties will be updated before lower priority ones. The default priority is 0.
3173                          * @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}
3174                          * @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.
3175                          * @return {CSSPropTween} The first CSSPropTween in the linked list which includes the new one(s) added by the parseComplex() call.
3176                          */
3177                         _parseComplex = CSSPlugin.parseComplex = function(t, p, b, e, clrs, dflt, pt, pr, plugin, setRatio) {
3178                                 //DEBUG: _log("parseComplex: "+p+", b: "+b+", e: "+e);
3179                                 b = b || dflt || "";
3180                                 pt = new CSSPropTween(t, p, 0, 0, pt, (setRatio ? 2 : 1), null, false, pr, b, e);
3181                                 e += ""; //ensures it's a string
3182                                 var ba = b.split(", ").join(",").split(" "), //beginning array
3183                                         ea = e.split(", ").join(",").split(" "), //ending array
3184                                         l = ba.length,
3185                                         autoRound = (_autoRound !== false),
3186                                         i, xi, ni, bv, ev, bnums, enums, bn, rgba, temp, cv, str;
3187                                 if (e.indexOf(",") !== -1 || b.indexOf(",") !== -1) {
3188                                         ba = ba.join(" ").replace(_commasOutsideParenExp, ", ").split(" ");
3189                                         ea = ea.join(" ").replace(_commasOutsideParenExp, ", ").split(" ");
3190                                         l = ba.length;
3191                                 }
3192                                 if (l !== ea.length) {
3193                                         //DEBUG: _log("mismatched formatting detected on " + p + " (" + b + " vs " + e + ")");
3194                                         ba = (dflt || "").split(" ");
3195                                         l = ba.length;
3196                                 }
3197                                 pt.plugin = plugin;
3198                                 pt.setRatio = setRatio;
3199                                 for (i = 0; i < l; i++) {
3200                                         bv = ba[i];
3201                                         ev = ea[i];
3202                                         bn = parseFloat(bv);
3203
3204                                         //if the value begins with a number (most common). It's fine if it has a suffix like px
3205                                         if (bn || bn === 0) {
3206                                                 pt.appendXtra("", bn, _parseChange(ev, bn), ev.replace(_relNumExp, ""), (autoRound && ev.indexOf("px") !== -1), true);
3207
3208                                         //if the value is a color
3209                                         } else if (clrs && (bv.charAt(0) === "#" || _colorLookup[bv] || _rgbhslExp.test(bv))) {
3210                                                 str = ev.charAt(ev.length - 1) === "," ? ")," : ")"; //if there's a comma at the end, retain it.
3211                                                 bv = _parseColor(bv);
3212                                                 ev = _parseColor(ev);
3213                                                 rgba = (bv.length + ev.length > 6);
3214                                                 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
3215                                                         pt["xs" + pt.l] += pt.l ? " transparent" : "transparent";
3216                                                         pt.e = pt.e.split(ea[i]).join("transparent");
3217                                                 } else {
3218                                                         if (!_supportsOpacity) { //old versions of IE don't support rgba().
3219                                                                 rgba = false;
3220                                                         }
3221                                                         pt.appendXtra((rgba ? "rgba(" : "rgb("), bv[0], ev[0] - bv[0], ",", true, true)
3222                                                                 .appendXtra("", bv[1], ev[1] - bv[1], ",", true)
3223                                                                 .appendXtra("", bv[2], ev[2] - bv[2], (rgba ? "," : str), true);
3224                                                         if (rgba) {
3225                                                                 bv = (bv.length < 4) ? 1 : bv[3];
3226                                                                 pt.appendXtra("", bv, ((ev.length < 4) ? 1 : ev[3]) - bv, str, false);
3227                                                         }
3228                                                 }
3229
3230                                         } else {
3231                                                 bnums = bv.match(_numExp); //gets each group of numbers in the beginning value string and drops them into an array
3232
3233                                                 //if no number is found, treat it as a non-tweening value and just append the string to the current xs.
3234                                                 if (!bnums) {
3235                                                         pt["xs" + pt.l] += pt.l ? " " + bv : bv;
3236
3237                                                 //loop through all the numbers that are found and construct the extra values on the pt.
3238                                                 } else {
3239                                                         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
3240                                                         if (!enums || enums.length !== bnums.length) {
3241                                                                 //DEBUG: _log("mismatched formatting detected on " + p + " (" + b + " vs " + e + ")");
3242                                                                 return pt;
3243                                                         }
3244                                                         ni = 0;
3245                                                         for (xi = 0; xi < bnums.length; xi++) {
3246                                                                 cv = bnums[xi];
3247                                                                 temp = bv.indexOf(cv, ni);
3248                                                                 pt.appendXtra(bv.substr(ni, temp - ni), Number(cv), _parseChange(enums[xi], cv), "", (autoRound && bv.substr(temp + cv.length, 2) === "px"), (xi === 0));
3249                                                                 ni = temp + cv.length;
3250                                                         }
3251                                                         pt["xs" + pt.l] += bv.substr(ni);
3252                                                 }
3253                                         }
3254                                 }
3255                                 //if there are relative values ("+=" or "-=" prefix), we need to adjust the ending value to eliminate the prefixes and combine the values properly.
3256                                 if (e.indexOf("=") !== -1) if (pt.data) {
3257                                         str = pt.xs0 + pt.data.s;
3258                                         for (i = 1; i < pt.l; i++) {
3259                                                 str += pt["xs" + i] + pt.data["xn" + i];
3260                                         }
3261                                         pt.e = str + pt["xs" + i];
3262                                 }
3263                                 if (!pt.l) {
3264                                         pt.type = -1;
3265                                         pt.xs0 = pt.e;
3266                                 }
3267                                 return pt.xfirst || pt;
3268                         },
3269                         i = 9;
3270
3271
3272                 p = CSSPropTween.prototype;
3273                 p.l = p.pr = 0; //length (number of extra properties like xn1, xn2, xn3, etc.
3274                 while (--i > 0) {
3275                         p["xn" + i] = 0;
3276                         p["xs" + i] = "";
3277                 }
3278                 p.xs0 = "";
3279                 p._next = p._prev = p.xfirst = p.data = p.plugin = p.setRatio = p.rxp = null;
3280
3281
3282                 /**
3283                  * 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:
3284                  * xs0:"rect(", s:10, xs1:"px, ", xn1:5, xs2:"px, ", xn2:0, xs3:"px, ", xn3:20, xn4:"px)"
3285                  * And they'd all get joined together when the CSSPlugin renders (in the setRatio() method).
3286                  * @param {string=} pfx Prefix (if any)
3287                  * @param {!number} s Starting value
3288                  * @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.
3289                  * @param {string=} sfx Suffix (if any)
3290                  * @param {boolean=} r Round (if true).
3291                  * @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.
3292                  * @return {CSSPropTween} returns itself so that multiple methods can be chained together.
3293                  */
3294                 p.appendXtra = function(pfx, s, c, sfx, r, pad) {
3295                         var pt = this,
3296                                 l = pt.l;
3297                         pt["xs" + l] += (pad && l) ? " " + pfx : pfx || "";
3298                         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!
3299                                 pt["xs" + l] += s + (sfx || "");
3300                                 return pt;
3301                         }
3302                         pt.l++;
3303                         pt.type = pt.setRatio ? 2 : 1;
3304                         pt["xs" + pt.l] = sfx || "";
3305                         if (l > 0) {
3306                                 pt.data["xn" + l] = s + c;
3307                                 pt.rxp["xn" + l] = r; //round extra property (we need to tap into this in the _parseToProxy() method)
3308                                 pt["xn" + l] = s;
3309                                 if (!pt.plugin) {
3310                                         pt.xfirst = new CSSPropTween(pt, "xn" + l, s, c, pt.xfirst || pt, 0, pt.n, r, pt.pr);
3311                                         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.
3312                                 }
3313                                 return pt;
3314                         }
3315                         pt.data = {s:s + c};
3316                         pt.rxp = {};
3317                         pt.s = s;
3318                         pt.c = c;
3319                         pt.r = r;
3320                         return pt;
3321                 };
3322
3323                 /**
3324                  * @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.
3325                  * @param {!string} p Property name (like "boxShadow" or "throwProps")
3326                  * @param {Object=} options An object containing any of the following configuration options:
3327                  *                      - defaultValue: the default value
3328                  *                      - 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)
3329                  *                      - 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.)
3330                  *                      - prefix: if true, we'll determine whether or not this property requires a vendor prefix (like Webkit or Moz or ms or O)
3331                  *                      - color: set this to true if the value for this SpecialProp may contain color-related values like rgb(), rgba(), etc.
3332                  *                      - priority: priority in the linked list order. Higher priority SpecialProps will be updated before lower priority ones. The default priority is 0.
3333                  *                      - multi: if true, the formatter should accommodate a comma-delimited list of values, like boxShadow could have multiple boxShadows listed out.
3334                  *                      - 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.
3335                  *                      - 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).
3336                  */
3337                 var SpecialProp = function(p, options) {
3338                                 options = options || {};
3339                                 this.p = options.prefix ? _checkPropPrefix(p) || p : p;
3340                                 _specialProps[p] = _specialProps[this.p] = this;
3341                                 this.format = options.formatter || _getFormatter(options.defaultValue, options.color, options.collapsible, options.multi);
3342                                 if (options.parser) {
3343                                         this.parse = options.parser;
3344                                 }
3345                                 this.clrs = options.color;
3346                                 this.multi = options.multi;
3347                                 this.keyword = options.keyword;
3348                                 this.dflt = options.defaultValue;
3349                                 this.pr = options.priority || 0;
3350                         },
3351
3352                         //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.
3353                         _registerComplexSpecialProp = _internals._registerComplexSpecialProp = function(p, options, defaults) {
3354                                 if (typeof(options) !== "object") {
3355                                         options = {parser:defaults}; //to make backwards compatible with older versions of BezierPlugin and ThrowPropsPlugin
3356                                 }
3357                                 var a = p.split(","),
3358                                         d = options.defaultValue,
3359                                         i, temp;
3360                                 defaults = defaults || [d];
3361                                 for (i = 0; i < a.length; i++) {
3362                                         options.prefix = (i === 0 && options.prefix);
3363                                         options.defaultValue = defaults[i] || d;
3364                                         temp = new SpecialProp(a[i], options);
3365                                 }
3366                         },
3367
3368                         //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.
3369                         _registerPluginProp = function(p) {
3370                                 if (!_specialProps[p]) {
3371                                         var pluginName = p.charAt(0).toUpperCase() + p.substr(1) + "Plugin";
3372                                         _registerComplexSpecialProp(p, {parser:function(t, e, p, cssp, pt, plugin, vars) {
3373                                                 var pluginClass = (window.GreenSockGlobals || window).com.greensock.plugins[pluginName];
3374                                                 if (!pluginClass) {
3375                                                         _log("Error: " + pluginName + " js file not loaded.");
3376                                                         return pt;
3377                                                 }
3378                                                 pluginClass._cssRegister();
3379                                                 return _specialProps[p].parse(t, e, p, cssp, pt, plugin, vars);
3380                                         }});
3381                                 }
3382                         };
3383
3384
3385                 p = SpecialProp.prototype;
3386
3387                 /**
3388                  * 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)
3389                  * @param {!Object} t target element
3390                  * @param {(string|number|object)} b beginning value
3391                  * @param {(string|number|object)} e ending (destination) value
3392                  * @param {CSSPropTween=} pt next CSSPropTween in the linked list
3393                  * @param {TweenPlugin=} plugin If another plugin will be tweening the complex value, that TweenPlugin instance goes here.
3394                  * @param {function=} setRatio If a custom setRatio() method should be used to handle this complex value, that goes here.
3395                  * @return {CSSPropTween=} First CSSPropTween in the linked list
3396                  */
3397                 p.parseComplex = function(t, b, e, pt, plugin, setRatio) {
3398                         var kwd = this.keyword,
3399                                 i, ba, ea, l, bi, ei;
3400                         //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)
3401                         if (this.multi) if (_commasOutsideParenExp.test(e) || _commasOutsideParenExp.test(b)) {
3402                                 ba = b.replace(_commasOutsideParenExp, "|").split("|");
3403                                 ea = e.replace(_commasOutsideParenExp, "|").split("|");
3404                         } else if (kwd) {
3405                                 ba = [b];
3406                                 ea = [e];
3407                         }
3408                         if (ea) {
3409                                 l = (ea.length > ba.length) ? ea.length : ba.length;
3410                                 for (i = 0; i < l; i++) {
3411                                         b = ba[i] = ba[i] || this.dflt;
3412                                         e = ea[i] = ea[i] || this.dflt;
3413                                         if (kwd) {
3414                                                 bi = b.indexOf(kwd);
3415                                                 ei = e.indexOf(kwd);
3416                                                 if (bi !== ei) {
3417                                                         e = (ei === -1) ? ea : ba;
3418                                                         e[i] += " " + kwd;
3419                                                 }
3420                                         }
3421                                 }
3422                                 b = ba.join(", ");
3423                                 e = ea.join(", ");
3424                         }
3425                         return _parseComplex(t, this.p, b, e, this.clrs, this.dflt, pt, this.pr, plugin, setRatio);
3426                 };
3427
3428                 /**
3429                  * 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:
3430                  * this._firstPT = sp.parse(element, "5px 10px 20px rgb(2550,102,51)", "boxShadow", this);
3431                  * 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).
3432                  * @param {!Object} t Target object whose property is being tweened
3433                  * @param {Object} e End value as provided in the vars object (typically a string, but not always - like a throwProps would be an object).
3434                  * @param {!string} p Property name
3435                  * @param {!CSSPlugin} cssp The CSSPlugin instance that should be associated with this tween.
3436                  * @param {?CSSPropTween} pt The CSSPropTween that is the current head of the linked list (we'll prepend to it)
3437                  * @param {TweenPlugin=} plugin If a plugin will be used to tween the parsed value, this is the plugin instance.
3438                  * @param {Object=} vars Original vars object that contains the data for parsing.
3439                  * @return {CSSPropTween} The first CSSPropTween in the linked list which includes the new one(s) added by the parse() call.
3440                  */
3441                 p.parse = function(t, e, p, cssp, pt, plugin, vars) {
3442                         return this.parseComplex(t.style, this.format(_getStyle(t, this.p, _cs, false, this.dflt)), this.format(e), pt, plugin);
3443                 };
3444
3445                 /**
3446                  * 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:
3447                  *  1) Target object whose property should be tweened (typically a DOM element)
3448                  *  2) The end/destination value (could be a string, number, object, or whatever you want)
3449                  *  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)
3450                  *
3451                  * 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:
3452                  *
3453                  * CSSPlugin.registerSpecialProp("myCustomProp", function(target, value, tween) {
3454                  *      var start = target.style.width;
3455                  *      return function(ratio) {
3456                  *              target.style.width = (start + value * ratio) + "px";
3457                  *              console.log("set width to " + target.style.width);
3458                  *          }
3459                  * }, 0);
3460                  *
3461                  * Then, when I do this tween, it will trigger my special property:
3462                  *
3463                  * TweenLite.to(element, 1, {css:{myCustomProp:100}});
3464                  *
3465                  * In the example, of course, we're just changing the width, but you can do anything you want.
3466                  *
3467                  * @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}})
3468                  * @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.
3469                  * @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.
3470                  */
3471                 CSSPlugin.registerSpecialProp = function(name, onInitTween, priority) {
3472                         _registerComplexSpecialProp(name, {parser:function(t, e, p, cssp, pt, plugin, vars) {
3473                                 var rv = new CSSPropTween(t, p, 0, 0, pt, 2, p, false, priority);
3474                                 rv.plugin = plugin;
3475                                 rv.setRatio = onInitTween(t, e, cssp._tween, p);
3476                                 return rv;
3477                         }, priority:priority});
3478                 };
3479
3480
3481
3482
3483
3484
3485
3486
3487                 //transform-related methods and properties
3488                 var _transformProps = ("scaleX,scaleY,scaleZ,x,y,z,skewX,skewY,rotation,rotationX,rotationY,perspective").split(","),
3489                         _transformProp = _checkPropPrefix("transform"), //the Javascript (camelCase) transform property, like msTransform, WebkitTransform, MozTransform, or OTransform.
3490                         _transformPropCSS = _prefixCSS + "transform",
3491                         _transformOriginProp = _checkPropPrefix("transformOrigin"),
3492                         _supports3D = (_checkPropPrefix("perspective") !== null),
3493                         Transform = _internals.Transform = function() {
3494                                 this.skewY = 0;
3495                         },
3496
3497                         /**
3498                          * 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.
3499                          * @param {!Object} t target element
3500                          * @param {Object=} cs computed style object (optional)
3501                          * @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...}
3502                          * @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)
3503                          * @return {object} object containing all of the transform properties/values like {x:0, y:0, z:0, scaleX:1...}
3504                          */
3505                         _getTransform = _internals.getTransform = function(t, cs, rec, parse) {
3506                                 if (t._gsTransform && rec && !parse) {
3507                                         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.
3508                                 }
3509                                 var tm = rec ? t._gsTransform || new Transform() : new Transform(),
3510                                         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.
3511                                         min = 0.00002,
3512                                         rnd = 100000,
3513                                         minAngle = 179.99,
3514                                         minPI = minAngle * _DEG2RAD,
3515                                         zOrigin = _supports3D ? parseFloat(_getStyle(t, _transformOriginProp, cs, false, "0 0 0").split(" ")[2]) || tm.zOrigin  || 0 : 0,
3516                                         s, m, i, n, dec, scaleX, scaleY, rotation, skewX, difX, difY, difR, difS;
3517                                 if (_transformProp) {
3518                                         s = _getStyle(t, _transformPropCSS, cs, true);
3519                                 } else if (t.currentStyle) {
3520                                         //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.
3521                                         s = t.currentStyle.filter.match(_ieGetMatrixExp);
3522                                         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(",") : "";
3523                                 }
3524                                 //split the matrix values out into an array (m for matrix)
3525                                 m = (s || "").match(/(?:\-|\b)[\d\-\.e]+\b/gi) || [];
3526                                 i = m.length;
3527                                 while (--i > -1) {
3528                                         n = Number(m[i]);
3529                                         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).
3530                                 }
3531                                 if (m.length === 16) {
3532
3533                                         //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)
3534                                         var a13 = m[8], a23 = m[9], a33 = m[10],
3535                                                 a14 = m[12], a24 = m[13], a34 = m[14];
3536
3537                                         //we manually compensate for non-zero z component of transformOrigin to work around bugs in Safari
3538                                         if (tm.zOrigin) {
3539                                                 a34 = -tm.zOrigin;
3540                                                 a14 = a13*a34-m[12];
3541                                                 a24 = a23*a34-m[13];
3542                                                 a34 = a33*a34+tm.zOrigin-m[14];
3543                                         }
3544
3545                                         //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.
3546                                         if (!rec || parse || tm.rotationX == null) {
3547                                                 var a11 = m[0], a21 = m[1], a31 = m[2], a41 = m[3],
3548                                                         a12 = m[4], a22 = m[5], a32 = m[6], a42 = m[7],
3549                                                         a43 = m[11],
3550                                                         angle = Math.atan2(a32, a33),
3551                                                         xFlip = (angle < -minPI || angle > minPI),
3552                                                         t1, t2, t3, cos, sin, yFlip, zFlip;
3553                                                 tm.rotationX = angle * _RAD2DEG;
3554                                                 //rotationX
3555                                                 if (angle) {
3556                                                         cos = Math.cos(-angle);
3557                                                         sin = Math.sin(-angle);
3558                                                         t1 = a12*cos+a13*sin;
3559                                                         t2 = a22*cos+a23*sin;
3560                                                         t3 = a32*cos+a33*sin;
3561                                                         a13 = a12*-sin+a13*cos;
3562                                                         a23 = a22*-sin+a23*cos;
3563                                                         a33 = a32*-sin+a33*cos;
3564                                                         a43 = a42*-sin+a43*cos;
3565                                                         a12 = t1;
3566                                                         a22 = t2;
3567                                                         a32 = t3;
3568                                                 }
3569                                                 //rotationY
3570                                                 angle = Math.atan2(a13, a11);
3571                                                 tm.rotationY = angle * _RAD2DEG;
3572                                                 if (angle) {
3573                                                         yFlip = (angle < -minPI || angle > minPI);
3574                                                         cos = Math.cos(-angle);
3575                                                         sin = Math.sin(-angle);
3576                                                         t1 = a11*cos-a13*sin;
3577                                                         t2 = a21*cos-a23*sin;
3578                                                         t3 = a31*cos-a33*sin;
3579                                                         a23 = a21*sin+a23*cos;
3580                                                         a33 = a31*sin+a33*cos;
3581                                                         a43 = a41*sin+a43*cos;
3582                                                         a11 = t1;
3583                                                         a21 = t2;
3584                                                         a31 = t3;
3585                                                 }
3586                                                 //rotationZ
3587                                                 angle = Math.atan2(a21, a22);
3588                                                 tm.rotation = angle * _RAD2DEG;
3589                                                 if (angle) {
3590                                                         zFlip = (angle < -minPI || angle > minPI);
3591                                                         cos = Math.cos(-angle);
3592                                                         sin = Math.sin(-angle);
3593                                                         a11 = a11*cos+a12*sin;
3594                                                         t2 = a21*cos+a22*sin;
3595                                                         a22 = a21*-sin+a22*cos;
3596                                                         a32 = a31*-sin+a32*cos;
3597                                                         a21 = t2;
3598                                                 }
3599
3600                                                 if (zFlip && xFlip) {
3601                                                         tm.rotation = tm.rotationX = 0;
3602                                                 } else if (zFlip && yFlip) {
3603                                                         tm.rotation = tm.rotationY = 0;
3604                                                 } else if (yFlip && xFlip) {
3605                                                         tm.rotationY = tm.rotationX = 0;
3606                                                 }
3607
3608                                                 tm.scaleX = ((Math.sqrt(a11 * a11 + a21 * a21) * rnd + 0.5) | 0) / rnd;
3609                                                 tm.scaleY = ((Math.sqrt(a22 * a22 + a23 * a23) * rnd + 0.5) | 0) / rnd;
3610                                                 tm.scaleZ = ((Math.sqrt(a32 * a32 + a33 * a33) * rnd + 0.5) | 0) / rnd;
3611                                                 tm.skewX = 0;
3612                                                 tm.perspective = a43 ? 1 / ((a43 < 0) ? -a43 : a43) : 0;
3613                                                 tm.x = a14;
3614                                                 tm.y = a24;
3615                                                 tm.z = a34;
3616                                         }
3617
3618                                 } 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.
3619                                         var k = (m.length >= 6),
3620                                                 a = k ? m[0] : 1,
3621                                                 b = m[1] || 0,
3622                                                 c = m[2] || 0,
3623                                                 d = k ? m[3] : 1;
3624                                         tm.x = m[4] || 0;
3625                                         tm.y = m[5] || 0;
3626                                         scaleX = Math.sqrt(a * a + b * b);
3627                                         scaleY = Math.sqrt(d * d + c * c);
3628                                         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).
3629                                         skewX = (c || d) ? Math.atan2(c, d) * _RAD2DEG + rotation : tm.skewX || 0;
3630                                         difX = scaleX - Math.abs(tm.scaleX || 0);
3631                                         difY = scaleY - Math.abs(tm.scaleY || 0);
3632                                         if (Math.abs(skewX) > 90 && Math.abs(skewX) < 270) {
3633                                                 if (invX) {
3634                                                         scaleX *= -1;
3635                                                         skewX += (rotation <= 0) ? 180 : -180;
3636                                                         rotation += (rotation <= 0) ? 180 : -180;
3637                                                 } else {
3638                                                         scaleY *= -1;
3639                                                         skewX += (skewX <= 0) ? 180 : -180;
3640                                                 }
3641                                         }
3642                                         difR = (rotation - tm.rotation) % 180; //note: matching ranges would be very small (+/-0.0001) or very close to 180.
3643                                         difS = (skewX - tm.skewX) % 180;
3644                                         //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.
3645                                         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)) {
3646                                                 tm.scaleX = scaleX;
3647                                                 tm.scaleY = scaleY;
3648                                                 tm.rotation = rotation;
3649                                                 tm.skewX = skewX;
3650                                         }
3651                                         if (_supports3D) {
3652                                                 tm.rotationX = tm.rotationY = tm.z = 0;
3653                                                 tm.perspective = parseFloat(CSSPlugin.defaultTransformPerspective) || 0;
3654                                                 tm.scaleZ = 1;
3655                                         }
3656                                 }
3657                                 tm.zOrigin = zOrigin;
3658
3659                                 //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.
3660                                 for (i in tm) {
3661                                         if (tm[i] < min) if (tm[i] > -min) {
3662                                                 tm[i] = 0;
3663                                         }
3664                                 }
3665                                 //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);
3666                                 if (rec) {
3667                                         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)
3668                                 }
3669                                 return tm;
3670                         },
3671
3672                         //for setting 2D transforms in IE6, IE7, and IE8 (must use a "filter" to emulate the behavior of modern day browser transforms)
3673                         _setIETransformRatio = function(v) {
3674                                 var t = this.data, //refers to the element's _gsTransform object
3675                                         ang = -t.rotation * _DEG2RAD,
3676                                         skew = ang + t.skewX * _DEG2RAD,
3677                                         rnd = 100000,
3678                                         a = ((Math.cos(ang) * t.scaleX * rnd) | 0) / rnd,
3679                                         b = ((Math.sin(ang) * t.scaleX * rnd) | 0) / rnd,
3680                                         c = ((Math.sin(skew) * -t.scaleY * rnd) | 0) / rnd,
3681                                         d = ((Math.cos(skew) * t.scaleY * rnd) | 0) / rnd,
3682                                         style = this.t.style,
3683                                         cs = this.t.currentStyle,
3684                                         filters, val;
3685                                 if (!cs) {
3686                                         return;
3687                                 }
3688                                 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)
3689                                 b = -c;
3690                                 c = -val;
3691                                 filters = cs.filter;
3692                                 style.filter = ""; //remove filters so that we can accurately measure offsetWidth/offsetHeight
3693                                 var w = this.t.offsetWidth,
3694                                         h = this.t.offsetHeight,
3695                                         clip = (cs.position !== "absolute"),
3696                                         m = "progid:DXImageTransform.Microsoft.Matrix(M11=" + a + ", M12=" + b + ", M21=" + c + ", M22=" + d,
3697                                         ox = t.x,
3698                                         oy = t.y,
3699                                         dx, dy;
3700
3701                                 //if transformOrigin is being used, adjust the offset x and y
3702                                 if (t.ox != null) {
3703                                         dx = ((t.oxp) ? w * t.ox * 0.01 : t.ox) - w / 2;
3704                                         dy = ((t.oyp) ? h * t.oy * 0.01 : t.oy) - h / 2;
3705                                         ox += dx - (dx * a + dy * b);
3706                                         oy += dy - (dx * c + dy * d);
3707                                 }
3708
3709                                 if (!clip) {
3710                                         m += ", sizingMethod='auto expand')";
3711                                 } else {
3712                                         dx = (w / 2);
3713                                         dy = (h / 2);
3714                                         //translate to ensure that transformations occur around the correct origin (default is center).
3715                                         m += ", Dx=" + (dx - (dx * a + dy * b) + ox) + ", Dy=" + (dy - (dx * c + dy * d) + oy) + ")";
3716                                 }
3717                                 if (filters.indexOf("DXImageTransform.Microsoft.Matrix(") !== -1) {
3718                                         style.filter = filters.replace(_ieSetMatrixExp, m);
3719                                 } else {
3720                                         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.
3721                                 }
3722
3723                                 //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.
3724                                 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) {
3725                                         style.removeAttribute("filter");
3726                                 }
3727
3728                                 //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).
3729                                 if (!clip) {
3730                                         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
3731                                                 marg, prop, dif;
3732                                         dx = t.ieOffsetX || 0;
3733                                         dy = t.ieOffsetY || 0;
3734                                         t.ieOffsetX = Math.round((w - ((a < 0 ? -a : a) * w + (b < 0 ? -b : b) * h)) / 2 + ox);
3735                                         t.ieOffsetY = Math.round((h - ((d < 0 ? -d : d) * h + (c < 0 ? -c : c) * w)) / 2 + oy);
3736                                         for (i = 0; i < 4; i++) {
3737                                                 prop = _margins[i];
3738                                                 marg = cs[prop];
3739                                                 //we need to get the current margin in case it is being tweened separately (we want to respect that tween's changes)
3740                                                 val = (marg.indexOf("px") !== -1) ? parseFloat(marg) : _convertToPixels(this.t, prop, parseFloat(marg), marg.replace(_suffixExp, "")) || 0;
3741                                                 if (val !== t[prop]) {
3742                                                         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.
3743                                                 } else {
3744                                                         dif = (i < 2) ? dx - t.ieOffsetX : dy - t.ieOffsetY;
3745                                                 }
3746                                                 style[prop] = (t[prop] = Math.round( val - dif * ((i === 0 || i === 2) ? 1 : mult) )) + "px";
3747                                         }
3748                                 }
3749                         },
3750
3751                         _set3DTransformRatio = _internals.set3DTransformRatio = function(v) {
3752                                 var t = this.data, //refers to the element's _gsTransform object
3753                                         style = this.t.style,
3754                                         angle = t.rotation * _DEG2RAD,
3755                                         sx = t.scaleX,
3756                                         sy = t.scaleY,
3757                                         sz = t.scaleZ,
3758                                         perspective = t.perspective,
3759                                         a11, a12, a13, a14,     a21, a22, a23, a24, a31, a32, a33, a34, a41, a42, a43,
3760                                         zOrigin, rnd, cos, sin, t1, t2, t3, t4;
3761                                 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
3762                                         _set2DTransformRatio.call(this, v);
3763                                         return;
3764                                 }
3765                                 if (_isFirefox) {
3766                                         var n = 0.0001;
3767                                         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.
3768                                                 sx = sz = 0.00002;
3769                                         }
3770                                         if (sy < n && sy > -n) {
3771                                                 sy = sz = 0.00002;
3772                                         }
3773                                         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).
3774                                                 perspective = 0;
3775                                         }
3776                                 }
3777                                 if (angle || t.skewX) {
3778                                         cos = Math.cos(angle);
3779                                         sin = Math.sin(angle);
3780                                         a11 = cos;
3781                                         a21 = sin;
3782                                         if (t.skewX) {
3783                                                 angle -= t.skewX * _DEG2RAD;
3784                                                 cos = Math.cos(angle);
3785                                                 sin = Math.sin(angle);
3786                                                 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
3787                                                         t1 = Math.tan(t.skewX * _DEG2RAD);
3788                                                         t1 = Math.sqrt(1 + t1 * t1);
3789                                                         cos *= t1;
3790                                                         sin *= t1;
3791                                                 }
3792                                         }
3793                                         a12 = -sin;
3794                                         a22 = cos;
3795
3796                                 } else if (!t.rotationY && !t.rotationX && sz === 1 && !perspective) { //if we're only translating and/or 2D scaling, this is faster...
3797                                         style[_transformProp] = "translate3d(" + t.x + "px," + t.y + "px," + t.z +"px)" + ((sx !== 1 || sy !== 1) ? " scale(" + sx + "," + sy + ")" : "");
3798                                         return;
3799                                 } else {
3800                                         a11 = a22 = 1;
3801                                         a12 = a21 = 0;
3802                                 }
3803                                 a33 = 1;
3804                                 a13 = a14 = a23 = a24 = a31 = a32 = a34 = a41 = a42 = 0;
3805                                 a43 = (perspective) ? -1 / perspective : 0;
3806                                 zOrigin = t.zOrigin;
3807                                 rnd = 100000;
3808                                 angle = t.rotationY * _DEG2RAD;
3809                                 if (angle) {
3810                                         cos = Math.cos(angle);
3811                                         sin = Math.sin(angle);
3812                                         a31 = a33*-sin;
3813                                         a41 = a43*-sin;
3814                                         a13 = a11*sin;
3815                                         a23 = a21*sin;
3816                                         a33 *= cos;
3817                                         a43 *= cos;
3818                                         a11 *= cos;
3819                                         a21 *= cos;
3820                                 }
3821                                 angle = t.rotationX * _DEG2RAD;
3822                                 if (angle) {
3823                                         cos = Math.cos(angle);
3824                                         sin = Math.sin(angle);
3825                                         t1 = a12*cos+a13*sin;
3826                                         t2 = a22*cos+a23*sin;
3827                                         t3 = a32*cos+a33*sin;
3828                                         t4 = a42*cos+a43*sin;
3829                                         a13 = a12*-sin+a13*cos;
3830                                         a23 = a22*-sin+a23*cos;
3831                                         a33 = a32*-sin+a33*cos;
3832                                         a43 = a42*-sin+a43*cos;
3833                                         a12 = t1;
3834                                         a22 = t2;
3835                                         a32 = t3;
3836                                         a42 = t4;
3837                                 }
3838                                 if (sz !== 1) {
3839                                         a13*=sz;
3840                                         a23*=sz;
3841                                         a33*=sz;
3842                                         a43*=sz;
3843                                 }
3844                                 if (sy !== 1) {
3845                                         a12*=sy;
3846                                         a22*=sy;
3847                                         a32*=sy;
3848                                         a42*=sy;
3849                                 }
3850                                 if (sx !== 1) {
3851                                         a11*=sx;
3852                                         a21*=sx;
3853                                         a31*=sx;
3854                                         a41*=sx;
3855                                 }
3856                                 if (zOrigin) {
3857                                         a34 -= zOrigin;
3858                                         a14 = a13*a34;
3859                                         a24 = a23*a34;
3860                                         a34 = a33*a34+zOrigin;
3861                                 }
3862                                 //we round the x, y, and z slightly differently to allow even larger values.
3863                                 a14 = (t1 = (a14 += t.x) - (a14 |= 0)) ? ((t1 * rnd + (t1 < 0 ? -0.5 : 0.5)) | 0) / rnd + a14 : a14;
3864                                 a24 = (t1 = (a24 += t.y) - (a24 |= 0)) ? ((t1 * rnd + (t1 < 0 ? -0.5 : 0.5)) | 0) / rnd + a24 : a24;
3865                                 a34 = (t1 = (a34 += t.z) - (a34 |= 0)) ? ((t1 * rnd + (t1 < 0 ? -0.5 : 0.5)) | 0) / rnd + a34 : a34;
3866                                 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(",") + ")";
3867                         },
3868
3869                         _set2DTransformRatio = _internals.set2DTransformRatio = function(v) {
3870                                 var t = this.data, //refers to the element's _gsTransform object
3871                                         targ = this.t,
3872                                         style = targ.style,
3873                                         ang, skew, rnd, sx, sy;
3874                                 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.
3875                                         this.setRatio = _set3DTransformRatio;
3876                                         _set3DTransformRatio.call(this, v);
3877                                         return;
3878                                 }
3879                                 if (!t.rotation && !t.skewX) {
3880                                         style[_transformProp] = "matrix(" + t.scaleX + ",0,0," + t.scaleY + "," + t.x + "," + t.y + ")";
3881                                 } else {
3882                                         ang = t.rotation * _DEG2RAD;
3883                                         skew = ang - t.skewX * _DEG2RAD;
3884                                         rnd = 100000;
3885                                         sx = t.scaleX * rnd;
3886                                         sy = t.scaleY * rnd;
3887                                         //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.
3888                                         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 + ")";
3889                                 }
3890                         };
3891
3892                 _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) {
3893                         if (cssp._transform) { return pt; } //only need to parse the transform once, and only if the browser supports it.
3894                         var m1 = cssp._transform = _getTransform(t, _cs, true, vars.parseTransform),
3895                                 style = t.style,
3896                                 min = 0.000001,
3897                                 i = _transformProps.length,
3898                                 v = vars,
3899                                 endRotations = {},
3900                                 m2, skewY, copy, orig, has3D, hasChange, dr;
3901                         if (typeof(v.transform) === "string" && _transformProp) { //for values like transform:"rotate(60deg) scale(0.5, 0.8)"
3902                                 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.
3903                                 copy[_transformProp] = v.transform;
3904                                 copy.display = "block"; //if display is "none", the browser often refuses to report the transform properties correctly.
3905                                 copy.position = "absolute";
3906                                 _doc.body.appendChild(_tempDiv);
3907                                 m2 = _getTransform(_tempDiv, null, false);
3908                                 _doc.body.removeChild(_tempDiv);
3909                         } else if (typeof(v) === "object") { //for values like scaleX, scaleY, rotation, x, y, skewX, and skewY or transform:{...} (object)
3910                                 m2 = {scaleX:_parseVal((v.scaleX != null) ? v.scaleX : v.scale, m1.scaleX),
3911                                         scaleY:_parseVal((v.scaleY != null) ? v.scaleY : v.scale, m1.scaleY),
3912                                         scaleZ:_parseVal(v.scaleZ, m1.scaleZ),
3913                                         x:_parseVal(v.x, m1.x),
3914                                         y:_parseVal(v.y, m1.y),
3915                                         z:_parseVal(v.z, m1.z),
3916                                         perspective:_parseVal(v.transformPerspective, m1.perspective)};
3917                                 dr = v.directionalRotation;
3918                                 if (dr != null) {
3919                                         if (typeof(dr) === "object") {
3920                                                 for (copy in dr) {
3921                                                         v[copy] = dr[copy];
3922                                                 }
3923                                         } else {
3924                                                 v.rotation = dr;
3925                                         }
3926                                 }
3927                                 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);
3928                                 if (_supports3D) {
3929                                         m2.rotationX = _parseAngle(("rotationX" in v) ? v.rotationX : ("shortRotationX" in v) ? v.shortRotationX + "_short" : m1.rotationX || 0, m1.rotationX, "rotationX", endRotations);
3930                                         m2.rotationY = _parseAngle(("rotationY" in v) ? v.rotationY : ("shortRotationY" in v) ? v.shortRotationY + "_short" : m1.rotationY || 0, m1.rotationY, "rotationY", endRotations);
3931                                 }
3932                                 m2.skewX = (v.skewX == null) ? m1.skewX : _parseAngle(v.skewX, m1.skewX);
3933
3934                                 //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.
3935                                 m2.skewY = (v.skewY == null) ? m1.skewY : _parseAngle(v.skewY, m1.skewY);
3936                                 if ((skewY = m2.skewY - m1.skewY)) {
3937                                         m2.skewX += skewY;
3938                                         m2.rotation += skewY;
3939                                 }
3940                         }
3941
3942                         if (_supports3D && v.force3D != null) {
3943                                 m1.force3D = v.force3D;
3944                                 hasChange = true;
3945                         }
3946
3947                         m1.skewType = v.skewType || m1.skewType || CSSPlugin.defaultSkewType;
3948
3949                         has3D = (m1.force3D || m1.z || m1.rotationX || m1.rotationY || m2.z || m2.rotationX || m2.rotationY || m2.perspective);
3950                         if (!has3D && v.scale != null) {
3951                                 m2.scaleZ = 1; //no need to tween scaleZ.
3952                         }
3953
3954                         while (--i > -1) {
3955                                 p = _transformProps[i];
3956                                 orig = m2[p] - m1[p];
3957                                 if (orig > min || orig < -min || _forcePT[p] != null) {
3958                                         hasChange = true;
3959                                         pt = new CSSPropTween(m1, p, m1[p], orig, pt);
3960                                         if (p in endRotations) {
3961                                                 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
3962                                         }
3963                                         pt.xs0 = 0; //ensures the value stays numeric in setRatio()
3964                                         pt.plugin = plugin;
3965                                         cssp._overwriteProps.push(pt.n);
3966                                 }
3967                         }
3968
3969                         orig = v.transformOrigin;
3970                         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).
3971                                 if (_transformProp) {
3972                                         hasChange = true;
3973                                         p = _transformOriginProp;
3974                                         orig = (orig || _getStyle(t, p, _cs, false, "50% 50%")) + ""; //cast as string to avoid errors
3975                                         pt = new CSSPropTween(style, p, 0, 0, pt, -1, "transformOrigin");
3976                                         pt.b = style[p];
3977                                         pt.plugin = plugin;
3978                                         if (_supports3D) {
3979                                                 copy = m1.zOrigin;
3980                                                 orig = orig.split(" ");
3981                                                 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.
3982                                                 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)!
3983                                                 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)
3984                                                 pt.b = copy;
3985                                                 pt.xs0 = pt.e = m1.zOrigin;
3986                                         } else {
3987                                                 pt.xs0 = pt.e = orig;
3988                                         }
3989
3990                                 //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).
3991                                 } else {
3992                                         _parsePosition(orig + "", m1);
3993                                 }
3994                         }
3995
3996                         if (hasChange) {
3997                                 cssp._transformType = (has3D || this._transformType === 3) ? 3 : 2; //quicker than calling cssp._enableTransforms();
3998                         }
3999                         return pt;
4000                 }, prefix:true});
4001
4002                 _registerComplexSpecialProp("boxShadow", {defaultValue:"0px 0px 0px 0px #999", prefix:true, color:true, multi:true, keyword:"inset"});
4003
4004                 _registerComplexSpecialProp("borderRadius", {defaultValue:"0px", parser:function(t, e, p, cssp, pt, plugin) {
4005                         e = this.format(e);
4006                         var props = ["borderTopLeftRadius","borderTopRightRadius","borderBottomRightRadius","borderBottomLeftRadius"],
4007                                 style = t.style,
4008                                 ea1, i, es2, bs2, bs, es, bn, en, w, h, esfx, bsfx, rel, hn, vn, em;
4009                         w = parseFloat(t.offsetWidth);
4010                         h = parseFloat(t.offsetHeight);
4011                         ea1 = e.split(" ");
4012                         for (i = 0; i < props.length; i++) { //if we're dealing with percentages, we must convert things separately for the horizontal and vertical axis!
4013                                 if (this.p.indexOf("border")) { //older browsers used a prefix
4014                                         props[i] = _checkPropPrefix(props[i]);
4015                                 }
4016                                 bs = bs2 = _getStyle(t, props[i], _cs, false, "0px");
4017                                 if (bs.indexOf(" ") !== -1) {
4018                                         bs2 = bs.split(" ");
4019                                         bs = bs2[0];
4020                                         bs2 = bs2[1];
4021                                 }
4022                                 es = es2 = ea1[i];
4023                                 bn = parseFloat(bs);
4024                                 bsfx = bs.substr((bn + "").length);
4025                                 rel = (es.charAt(1) === "=");
4026                                 if (rel) {
4027                                         en = parseInt(es.charAt(0)+"1", 10);
4028                                         es = es.substr(2);
4029                                         en *= parseFloat(es);
4030                                         esfx = es.substr((en + "").length - (en < 0 ? 1 : 0)) || "";
4031                                 } else {
4032                                         en = parseFloat(es);
4033                                         esfx = es.substr((en + "").length);
4034                                 }
4035                                 if (esfx === "") {
4036                                         esfx = _suffixMap[p] || bsfx;
4037                                 }
4038                                 if (esfx !== bsfx) {
4039                                         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.
4040                                         vn = _convertToPixels(t, "borderTop", bn, bsfx); //vertical number
4041                                         if (esfx === "%") {
4042                                                 bs = (hn / w * 100) + "%";
4043                                                 bs2 = (vn / h * 100) + "%";
4044                                         } else if (esfx === "em") {
4045                                                 em = _convertToPixels(t, "borderLeft", 1, "em");
4046                                                 bs = (hn / em) + "em";
4047                                                 bs2 = (vn / em) + "em";
4048                                         } else {
4049                                                 bs = hn + "px";
4050                                                 bs2 = vn + "px";
4051                                         }
4052                                         if (rel) {
4053                                                 es = (parseFloat(bs) + en) + esfx;
4054                                                 es2 = (parseFloat(bs2) + en) + esfx;
4055                                         }
4056                                 }
4057                                 pt = _parseComplex(style, props[i], bs + " " + bs2, es + " " + es2, false, "0px", pt);
4058                         }
4059                         return pt;
4060                 }, prefix:true, formatter:_getFormatter("0px 0px 0px 0px", false, true)});
4061                 _registerComplexSpecialProp("backgroundPosition", {defaultValue:"0 0", parser:function(t, e, p, cssp, pt, plugin) {
4062                         var bp = "background-position",
4063                                 cs = (_cs || _getComputedStyle(t, null)),
4064                                 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
4065                                 es = this.format(e),
4066                                 ba, ea, i, pct, overlap, src;
4067                         if ((bs.indexOf("%") !== -1) !== (es.indexOf("%") !== -1)) {
4068                                 src = _getStyle(t, "backgroundImage").replace(_urlExp, "");
4069                                 if (src && src !== "none") {
4070                                         ba = bs.split(" ");
4071                                         ea = es.split(" ");
4072                                         _tempImg.setAttribute("src", src); //set the temp <img>'s src to the background-image so that we can measure its width/height
4073                                         i = 2;
4074                                         while (--i > -1) {
4075                                                 bs = ba[i];
4076                                                 pct = (bs.indexOf("%") !== -1);
4077                                                 if (pct !== (ea[i].indexOf("%") !== -1)) {
4078                                                         overlap = (i === 0) ? t.offsetWidth - _tempImg.width : t.offsetHeight - _tempImg.height;
4079                                                         ba[i] = pct ? (parseFloat(bs) / 100 * overlap) + "px" : (parseFloat(bs) / overlap * 100) + "%";
4080                                                 }
4081                                         }
4082                                         bs = ba.join(" ");
4083                                 }
4084                         }
4085                         return this.parseComplex(t.style, bs, es, pt, plugin);
4086                 }, formatter:_parsePosition});
4087                 _registerComplexSpecialProp("backgroundSize", {defaultValue:"0 0", formatter:_parsePosition});
4088                 _registerComplexSpecialProp("perspective", {defaultValue:"0px", prefix:true});
4089                 _registerComplexSpecialProp("perspectiveOrigin", {defaultValue:"50% 50%", prefix:true});
4090                 _registerComplexSpecialProp("transformStyle", {prefix:true});
4091                 _registerComplexSpecialProp("backfaceVisibility", {prefix:true});
4092                 _registerComplexSpecialProp("userSelect", {prefix:true});
4093                 _registerComplexSpecialProp("margin", {parser:_getEdgeParser("marginTop,marginRight,marginBottom,marginLeft")});
4094                 _registerComplexSpecialProp("padding", {parser:_getEdgeParser("paddingTop,paddingRight,paddingBottom,paddingLeft")});
4095                 _registerComplexSpecialProp("clip", {defaultValue:"rect(0px,0px,0px,0px)", parser:function(t, e, p, cssp, pt, plugin){
4096                         var b, cs, delim;
4097                         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.
4098                                 cs = t.currentStyle;
4099                                 delim = _ieVers < 8 ? " " : ",";
4100                                 b = "rect(" + cs.clipTop + delim + cs.clipRight + delim + cs.clipBottom + delim + cs.clipLeft + ")";
4101                                 e = this.format(e).split(",").join(delim);
4102                         } else {
4103                                 b = this.format(_getStyle(t, this.p, _cs, false, this.dflt));
4104                                 e = this.format(e);
4105                         }
4106                         return this.parseComplex(t.style, b, e, pt, plugin);
4107                 }});
4108                 _registerComplexSpecialProp("textShadow", {defaultValue:"0px 0px 0px #999", color:true, multi:true});
4109                 _registerComplexSpecialProp("autoRound,strictUnits", {parser:function(t, e, p, cssp, pt) {return pt;}}); //just so that we can ignore these properties (not tween them)
4110                 _registerComplexSpecialProp("border", {defaultValue:"0px solid #000", parser:function(t, e, p, cssp, pt, plugin) {
4111                                 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);
4112                         }, color:true, formatter:function(v) {
4113                                 var a = v.split(" ");
4114                                 return a[0] + " " + (a[1] || "solid") + " " + (v.match(_colorExp) || ["#000"])[0];
4115                         }});
4116                 _registerComplexSpecialProp("borderWidth", {parser:_getEdgeParser("borderTopWidth,borderRightWidth,borderBottomWidth,borderLeftWidth")}); //Firefox doesn't pick up on borderWidth set in style sheets (only inline).
4117                 _registerComplexSpecialProp("float,cssFloat,styleFloat", {parser:function(t, e, p, cssp, pt, plugin) {
4118                         var s = t.style,
4119                                 prop = ("cssFloat" in s) ? "cssFloat" : "styleFloat";
4120                         return new CSSPropTween(s, prop, 0, 0, pt, -1, p, false, 0, s[prop], e);
4121                 }});
4122
4123                 //opacity-related
4124                 var _setIEOpacityRatio = function(v) {
4125                                 var t = this.t, //refers to the element's style property
4126                                         filters = t.filter || _getStyle(this.data, "filter"),
4127                                         val = (this.s + this.c * v) | 0,
4128                                         skip;
4129                                 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.
4130                                         if (filters.indexOf("atrix(") === -1 && filters.indexOf("radient(") === -1 && filters.indexOf("oader(") === -1) {
4131                                                 t.removeAttribute("filter");
4132                                                 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.
4133                                         } else {
4134                                                 t.filter = filters.replace(_alphaFilterExp, "");
4135                                                 skip = true;
4136                                         }
4137                                 }
4138                                 if (!skip) {
4139                                         if (this.xn1) {
4140                                                 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.
4141                                         }
4142                                         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
4143                                                 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)
4144                                                         t.filter = filters + " alpha(opacity=" + val + ")"; //we round the value because otherwise, bugs in IE7/8 can prevent "visibility" changes from being applied properly.
4145                                                 }
4146                                         } else {
4147                                                 t.filter = filters.replace(_opacityExp, "opacity=" + val);
4148                                         }
4149                                 }
4150                         };
4151                 _registerComplexSpecialProp("opacity,alpha,autoAlpha", {defaultValue:"1", parser:function(t, e, p, cssp, pt, plugin) {
4152                         var b = parseFloat(_getStyle(t, "opacity", _cs, false, "1")),
4153                                 style = t.style,
4154                                 isAutoAlpha = (p === "autoAlpha");
4155                         if (typeof(e) === "string" && e.charAt(1) === "=") {
4156                                 e = ((e.charAt(0) === "-") ? -1 : 1) * parseFloat(e.substr(2)) + b;
4157                         }
4158                         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)
4159                                 b = 0;
4160                         }
4161                         if (_supportsOpacity) {
4162                                 pt = new CSSPropTween(style, "opacity", b, e - b, pt);
4163                         } else {
4164                                 pt = new CSSPropTween(style, "opacity", b * 100, (e - b) * 100, pt);
4165                                 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.
4166                                 style.zoom = 1; //helps correct an IE issue.
4167                                 pt.type = 2;
4168                                 pt.b = "alpha(opacity=" + pt.s + ")";
4169                                 pt.e = "alpha(opacity=" + (pt.s + pt.c) + ")";
4170                                 pt.data = t;
4171                                 pt.plugin = plugin;
4172                                 pt.setRatio = _setIEOpacityRatio;
4173                         }
4174                         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
4175                                 pt = new CSSPropTween(style, "visibility", 0, 0, pt, -1, null, false, 0, ((b !== 0) ? "inherit" : "hidden"), ((e === 0) ? "hidden" : "inherit"));
4176                                 pt.xs0 = "inherit";
4177                                 cssp._overwriteProps.push(pt.n);
4178                                 cssp._overwriteProps.push(p);
4179                         }
4180                         return pt;
4181                 }});
4182
4183
4184                 var _removeProp = function(s, p) {
4185                                 if (p) {
4186                                         if (s.removeProperty) {
4187                                                 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)
4188                                                         p = "M" + p.substr(1);
4189                                                 }
4190                                                 s.removeProperty(p.replace(_capsExp, "-$1").toLowerCase());
4191                                         } else { //note: old versions of IE use "removeAttribute()" instead of "removeProperty()"
4192                                                 s.removeAttribute(p);
4193                                         }
4194                                 }
4195                         },
4196                         _setClassNameRatio = function(v) {
4197                                 this.t._gsClassPT = this;
4198                                 if (v === 1 || v === 0) {
4199                                         this.t.setAttribute("class", (v === 0) ? this.b : this.e);
4200                                         var mpt = this.data, //first MiniPropTween
4201                                                 s = this.t.style;
4202                                         while (mpt) {
4203                                                 if (!mpt.v) {
4204                                                         _removeProp(s, mpt.p);
4205                                                 } else {
4206                                                         s[mpt.p] = mpt.v;
4207                                                 }
4208                                                 mpt = mpt._next;
4209                                         }
4210                                         if (v === 1 && this.t._gsClassPT === this) {
4211                                                 this.t._gsClassPT = null;
4212                                         }
4213                                 } else if (this.t.getAttribute("class") !== this.e) {
4214                                         this.t.setAttribute("class", this.e);
4215                                 }
4216                         };
4217                 _registerComplexSpecialProp("className", {parser:function(t, e, p, cssp, pt, plugin, vars) {
4218                         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.
4219                                 cssText = t.style.cssText,
4220                                 difData, bs, cnpt, cnptLookup, mpt;
4221                         pt = cssp._classNamePT = new CSSPropTween(t, p, 0, 0, pt, 2);
4222                         pt.setRatio = _setClassNameRatio;
4223                         pt.pr = -11;
4224                         _hasPriority = true;
4225                         pt.b = b;
4226                         bs = _getAllStyles(t, _cs);
4227                         //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)
4228                         cnpt = t._gsClassPT;
4229                         if (cnpt) {
4230                                 cnptLookup = {};
4231                                 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.
4232                                 while (mpt) {
4233                                         cnptLookup[mpt.p] = 1;
4234                                         mpt = mpt._next;
4235                                 }
4236                                 cnpt.setRatio(1);
4237                         }
4238                         t._gsClassPT = pt;
4239                         pt.e = (e.charAt(1) !== "=") ? e : b.replace(new RegExp("\\s*\\b" + e.substr(2) + "\\b"), "") + ((e.charAt(0) === "+") ? " " + e.substr(2) : "");
4240                         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.
4241                                 t.setAttribute("class", pt.e);
4242                                 difData = _cssDif(t, bs, _getAllStyles(t), vars, cnptLookup);
4243                                 t.setAttribute("class", b);
4244                                 pt.data = difData.firstMPT;
4245                                 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).
4246                                 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)
4247                         }
4248                         return pt;
4249                 }});
4250
4251
4252                 var _setClearPropsRatio = function(v) {
4253                         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).
4254                                 var s = this.t.style,
4255                                         transformParse = _specialProps.transform.parse,
4256                                         a, p, i, clearTransform;
4257                                 if (this.e === "all") {
4258                                         s.cssText = "";
4259                                         clearTransform = true;
4260                                 } else {
4261                                         a = this.e.split(",");
4262                                         i = a.length;
4263                                         while (--i > -1) {
4264                                                 p = a[i];
4265                                                 if (_specialProps[p]) {
4266                                                         if (_specialProps[p].parse === transformParse) {
4267                                                                 clearTransform = true;
4268                                                         } else {
4269                                                                 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"
4270                                                         }
4271                                                 }
4272                                                 _removeProp(s, p);
4273                                         }
4274                                 }
4275                                 if (clearTransform) {
4276                                         _removeProp(s, _transformProp);
4277                                         if (this.t._gsTransform) {
4278                                                 delete this.t._gsTransform;
4279                                         }
4280                                 }
4281
4282                         }
4283                 };
4284                 _registerComplexSpecialProp("clearProps", {parser:function(t, e, p, cssp, pt) {
4285                         pt = new CSSPropTween(t, p, 0, 0, pt, 2);
4286                         pt.setRatio = _setClearPropsRatio;
4287                         pt.e = e;
4288                         pt.pr = -10;
4289                         pt.data = cssp._tween;
4290                         _hasPriority = true;
4291                         return pt;
4292                 }});
4293
4294                 p = "bezier,throwProps,physicsProps,physics2D".split(",");
4295                 i = p.length;
4296                 while (i--) {
4297                         _registerPluginProp(p[i]);
4298                 }
4299
4300
4301
4302
4303
4304
4305
4306
4307                 p = CSSPlugin.prototype;
4308                 p._firstPT = null;
4309
4310                 //gets called when the tween renders for the first time. This kicks everything off, recording start/end values, etc.
4311                 p._onInitTween = function(target, vars, tween) {
4312                         if (!target.nodeType) { //css is only for dom elements
4313                                 return false;
4314                         }
4315                         this._target = target;
4316                         this._tween = tween;
4317                         this._vars = vars;
4318                         _autoRound = vars.autoRound;
4319                         _hasPriority = false;
4320                         _suffixMap = vars.suffixMap || CSSPlugin.suffixMap;
4321                         _cs = _getComputedStyle(target, "");
4322                         _overwriteProps = this._overwriteProps;
4323                         var style = target.style,
4324                                 v, pt, pt2, first, last, next, zIndex, tpt, threeD;
4325                         if (_reqSafariFix) if (style.zIndex === "") {
4326                                 v = _getStyle(target, "zIndex", _cs);
4327                                 if (v === "auto" || v === "") {
4328                                         //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.
4329                                         this._addLazySet(style, "zIndex", 0);
4330                                 }
4331                         }
4332
4333                         if (typeof(vars) === "string") {
4334                                 first = style.cssText;
4335                                 v = _getAllStyles(target, _cs);
4336                                 style.cssText = first + ";" + vars;
4337                                 v = _cssDif(target, v, _getAllStyles(target)).difs;
4338                                 if (!_supportsOpacity && _opacityValExp.test(vars)) {
4339                                         v.opacity = parseFloat( RegExp.$1 );
4340                                 }
4341                                 vars = v;
4342                                 style.cssText = first;
4343                         }
4344                         this._firstPT = pt = this.parse(target, vars, null);
4345
4346                         if (this._transformType) {
4347                                 threeD = (this._transformType === 3);
4348                                 if (!_transformProp) {
4349                                         style.zoom = 1; //helps correct an IE issue.
4350                                 } else if (_isSafari) {
4351                                         _reqSafariFix = true;
4352                                         //if zIndex isn't set, iOS Safari doesn't repaint things correctly sometimes (seemingly at random).
4353                                         if (style.zIndex === "") {
4354                                                 zIndex = _getStyle(target, "zIndex", _cs);
4355                                                 if (zIndex === "auto" || zIndex === "") {
4356                                                         this._addLazySet(style, "zIndex", 0);
4357                                                 }
4358                                         }
4359                                         //Setting WebkitBackfaceVisibility corrects 3 bugs:
4360                                         // 1) [non-Android] Safari skips rendering changes to "top" and "left" that are made on the same frame/render as a transform update.
4361                                         // 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.
4362                                         // 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.
4363                                         //Note: we allow the user to override the auto-setting by defining WebkitBackfaceVisibility in the vars of the tween.
4364                                         if (_isSafariLT6) {
4365                                                 this._addLazySet(style, "WebkitBackfaceVisibility", this._vars.WebkitBackfaceVisibility || (threeD ? "visible" : "hidden"));
4366                                         }
4367                                 }
4368                                 pt2 = pt;
4369                                 while (pt2 && pt2._next) {
4370                                         pt2 = pt2._next;
4371                                 }
4372                                 tpt = new CSSPropTween(target, "transform", 0, 0, null, 2);
4373                                 this._linkCSSP(tpt, null, pt2);
4374                                 tpt.setRatio = (threeD && _supports3D) ? _set3DTransformRatio : _transformProp ? _set2DTransformRatio : _setIETransformRatio;
4375                                 tpt.data = this._transform || _getTransform(target, _cs, true);
4376                                 _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.
4377                         }
4378
4379                         if (_hasPriority) {
4380                                 //reorders the linked list in order of pr (priority)
4381                                 while (pt) {
4382                                         next = pt._next;
4383                                         pt2 = first;
4384                                         while (pt2 && pt2.pr > pt.pr) {
4385                                                 pt2 = pt2._next;
4386                                         }
4387                                         if ((pt._prev = pt2 ? pt2._prev : last)) {
4388                                                 pt._prev._next = pt;
4389                                         } else {
4390                                                 first = pt;
4391                                         }
4392                                         if ((pt._next = pt2)) {
4393                                                 pt2._prev = pt;
4394                                         } else {
4395                                                 last = pt;
4396                                         }
4397                                         pt = next;
4398                                 }
4399                                 this._firstPT = first;
4400                         }
4401                         return true;
4402                 };
4403
4404
4405                 p.parse = function(target, vars, pt, plugin) {
4406                         var style = target.style,
4407                                 p, sp, bn, en, bs, es, bsfx, esfx, isStr, rel;
4408                         for (p in vars) {
4409                                 es = vars[p]; //ending value string
4410                                 sp = _specialProps[p]; //SpecialProp lookup.
4411                                 if (sp) {
4412                                         pt = sp.parse(target, es, p, this, pt, plugin, vars);
4413
4414                                 } else {
4415                                         bs = _getStyle(target, p, _cs) + "";
4416                                         isStr = (typeof(es) === "string");
4417                                         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:
4418                                                 if (!isStr) {
4419                                                         es = _parseColor(es);
4420                                                         es = ((es.length > 3) ? "rgba(" : "rgb(") + es.join(",") + ")";
4421                                                 }
4422                                                 pt = _parseComplex(style, p, bs, es, true, "transparent", pt, 0, plugin);
4423
4424                                         } else if (isStr && (es.indexOf(" ") !== -1 || es.indexOf(",") !== -1)) {
4425                                                 pt = _parseComplex(style, p, bs, es, true, null, pt, 0, plugin);
4426
4427                                         } else {
4428                                                 bn = parseFloat(bs);
4429                                                 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.
4430
4431                                                 if (bs === "" || bs === "auto") {
4432                                                         if (p === "width" || p === "height") {
4433                                                                 bn = _getDimension(target, p, _cs);
4434                                                                 bsfx = "px";
4435                                                         } else if (p === "left" || p === "top") {
4436                                                                 bn = _calculateOffset(target, p, _cs);
4437                                                                 bsfx = "px";
4438                                                         } else {
4439                                                                 bn = (p !== "opacity") ? 0 : 1;
4440                                                                 bsfx = "";
4441                                                         }
4442                                                 }
4443
4444                                                 rel = (isStr && es.charAt(1) === "=");
4445                                                 if (rel) {
4446                                                         en = parseInt(es.charAt(0) + "1", 10);
4447                                                         es = es.substr(2);
4448                                                         en *= parseFloat(es);
4449                                                         esfx = es.replace(_suffixExp, "");
4450                                                 } else {
4451                                                         en = parseFloat(es);
4452                                                         esfx = isStr ? es.substr((en + "").length) || "" : "";
4453                                                 }
4454
4455                                                 if (esfx === "") {
4456                                                         esfx = (p in _suffixMap) ? _suffixMap[p] : bsfx; //populate the end suffix, prioritizing the map, then if none is found, use the beginning suffix.
4457                                                 }
4458
4459                                                 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.
4460
4461                                                 //if the beginning/ending suffixes don't match, normalize them...
4462                                                 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!
4463                                                         bn = _convertToPixels(target, p, bn, bsfx);
4464                                                         if (esfx === "%") {
4465                                                                 bn /= _convertToPixels(target, p, 100, "%") / 100;
4466                                                                 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.
4467                                                                         bs = bn + "%";
4468                                                                 }
4469
4470                                                         } else if (esfx === "em") {
4471                                                                 bn /= _convertToPixels(target, p, 1, "em");
4472
4473                                                         //otherwise convert to pixels.
4474                                                         } else if (esfx !== "px") {
4475                                                                 en = _convertToPixels(target, p, en, esfx);
4476                                                                 esfx = "px"; //we don't use bsfx after this, so we don't need to set it to px too.
4477                                                         }
4478                                                         if (rel) if (en || en === 0) {
4479                                                                 es = (en + bn) + esfx; //the changes we made affect relative calculations, so adjust the end value here.
4480                                                         }
4481                                                 }
4482
4483                                                 if (rel) {
4484                                                         en += bn;
4485                                                 }
4486
4487                                                 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.
4488                                                         pt = new CSSPropTween(style, p, bn, en - bn, pt, 0, p, (_autoRound !== false && (esfx === "px" || p === "zIndex")), 0, bs, es);
4489                                                         pt.xs0 = esfx;
4490                                                         //DEBUG: _log("tween "+p+" from "+pt.b+" ("+bn+esfx+") to "+pt.e+" with suffix: "+pt.xs0);
4491                                                 } else if (style[p] === undefined || !es && (es + "" === "NaN" || es == null)) {
4492                                                         _log("invalid " + p + " tween value: " + vars[p]);
4493                                                 } else {
4494                                                         pt = new CSSPropTween(style, p, en || bn || 0, 0, pt, -1, p, false, 0, bs, es);
4495                                                         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.
4496                                                         //DEBUG: _log("non-tweening value "+p+": "+pt.xs0);
4497                                                 }
4498                                         }
4499                                 }
4500                                 if (plugin) if (pt && !pt.plugin) {
4501                                         pt.plugin = plugin;
4502                                 }
4503                         }
4504                         return pt;
4505                 };
4506
4507
4508                 //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.
4509                 p.setRatio = function(v) {
4510                         var pt = this._firstPT,
4511                                 min = 0.000001,
4512                                 val, str, i;
4513
4514                         //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).
4515                         if (v === 1 && (this._tween._time === this._tween._duration || this._tween._time === 0)) {
4516                                 while (pt) {
4517                                         if (pt.type !== 2) {
4518                                                 pt.t[pt.p] = pt.e;
4519                                         } else {
4520                                                 pt.setRatio(v);
4521                                         }
4522                                         pt = pt._next;
4523                                 }
4524
4525                         } else if (v || !(this._tween._time === this._tween._duration || this._tween._time === 0) || this._tween._rawPrevTime === -0.000001) {
4526                                 while (pt) {
4527                                         val = pt.c * v + pt.s;
4528                                         if (pt.r) {
4529                                                 val = Math.round(val);
4530                                         } else if (val < min) if (val > -min) {
4531                                                 val = 0;
4532                                         }
4533                                         if (!pt.type) {
4534                                                 pt.t[pt.p] = val + pt.xs0;
4535                                         } else if (pt.type === 1) { //complex value (one that typically has multiple numbers inside a string, like "rect(5px,10px,20px,25px)"
4536                                                 i = pt.l;
4537                                                 if (i === 2) {
4538                                                         pt.t[pt.p] = pt.xs0 + val + pt.xs1 + pt.xn1 + pt.xs2;
4539                                                 } else if (i === 3) {
4540                                                         pt.t[pt.p] = pt.xs0 + val + pt.xs1 + pt.xn1 + pt.xs2 + pt.xn2 + pt.xs3;
4541                                                 } else if (i === 4) {
4542                                                         pt.t[pt.p] = pt.xs0 + val + pt.xs1 + pt.xn1 + pt.xs2 + pt.xn2 + pt.xs3 + pt.xn3 + pt.xs4;
4543                                                 } else if (i === 5) {
4544                                                         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;
4545                                                 } else {
4546                                                         str = pt.xs0 + val + pt.xs1;
4547                                                         for (i = 1; i < pt.l; i++) {
4548                                                                 str += pt["xn"+i] + pt["xs"+(i+1)];
4549                                                         }
4550                                                         pt.t[pt.p] = str;
4551                                                 }
4552
4553                                         } else if (pt.type === -1) { //non-tweening value
4554                                                 pt.t[pt.p] = pt.xs0;
4555
4556                                         } else if (pt.setRatio) { //custom setRatio() for things like SpecialProps, external plugins, etc.
4557                                                 pt.setRatio(v);
4558                                         }
4559                                         pt = pt._next;
4560                                 }
4561
4562                         //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).
4563                         } else {
4564                                 while (pt) {
4565                                         if (pt.type !== 2) {
4566                                                 pt.t[pt.p] = pt.b;
4567                                         } else {
4568                                                 pt.setRatio(v);
4569                                         }
4570                                         pt = pt._next;
4571                                 }
4572                         }
4573                 };
4574
4575                 /**
4576                  * @private
4577                  * Forces rendering of the target's transforms (rotation, scale, etc.) whenever the CSSPlugin's setRatio() is called.
4578                  * Basically, this tells the CSSPlugin to create a CSSPropTween (type 2) after instantiation that runs last in the linked
4579                  * list and calls the appropriate (3D or 2D) rendering function. We separate this into its own method so that we can call
4580                  * it from other plugins like BezierPlugin if, for example, it needs to apply an autoRotation and this CSSPlugin
4581                  * doesn't have any transform-related properties of its own. You can call this method as many times as you
4582                  * want and it won't create duplicate CSSPropTweens.
4583                  *
4584                  * @param {boolean} threeD if true, it should apply 3D tweens (otherwise, just 2D ones are fine and typically faster)
4585                  */
4586                 p._enableTransforms = function(threeD) {
4587                         this._transformType = (threeD || this._transformType === 3) ? 3 : 2;
4588                         this._transform = this._transform || _getTransform(this._target, _cs, true); //ensures that the element has a _gsTransform property with the appropriate values.
4589                 };
4590
4591                 var lazySet = function(v) {
4592                         this.t[this.p] = this.e;
4593                         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.
4594                 };
4595                 /** @private Gives us a way to set a value on the first render (and only the first render). **/
4596                 p._addLazySet = function(t, p, v) {
4597                         var pt = this._firstPT = new CSSPropTween(t, p, 0, 0, this._firstPT, 2);
4598                         pt.e = v;
4599                         pt.setRatio = lazySet;
4600                         pt.data = this;
4601                 };
4602
4603                 /** @private **/
4604                 p._linkCSSP = function(pt, next, prev, remove) {
4605                         if (pt) {
4606                                 if (next) {
4607                                         next._prev = pt;
4608                                 }
4609                                 if (pt._next) {
4610                                         pt._next._prev = pt._prev;
4611                                 }
4612                                 if (pt._prev) {
4613                                         pt._prev._next = pt._next;
4614                                 } else if (this._firstPT === pt) {
4615                                         this._firstPT = pt._next;
4616                                         remove = true; //just to prevent resetting this._firstPT 5 lines down in case pt._next is null. (optimized for speed)
4617                                 }
4618                                 if (prev) {
4619                                         prev._next = pt;
4620                                 } else if (!remove && this._firstPT === null) {
4621                                         this._firstPT = pt;
4622                                 }
4623                                 pt._next = next;
4624                                 pt._prev = prev;
4625                         }
4626                         return pt;
4627                 };
4628
4629                 //we need to make sure that if alpha or autoAlpha is killed, opacity is too. And autoAlpha affects the "visibility" property.
4630                 p._kill = function(lookup) {
4631                         var copy = lookup,
4632                                 pt, p, xfirst;
4633                         if (lookup.autoAlpha || lookup.alpha) {
4634                                 copy = {};
4635                                 for (p in lookup) { //copy the lookup so that we're not changing the original which may be passed elsewhere.
4636                                         copy[p] = lookup[p];
4637                                 }
4638                                 copy.opacity = 1;
4639                                 if (copy.autoAlpha) {
4640                                         copy.visibility = 1;
4641                                 }
4642                         }
4643                         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".
4644                                 xfirst = pt.xfirst;
4645                                 if (xfirst && xfirst._prev) {
4646                                         this._linkCSSP(xfirst._prev, pt._next, xfirst._prev._prev); //break off the prev
4647                                 } else if (xfirst === this._firstPT) {
4648                                         this._firstPT = pt._next;
4649                                 }
4650                                 if (pt._next) {
4651                                         this._linkCSSP(pt._next, pt._next._next, xfirst._prev);
4652                                 }
4653                                 this._classNamePT = null;
4654                         }
4655                         return TweenPlugin.prototype._kill.call(this, copy);
4656                 };
4657
4658
4659
4660                 //used by cascadeTo() for gathering all the style properties of each child element into an array for comparison.
4661                 var _getChildStyles = function(e, props, targets) {
4662                                 var children, i, child, type;
4663                                 if (e.slice) {
4664                                         i = e.length;
4665                                         while (--i > -1) {
4666                                                 _getChildStyles(e[i], props, targets);
4667                                         }
4668                                         return;
4669                                 }
4670                                 children = e.childNodes;
4671                                 i = children.length;
4672                                 while (--i > -1) {
4673                                         child = children[i];
4674                                         type = child.type;
4675                                         if (child.style) {
4676                                                 props.push(_getAllStyles(child));
4677                                                 if (targets) {
4678                                                         targets.push(child);
4679                                                 }
4680                                         }
4681                                         if ((type === 1 || type === 9 || type === 11) && child.childNodes.length) {
4682                                                 _getChildStyles(child, props, targets);
4683                                         }
4684                                 }
4685                         };
4686
4687                 /**
4688                  * Typically only useful for className tweens that may affect child elements, this method creates a TweenLite
4689                  * and then compares the style properties of all the target's child elements at the tween's start and end, and
4690                  * if any are different, it also creates tweens for those and returns an array containing ALL of the resulting
4691                  * tweens (so that you can easily add() them to a TimelineLite, for example). The reason this functionality is
4692                  * wrapped into a separate static method of CSSPlugin instead of being integrated into all regular className tweens
4693                  * is because it creates entirely new tweens that may have completely different targets than the original tween,
4694                  * so if they were all lumped into the original tween instance, it would be inconsistent with the rest of the API
4695                  * and it would create other problems. For example:
4696                  *  - 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)
4697                  *  - 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.
4698                  *  - 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.
4699                  *
4700                  * @param {Object} target object to be tweened
4701                  * @param {number} Duration in seconds (or frames for frames-based tweens)
4702                  * @param {Object} Object containing the end values, like {className:"newClass", ease:Linear.easeNone}
4703                  * @return {Array} An array of TweenLite instances
4704                  */
4705                 CSSPlugin.cascadeTo = function(target, duration, vars) {
4706                         var tween = TweenLite.to(target, duration, vars),
4707                                 results = [tween],
4708                                 b = [],
4709                                 e = [],
4710                                 targets = [],
4711                                 _reservedProps = TweenLite._internals.reservedProps,
4712                                 i, difs, p;
4713                         target = tween._targets || tween.target;
4714                         _getChildStyles(target, b, targets);
4715                         tween.render(duration, true);
4716                         _getChildStyles(target, e);
4717                         tween.render(0, true);
4718                         tween._enabled(true);
4719                         i = targets.length;
4720                         while (--i > -1) {
4721                                 difs = _cssDif(targets[i], b[i], e[i]);
4722                                 if (difs.firstMPT) {
4723                                         difs = difs.difs;
4724                                         for (p in vars) {
4725                                                 if (_reservedProps[p]) {
4726                                                         difs[p] = vars[p];
4727                                                 }
4728                                         }
4729                                         results.push( TweenLite.to(targets[i], duration, difs) );
4730                                 }
4731                         }
4732                         return results;
4733                 };
4734
4735                 TweenPlugin.activate([CSSPlugin]);
4736                 return CSSPlugin;
4737
4738         }, true);
4739
4740         
4741         
4742         
4743         
4744         
4745         
4746         
4747         
4748         
4749         
4750 /*
4751  * ----------------------------------------------------------------
4752  * RoundPropsPlugin
4753  * ----------------------------------------------------------------
4754  */
4755         (function() {
4756
4757                 var RoundPropsPlugin = window._gsDefine.plugin({
4758                                 propName: "roundProps",
4759                                 priority: -1,
4760                                 API: 2,
4761
4762                                 //called when the tween renders for the first time. This is where initial values should be recorded and any setup routines should run.
4763                                 init: function(target, value, tween) {
4764                                         this._tween = tween;
4765                                         return true;
4766                                 }
4767
4768                         }),
4769                         p = RoundPropsPlugin.prototype;
4770
4771                 p._onInitAllProps = function() {
4772                         var tween = this._tween,
4773                                 rp = (tween.vars.roundProps instanceof Array) ? tween.vars.roundProps : tween.vars.roundProps.split(","),
4774                                 i = rp.length,
4775                                 lookup = {},
4776                                 rpt = tween._propLookup.roundProps,
4777                                 prop, pt, next;
4778                         while (--i > -1) {
4779                                 lookup[rp[i]] = 1;
4780                         }
4781                         i = rp.length;
4782                         while (--i > -1) {
4783                                 prop = rp[i];
4784                                 pt = tween._firstPT;
4785                                 while (pt) {
4786                                         next = pt._next; //record here, because it may get removed
4787                                         if (pt.pg) {
4788                                                 pt.t._roundProps(lookup, true);
4789                                         } else if (pt.n === prop) {
4790                                                 this._add(pt.t, prop, pt.s, pt.c);
4791                                                 //remove from linked list
4792                                                 if (next) {
4793                                                         next._prev = pt._prev;
4794                                                 }
4795                                                 if (pt._prev) {
4796                                                         pt._prev._next = next;
4797                                                 } else if (tween._firstPT === pt) {
4798                                                         tween._firstPT = next;
4799                                                 }
4800                                                 pt._next = pt._prev = null;
4801                                                 tween._propLookup[prop] = rpt;
4802                                         }
4803                                         pt = next;
4804                                 }
4805                         }
4806                         return false;
4807                 };
4808
4809                 p._add = function(target, p, s, c) {
4810                         this._addTween(target, p, s, s + c, p, true);
4811                         this._overwriteProps.push(p);
4812                 };
4813
4814         }());
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825 /*
4826  * ----------------------------------------------------------------
4827  * AttrPlugin
4828  * ----------------------------------------------------------------
4829  */
4830         window._gsDefine.plugin({
4831                 propName: "attr",
4832                 API: 2,
4833                 version: "0.3.2",
4834
4835                 //called when the tween renders for the first time. This is where initial values should be recorded and any setup routines should run.
4836                 init: function(target, value, tween) {
4837                         var p, start, end;
4838                         if (typeof(target.setAttribute) !== "function") {
4839                                 return false;
4840                         }
4841                         this._target = target;
4842                         this._proxy = {};
4843                         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.
4844                         this._end = {};
4845                         for (p in value) {
4846                                 this._start[p] = this._proxy[p] = start = target.getAttribute(p);
4847                                 end = this._addTween(this._proxy, p, parseFloat(start), value[p], p);
4848                                 this._end[p] = end ? end.s + end.c : value[p];
4849                                 this._overwriteProps.push(p);
4850                         }
4851                         return true;
4852                 },
4853
4854                 //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.)
4855                 set: function(ratio) {
4856                         this._super.setRatio.call(this, ratio);
4857                         var props = this._overwriteProps,
4858                                 i = props.length,
4859                                 lookup = (ratio === 1) ? this._end : ratio ? this._proxy : this._start,
4860                                 p;
4861                         while (--i > -1) {
4862                                 p = props[i];
4863                                 this._target.setAttribute(p, lookup[p] + "");
4864                         }
4865                 }
4866
4867         });
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878 /*
4879  * ----------------------------------------------------------------
4880  * DirectionalRotationPlugin
4881  * ----------------------------------------------------------------
4882  */
4883         window._gsDefine.plugin({
4884                 propName: "directionalRotation",
4885                 API: 2,
4886                 version: "0.2.0",
4887
4888                 //called when the tween renders for the first time. This is where initial values should be recorded and any setup routines should run.
4889                 init: function(target, value, tween) {
4890                         if (typeof(value) !== "object") {
4891                                 value = {rotation:value};
4892                         }
4893                         this.finals = {};
4894                         var cap = (value.useRadians === true) ? Math.PI * 2 : 360,
4895                                 min = 0.000001,
4896                                 p, v, start, end, dif, split;
4897                         for (p in value) {
4898                                 if (p !== "useRadians") {
4899                                         split = (value[p] + "").split("_");
4900                                         v = split[0];
4901                                         start = parseFloat( (typeof(target[p]) !== "function") ? target[p] : target[ ((p.indexOf("set") || typeof(target["get" + p.substr(3)]) !== "function") ? p : "get" + p.substr(3)) ]() );
4902                                         end = this.finals[p] = (typeof(v) === "string" && v.charAt(1) === "=") ? start + parseInt(v.charAt(0) + "1", 10) * Number(v.substr(2)) : Number(v) || 0;
4903                                         dif = end - start;
4904                                         if (split.length) {
4905                                                 v = split.join("_");
4906                                                 if (v.indexOf("short") !== -1) {
4907                                                         dif = dif % cap;
4908                                                         if (dif !== dif % (cap / 2)) {
4909                                                                 dif = (dif < 0) ? dif + cap : dif - cap;
4910                                                         }
4911                                                 }
4912                                                 if (v.indexOf("_cw") !== -1 && dif < 0) {
4913                                                         dif = ((dif + cap * 9999999999) % cap) - ((dif / cap) | 0) * cap;
4914                                                 } else if (v.indexOf("ccw") !== -1 && dif > 0) {
4915                                                         dif = ((dif - cap * 9999999999) % cap) - ((dif / cap) | 0) * cap;
4916                                                 }
4917                                         }
4918                                         if (dif > min || dif < -min) {
4919                                                 this._addTween(target, p, start, start + dif, p);
4920                                                 this._overwriteProps.push(p);
4921                                         }
4922                                 }
4923                         }
4924                         return true;
4925                 },
4926
4927                 //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.)
4928                 set: function(ratio) {
4929                         var pt;
4930                         if (ratio !== 1) {
4931                                 this._super.setRatio.call(this, ratio);
4932                         } else {
4933                                 pt = this._firstPT;
4934                                 while (pt) {
4935                                         if (pt.f) {
4936                                                 pt.t[pt.p](this.finals[pt.p]);
4937                                         } else {
4938                                                 pt.t[pt.p] = this.finals[pt.p];
4939                                         }
4940                                         pt = pt._next;
4941                                 }
4942                         }
4943                 }
4944
4945         })._autoCSS = true;
4946
4947
4948
4949
4950
4951
4952
4953         
4954         
4955         
4956         
4957 /*
4958  * ----------------------------------------------------------------
4959  * EasePack
4960  * ----------------------------------------------------------------
4961  */
4962         window._gsDefine("easing.Back", ["easing.Ease"], function(Ease) {
4963                 
4964                 var w = (window.GreenSockGlobals || window),
4965                         gs = w.com.greensock,
4966                         _2PI = Math.PI * 2,
4967                         _HALF_PI = Math.PI / 2,
4968                         _class = gs._class,
4969                         _create = function(n, f) {
4970                                 var C = _class("easing." + n, function(){}, true),
4971                                         p = C.prototype = new Ease();
4972                                 p.constructor = C;
4973                                 p.getRatio = f;
4974                                 return C;
4975                         },
4976                         _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.
4977                         _wrap = function(name, EaseOut, EaseIn, EaseInOut, aliases) {
4978                                 var C = _class("easing."+name, {
4979                                         easeOut:new EaseOut(),
4980                                         easeIn:new EaseIn(),
4981                                         easeInOut:new EaseInOut()
4982                                 }, true);
4983                                 _easeReg(C, name);
4984                                 return C;
4985                         },
4986                         EasePoint = function(time, value, next) {
4987                                 this.t = time;
4988                                 this.v = value;
4989                                 if (next) {
4990                                         this.next = next;
4991                                         next.prev = this;
4992                                         this.c = next.v - value;
4993                                         this.gap = next.t - time;
4994                                 }
4995                         },
4996
4997                         //Back
4998                         _createBack = function(n, f) {
4999                                 var C = _class("easing." + n, function(overshoot) {
5000                                                 this._p1 = (overshoot || overshoot === 0) ? overshoot : 1.70158;
5001                                                 this._p2 = this._p1 * 1.525;
5002                                         }, true),
5003                                         p = C.prototype = new Ease();
5004                                 p.constructor = C;
5005                                 p.getRatio = f;
5006                                 p.config = function(overshoot) {
5007                                         return new C(overshoot);
5008                                 };
5009                                 return C;
5010                         },
5011
5012                         Back = _wrap("Back",
5013                                 _createBack("BackOut", function(p) {
5014                                         return ((p = p - 1) * p * ((this._p1 + 1) * p + this._p1) + 1);
5015                                 }),
5016                                 _createBack("BackIn", function(p) {
5017                                         return p * p * ((this._p1 + 1) * p - this._p1);
5018                                 }),
5019                                 _createBack("BackInOut", function(p) {
5020                                         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);
5021                                 })
5022                         ),
5023
5024
5025                         //SlowMo
5026                         SlowMo = _class("easing.SlowMo", function(linearRatio, power, yoyoMode) {
5027                                 power = (power || power === 0) ? power : 0.7;
5028                                 if (linearRatio == null) {
5029                                         linearRatio = 0.7;
5030                                 } else if (linearRatio > 1) {
5031                                         linearRatio = 1;
5032                                 }
5033                                 this._p = (linearRatio !== 1) ? power : 0;
5034                                 this._p1 = (1 - linearRatio) / 2;
5035                                 this._p2 = linearRatio;
5036                                 this._p3 = this._p1 + this._p2;
5037                                 this._calcEnd = (yoyoMode === true);
5038                         }, true),
5039                         p = SlowMo.prototype = new Ease(),
5040                         SteppedEase, RoughEase, _createElastic;
5041
5042                 p.constructor = SlowMo;
5043                 p.getRatio = function(p) {
5044                         var r = p + (0.5 - p) * this._p;
5045                         if (p < this._p1) {
5046                                 return this._calcEnd ? 1 - ((p = 1 - (p / this._p1)) * p) : r - ((p = 1 - (p / this._p1)) * p * p * p * r);
5047                         } else if (p > this._p3) {
5048                                 return this._calcEnd ? 1 - (p = (p - this._p3) / this._p1) * p : r + ((p - r) * (p = (p - this._p3) / this._p1) * p * p * p);
5049                         }
5050                         return this._calcEnd ? 1 : r;
5051                 };
5052                 SlowMo.ease = new SlowMo(0.7, 0.7);
5053
5054                 p.config = SlowMo.config = function(linearRatio, power, yoyoMode) {
5055                         return new SlowMo(linearRatio, power, yoyoMode);
5056                 };
5057
5058
5059                 //SteppedEase
5060                 SteppedEase = _class("easing.SteppedEase", function(steps) {
5061                                 steps = steps || 1;
5062                                 this._p1 = 1 / steps;
5063                                 this._p2 = steps + 1;
5064                         }, true);
5065                 p = SteppedEase.prototype = new Ease();
5066                 p.constructor = SteppedEase;
5067                 p.getRatio = function(p) {
5068                         if (p < 0) {
5069                                 p = 0;
5070                         } else if (p >= 1) {
5071                                 p = 0.999999999;
5072                         }
5073                         return ((this._p2 * p) >> 0) * this._p1;
5074                 };
5075                 p.config = SteppedEase.config = function(steps) {
5076                         return new SteppedEase(steps);
5077                 };
5078
5079
5080                 //RoughEase
5081                 RoughEase = _class("easing.RoughEase", function(vars) {
5082                         vars = vars || {};
5083                         var taper = vars.taper || "none",
5084                                 a = [],
5085                                 cnt = 0,
5086                                 points = (vars.points || 20) | 0,
5087                                 i = points,
5088                                 randomize = (vars.randomize !== false),
5089                                 clamp = (vars.clamp === true),
5090                                 template = (vars.template instanceof Ease) ? vars.template : null,
5091                                 strength = (typeof(vars.strength) === "number") ? vars.strength * 0.4 : 0.4,
5092                                 x, y, bump, invX, obj, pnt;
5093                         while (--i > -1) {
5094                                 x = randomize ? Math.random() : (1 / points) * i;
5095                                 y = template ? template.getRatio(x) : x;
5096                                 if (taper === "none") {
5097                                         bump = strength;
5098                                 } else if (taper === "out") {
5099                                         invX = 1 - x;
5100                                         bump = invX * invX * strength;
5101                                 } else if (taper === "in") {
5102                                         bump = x * x * strength;
5103                                 } else if (x < 0.5) {  //"both" (start)
5104                                         invX = x * 2;
5105                                         bump = invX * invX * 0.5 * strength;
5106                                 } else {                                //"both" (end)
5107                                         invX = (1 - x) * 2;
5108                                         bump = invX * invX * 0.5 * strength;
5109                                 }
5110                                 if (randomize) {
5111                                         y += (Math.random() * bump) - (bump * 0.5);
5112                                 } else if (i % 2) {
5113                                         y += bump * 0.5;
5114                                 } else {
5115                                         y -= bump * 0.5;
5116                                 }
5117                                 if (clamp) {
5118                                         if (y > 1) {
5119                                                 y = 1;
5120                                         } else if (y < 0) {
5121                                                 y = 0;
5122                                         }
5123                                 }
5124                                 a[cnt++] = {x:x, y:y};
5125                         }
5126                         a.sort(function(a, b) {
5127                                 return a.x - b.x;
5128                         });
5129
5130                         pnt = new EasePoint(1, 1, null);
5131                         i = points;
5132                         while (--i > -1) {
5133                                 obj = a[i];
5134                                 pnt = new EasePoint(obj.x, obj.y, pnt);
5135                         }
5136
5137                         this._prev = new EasePoint(0, 0, (pnt.t !== 0) ? pnt : pnt.next);
5138                 }, true);
5139                 p = RoughEase.prototype = new Ease();
5140                 p.constructor = RoughEase;
5141                 p.getRatio = function(p) {
5142                         var pnt = this._prev;
5143                         if (p > pnt.t) {
5144                                 while (pnt.next && p >= pnt.t) {
5145                                         pnt = pnt.next;
5146                                 }
5147                                 pnt = pnt.prev;
5148                         } else {
5149                                 while (pnt.prev && p <= pnt.t) {
5150                                         pnt = pnt.prev;
5151                                 }
5152                         }
5153                         this._prev = pnt;
5154                         return (pnt.v + ((p - pnt.t) / pnt.gap) * pnt.c);
5155                 };
5156                 p.config = function(vars) {
5157                         return new RoughEase(vars);
5158                 };
5159                 RoughEase.ease = new RoughEase();
5160
5161
5162                 //Bounce
5163                 _wrap("Bounce",
5164                         _create("BounceOut", function(p) {
5165                                 if (p < 1 / 2.75) {
5166                                         return 7.5625 * p * p;
5167                                 } else if (p < 2 / 2.75) {
5168                                         return 7.5625 * (p -= 1.5 / 2.75) * p + 0.75;
5169                                 } else if (p < 2.5 / 2.75) {
5170                                         return 7.5625 * (p -= 2.25 / 2.75) * p + 0.9375;
5171                                 }
5172                                 return 7.5625 * (p -= 2.625 / 2.75) * p + 0.984375;
5173                         }),
5174                         _create("BounceIn", function(p) {
5175                                 if ((p = 1 - p) < 1 / 2.75) {
5176                                         return 1 - (7.5625 * p * p);
5177                                 } else if (p < 2 / 2.75) {
5178                                         return 1 - (7.5625 * (p -= 1.5 / 2.75) * p + 0.75);
5179                                 } else if (p < 2.5 / 2.75) {
5180                                         return 1 - (7.5625 * (p -= 2.25 / 2.75) * p + 0.9375);
5181                                 }
5182                                 return 1 - (7.5625 * (p -= 2.625 / 2.75) * p + 0.984375);
5183                         }),
5184                         _create("BounceInOut", function(p) {
5185                                 var invert = (p < 0.5);
5186                                 if (invert) {
5187                                         p = 1 - (p * 2);
5188                                 } else {
5189                                         p = (p * 2) - 1;
5190                                 }
5191                                 if (p < 1 / 2.75) {
5192                                         p = 7.5625 * p * p;
5193                                 } else if (p < 2 / 2.75) {
5194                                         p = 7.5625 * (p -= 1.5 / 2.75) * p + 0.75;
5195                                 } else if (p < 2.5 / 2.75) {
5196                                         p = 7.5625 * (p -= 2.25 / 2.75) * p + 0.9375;
5197                                 } else {
5198                                         p = 7.5625 * (p -= 2.625 / 2.75) * p + 0.984375;
5199                                 }
5200                                 return invert ? (1 - p) * 0.5 : p * 0.5 + 0.5;
5201                         })
5202                 );
5203
5204
5205                 //CIRC
5206                 _wrap("Circ",
5207                         _create("CircOut", function(p) {
5208                                 return Math.sqrt(1 - (p = p - 1) * p);
5209                         }),
5210                         _create("CircIn", function(p) {
5211                                 return -(Math.sqrt(1 - (p * p)) - 1);
5212                         }),
5213                         _create("CircInOut", function(p) {
5214                                 return ((p*=2) < 1) ? -0.5 * (Math.sqrt(1 - p * p) - 1) : 0.5 * (Math.sqrt(1 - (p -= 2) * p) + 1);
5215                         })
5216                 );
5217
5218
5219                 //Elastic
5220                 _createElastic = function(n, f, def) {
5221                         var C = _class("easing." + n, function(amplitude, period) {
5222                                         this._p1 = amplitude || 1;
5223                                         this._p2 = period || def;
5224                                         this._p3 = this._p2 / _2PI * (Math.asin(1 / this._p1) || 0);
5225                                 }, true),
5226                                 p = C.prototype = new Ease();
5227                         p.constructor = C;
5228                         p.getRatio = f;
5229                         p.config = function(amplitude, period) {
5230                                 return new C(amplitude, period);
5231                         };
5232                         return C;
5233                 };
5234                 _wrap("Elastic",
5235                         _createElastic("ElasticOut", function(p) {
5236                                 return this._p1 * Math.pow(2, -10 * p) * Math.sin( (p - this._p3) * _2PI / this._p2 ) + 1;
5237                         }, 0.3),
5238                         _createElastic("ElasticIn", function(p) {
5239                                 return -(this._p1 * Math.pow(2, 10 * (p -= 1)) * Math.sin( (p - this._p3) * _2PI / this._p2 ));
5240                         }, 0.3),
5241                         _createElastic("ElasticInOut", function(p) {
5242                                 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;
5243                         }, 0.45)
5244                 );
5245
5246
5247                 //Expo
5248                 _wrap("Expo",
5249                         _create("ExpoOut", function(p) {
5250                                 return 1 - Math.pow(2, -10 * p);
5251                         }),
5252                         _create("ExpoIn", function(p) {
5253                                 return Math.pow(2, 10 * (p - 1)) - 0.001;
5254                         }),
5255                         _create("ExpoInOut", function(p) {
5256                                 return ((p *= 2) < 1) ? 0.5 * Math.pow(2, 10 * (p - 1)) : 0.5 * (2 - Math.pow(2, -10 * (p - 1)));
5257                         })
5258                 );
5259
5260
5261                 //Sine
5262                 _wrap("Sine",
5263                         _create("SineOut", function(p) {
5264                                 return Math.sin(p * _HALF_PI);
5265                         }),
5266                         _create("SineIn", function(p) {
5267                                 return -Math.cos(p * _HALF_PI) + 1;
5268                         }),
5269                         _create("SineInOut", function(p) {
5270                                 return -0.5 * (Math.cos(Math.PI * p) - 1);
5271                         })
5272                 );
5273
5274                 _class("easing.EaseLookup", {
5275                                 find:function(s) {
5276                                         return Ease.map[s];
5277                                 }
5278                         }, true);
5279
5280                 //register the non-standard eases
5281                 _easeReg(w.SlowMo, "SlowMo", "ease,");
5282                 _easeReg(RoughEase, "RoughEase", "ease,");
5283                 _easeReg(SteppedEase, "SteppedEase", "ease,");
5284
5285                 return Back;
5286                 
5287         }, true);
5288
5289
5290 }); 
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302 /*
5303  * ----------------------------------------------------------------
5304  * Base classes like TweenLite, SimpleTimeline, Ease, Ticker, etc.
5305  * ----------------------------------------------------------------
5306  */
5307 (function(window) {
5308
5309                 "use strict";
5310                 var _globals = window.GreenSockGlobals || window;
5311                 if (_globals.TweenLite) {
5312                         return; //in case the core set of classes is already loaded, don't instantiate twice.
5313                 }
5314                 var _namespace = function(ns) {
5315                                 var a = ns.split("."),
5316                                         p = _globals, i;
5317                                 for (i = 0; i < a.length; i++) {
5318                                         p[a[i]] = p = p[a[i]] || {};
5319                                 }
5320                                 return p;
5321                         },
5322                         gs = _namespace("com.greensock"),
5323                         _tinyNum = 0.0000000001,
5324                         _slice = [].slice,
5325                         _emptyFunc = function() {},
5326                         _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)
5327                                 var toString = Object.prototype.toString,
5328                                         array = toString.call([]);
5329                                 return function(obj) {
5330                                         return obj != null && (obj instanceof Array || (typeof(obj) === "object" && !!obj.push && toString.call(obj) === array));
5331                                 };
5332                         }()),
5333                         a, i, p, _ticker, _tickerActive,
5334                         _defLookup = {},
5335
5336                         /**
5337                          * @constructor
5338                          * Defines a GreenSock class, optionally with an array of dependencies that must be instantiated first and passed into the definition.
5339                          * This allows users to load GreenSock JS files in any order even if they have interdependencies (like CSSPlugin extends TweenPlugin which is
5340                          * inside TweenLite.js, but if CSSPlugin is loaded first, it should wait to run its code until TweenLite.js loads and instantiates TweenPlugin
5341                          * and then pass TweenPlugin to CSSPlugin's definition). This is all done automatically and internally.
5342                          *
5343                          * Every definition will be added to a "com.greensock" global object (typically window, but if a window.GreenSockGlobals object is found,
5344                          * 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,
5345                          * it is ALSO referenced at window.TweenLite. However some classes aren't considered global, like the base com.greensock.core.Animation class, so
5346                          * those will only be at the package like window.com.greensock.core.Animation. Again, if you define a GreenSockGlobals object on the window, everything
5347                          * gets tucked neatly inside there instead of on the window directly. This allows you to do advanced things like load multiple versions of GreenSock
5348                          * 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
5349                          * sandbox the banner one like:
5350                          *
5351                          * <script>
5352                          *     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.
5353                          * </script>
5354                          * <script src="js/greensock/v1.7/TweenMax.js"></script>
5355                          * <script>
5356                          *     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(...)
5357                          * </script>
5358                          * <script src="js/greensock/v1.6/TweenMax.js"></script>
5359                          * <script>
5360                          *     gs.TweenLite.to(...); //would use v1.7
5361                          *     TweenLite.to(...); //would use v1.6
5362                          * </script>
5363                          *
5364                          * @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".
5365                          * @param {!Array.<string>} dependencies An array of dependencies (described as their namespaces minus "com.greensock." prefix). For example ["TweenLite","plugins.TweenPlugin","core.Animation"]
5366                          * @param {!function():Object} func The function that should be called and passed the resolved dependencies which will return the actual class for this definition.
5367                          * @param {boolean=} global If true, the class will be added to the global scope (typically window unless you define a window.GreenSockGlobals object)
5368                          */
5369                         Definition = function(ns, dependencies, func, global) {
5370                                 this.sc = (_defLookup[ns]) ? _defLookup[ns].sc : []; //subclasses
5371                                 _defLookup[ns] = this;
5372                                 this.gsClass = null;
5373                                 this.func = func;
5374                                 var _classes = [];
5375                                 this.check = function(init) {
5376                                         var i = dependencies.length,
5377                                                 missing = i,
5378                                                 cur, a, n, cl;
5379                                         while (--i > -1) {
5380                                                 if ((cur = _defLookup[dependencies[i]] || new Definition(dependencies[i], [])).gsClass) {
5381                                                         _classes[i] = cur.gsClass;
5382                                                         missing--;
5383                                                 } else if (init) {
5384                                                         cur.sc.push(this);
5385                                                 }
5386                                         }
5387                                         if (missing === 0 && func) {
5388                                                 a = ("com.greensock." + ns).split(".");
5389                                                 n = a.pop();
5390                                                 cl = _namespace(a.join("."))[n] = this.gsClass = func.apply(func, _classes);
5391
5392                                                 //exports to multiple environments
5393                                                 if (global) {
5394                                                         _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.)
5395                                                         if (typeof(define) === "function" && define.amd){ //AMD
5396                                                                 define((window.GreenSockAMDPath ? window.GreenSockAMDPath + "/" : "") + ns.split(".").join("/"), [], function() { return cl; });
5397                                                         } else if (typeof(module) !== "undefined" && module.exports){ //node
5398                                                                 module.exports = cl;
5399                                                         }
5400                                                 }
5401                                                 for (i = 0; i < this.sc.length; i++) {
5402                                                         this.sc[i].check();
5403                                                 }
5404                                         }
5405                                 };
5406                                 this.check(true);
5407                         },
5408
5409                         //used to create Definition instances (which basically registers a class that has dependencies).
5410                         _gsDefine = window._gsDefine = function(ns, dependencies, func, global) {
5411                                 return new Definition(ns, dependencies, func, global);
5412                         },
5413
5414                         //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).
5415                         _class = gs._class = function(ns, func, global) {
5416                                 func = func || function() {};
5417                                 _gsDefine(ns, [], function(){ return func; }, global);
5418                                 return func;
5419                         };
5420
5421                 _gsDefine.globals = _globals;
5422
5423
5424
5425 /*
5426  * ----------------------------------------------------------------
5427  * Ease
5428  * ----------------------------------------------------------------
5429  */
5430                 var _baseParams = [0, 0, 1, 1],
5431                         _blankArray = [],
5432                         Ease = _class("easing.Ease", function(func, extraParams, type, power) {
5433                                 this._func = func;
5434                                 this._type = type || 0;
5435                                 this._power = power || 0;
5436                                 this._params = extraParams ? _baseParams.concat(extraParams) : _baseParams;
5437                         }, true),
5438                         _easeMap = Ease.map = {},
5439                         _easeReg = Ease.register = function(ease, names, types, create) {
5440                                 var na = names.split(","),
5441                                         i = na.length,
5442                                         ta = (types || "easeIn,easeOut,easeInOut").split(","),
5443                                         e, name, j, type;
5444                                 while (--i > -1) {
5445                                         name = na[i];
5446                                         e = create ? _class("easing."+name, null, true) : gs.easing[name] || {};
5447                                         j = ta.length;
5448                                         while (--j > -1) {
5449                                                 type = ta[j];
5450                                                 _easeMap[name + "." + type] = _easeMap[type + name] = e[type] = ease.getRatio ? ease : ease[type] || new ease();
5451                                         }
5452                                 }
5453                         };
5454
5455                 p = Ease.prototype;
5456                 p._calcEnd = false;
5457                 p.getRatio = function(p) {
5458                         if (this._func) {
5459                                 this._params[0] = p;
5460                                 return this._func.apply(null, this._params);
5461                         }
5462                         var t = this._type,
5463                                 pw = this._power,
5464                                 r = (t === 1) ? 1 - p : (t === 2) ? p : (p < 0.5) ? p * 2 : (1 - p) * 2;
5465                         if (pw === 1) {
5466                                 r *= r;
5467                         } else if (pw === 2) {
5468                                 r *= r * r;
5469                         } else if (pw === 3) {
5470                                 r *= r * r * r;
5471                         } else if (pw === 4) {
5472                                 r *= r * r * r * r;
5473                         }
5474                         return (t === 1) ? 1 - r : (t === 2) ? r : (p < 0.5) ? r / 2 : 1 - (r / 2);
5475                 };
5476
5477                 //create all the standard eases like Linear, Quad, Cubic, Quart, Quint, Strong, Power0, Power1, Power2, Power3, and Power4 (each with easeIn, easeOut, and easeInOut)
5478                 a = ["Linear","Quad","Cubic","Quart","Quint,Strong"];
5479                 i = a.length;
5480                 while (--i > -1) {
5481                         p = a[i]+",Power"+i;
5482                         _easeReg(new Ease(null,null,1,i), p, "easeOut", true);
5483                         _easeReg(new Ease(null,null,2,i), p, "easeIn" + ((i === 0) ? ",easeNone" : ""));
5484                         _easeReg(new Ease(null,null,3,i), p, "easeInOut");
5485                 }
5486                 _easeMap.linear = gs.easing.Linear.easeIn;
5487                 _easeMap.swing = gs.easing.Quad.easeInOut; //for jQuery folks
5488
5489
5490 /*
5491  * ----------------------------------------------------------------
5492  * EventDispatcher
5493  * ----------------------------------------------------------------
5494  */
5495                 var EventDispatcher = _class("events.EventDispatcher", function(target) {
5496                         this._listeners = {};
5497                         this._eventTarget = target || this;
5498                 });
5499                 p = EventDispatcher.prototype;
5500
5501                 p.addEventListener = function(type, callback, scope, useParam, priority) {
5502                         priority = priority || 0;
5503                         var list = this._listeners[type],
5504                                 index = 0,
5505                                 listener, i;
5506                         if (list == null) {
5507                                 this._listeners[type] = list = [];
5508                         }
5509                         i = list.length;
5510                         while (--i > -1) {
5511                                 listener = list[i];
5512                                 if (listener.c === callback && listener.s === scope) {
5513                                         list.splice(i, 1);
5514                                 } else if (index === 0 && listener.pr < priority) {
5515                                         index = i + 1;
5516                                 }
5517                         }
5518                         list.splice(index, 0, {c:callback, s:scope, up:useParam, pr:priority});
5519                         if (this === _ticker && !_tickerActive) {
5520                                 _ticker.wake();
5521                         }
5522                 };
5523
5524                 p.removeEventListener = function(type, callback) {
5525                         var list = this._listeners[type], i;
5526                         if (list) {
5527                                 i = list.length;
5528                                 while (--i > -1) {
5529                                         if (list[i].c === callback) {
5530                                                 list.splice(i, 1);
5531                                                 return;
5532                                         }
5533                                 }
5534                         }
5535                 };
5536
5537                 p.dispatchEvent = function(type) {
5538                         var list = this._listeners[type],
5539                                 i, t, listener;
5540                         if (list) {
5541                                 i = list.length;
5542                                 t = this._eventTarget;
5543                                 while (--i > -1) {
5544                                         listener = list[i];
5545                                         if (listener.up) {
5546                                                 listener.c.call(listener.s || t, {type:type, target:t});
5547                                         } else {
5548                                                 listener.c.call(listener.s || t);
5549                                         }
5550                                 }
5551                         }
5552                 };
5553
5554
5555 /*
5556  * ----------------------------------------------------------------
5557  * Ticker
5558  * ----------------------------------------------------------------
5559  */
5560                 var _reqAnimFrame = window.requestAnimationFrame,
5561                         _cancelAnimFrame = window.cancelAnimationFrame,
5562                         _getTime = Date.now || function() {return new Date().getTime();},
5563                         _lastUpdate = _getTime();
5564
5565                 //now try to determine the requestAnimationFrame and cancelAnimationFrame functions and if none are found, we'll use a setTimeout()/clearTimeout() polyfill.
5566                 a = ["ms","moz","webkit","o"];
5567                 i = a.length;
5568                 while (--i > -1 && !_reqAnimFrame) {
5569                         _reqAnimFrame = window[a[i] + "RequestAnimationFrame"];
5570                         _cancelAnimFrame = window[a[i] + "CancelAnimationFrame"] || window[a[i] + "CancelRequestAnimationFrame"];
5571                 }
5572
5573                 _class("Ticker", function(fps, useRAF) {
5574                         var _self = this,
5575                                 _startTime = _getTime(),
5576                                 _useRAF = (useRAF !== false && _reqAnimFrame),
5577                                 _lagThreshold = 500,
5578                                 _adjustedLag = 33,
5579                                 _fps, _req, _id, _gap, _nextTime,
5580                                 _tick = function(manual) {
5581                                         var elapsed = _getTime() - _lastUpdate,
5582                                                 overlap, dispatch;
5583                                         if (elapsed > _lagThreshold) {
5584                                                 _startTime += elapsed - _adjustedLag;
5585                                         }
5586                                         _lastUpdate += elapsed;
5587                                         _self.time = (_lastUpdate - _startTime) / 1000;
5588                                         overlap = _self.time - _nextTime;
5589                                         if (!_fps || overlap > 0 || manual === true) {
5590                                                 _self.frame++;
5591                                                 _nextTime += overlap + (overlap >= _gap ? 0.004 : _gap - overlap);
5592                                                 dispatch = true;
5593                                         }
5594                                         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.
5595                                                 _id = _req(_tick);
5596                                         }
5597                                         if (dispatch) {
5598                                                 _self.dispatchEvent("tick");
5599                                         }
5600                                 };
5601
5602                         EventDispatcher.call(_self);
5603                         _self.time = _self.frame = 0;
5604                         _self.tick = function() {
5605                                 _tick(true);
5606                         };
5607
5608                         _self.lagSmoothing = function(threshold, adjustedLag) {
5609                                 _lagThreshold = threshold || (1 / _tinyNum); //zero should be interpreted as basically unlimited
5610                                 _adjustedLag = Math.min(adjustedLag, _lagThreshold, 0);
5611                         };
5612
5613                         _self.sleep = function() {
5614                                 if (_id == null) {
5615                                         return;
5616                                 }
5617                                 if (!_useRAF || !_cancelAnimFrame) {
5618                                         clearTimeout(_id);
5619                                 } else {
5620                                         _cancelAnimFrame(_id);
5621                                 }
5622                                 _req = _emptyFunc;
5623                                 _id = null;
5624                                 if (_self === _ticker) {
5625                                         _tickerActive = false;
5626                                 }
5627                         };
5628
5629                         _self.wake = function() {
5630                                 if (_id !== null) {
5631                                         _self.sleep();
5632                                 } 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().
5633                                         _lastUpdate = _getTime() - _lagThreshold + 5;
5634                                 }
5635                                 _req = (_fps === 0) ? _emptyFunc : (!_useRAF || !_reqAnimFrame) ? function(f) { return setTimeout(f, ((_nextTime - _self.time) * 1000 + 1) | 0); } : _reqAnimFrame;
5636                                 if (_self === _ticker) {
5637                                         _tickerActive = true;
5638                                 }
5639                                 _tick(2);
5640                         };
5641
5642                         _self.fps = function(value) {
5643                                 if (!arguments.length) {
5644                                         return _fps;
5645                                 }
5646                                 _fps = value;
5647                                 _gap = 1 / (_fps || 60);
5648                                 _nextTime = this.time + _gap;
5649                                 _self.wake();
5650                         };
5651
5652                         _self.useRAF = function(value) {
5653                                 if (!arguments.length) {
5654                                         return _useRAF;
5655                                 }
5656                                 _self.sleep();
5657                                 _useRAF = value;
5658                                 _self.fps(_fps);
5659                         };
5660                         _self.fps(fps);
5661
5662                         //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.
5663                         setTimeout(function() {
5664                                 if (_useRAF && (!_id || _self.frame < 5)) {
5665                                         _self.useRAF(false);
5666                                 }
5667                         }, 1500);
5668                 });
5669
5670                 p = gs.Ticker.prototype = new gs.events.EventDispatcher();
5671                 p.constructor = gs.Ticker;
5672
5673
5674 /*
5675  * ----------------------------------------------------------------
5676  * Animation
5677  * ----------------------------------------------------------------
5678  */
5679                 var Animation = _class("core.Animation", function(duration, vars) {
5680                                 this.vars = vars = vars || {};
5681                                 this._duration = this._totalDuration = duration || 0;
5682                                 this._delay = Number(vars.delay) || 0;
5683                                 this._timeScale = 1;
5684                                 this._active = (vars.immediateRender === true);
5685                                 this.data = vars.data;
5686                                 this._reversed = (vars.reversed === true);
5687
5688                                 if (!_rootTimeline) {
5689                                         return;
5690                                 }
5691                                 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.
5692                                         _ticker.wake();
5693                                 }
5694
5695                                 var tl = this.vars.useFrames ? _rootFramesTimeline : _rootTimeline;
5696                                 tl.add(this, tl._time);
5697
5698                                 if (this.vars.paused) {
5699                                         this.paused(true);
5700                                 }
5701                         });
5702
5703                 _ticker = Animation.ticker = new gs.Ticker();
5704                 p = Animation.prototype;
5705                 p._dirty = p._gc = p._initted = p._paused = false;
5706                 p._totalTime = p._time = 0;
5707                 p._rawPrevTime = -1;
5708                 p._next = p._last = p._onUpdate = p._timeline = p.timeline = null;
5709                 p._paused = false;
5710
5711
5712                 //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.
5713                 var _checkTimeout = function() {
5714                                 if (_tickerActive && _getTime() - _lastUpdate > 2000) {
5715                                         _ticker.wake();
5716                                 }
5717                                 setTimeout(_checkTimeout, 2000);
5718                         };
5719                 _checkTimeout();
5720
5721
5722                 p.play = function(from, suppressEvents) {
5723                         if (from != null) {
5724                                 this.seek(from, suppressEvents);
5725                         }
5726                         return this.reversed(false).paused(false);
5727                 };
5728
5729                 p.pause = function(atTime, suppressEvents) {
5730                         if (atTime != null) {
5731                                 this.seek(atTime, suppressEvents);
5732                         }
5733                         return this.paused(true);
5734                 };
5735
5736                 p.resume = function(from, suppressEvents) {
5737                         if (from != null) {
5738                                 this.seek(from, suppressEvents);
5739                         }
5740                         return this.paused(false);
5741                 };
5742
5743                 p.seek = function(time, suppressEvents) {
5744                         return this.totalTime(Number(time), suppressEvents !== false);
5745                 };
5746
5747                 p.restart = function(includeDelay, suppressEvents) {
5748                         return this.reversed(false).paused(false).totalTime(includeDelay ? -this._delay : 0, (suppressEvents !== false), true);
5749                 };
5750
5751                 p.reverse = function(from, suppressEvents) {
5752                         if (from != null) {
5753                                 this.seek((from || this.totalDuration()), suppressEvents);
5754                         }
5755                         return this.reversed(true).paused(false);
5756                 };
5757
5758                 p.render = function(time, suppressEvents, force) {
5759                         //stub - we override this method in subclasses.
5760                 };
5761
5762                 p.invalidate = function() {
5763                         return this;
5764                 };
5765
5766                 p.isActive = function() {
5767                         var tl = this._timeline, //the 2 root timelines won't have a _timeline; they're always active.
5768                                 startTime = this._startTime,
5769                                 rawTime;
5770                         return (!tl || (!this._gc && !this._paused && tl.isActive() && (rawTime = tl.rawTime()) >= startTime && rawTime < startTime + this.totalDuration() / this._timeScale));
5771                 };
5772
5773                 p._enabled = function (enabled, ignoreTimeline) {
5774                         if (!_tickerActive) {
5775                                 _ticker.wake();
5776                         }
5777                         this._gc = !enabled;
5778                         this._active = this.isActive();
5779                         if (ignoreTimeline !== true) {
5780                                 if (enabled && !this.timeline) {
5781                                         this._timeline.add(this, this._startTime - this._delay);
5782                                 } else if (!enabled && this.timeline) {
5783                                         this._timeline._remove(this, true);
5784                                 }
5785                         }
5786                         return false;
5787                 };
5788
5789
5790                 p._kill = function(vars, target) {
5791                         return this._enabled(false, false);
5792                 };
5793
5794                 p.kill = function(vars, target) {
5795                         this._kill(vars, target);
5796                         return this;
5797                 };
5798
5799                 p._uncache = function(includeSelf) {
5800                         var tween = includeSelf ? this : this.timeline;
5801                         while (tween) {
5802                                 tween._dirty = true;
5803                                 tween = tween.timeline;
5804                         }
5805                         return this;
5806                 };
5807
5808                 p._swapSelfInParams = function(params) {
5809                         var i = params.length,
5810                                 copy = params.concat();
5811                         while (--i > -1) {
5812                                 if (params[i] === "{self}") {
5813                                         copy[i] = this;
5814                                 }
5815                         }
5816                         return copy;
5817                 };
5818
5819 //----Animation getters/setters --------------------------------------------------------
5820
5821                 p.eventCallback = function(type, callback, params, scope) {
5822                         if ((type || "").substr(0,2) === "on") {
5823                                 var v = this.vars;
5824                                 if (arguments.length === 1) {
5825                                         return v[type];
5826                                 }
5827                                 if (callback == null) {
5828                                         delete v[type];
5829                                 } else {
5830                                         v[type] = callback;
5831                                         v[type + "Params"] = (_isArray(params) && params.join("").indexOf("{self}") !== -1) ? this._swapSelfInParams(params) : params;
5832                                         v[type + "Scope"] = scope;
5833                                 }
5834                                 if (type === "onUpdate") {
5835                                         this._onUpdate = callback;
5836                                 }
5837                         }
5838                         return this;
5839                 };
5840
5841                 p.delay = function(value) {
5842                         if (!arguments.length) {
5843                                 return this._delay;
5844                         }
5845                         if (this._timeline.smoothChildTiming) {
5846                                 this.startTime( this._startTime + value - this._delay );
5847                         }
5848                         this._delay = value;
5849                         return this;
5850                 };
5851
5852                 p.duration = function(value) {
5853                         if (!arguments.length) {
5854                                 this._dirty = false;
5855                                 return this._duration;
5856                         }
5857                         this._duration = this._totalDuration = value;
5858                         this._uncache(true); //true in case it's a TweenMax or TimelineMax that has a repeat - we'll need to refresh the totalDuration.
5859                         if (this._timeline.smoothChildTiming) if (this._time > 0) if (this._time < this._duration) if (value !== 0) {
5860                                 this.totalTime(this._totalTime * (value / this._duration), true);
5861                         }
5862                         return this;
5863                 };
5864
5865                 p.totalDuration = function(value) {
5866                         this._dirty = false;
5867                         return (!arguments.length) ? this._totalDuration : this.duration(value);
5868                 };
5869
5870                 p.time = function(value, suppressEvents) {
5871                         if (!arguments.length) {
5872                                 return this._time;
5873                         }
5874                         if (this._dirty) {
5875                                 this.totalDuration();
5876                         }
5877                         return this.totalTime((value > this._duration) ? this._duration : value, suppressEvents);
5878                 };
5879
5880                 p.totalTime = function(time, suppressEvents, uncapped) {
5881                         if (!_tickerActive) {
5882                                 _ticker.wake();
5883                         }
5884                         if (!arguments.length) {
5885                                 return this._totalTime;
5886                         }
5887                         if (this._timeline) {
5888                                 if (time < 0 && !uncapped) {
5889                                         time += this.totalDuration();
5890                                 }
5891                                 if (this._timeline.smoothChildTiming) {
5892                                         if (this._dirty) {
5893                                                 this.totalDuration();
5894                                         }
5895                                         var totalDuration = this._totalDuration,
5896                                                 tl = this._timeline;
5897                                         if (time > totalDuration && !uncapped) {
5898                                                 time = totalDuration;
5899                                         }
5900                                         this._startTime = (this._paused ? this._pauseTime : tl._time) - ((!this._reversed ? time : totalDuration - time) / this._timeScale);
5901                                         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.
5902                                                 this._uncache(false);
5903                                         }
5904                                         //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.
5905                                         if (tl._timeline) {
5906                                                 while (tl._timeline) {
5907                                                         if (tl._timeline._time !== (tl._startTime + tl._totalTime) / tl._timeScale) {
5908                                                                 tl.totalTime(tl._totalTime, true);
5909                                                         }
5910                                                         tl = tl._timeline;
5911                                                 }
5912                                         }
5913                                 }
5914                                 if (this._gc) {
5915                                         this._enabled(true, false);
5916                                 }
5917                                 if (this._totalTime !== time || this._duration === 0) {
5918                                         this.render(time, suppressEvents, false);
5919                                         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.
5920                                                 _lazyRender();
5921                                         }
5922                                 }
5923                         }
5924                         return this;
5925                 };
5926
5927                 p.progress = p.totalProgress = function(value, suppressEvents) {
5928                         return (!arguments.length) ? this._time / this.duration() : this.totalTime(this.duration() * value, suppressEvents);
5929                 };
5930
5931                 p.startTime = function(value) {
5932                         if (!arguments.length) {
5933                                 return this._startTime;
5934                         }
5935                         if (value !== this._startTime) {
5936                                 this._startTime = value;
5937                                 if (this.timeline) if (this.timeline._sortChildren) {
5938                                         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.
5939                                 }
5940                         }
5941                         return this;
5942                 };
5943
5944                 p.timeScale = function(value) {
5945                         if (!arguments.length) {
5946                                 return this._timeScale;
5947                         }
5948                         value = value || _tinyNum; //can't allow zero because it'll throw the math off
5949                         if (this._timeline && this._timeline.smoothChildTiming) {
5950                                 var pauseTime = this._pauseTime,
5951                                         t = (pauseTime || pauseTime === 0) ? pauseTime : this._timeline.totalTime();
5952                                 this._startTime = t - ((t - this._startTime) * this._timeScale / value);
5953                         }
5954                         this._timeScale = value;
5955                         return this._uncache(false);
5956                 };
5957
5958                 p.reversed = function(value) {
5959                         if (!arguments.length) {
5960                                 return this._reversed;
5961                         }
5962                         if (value != this._reversed) {
5963                                 this._reversed = value;
5964                                 this.totalTime(((this._timeline && !this._timeline.smoothChildTiming) ? this.totalDuration() - this._totalTime : this._totalTime), true);
5965                         }
5966                         return this;
5967                 };
5968
5969                 p.paused = function(value) {
5970                         if (!arguments.length) {
5971                                 return this._paused;
5972                         }
5973                         if (value != this._paused) if (this._timeline) {
5974                                 if (!_tickerActive && !value) {
5975                                         _ticker.wake();
5976                                 }
5977                                 var tl = this._timeline,
5978                                         raw = tl.rawTime(),
5979                                         elapsed = raw - this._pauseTime;
5980                                 if (!value && tl.smoothChildTiming) {
5981                                         this._startTime += elapsed;
5982                                         this._uncache(false);
5983                                 }
5984                                 this._pauseTime = value ? raw : null;
5985                                 this._paused = value;
5986                                 this._active = this.isActive();
5987                                 if (!value && elapsed !== 0 && this._initted && this.duration()) {
5988                                         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.
5989                                 }
5990                         }
5991                         if (this._gc && !value) {
5992                                 this._enabled(true, false);
5993                         }
5994                         return this;
5995                 };
5996
5997
5998 /*
5999  * ----------------------------------------------------------------
6000  * SimpleTimeline
6001  * ----------------------------------------------------------------
6002  */
6003                 var SimpleTimeline = _class("core.SimpleTimeline", function(vars) {
6004                         Animation.call(this, 0, vars);
6005                         this.autoRemoveChildren = this.smoothChildTiming = true;
6006                 });
6007
6008                 p = SimpleTimeline.prototype = new Animation();
6009                 p.constructor = SimpleTimeline;
6010                 p.kill()._gc = false;
6011                 p._first = p._last = null;
6012                 p._sortChildren = false;
6013
6014                 p.add = p.insert = function(child, position, align, stagger) {
6015                         var prevTween, st;
6016                         child._startTime = Number(position || 0) + child._delay;
6017                         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).
6018                                 child._pauseTime = child._startTime + ((this.rawTime() - child._startTime) / child._timeScale);
6019                         }
6020                         if (child.timeline) {
6021                                 child.timeline._remove(child, true); //removes from existing timeline so that it can be properly added to this one.
6022                         }
6023                         child.timeline = child._timeline = this;
6024                         if (child._gc) {
6025                                 child._enabled(true, true);
6026                         }
6027                         prevTween = this._last;
6028                         if (this._sortChildren) {
6029                                 st = child._startTime;
6030                                 while (prevTween && prevTween._startTime > st) {
6031                                         prevTween = prevTween._prev;
6032                                 }
6033                         }
6034                         if (prevTween) {
6035                                 child._next = prevTween._next;
6036                                 prevTween._next = child;
6037                         } else {
6038                                 child._next = this._first;
6039                                 this._first = child;
6040                         }
6041                         if (child._next) {
6042                                 child._next._prev = child;
6043                         } else {
6044                                 this._last = child;
6045                         }
6046                         child._prev = prevTween;
6047                         if (this._timeline) {
6048                                 this._uncache(true);
6049                         }
6050                         return this;
6051                 };
6052
6053                 p._remove = function(tween, skipDisable) {
6054                         if (tween.timeline === this) {
6055                                 if (!skipDisable) {
6056                                         tween._enabled(false, true);
6057                                 }
6058                                 tween.timeline = null;
6059
6060                                 if (tween._prev) {
6061                                         tween._prev._next = tween._next;
6062                                 } else if (this._first === tween) {
6063                                         this._first = tween._next;
6064                                 }
6065                                 if (tween._next) {
6066                                         tween._next._prev = tween._prev;
6067                                 } else if (this._last === tween) {
6068                                         this._last = tween._prev;
6069                                 }
6070
6071                                 if (this._timeline) {
6072                                         this._uncache(true);
6073                                 }
6074                         }
6075                         return this;
6076                 };
6077
6078                 p.render = function(time, suppressEvents, force) {
6079                         var tween = this._first,
6080                                 next;
6081                         this._totalTime = this._time = this._rawPrevTime = time;
6082                         while (tween) {
6083                                 next = tween._next; //record it here because the value could change after rendering...
6084                                 if (tween._active || (time >= tween._startTime && !tween._paused)) {
6085                                         if (!tween._reversed) {
6086                                                 tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force);
6087                                         } else {
6088                                                 tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force);
6089                                         }
6090                                 }
6091                                 tween = next;
6092                         }
6093                 };
6094
6095                 p.rawTime = function() {
6096                         if (!_tickerActive) {
6097                                 _ticker.wake();
6098                         }
6099                         return this._totalTime;
6100                 };
6101
6102 /*
6103  * ----------------------------------------------------------------
6104  * TweenLite
6105  * ----------------------------------------------------------------
6106  */
6107                 var TweenLite = _class("TweenLite", function(target, duration, vars) {
6108                                 Animation.call(this, duration, vars);
6109                                 this.render = TweenLite.prototype.render; //speed optimization (avoid prototype lookup on this "hot" method)
6110
6111                                 if (target == null) {
6112                                         throw "Cannot tween a null target.";
6113                                 }
6114
6115                                 this.target = target = (typeof(target) !== "string") ? target : TweenLite.selector(target) || target;
6116
6117                                 var isSelector = (target.jquery || (target.length && target !== window && target[0] && (target[0] === window || (target[0].nodeType && target[0].style && !target.nodeType)))),
6118                                         overwrite = this.vars.overwrite,
6119                                         i, targ, targets;
6120
6121                                 this._overwrite = overwrite = (overwrite == null) ? _overwriteLookup[TweenLite.defaultOverwrite] : (typeof(overwrite) === "number") ? overwrite >> 0 : _overwriteLookup[overwrite];
6122
6123                                 if ((isSelector || target instanceof Array || (target.push && _isArray(target))) && typeof(target[0]) !== "number") {
6124                                         this._targets = targets = _slice.call(target, 0);
6125                                         this._propLookup = [];
6126                                         this._siblings = [];
6127                                         for (i = 0; i < targets.length; i++) {
6128                                                 targ = targets[i];
6129                                                 if (!targ) {
6130                                                         targets.splice(i--, 1);
6131                                                         continue;
6132                                                 } else if (typeof(targ) === "string") {
6133                                                         targ = targets[i--] = TweenLite.selector(targ); //in case it's an array of strings
6134                                                         if (typeof(targ) === "string") {
6135                                                                 targets.splice(i+1, 1); //to avoid an endless loop (can't imagine why the selector would return a string, but just in case)
6136                                                         }
6137                                                         continue;
6138                                                 } 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.
6139                                                         targets.splice(i--, 1);
6140                                                         this._targets = targets = targets.concat(_slice.call(targ, 0));
6141                                                         continue;
6142                                                 }
6143                                                 this._siblings[i] = _register(targ, this, false);
6144                                                 if (overwrite === 1) if (this._siblings[i].length > 1) {
6145                                                         _applyOverwrite(targ, this, null, 1, this._siblings[i]);
6146                                                 }
6147                                         }
6148
6149                                 } else {
6150                                         this._propLookup = {};
6151                                         this._siblings = _register(target, this, false);
6152                                         if (overwrite === 1) if (this._siblings.length > 1) {
6153                                                 _applyOverwrite(target, this, null, 1, this._siblings);
6154                                         }
6155                                 }
6156                                 if (this.vars.immediateRender || (duration === 0 && this._delay === 0 && this.vars.immediateRender !== false)) {
6157                                         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)
6158                                         this.render(-this._delay);
6159                                 }
6160                         }, true),
6161                         _isSelector = function(v) {
6162                                 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.
6163                         },
6164                         _autoCSS = function(vars, target) {
6165                                 var css = {},
6166                                         p;
6167                                 for (p in vars) {
6168                                         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.
6169                                                 css[p] = vars[p];
6170                                                 delete vars[p];
6171                                         }
6172                                 }
6173                                 vars.css = css;
6174                         };
6175
6176                 p = TweenLite.prototype = new Animation();
6177                 p.constructor = TweenLite;
6178                 p.kill()._gc = false;
6179
6180 //----TweenLite defaults, overwrite management, and root updates ----------------------------------------------------
6181
6182                 p.ratio = 0;
6183                 p._firstPT = p._targets = p._overwrittenProps = p._startAt = null;
6184                 p._notifyPluginsOfEnabled = p._lazy = false;
6185
6186                 TweenLite.version = "1.12.1";
6187                 TweenLite.defaultEase = p._ease = new Ease(null, null, 1, 1);
6188                 TweenLite.defaultOverwrite = "auto";
6189                 TweenLite.ticker = _ticker;
6190                 TweenLite.autoSleep = true;
6191                 TweenLite.lagSmoothing = function(threshold, adjustedLag) {
6192                         _ticker.lagSmoothing(threshold, adjustedLag);
6193                 };
6194                 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; };
6195
6196                 var _lazyTweens = [],
6197                         _lazyLookup = {},
6198                         _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.
6199                         _plugins = TweenLite._plugins = {},
6200                         _tweenLookup = _internals.tweenLookup = {},
6201                         _tweenLookupNum = 0,
6202                         _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},
6203                         _overwriteLookup = {none:0, all:1, auto:2, concurrent:3, allOnStart:4, preexisting:5, "true":1, "false":0},
6204                         _rootFramesTimeline = Animation._rootFramesTimeline = new SimpleTimeline(),
6205                         _rootTimeline = Animation._rootTimeline = new SimpleTimeline(),
6206                         _lazyRender = function() {
6207                                 var i = _lazyTweens.length;
6208                                 _lazyLookup = {};
6209                                 while (--i > -1) {
6210                                         a = _lazyTweens[i];
6211                                         if (a && a._lazy !== false) {
6212                                                 a.render(a._lazy, false, true);
6213                                                 a._lazy = false;
6214                                         }
6215                                 }
6216                                 _lazyTweens.length = 0;
6217                         };
6218
6219                 _rootTimeline._startTime = _ticker.time;
6220                 _rootFramesTimeline._startTime = _ticker.frame;
6221                 _rootTimeline._active = _rootFramesTimeline._active = true;
6222                 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".
6223
6224                 Animation._updateRoot = TweenLite.render = function() {
6225                                 var i, a, p;
6226                                 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.
6227                                         _lazyRender();
6228                                 }
6229                                 _rootTimeline.render((_ticker.time - _rootTimeline._startTime) * _rootTimeline._timeScale, false, false);
6230                                 _rootFramesTimeline.render((_ticker.frame - _rootFramesTimeline._startTime) * _rootFramesTimeline._timeScale, false, false);
6231                                 if (_lazyTweens.length) {
6232                                         _lazyRender();
6233                                 }
6234                                 if (!(_ticker.frame % 120)) { //dump garbage every 120 frames...
6235                                         for (p in _tweenLookup) {
6236                                                 a = _tweenLookup[p].tweens;
6237                                                 i = a.length;
6238                                                 while (--i > -1) {
6239                                                         if (a[i]._gc) {
6240                                                                 a.splice(i, 1);
6241                                                         }
6242                                                 }
6243                                                 if (a.length === 0) {
6244                                                         delete _tweenLookup[p];
6245                                                 }
6246                                         }
6247                                         //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
6248                                         p = _rootTimeline._first;
6249                                         if (!p || p._paused) if (TweenLite.autoSleep && !_rootFramesTimeline._first && _ticker._listeners.tick.length === 1) {
6250                                                 while (p && p._paused) {
6251                                                         p = p._next;
6252                                                 }
6253                                                 if (!p) {
6254                                                         _ticker.sleep();
6255                                                 }
6256                                         }
6257                                 }
6258                         };
6259
6260                 _ticker.addEventListener("tick", Animation._updateRoot);
6261
6262                 var _register = function(target, tween, scrub) {
6263                                 var id = target._gsTweenID, a, i;
6264                                 if (!_tweenLookup[id || (target._gsTweenID = id = "t" + (_tweenLookupNum++))]) {
6265                                         _tweenLookup[id] = {target:target, tweens:[]};
6266                                 }
6267                                 if (tween) {
6268                                         a = _tweenLookup[id].tweens;
6269                                         a[(i = a.length)] = tween;
6270                                         if (scrub) {
6271                                                 while (--i > -1) {
6272                                                         if (a[i] === tween) {
6273                                                                 a.splice(i, 1);
6274                                                         }
6275                                                 }
6276                                         }
6277                                 }
6278                                 return _tweenLookup[id].tweens;
6279                         },
6280
6281                         _applyOverwrite = function(target, tween, props, mode, siblings) {
6282                                 var i, changed, curTween, l;
6283                                 if (mode === 1 || mode >= 4) {
6284                                         l = siblings.length;
6285                                         for (i = 0; i < l; i++) {
6286                                                 if ((curTween = siblings[i]) !== tween) {
6287                                                         if (!curTween._gc) if (curTween._enabled(false, false)) {
6288                                                                 changed = true;
6289                                                         }
6290                                                 } else if (mode === 5) {
6291                                                         break;
6292                                                 }
6293                                         }
6294                                         return changed;
6295                                 }
6296                                 //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)
6297                                 var startTime = tween._startTime + _tinyNum,
6298                                         overlaps = [],
6299                                         oCount = 0,
6300                                         zeroDur = (tween._duration === 0),
6301                                         globalStart;
6302                                 i = siblings.length;
6303                                 while (--i > -1) {
6304                                         if ((curTween = siblings[i]) === tween || curTween._gc || curTween._paused) {
6305                                                 //ignore
6306                                         } else if (curTween._timeline !== tween._timeline) {
6307                                                 globalStart = globalStart || _checkOverlap(tween, 0, zeroDur);
6308                                                 if (_checkOverlap(curTween, globalStart, zeroDur) === 0) {
6309                                                         overlaps[oCount++] = curTween;
6310                                                 }
6311                                         } else if (curTween._startTime <= startTime) if (curTween._startTime + curTween.totalDuration() / curTween._timeScale > startTime) if (!((zeroDur || !curTween._initted) && startTime - curTween._startTime <= 0.0000000002)) {
6312                                                 overlaps[oCount++] = curTween;
6313                                         }
6314                                 }
6315
6316                                 i = oCount;
6317                                 while (--i > -1) {
6318                                         curTween = overlaps[i];
6319                                         if (mode === 2) if (curTween._kill(props, target)) {
6320                                                 changed = true;
6321                                         }
6322                                         if (mode !== 2 || (!curTween._firstPT && curTween._initted)) {
6323                                                 if (curTween._enabled(false, false)) { //if all property tweens have been overwritten, kill the tween.
6324                                                         changed = true;
6325                                                 }
6326                                         }
6327                                 }
6328                                 return changed;
6329                         },
6330
6331                         _checkOverlap = function(tween, reference, zeroDur) {
6332                                 var tl = tween._timeline,
6333                                         ts = tl._timeScale,
6334                                         t = tween._startTime;
6335                                 while (tl._timeline) {
6336                                         t += tl._startTime;
6337                                         ts *= tl._timeScale;
6338                                         if (tl._paused) {
6339                                                 return -100;
6340                                         }
6341                                         tl = tl._timeline;
6342                                 }
6343                                 t /= ts;
6344                                 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;
6345                         };
6346
6347
6348 //---- TweenLite instance methods -----------------------------------------------------------------------------
6349
6350                 p._init = function() {
6351                         var v = this.vars,
6352                                 op = this._overwrittenProps,
6353                                 dur = this._duration,
6354                                 immediate = !!v.immediateRender,
6355                                 ease = v.ease,
6356                                 i, initPlugins, pt, p, startVars;
6357                         if (v.startAt) {
6358                                 if (this._startAt) {
6359                                         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.
6360                                         this._startAt.kill();
6361                                 }
6362                                 startVars = {};
6363                                 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);
6364                                         startVars[p] = v.startAt[p];
6365                                 }
6366                                 startVars.overwrite = false;
6367                                 startVars.immediateRender = true;
6368                                 startVars.lazy = (immediate && v.lazy !== false);
6369                                 startVars.startAt = startVars.delay = null; //no nesting of startAt objects allowed (otherwise it could cause an infinite loop).
6370                                 this._startAt = TweenLite.to(this.target, 0, startVars);
6371                                 if (immediate) {
6372                                         if (this._time > 0) {
6373                                                 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()).
6374                                         } else if (dur !== 0) {
6375                                                 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.
6376                                         }
6377                                 }
6378                         } else if (v.runBackwards && dur !== 0) {
6379                                 //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)
6380                                 if (this._startAt) {
6381                                         this._startAt.render(-1, true);
6382                                         this._startAt.kill();
6383                                         this._startAt = null;
6384                                 } else {
6385                                         pt = {};
6386                                         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.
6387                                                 if (!_reservedProps[p] || p === "autoCSS") {
6388                                                         pt[p] = v[p];
6389                                                 }
6390                                         }
6391                                         pt.overwrite = 0;
6392                                         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.
6393                                         pt.lazy = (immediate && v.lazy !== false);
6394                                         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)
6395                                         this._startAt = TweenLite.to(this.target, 0, pt);
6396                                         if (!immediate) {
6397                                                 this._startAt._init(); //ensures that the initial values are recorded
6398                                                 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.
6399                                         } else if (this._time === 0) {
6400                                                 return;
6401                                         }
6402                                 }
6403                         }
6404                         if (!ease) {
6405                                 this._ease = TweenLite.defaultEase;
6406                         } else if (ease instanceof Ease) {
6407                                 this._ease = (v.easeParams instanceof Array) ? ease.config.apply(ease, v.easeParams) : ease;
6408                         } else {
6409                                 this._ease = (typeof(ease) === "function") ? new Ease(ease, v.easeParams) : _easeMap[ease] || TweenLite.defaultEase;
6410                         }
6411                         this._easeType = this._ease._type;
6412                         this._easePower = this._ease._power;
6413                         this._firstPT = null;
6414
6415                         if (this._targets) {
6416                                 i = this._targets.length;
6417                                 while (--i > -1) {
6418                                         if ( this._initProps( this._targets[i], (this._propLookup[i] = {}), this._siblings[i], (op ? op[i] : null)) ) {
6419                                                 initPlugins = true;
6420                                         }
6421                                 }
6422                         } else {
6423                                 initPlugins = this._initProps(this.target, this._propLookup, this._siblings, op);
6424                         }
6425
6426                         if (initPlugins) {
6427                                 TweenLite._onPluginEvent("_onInitAllProps", this); //reorders the array in order of priority. Uses a static TweenPlugin method in order to minimize file size in TweenLite
6428                         }
6429                         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.
6430                                 this._enabled(false, false);
6431                         }
6432                         if (v.runBackwards) {
6433                                 pt = this._firstPT;
6434                                 while (pt) {
6435                                         pt.s += pt.c;
6436                                         pt.c = -pt.c;
6437                                         pt = pt._next;
6438                                 }
6439                         }
6440                         this._onUpdate = v.onUpdate;
6441                         this._initted = true;
6442                 };
6443
6444                 p._initProps = function(target, propLookup, siblings, overwrittenProps) {
6445                         var p, i, initPlugins, plugin, pt, v;
6446                         if (target == null) {
6447                                 return false;
6448                         }
6449
6450                         if (_lazyLookup[target._gsTweenID]) {
6451                                 _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)
6452                         }
6453
6454                         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.
6455                                 _autoCSS(this.vars, target);
6456                         }
6457                         for (p in this.vars) {
6458                                 v = this.vars[p];
6459                                 if (_reservedProps[p]) {
6460                                         if (v) if ((v instanceof Array) || (v.push && _isArray(v))) if (v.join("").indexOf("{self}") !== -1) {
6461                                                 this.vars[p] = v = this._swapSelfInParams(v, this);
6462                                         }
6463
6464                                 } else if (_plugins[p] && (plugin = new _plugins[p]())._onInitTween(target, this.vars[p], this)) {
6465
6466                                         //t - target            [object]
6467                                         //p - property          [string]
6468                                         //s - start                     [number]
6469                                         //c - change            [number]
6470                                         //f - isFunction        [boolean]
6471                                         //n - name                      [string]
6472                                         //pg - isPlugin         [boolean]
6473                                         //pr - priority         [number]
6474                                         this._firstPT = pt = {_next:this._firstPT, t:plugin, p:"setRatio", s:0, c:1, f:true, n:p, pg:true, pr:plugin._priority};
6475                                         i = plugin._overwriteProps.length;
6476                                         while (--i > -1) {
6477                                                 propLookup[plugin._overwriteProps[i]] = this._firstPT;
6478                                         }
6479                                         if (plugin._priority || plugin._onInitAllProps) {
6480                                                 initPlugins = true;
6481                                         }
6482                                         if (plugin._onDisable || plugin._onEnable) {
6483                                                 this._notifyPluginsOfEnabled = true;
6484                                         }
6485
6486                                 } else {
6487                                         this._firstPT = propLookup[p] = pt = {_next:this._firstPT, t:target, p:p, f:(typeof(target[p]) === "function"), n:p, pg:false, pr:0};
6488                                         pt.s = (!pt.f) ? parseFloat(target[p]) : target[ ((p.indexOf("set") || typeof(target["get" + p.substr(3)]) !== "function") ? p : "get" + p.substr(3)) ]();
6489                                         pt.c = (typeof(v) === "string" && v.charAt(1) === "=") ? parseInt(v.charAt(0) + "1", 10) * Number(v.substr(2)) : (Number(v) - pt.s) || 0;
6490                                 }
6491                                 if (pt) if (pt._next) {
6492                                         pt._next._prev = pt;
6493                                 }
6494                         }
6495
6496                         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)
6497                                 return this._initProps(target, propLookup, siblings, overwrittenProps);
6498                         }
6499                         if (this._overwrite > 1) if (this._firstPT) if (siblings.length > 1) if (_applyOverwrite(target, this, propLookup, this._overwrite, siblings)) {
6500                                 this._kill(propLookup, target);
6501                                 return this._initProps(target, propLookup, siblings, overwrittenProps);
6502                         }
6503                         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.
6504                                 _lazyLookup[target._gsTweenID] = true;
6505                         }
6506                         return initPlugins;
6507                 };
6508
6509                 p.render = function(time, suppressEvents, force) {
6510                         var prevTime = this._time,
6511                                 duration = this._duration,
6512                                 prevRawPrevTime = this._rawPrevTime,
6513                                 isComplete, callback, pt, rawPrevTime;
6514                         if (time >= duration) {
6515                                 this._totalTime = this._time = duration;
6516                                 this.ratio = this._ease._calcEnd ? this._ease.getRatio(1) : 1;
6517                                 if (!this._reversed ) {
6518                                         isComplete = true;
6519                                         callback = "onComplete";
6520                                 }
6521                                 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.
6522                                         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.
6523                                                 time = 0;
6524                                         }
6525                                         if (time === 0 || prevRawPrevTime < 0 || prevRawPrevTime === _tinyNum) if (prevRawPrevTime !== time) {
6526                                                 force = true;
6527                                                 if (prevRawPrevTime > _tinyNum) {
6528                                                         callback = "onReverseComplete";
6529                                                 }
6530                                         }
6531                                         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.
6532                                 }
6533
6534                         } else if (time < 0.0000001) { //to work around occasional floating point math artifacts, round super small values to 0.
6535                                 this._totalTime = this._time = 0;
6536                                 this.ratio = this._ease._calcEnd ? this._ease.getRatio(0) : 0;
6537                                 if (prevTime !== 0 || (duration === 0 && prevRawPrevTime > 0 && prevRawPrevTime !== _tinyNum)) {
6538                                         callback = "onReverseComplete";
6539                                         isComplete = this._reversed;
6540                                 }
6541                                 if (time < 0) {
6542                                         this._active = false;
6543                                         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.
6544                                                 if (prevRawPrevTime >= 0) {
6545                                                         force = true;
6546                                                 }
6547                                                 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.
6548                                         }
6549                                 } 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.
6550                                         force = true;
6551                                 }
6552                         } else {
6553                                 this._totalTime = this._time = time;
6554
6555                                 if (this._easeType) {
6556                                         var r = time / duration, type = this._easeType, pow = this._easePower;
6557                                         if (type === 1 || (type === 3 && r >= 0.5)) {
6558                                                 r = 1 - r;
6559                                         }
6560                                         if (type === 3) {
6561                                                 r *= 2;
6562                                         }
6563                                         if (pow === 1) {
6564                                                 r *= r;
6565                                         } else if (pow === 2) {
6566                                                 r *= r * r;
6567                                         } else if (pow === 3) {
6568                                                 r *= r * r * r;
6569                                         } else if (pow === 4) {
6570                                                 r *= r * r * r * r;
6571                                         }
6572
6573                                         if (type === 1) {
6574                                                 this.ratio = 1 - r;
6575                                         } else if (type === 2) {
6576                                                 this.ratio = r;
6577                                         } else if (time / duration < 0.5) {
6578                                                 this.ratio = r / 2;
6579                                         } else {
6580                                                 this.ratio = 1 - (r / 2);
6581                                         }
6582
6583                                 } else {
6584                                         this.ratio = this._ease.getRatio(time / duration);
6585                                 }
6586                         }
6587
6588                         if (this._time === prevTime && !force) {
6589                                 return;
6590                         } else if (!this._initted) {
6591                                 this._init();
6592                                 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.
6593                                         return;
6594                                 } else if (!force && this._firstPT && ((this.vars.lazy !== false && this._duration) || (this.vars.lazy && !this._duration))) {
6595                                         this._time = this._totalTime = prevTime;
6596                                         this._rawPrevTime = prevRawPrevTime;
6597                                         _lazyTweens.push(this);
6598                                         this._lazy = time;
6599                                         return;
6600                                 }
6601                                 //_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.
6602                                 if (this._time && !isComplete) {
6603                                         this.ratio = this._ease.getRatio(this._time / duration);
6604                                 } else if (isComplete && this._ease._calcEnd) {
6605                                         this.ratio = this._ease.getRatio((this._time === 0) ? 0 : 1);
6606                                 }
6607                         }
6608                         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.
6609                                 this._lazy = false;
6610                         }
6611                         if (!this._active) if (!this._paused && this._time !== prevTime && time >= 0) {
6612                                 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.
6613                         }
6614                         if (prevTime === 0) {
6615                                 if (this._startAt) {
6616                                         if (time >= 0) {
6617                                                 this._startAt.render(time, suppressEvents, force);
6618                                         } else if (!callback) {
6619                                                 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.
6620                                         }
6621                                 }
6622                                 if (this.vars.onStart) if (this._time !== 0 || duration === 0) if (!suppressEvents) {
6623                                         this.vars.onStart.apply(this.vars.onStartScope || this, this.vars.onStartParams || _blankArray);
6624                                 }
6625                         }
6626
6627                         pt = this._firstPT;
6628                         while (pt) {
6629                                 if (pt.f) {
6630                                         pt.t[pt.p](pt.c * this.ratio + pt.s);
6631                                 } else {
6632                                         pt.t[pt.p] = pt.c * this.ratio + pt.s;
6633                                 }
6634                                 pt = pt._next;
6635                         }
6636
6637                         if (this._onUpdate) {
6638                                 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.
6639                                         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.
6640                                 }
6641                                 if (!suppressEvents) if (this._time !== prevTime || isComplete) {
6642                                         this._onUpdate.apply(this.vars.onUpdateScope || this, this.vars.onUpdateParams || _blankArray);
6643                                 }
6644                         }
6645
6646                         if (callback) if (!this._gc) { //check _gc because there's a chance that kill() could be called in an onUpdate
6647                                 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.
6648                                         this._startAt.render(time, suppressEvents, force);
6649                                 }
6650                                 if (isComplete) {
6651                                         if (this._timeline.autoRemoveChildren) {
6652                                                 this._enabled(false, false);
6653                                         }
6654                                         this._active = false;
6655                                 }
6656                                 if (!suppressEvents && this.vars[callback]) {
6657                                         this.vars[callback].apply(this.vars[callback + "Scope"] || this, this.vars[callback + "Params"] || _blankArray);
6658                                 }
6659                                 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.
6660                                         this._rawPrevTime = 0;
6661                                 }
6662                         }
6663
6664                 };
6665
6666                 p._kill = function(vars, target) {
6667                         if (vars === "all") {
6668                                 vars = null;
6669                         }
6670                         if (vars == null) if (target == null || target === this.target) {
6671                                 this._lazy = false;
6672                                 return this._enabled(false, false);
6673                         }
6674                         target = (typeof(target) !== "string") ? (target || this._targets || this.target) : TweenLite.selector(target) || target;
6675                         var i, overwrittenProps, p, pt, propLookup, changed, killProps, record;
6676                         if ((_isArray(target) || _isSelector(target)) && typeof(target[0]) !== "number") {
6677                                 i = target.length;
6678                                 while (--i > -1) {
6679                                         if (this._kill(vars, target[i])) {
6680                                                 changed = true;
6681                                         }
6682                                 }
6683                         } else {
6684                                 if (this._targets) {
6685                                         i = this._targets.length;
6686                                         while (--i > -1) {
6687                                                 if (target === this._targets[i]) {
6688                                                         propLookup = this._propLookup[i] || {};
6689                                                         this._overwrittenProps = this._overwrittenProps || [];
6690                                                         overwrittenProps = this._overwrittenProps[i] = vars ? this._overwrittenProps[i] || {} : "all";
6691                                                         break;
6692                                                 }
6693                                         }
6694                                 } else if (target !== this.target) {
6695                                         return false;
6696                                 } else {
6697                                         propLookup = this._propLookup;
6698                                         overwrittenProps = this._overwrittenProps = vars ? this._overwrittenProps || {} : "all";
6699                                 }
6700
6701                                 if (propLookup) {
6702                                         killProps = vars || propLookup;
6703                                         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)
6704                                         for (p in killProps) {
6705                                                 if ((pt = propLookup[p])) {
6706                                                         if (pt.pg && pt.t._kill(killProps)) {
6707                                                                 changed = true; //some plugins need to be notified so they can perform cleanup tasks first
6708                                                         }
6709                                                         if (!pt.pg || pt.t._overwriteProps.length === 0) {
6710                                                                 if (pt._prev) {
6711                                                                         pt._prev._next = pt._next;
6712                                                                 } else if (pt === this._firstPT) {
6713                                                                         this._firstPT = pt._next;
6714                                                                 }
6715                                                                 if (pt._next) {
6716                                                                         pt._next._prev = pt._prev;
6717                                                                 }
6718                                                                 pt._next = pt._prev = null;
6719                                                         }
6720                                                         delete propLookup[p];
6721                                                 }
6722                                                 if (record) {
6723                                                         overwrittenProps[p] = 1;
6724                                                 }
6725                                         }
6726                                         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.
6727                                                 this._enabled(false, false);
6728                                         }
6729                                 }
6730                         }
6731                         return changed;
6732                 };
6733
6734                 p.invalidate = function() {
6735                         if (this._notifyPluginsOfEnabled) {
6736                                 TweenLite._onPluginEvent("_onDisable", this);
6737                         }
6738                         this._firstPT = null;
6739                         this._overwrittenProps = null;
6740                         this._onUpdate = null;
6741                         this._startAt = null;
6742                         this._initted = this._active = this._notifyPluginsOfEnabled = this._lazy = false;
6743                         this._propLookup = (this._targets) ? {} : [];
6744                         return this;
6745                 };
6746
6747                 p._enabled = function(enabled, ignoreTimeline) {
6748                         if (!_tickerActive) {
6749                                 _ticker.wake();
6750                         }
6751                         if (enabled && this._gc) {
6752                                 var targets = this._targets,
6753                                         i;
6754                                 if (targets) {
6755                                         i = targets.length;
6756                                         while (--i > -1) {
6757                                                 this._siblings[i] = _register(targets[i], this, true);
6758                                         }
6759                                 } else {
6760                                         this._siblings = _register(this.target, this, true);
6761                                 }
6762                         }
6763                         Animation.prototype._enabled.call(this, enabled, ignoreTimeline);
6764                         if (this._notifyPluginsOfEnabled) if (this._firstPT) {
6765                                 return TweenLite._onPluginEvent((enabled ? "_onEnable" : "_onDisable"), this);
6766                         }
6767                         return false;
6768                 };
6769
6770
6771 //----TweenLite static methods -----------------------------------------------------
6772
6773                 TweenLite.to = function(target, duration, vars) {
6774                         return new TweenLite(target, duration, vars);
6775                 };
6776
6777                 TweenLite.from = function(target, duration, vars) {
6778                         vars.runBackwards = true;
6779                         vars.immediateRender = (vars.immediateRender != false);
6780                         return new TweenLite(target, duration, vars);
6781                 };
6782
6783                 TweenLite.fromTo = function(target, duration, fromVars, toVars) {
6784                         toVars.startAt = fromVars;
6785                         toVars.immediateRender = (toVars.immediateRender != false && fromVars.immediateRender != false);
6786                         return new TweenLite(target, duration, toVars);
6787                 };
6788
6789                 TweenLite.delayedCall = function(delay, callback, params, scope, useFrames) {
6790                         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});
6791                 };
6792
6793                 TweenLite.set = function(target, vars) {
6794                         return new TweenLite(target, 0, vars);
6795                 };
6796
6797                 TweenLite.getTweensOf = function(target, onlyActive) {
6798                         if (target == null) { return []; }
6799                         target = (typeof(target) !== "string") ? target : TweenLite.selector(target) || target;
6800                         var i, a, j, t;
6801                         if ((_isArray(target) || _isSelector(target)) && typeof(target[0]) !== "number") {
6802                                 i = target.length;
6803                                 a = [];
6804                                 while (--i > -1) {
6805                                         a = a.concat(TweenLite.getTweensOf(target[i], onlyActive));
6806                                 }
6807                                 i = a.length;
6808                                 //now get rid of any duplicates (tweens of arrays of objects could cause duplicates)
6809                                 while (--i > -1) {
6810                                         t = a[i];
6811                                         j = i;
6812                                         while (--j > -1) {
6813                                                 if (t === a[j]) {
6814                                                         a.splice(i, 1);
6815                                                 }
6816                                         }
6817                                 }
6818                         } else {
6819                                 a = _register(target).concat();
6820                                 i = a.length;
6821                                 while (--i > -1) {
6822                                         if (a[i]._gc || (onlyActive && !a[i].isActive())) {
6823                                                 a.splice(i, 1);
6824                                         }
6825                                 }
6826                         }
6827                         return a;
6828                 };
6829
6830                 TweenLite.killTweensOf = TweenLite.killDelayedCallsTo = function(target, onlyActive, vars) {
6831                         if (typeof(onlyActive) === "object") {
6832                                 vars = onlyActive; //for backwards compatibility (before "onlyActive" parameter was inserted)
6833                                 onlyActive = false;
6834                         }
6835                         var a = TweenLite.getTweensOf(target, onlyActive),
6836                                 i = a.length;
6837                         while (--i > -1) {
6838                                 a[i]._kill(vars, target);
6839                         }
6840                 };
6841
6842
6843
6844 /*
6845  * ----------------------------------------------------------------
6846  * 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)
6847  * ----------------------------------------------------------------
6848  */
6849                 var TweenPlugin = _class("plugins.TweenPlugin", function(props, priority) {
6850                                         this._overwriteProps = (props || "").split(",");
6851                                         this._propName = this._overwriteProps[0];
6852                                         this._priority = priority || 0;
6853                                         this._super = TweenPlugin.prototype;
6854                                 }, true);
6855
6856                 p = TweenPlugin.prototype;
6857                 TweenPlugin.version = "1.10.1";
6858                 TweenPlugin.API = 2;
6859                 p._firstPT = null;
6860
6861                 p._addTween = function(target, prop, start, end, overwriteProp, round) {
6862                         var c, pt;
6863                         if (end != null && (c = (typeof(end) === "number" || end.charAt(1) !== "=") ? Number(end) - start : parseInt(end.charAt(0) + "1", 10) * Number(end.substr(2)))) {
6864                                 this._firstPT = pt = {_next:this._firstPT, t:target, p:prop, s:start, c:c, f:(typeof(target[prop]) === "function"), n:overwriteProp || prop, r:round};
6865                                 if (pt._next) {
6866                                         pt._next._prev = pt;
6867                                 }
6868                                 return pt;
6869                         }
6870                 };
6871
6872                 p.setRatio = function(v) {
6873                         var pt = this._firstPT,
6874                                 min = 0.000001,
6875                                 val;
6876                         while (pt) {
6877                                 val = pt.c * v + pt.s;
6878                                 if (pt.r) {
6879                                         val = Math.round(val);
6880                                 } else if (val < min) if (val > -min) { //prevents issues with converting very small numbers to strings in the browser
6881                                         val = 0;
6882                                 }
6883                                 if (pt.f) {
6884                                         pt.t[pt.p](val);
6885                                 } else {
6886                                         pt.t[pt.p] = val;
6887                                 }
6888                                 pt = pt._next;
6889                         }
6890                 };
6891
6892                 p._kill = function(lookup) {
6893                         var a = this._overwriteProps,
6894                                 pt = this._firstPT,
6895                                 i;
6896                         if (lookup[this._propName] != null) {
6897                                 this._overwriteProps = [];
6898                         } else {
6899                                 i = a.length;
6900                                 while (--i > -1) {
6901                                         if (lookup[a[i]] != null) {
6902                                                 a.splice(i, 1);
6903                                         }
6904                                 }
6905                         }
6906                         while (pt) {
6907                                 if (lookup[pt.n] != null) {
6908                                         if (pt._next) {
6909                                                 pt._next._prev = pt._prev;
6910                                         }
6911                                         if (pt._prev) {
6912                                                 pt._prev._next = pt._next;
6913                                                 pt._prev = null;
6914                                         } else if (this._firstPT === pt) {
6915                                                 this._firstPT = pt._next;
6916                                         }
6917                                 }
6918                                 pt = pt._next;
6919                         }
6920                         return false;
6921                 };
6922
6923                 p._roundProps = function(lookup, value) {
6924                         var pt = this._firstPT;
6925                         while (pt) {
6926                                 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.
6927                                         pt.r = value;
6928                                 }
6929                                 pt = pt._next;
6930                         }
6931                 };
6932
6933                 TweenLite._onPluginEvent = function(type, tween) {
6934                         var pt = tween._firstPT,
6935                                 changed, pt2, first, last, next;
6936                         if (type === "_onInitAllProps") {
6937                                 //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.
6938                                 while (pt) {
6939                                         next = pt._next;
6940                                         pt2 = first;
6941                                         while (pt2 && pt2.pr > pt.pr) {
6942                                                 pt2 = pt2._next;
6943                                         }
6944                                         if ((pt._prev = pt2 ? pt2._prev : last)) {
6945                                                 pt._prev._next = pt;
6946                                         } else {
6947                                                 first = pt;
6948                                         }
6949                                         if ((pt._next = pt2)) {
6950                                                 pt2._prev = pt;
6951                                         } else {
6952                                                 last = pt;
6953                                         }
6954                                         pt = next;
6955                                 }
6956                                 pt = tween._firstPT = first;
6957                         }
6958                         while (pt) {
6959                                 if (pt.pg) if (typeof(pt.t[type]) === "function") if (pt.t[type]()) {
6960                                         changed = true;
6961                                 }
6962                                 pt = pt._next;
6963                         }
6964                         return changed;
6965                 };
6966
6967                 TweenPlugin.activate = function(plugins) {
6968                         var i = plugins.length;
6969                         while (--i > -1) {
6970                                 if (plugins[i].API === TweenPlugin.API) {
6971                                         _plugins[(new plugins[i]())._propName] = plugins[i];
6972                                 }
6973                         }
6974                         return true;
6975                 };
6976
6977                 //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.
6978                 _gsDefine.plugin = function(config) {
6979                         if (!config || !config.propName || !config.init || !config.API) { throw "illegal plugin definition."; }
6980                         var propName = config.propName,
6981                                 priority = config.priority || 0,
6982                                 overwriteProps = config.overwriteProps,
6983                                 map = {init:"_onInitTween", set:"setRatio", kill:"_kill", round:"_roundProps", initAll:"_onInitAllProps"},
6984                                 Plugin = _class("plugins." + propName.charAt(0).toUpperCase() + propName.substr(1) + "Plugin",
6985                                         function() {
6986                                                 TweenPlugin.call(this, propName, priority);
6987                                                 this._overwriteProps = overwriteProps || [];
6988                                         }, (config.global === true)),
6989                                 p = Plugin.prototype = new TweenPlugin(propName),
6990                                 prop;
6991                         p.constructor = Plugin;
6992                         Plugin.API = config.API;
6993                         for (prop in map) {
6994                                 if (typeof(config[prop]) === "function") {
6995                                         p[map[prop]] = config[prop];
6996                                 }
6997                         }
6998                         Plugin.version = config.version;
6999                         TweenPlugin.activate([Plugin]);
7000                         return Plugin;
7001                 };
7002
7003
7004                 //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.
7005                 a = window._gsQueue;
7006                 if (a) {
7007                         for (i = 0; i < a.length; i++) {
7008                                 a[i]();
7009                         }
7010                         for (p in _defLookup) {
7011                                 if (!_defLookup[p].func) {
7012                                         //window.console.log("GSAP encountered missing dependency: com.greensock." + p);
7013                                 }
7014                         }
7015                 }
7016
7017                 _tickerActive = false; //ensures that the first official animation forces a ticker.tick() to update the time when it is instantiated
7018
7019 })(window);
7020
7021 angular.module('att.abs.transition', [])
7022
7023 .factory('$transition', ['$q', '$timeout', '$rootScope', function($q, $timeout, $rootScope) {
7024
7025   var $transition = function(element, trigger, options) {
7026     options = options || {};
7027     var deferred = $q.defer();
7028     var endEventName = $transition[options.animation ? "animationEndEventName" : "transitionEndEventName"];
7029
7030     var transitionEndHandler = function(event) {
7031       $rootScope.$apply(function() {
7032         element.unbind(endEventName, transitionEndHandler);
7033         deferred.resolve(element);
7034       });
7035     };
7036
7037     if (endEventName) {
7038       element.bind(endEventName, transitionEndHandler);
7039     }
7040
7041     // Wrap in a timeout to allow the browser time to update the DOM before the transition is to occur
7042     $timeout(function() {
7043       if ( angular.isString(trigger) ) {
7044         element.addClass(trigger);
7045       } else if ( angular.isFunction(trigger) ) {
7046         trigger(element);
7047       } else if ( angular.isObject(trigger) ) {
7048         element.css(trigger);
7049       }
7050       //If browser does not support transitions, instantly resolve
7051       if ( !endEventName ) {
7052         deferred.resolve(element);
7053       }
7054     }, 100);
7055
7056     // Add our custom cancel function to the promise that is returned
7057     // We can call this if we are about to run a new transition, which we know will prevent this transition from ending,
7058     // i.e. it will therefore never raise a transitionEnd event for that transition
7059     deferred.promise.cancel = function() {
7060       if ( endEventName ) {
7061         element.unbind(endEventName, transitionEndHandler);
7062       }
7063       deferred.reject('Transition cancelled');
7064     };
7065
7066     return deferred.promise;
7067   };
7068
7069   // Work out the name of the transitionEnd event
7070   var transElement = document.createElement('trans');
7071   var transitionEndEventNames = {
7072     'WebkitTransition': 'webkitTransitionEnd',
7073     'MozTransition': 'transitionend',
7074     'OTransition': 'oTransitionEnd',
7075     'transition': 'transitionend'
7076   };
7077   var animationEndEventNames = {
7078     'WebkitTransition': 'webkitAnimationEnd',
7079     'MozTransition': 'animationend',
7080     'OTransition': 'oAnimationEnd',
7081     'transition': 'animationend'
7082   };
7083   function findEndEventName(endEventNames) {
7084     for (var name in endEventNames){
7085       if (transElement.style[name] !== undefined) {
7086         return endEventNames[name];
7087       }
7088     }
7089   }
7090   $transition.transitionEndEventName = findEndEventName(transitionEndEventNames);
7091   $transition.animationEndEventName = findEndEventName(animationEndEventNames);
7092   return $transition;
7093 }])
7094
7095 .factory('$scrollTo', ['$window', function($window) {
7096     var $scrollTo = function(offsetLeft, offsetTop, duration) {
7097         TweenMax.to($window, duration || 1, {scrollTo: {y: offsetTop, x: offsetLeft}, ease: Power4.easeOut});
7098     };    
7099     return $scrollTo;
7100 }])
7101 .factory('animation', function(){
7102     return TweenMax;
7103 })
7104 .factory('$progressBar', function(){
7105
7106    //Provides a function to pass in code for closure purposes
7107    var loadingAnimationCreator = function(onUpdateCallback){
7108
7109       //Use closure to setup some resuable code
7110       var loadingAnimation = function(callback, duration){
7111           TweenMax.to({}, duration, {
7112               onUpdateParams: ["{self}"],
7113               onUpdate: onUpdateCallback,
7114               onComplete: callback
7115           });
7116       };
7117       //Returns a function that takes a callback function and a duration for the animation
7118       return (function(){
7119         return loadingAnimation;
7120       })();
7121     
7122     };
7123
7124   return loadingAnimationCreator;
7125 })
7126 .factory('$height', function(){
7127   var heightAnimation = function(element,duration,height,alpha){
7128     TweenMax.to(element,
7129       duration,
7130       {height:height, autoAlpha:alpha},
7131       0);
7132   };
7133   return heightAnimation;
7134 });
7135 'use strict';
7136 angular.module('att.abs.accordion', ['att.abs.position','att.abs.transition'])
7137 .constant('accordionConfig', {
7138     closeOthers: false
7139 })
7140
7141 .controller('AccordionController',['$scope', '$attrs', 'accordionConfig', '$log',
7142     function($scope, $attrs, accordionConfig, $log) {
7143     // This array keeps track of the accordion groups
7144     this.groups = [];
7145     this.index = -1;
7146
7147     // Keep reference to user's scope to properly assign `is-open`
7148     this.scope = $scope;
7149     $scope.forceExpand=false;
7150     // Ensure that all the groups in this accordion are closed, unless close-others explicitly says not to
7151      this.closeOthers = function(openGroup) {
7152         var closeOthers = angular.isDefined($attrs.closeOthers) ? $scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers;
7153         if(closeOthers && !$scope.forceExpand) {
7154             angular.forEach(this.groups, function(group) {                
7155                 if (group !== openGroup) {
7156                         group.isOpen=false;
7157                 }
7158             });       
7159         }
7160         if(this.groups.indexOf(openGroup)===(this.groups.length-1) && $scope.forceExpand){
7161             $scope.forceExpand=false;
7162         }
7163     };
7164     
7165     this.expandAll = function() {
7166         $scope.forceExpand=true; 
7167         angular.forEach(this.groups, function(group) {                               
7168             group.isOpen = true;
7169         });
7170     };
7171     
7172     this.collapseAll = function() {
7173         angular.forEach(this.groups, function(group) {                                
7174             group.isOpen = false;                                
7175         });
7176     };
7177     /**
7178      *
7179      * function focus
7180      * @param focusGroup
7181      */
7182     this.focus = function(focusGroup) {
7183         var self = this;
7184         $log.log("entering focus");
7185         angular.forEach(this.groups, function(group, index) {
7186             if (group !== focusGroup) {
7187                 group.focused = false;
7188             } else {
7189                 self.index = index;
7190                 group.focused = true;
7191             }
7192         });
7193     };
7194     /**
7195      *
7196      * @param blurGroup
7197      */
7198     this.blur = function(blurGroup) {
7199         blurGroup.focused = false;
7200         this.index = -1;
7201         $log.log("accordion.blur()", blurGroup);
7202     };
7203     /**
7204      *
7205      * @param group - the group in current focus
7206      * @param down - cycling down
7207      */
7208     this.cycle = function(group, down, noRecycle) {
7209         if (!down) {
7210             if (this.index <= 0 && !noRecycle) {
7211                 this.index = this.groups.length - 1;
7212             } else {
7213                 this.index--;
7214             }
7215         } else {
7216             
7217             /*if (this.index === (this.groups.length - 1) && !noRecycle) {
7218                 this.index = 0;
7219             } else if (this.index === (this.groups.length - 1) && noRecycle) {
7220                 this.index = 0;
7221                 return;
7222             } else {
7223                 this.index++;
7224             } */
7225             if (this.index === (this.groups.length - 1)) 
7226             {                                
7227                 if(noRecycle){
7228                     this.index = 0;                    
7229                     group.focused = false;
7230                     $scope.$apply();
7231                     return;
7232                 }
7233                 else
7234                 {
7235                     this.index = 0;
7236                 }
7237             } else {
7238                 this.index++;
7239             }   
7240             
7241             
7242         }
7243         group.focused = false;
7244         this.groups[this.index].focused = true;
7245         $log.log("accordion.cycle()", group, down);
7246         $log.log("group unfocused", group);
7247         $log.log("group focused", this.groups[this.index]);
7248         $scope.$apply();
7249     };
7250
7251     // This is called from the accordion-group directive to add itself to the accordion
7252     this.addGroup = function(groupScope) {
7253         var that = this;
7254         groupScope.index = this.groups.length;
7255         groupScope.focused = false;
7256         this.groups.push(groupScope);
7257
7258         groupScope.$on('$destroy', function(event) {
7259             that.removeGroup(groupScope);
7260         });
7261     };
7262
7263     // This is called from the accordion-group directive when to remove itself
7264     this.removeGroup = function(group) {
7265         var index = this.groups.indexOf(group);
7266         if (index !== -1) {
7267             this.groups.splice(this.groups.indexOf(group), 1);
7268         }
7269     };
7270
7271 }])
7272
7273 // The accordion directive simply sets up the directive controller
7274 // and adds an accordion CSS class to itself element.
7275 .directive('accordion', function() {
7276     return {
7277         restrict: 'EA',
7278         controller: 'AccordionController',
7279         transclude: true,
7280         replace: false,
7281         scope: {
7282             cClass: '@css',
7283             expandAll:"=?",
7284             collapseAll:"=?"
7285         },
7286         template: '<div class="{{cClass}}" ng-transclude></div>',
7287         link:function(scope,elem,attribute,ctrl)  {
7288             
7289             scope.$watch("expandAll", function(value) {
7290                 if (value===true) {
7291                      ctrl.expandAll();
7292                      scope.expandAll=false;
7293                 }
7294             });
7295              scope.$watch("collapseAll", function(value) {
7296                 if (value===true) {
7297                      ctrl.collapseAll();
7298                      scope.collapseAll = false;
7299                 }
7300             });
7301         }   
7302     };
7303 })
7304
7305 // The accordion-group directive indicates a block of html that will expand and collapse in an accordion
7306 .directive('accordionGroup', ['$parse', '$transition', '$scrollTo', '$timeout', '$log', '$position', '$window', function($parse, $transition, $scrollTo, $timeout, $log, $position, $window) {
7307     return {
7308         require: ['^accordion', 'accordionGroup'], // We need this directive to be inside an accordion
7309         restrict: 'EA',
7310         transclude: true, // It transcludes the contents of the directive into the template
7311         replace: true, // The element containing the directive will be replaced with the template
7312         templateUrl:'app/scripts/ng_js_att_tpls/accordion/accordion.html',
7313         //templateUrl:'app/scripts/ng_js_att_tpls/accordion/accordion_alt.html',
7314         
7315         scope: {
7316             heading: '@',
7317             isOpen: '=?'
7318         }, // Create an isolated scope and interpolate the heading attribute onto this scope
7319         controller:['$scope', function($scope)
7320         {
7321             $scope.showico = true;
7322             this.setHeading = function(element)
7323             {
7324                 this.heading = element;
7325                 $scope.showico = false;
7326             };                                   
7327             this.isIsOpen = function()
7328             {
7329                 return $scope.isOpen;
7330             };
7331         }],
7332         link: function(scope, element, attrs, ctrl) {
7333             var accordionCtrl = ctrl[0];
7334             var accordionGroupCtrl = ctrl[1];
7335             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};
7336
7337             //not a fix
7338             var tab = element.children().eq(0);
7339             var panel = element.children().eq(1);
7340
7341             var handleKeydown = function(ev) {
7342                 $log.log("Enter handleKeydown on: ", ev);
7343                 var boolFlag = true;
7344                 switch (ev.keyCode)
7345                 {
7346                     case keys.enter:
7347                         ev.preventDefault();
7348                         scope.toggle();
7349                         scope.$apply();
7350                         break;
7351                         //return true;
7352                     case keys.up:
7353                     case keys.left:
7354                         ev.preventDefault();
7355                         $log.log("cycle up");
7356                         accordionCtrl.cycle(scope, false);
7357                         break;
7358                         //return true;
7359                     case keys.down:
7360                     case keys.right:
7361                         ev.preventDefault();
7362                         $log.log("cycle down");
7363                         accordionCtrl.cycle(scope, true);
7364                         break;
7365                         //return true;
7366                     case keys.tab:
7367 //                        if(ev.shiftKey === true)
7368 //                        {
7369 //                            $log.log("shift with Tab");
7370 //                            accordionCtrl.cycle(scope, false);                            
7371 //                        }
7372 //                        else
7373 //                        {
7374 //                            accordionCtrl.cycle(scope, true, true);
7375 //                        }                        
7376 //                        break;
7377                     default:
7378                         boolFlag = false;
7379                         break;
7380                         //return false;
7381                 }
7382                 ev.stopPropagation();
7383                 return boolFlag;
7384             };
7385
7386             var swallowKeypress = function(e) {
7387                 $log.log("keypress", e);
7388                 if (e.altKey) {
7389                     // do nothing
7390                     return true;
7391                 }
7392                 var boolFlag = true;
7393                 switch (e.keyCode)
7394                 {
7395                     case keys.enter:
7396                     case keys.space:
7397                     case keys.left:
7398                     case keys.up:
7399                     case keys.right:
7400                     case keys.down:
7401                     case keys.home:
7402                     case keys.end:
7403                         e.stopPropagation();
7404                         boolFlag = false;
7405                         break;
7406                         //return false;
7407                     case keys.pageup:
7408                     case keys.pagedown:
7409                         // The tab keypress handler must consume pageup and pagedown
7410                         // keypresses to prevent Firefox from switching tabs
7411                         // on ctrl+pageup and ctrl+pagedown
7412                         if (!e.ctrlKey)
7413                         {
7414                             boolFlag = true;
7415                             break;
7416                             //return true;
7417                         }
7418                         e.stopPropagation();
7419                         boolFlag = false;
7420                         break;
7421                         //return false;
7422                     default:
7423                         break;
7424                 }
7425                 return boolFlag;
7426                 //return true;
7427             };
7428             
7429             if(angular.isUndefined(scope.isOpen)) {
7430                 scope.isOpen = false;
7431             }
7432
7433             panel.bind("keypress", swallowKeypress);
7434             tab.bind("keydown", handleKeydown);
7435
7436             tab.bind("focus", function(ev) {
7437                 tab.attr("tabindex", "0");
7438             });
7439
7440             tab.bind("blur", function(ev) {
7441                 if (scope.index !== 0) {
7442                     tab.attr("tabindex", "-1");
7443                 }
7444             });
7445
7446             accordionCtrl.addGroup(scope);
7447
7448             if (scope.index === 0) {
7449                 tab.attr("tabindex", "0");
7450             }
7451
7452             accordionGroupCtrl.toggle = scope.toggle = function() {
7453                 scope.isOpen = !scope.isOpen;
7454                 accordionCtrl.focus(scope);
7455                 if (scope.isOpen === true) {
7456                     if (navigator.userAgent.match(/MSIE 8/) === null) {
7457                        // $scrollTo(0, $position.offset(element).top, 0.5);
7458                     }
7459                 } 
7460                 return scope.isOpen;
7461             };
7462             
7463             scope.$watch('isOpen', function(value) {
7464                 if (value) {
7465                     accordionCtrl.closeOthers(scope);
7466                 }
7467             });
7468
7469             scope.$watch("focused", function(value) {
7470                 if (!!value) {
7471                     $timeout(function() {
7472                         tab.attr("tabindex", "0");
7473                         tab[0].focus();
7474                     }, 0);
7475                 }
7476             });
7477         }
7478     };
7479 }])
7480 // Use accordion-heading below an accordion-group to provide a heading containing HTML
7481 // <accordion-group>
7482 //   <accordion-heading>Heading containing HTML - <img src="..."></accordion-heading>
7483 // </accordion-group>
7484 //accordionToggle
7485 .directive('accordionToggle',function(){
7486     return{
7487         restrict: 'EA',
7488         require: '^accordionGroup',
7489         scope:{
7490             expandIcon:'@',
7491             collapseIcon:'@'
7492         },
7493         link: function(scope, element, attr, accordionCtrl)
7494         {      
7495                        
7496             var setIcon = function(isOpen){                                            
7497                 if(scope.expandIcon && scope.collapseIcon)
7498                 {
7499                     if(isOpen){
7500                         element.removeClass(scope.expandIcon);
7501                         element.addClass(scope.collapseIcon);
7502                     }
7503                     else{
7504                         element.removeClass(scope.collapseIcon);
7505                         element.addClass(scope.expandIcon);                        
7506                     }                                    
7507                 }
7508             };  
7509                    
7510             element.bind('click', function()
7511             {                
7512                 accordionCtrl.toggle();
7513                 scope.$apply();
7514             });
7515                         
7516             scope.$watch(function(){
7517                 return accordionCtrl.isIsOpen();
7518             }, function(value){
7519                 setIcon(value);
7520             });                    
7521         }                
7522     };   
7523 })
7524
7525 .directive('accordionHeading', function() {
7526     return {
7527         restrict: 'EA',
7528         transclude: true, // Grab the contents to be used as the heading
7529         template: '', // In effect remove this element!
7530         //replace: true,
7531         require: '^accordionGroup',        
7532         compile: function(element, attr, transclude) {
7533             return function link(scope, element, attr, accordionGroupCtrl) {
7534                 // Pass the heading to the accordion-group controller
7535                 // so that it can be transcluded into the right place in the template
7536                 // [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat]                
7537                 transclude(scope, function(clone) {
7538                     element.append(clone);
7539                     accordionGroupCtrl.setHeading(element);
7540                 });
7541             };
7542         }
7543
7544 //        compile: function(element, attr, transclude) {
7545 //            return function link(scope, element, attr, accordionGroupCtrl) {
7546 //                // Pass the heading to the accordion-group controller
7547 //                // so that it can be transcluded into the right place in the template
7548 //                // [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat]
7549 //                accordionGroupCtrl.setHeading(transclude(scope, function() {
7550 //                }));
7551 //            };
7552 //        }        
7553     };
7554 })
7555
7556 // Use in the accordion-group template to indicate where you want the heading to be transcluded
7557 // You must provide the property on the accordion-group controller that will hold the transcluded element
7558 // <div class="accordion-group">
7559 //   <div class="accordion-heading" ><a ... accordion-transclude="heading">...</a></div>
7560 //   ...
7561 // </div>
7562 .directive('accordionTransclude', function() {
7563     return {
7564         require: '^accordionGroup',
7565         link: function(scope, element, attr, controller) {
7566             scope.$watch(function() {
7567                 return controller[attr.accordionTransclude];
7568             }, function(heading) {
7569                 if (heading) {
7570                     element.find("span").eq(0).prepend(heading);
7571                 }
7572             });
7573         }
7574     };
7575 })
7576
7577 .directive('attGoTop',['$scrollTo', function($scrollTo){    
7578     return {
7579       restrict: 'A',        
7580       transclude: false,                   
7581       link: function (scope, elem, attrs) 
7582       {         
7583           elem.bind('click', function() 
7584           {
7585              $scrollTo(0,attrs["attGoTop"]);
7586           });
7587       }    
7588 };
7589 }])
7590
7591 .directive('attGoTo',['$anchorScroll','$location', function($anchorScroll, $location){    
7592     return {
7593       restrict: 'A',        
7594       transclude: false,                   
7595       link: function (scope, elem, attrs) 
7596        {         
7597           elem.bind('click', function() 
7598           {                
7599                 var newHash = attrs["attGoTo"];
7600                 if ($location.hash() !== newHash) 
7601                 {
7602                     $location.hash(attrs["attGoTo"]);
7603                 }
7604                 else 
7605                 {
7606                     $anchorScroll();
7607                 }
7608           });
7609         }    
7610     };
7611 }])
7612
7613 .directive('freeStanding',function(){    
7614     return {
7615       restrict: 'EA',
7616       transclude: true,                   
7617       replace:true,
7618       scope:true,
7619       template: "<div><span class='att-accordion__freestanding' ng-show='showAccordion'></span>\n" +                         
7620             "<div class='section-toggle'>\n" +
7621             "<button class='section-toggle__button' ng-click='fsToggle()'>\n" + 
7622             "    {{btnText}}<i style='font-size:0.875rem' ng-class='{\"icon-chevron-up\": showAccordion,\"icon-chevron-down\": !showAccordion, }'></i> \n" +
7623             "</button>\n" + 
7624             "</div></div>",       
7625         compile: function(element, attr, transclude) 
7626         {
7627             return function link(scope, elem, attrs) 
7628             {                
7629                 scope.content = "";
7630                 transclude(scope, function(clone) 
7631                 {
7632                     elem.find("span").append(clone);                                        
7633                 });           
7634                 scope.showAccordion = false;
7635                 scope.btnText = scope.showAccordion? attrs.hideMsg:attrs.showMsg;                                  
7636                 scope.fsToggle = function()
7637                 {
7638                       scope.showAccordion = !scope.showAccordion;              
7639                       scope.btnText = scope.showAccordion? attrs.hideMsg:attrs.showMsg;                    
7640                 }                
7641             };
7642         }
7643     };
7644 })
7645
7646 .directive('expanders',function(){
7647     return{
7648         restrict: 'EA',
7649         replace:true,
7650         transclude:true,        
7651         template:"<div ng-transclude></div>",
7652         controller: ['$scope',function($scope){
7653             var bodyScope = null;
7654             this.setScope = function(scope){               
7655                 bodyScope = scope;               
7656             };
7657             this.toggle = function(){             
7658                bodyScope.isOpen = !bodyScope.isOpen;
7659                return bodyScope.isOpen;
7660             };
7661         }],
7662         
7663         link: function(scope, element, attrs, accordionCtrl)
7664         {           
7665             scope.isOpen = false;
7666             element.bind('click', function() 
7667             {
7668                 scope.isOpen = !scope.isOpen; 
7669             });
7670         }         
7671     };
7672 })
7673
7674 .directive('expanderHeading',function(){
7675    
7676     return{
7677         require:"^expanders",
7678         restrict: 'EA',
7679         replace:true,
7680         transclude:true,
7681         scope:true,
7682         template: "<div style='padding:10px !important' ng-transclude></div>"
7683     };
7684     
7685 })
7686
7687 .directive('expanderBody',function(){
7688    
7689     return{
7690         restrict: 'EA',
7691         require:"^expanders",
7692         replace:true,
7693         transclude:true,
7694         scope:{},
7695         template: "<div collapse='!isOpen'><div ng-transclude></div></div>",        
7696         link:function(scope, elem, attr, myCtrl){            
7697           scope.isOpen = false; 
7698           myCtrl.setScope(scope);
7699         }   
7700     };
7701 })
7702
7703 .directive('expanderToggle',function(){
7704    
7705    return{
7706         restrict: 'EA',
7707         require:"^expanders",
7708         scope:{
7709             expandIcon:'@',
7710             collapseIcon:'@'
7711         },
7712         link: function(scope, element, attr, myCtrl)
7713         {      
7714             var isOpen=false;                       
7715             var setIcon = function(){                                            
7716                 if(scope.expandIcon && scope.collapseIcon)
7717                 {
7718                     if(isOpen) {
7719                         element.removeClass(scope.expandIcon);
7720                         element.addClass(scope.collapseIcon);
7721                     }
7722                     else {
7723                         element.removeClass(scope.collapseIcon);
7724                         element.addClass(scope.expandIcon);                        
7725                     }                                    
7726                 }
7727             };    
7728                         
7729             element.bind("keydown", function(e){
7730                 if(e.keyCode === 13)
7731                 {
7732                     scope.toggleit();
7733                 }                
7734             }); 
7735                         
7736             element.bind('click', function() 
7737             { 
7738                 scope.toggleit();                
7739             }); 
7740             
7741             scope.toggleit = function()
7742             {
7743                  isOpen = myCtrl.toggle();
7744                  setIcon();
7745                  scope.$apply();
7746             };            
7747             setIcon();
7748         }                
7749     };             
7750 })
7751         
7752 .directive('collapse', ['$transition', function($transition) {
7753   // CSS transitions don't work with height: auto, so we have to manually change the height to a
7754   // specific value and then once the animation completes, we can reset the height to auto.
7755   // Unfortunately if you do this while the CSS transitions are specified (i.e. in the CSS class
7756   // "collapse") then you trigger a change to height 0 in between.
7757   // The fix is to remove the "collapse" CSS class while changing the height back to auto - phew!
7758
7759   var props = {
7760         open : {            
7761             marginTop: null,
7762             marginBottom: null,
7763             paddingTop: null,
7764             paddingBottom: null,
7765             display:'block'
7766         },
7767         closed: {
7768             marginTop: 0,
7769             marginBottom: 0,
7770             paddingTop: 0,
7771             paddingBottom: 0,
7772             display:'none'
7773         }
7774     };
7775
7776   var fixUpHeight = function(scope, element, height) {
7777     // We remove the collapse CSS class to prevent a transition when we change to height: auto
7778     element.removeClass('collapse');
7779     element.css({ height: height });
7780       //adjusting for any margin or padding
7781       if (height===0) {
7782           element.css(props.closed);
7783       } else {
7784           element.css(props.open);
7785       }
7786     // It appears that  reading offsetWidth makes the browser realise that we have changed the
7787     // height already :-/
7788     var x = element[0].offsetWidth;
7789     element.addClass('collapse');
7790   };
7791
7792   return {
7793     link: function(scope, element, attrs) {
7794
7795        // alert(element.css("marginTop"));
7796       var isCollapsed;
7797       var initialAnimSkip = true;
7798       scope.$watch(function (){ return element[0].scrollHeight; }, function (value) {
7799         //The listener is called when scrollHeight changes
7800         //It actually does on 2 scenarios: 
7801         // 1. Parent is set to display none
7802         // 2. angular bindings inside are resolved
7803         //When we have a change of scrollHeight we are setting again the correct height if the group is opened
7804         if (element[0].scrollHeight !== 0) {
7805           if (!isCollapsed) {
7806             if (initialAnimSkip) {
7807               fixUpHeight(scope, element, element[0].scrollHeight + 'px');
7808             } else {
7809               fixUpHeight(scope, element, 'auto');
7810             }
7811           }
7812         }
7813       });
7814       
7815       scope.$watch(attrs.collapse, function(value) {
7816         if (value) {
7817           collapse();
7818         } else {
7819           expand();
7820         }
7821       });
7822       
7823
7824       var currentTransition;
7825       var doTransition = function(change) {
7826         if ( currentTransition ) {
7827           currentTransition.cancel();
7828         }
7829         currentTransition = $transition(element,change);
7830         currentTransition.then(
7831           function() { currentTransition = undefined; },
7832           function() { currentTransition = undefined; }
7833         );
7834         return currentTransition;
7835       };
7836
7837       var expand = function() {
7838         //element.show();
7839           scope.postTransition = true;
7840         if (initialAnimSkip) {
7841           initialAnimSkip = false;
7842           if ( !isCollapsed ) {
7843             fixUpHeight(scope, element, 'auto');
7844           }
7845         } else {
7846           //doTransition({ height : element[0].scrollHeight + 'px' })
7847           doTransition(angular.extend({ height : element[0].scrollHeight + 'px' }, props.open))
7848           .then(function() {
7849             // This check ensures that we don't accidentally update the height if the user has closed
7850             // the group while the animation was still running
7851             if ( !isCollapsed ) 
7852             {
7853               fixUpHeight(scope, element, 'auto');
7854             }
7855           });
7856         }
7857         isCollapsed = false;
7858       };
7859       
7860       var collapse = function() {
7861         isCollapsed = true;
7862         if (initialAnimSkip) {
7863           initialAnimSkip = false;
7864           fixUpHeight(scope, element, 0);
7865         } else {
7866           fixUpHeight(scope, element, element[0].scrollHeight + 'px');
7867           //doTransition({'height':'0'}).then(function() {
7868             doTransition(angular.extend({height:0}, props.closed)).then(function() {
7869               //element.hide();
7870               scope.postTransition = false;
7871           });
7872         }
7873       };
7874     }
7875   };
7876 }])
7877 .directive('attAccord', function(){
7878     return {
7879         restrict: 'EA',
7880         transclude: true,
7881         replace:true,
7882         scope: {},
7883         controller: 'AttAccordCtrl',
7884         templateUrl: 'app/scripts/ng_js_att_tpls/accordion/attAccordHeader.html',
7885         link: function(scope,element,attr,ctrls){
7886         }
7887     }
7888 })
7889 .controller('AttAccordCtrl', ['$scope', function($scope){
7890
7891     this.type='attAccord';
7892     this.headerCtrl;
7893     this.bodyCtrl;
7894     var isOpen = true;
7895
7896     this.toggleBody = function(){
7897         if(isOpen)
7898             this.expandBody();
7899         else
7900             this.collapseBody();
7901
7902         isOpen = !isOpen;
7903     };
7904
7905     this.expandBody = function(){
7906         this.bodyCtrl.expand();
7907     };
7908
7909     this.collapseBody = function(){
7910         this.bodyCtrl.collapse();
7911     }
7912
7913 }])
7914 .controller('AttAccordHeaderCtrl',['$scope', function($scope){
7915     this.type='header';
7916 }])
7917 .directive('attAccordHeader', function(){
7918     return {
7919         restrict: 'EA',
7920         transclude: true,
7921         replace:true,
7922         require:['^attAccord','attAccordHeader'],
7923         controller: 'AttAccordHeaderCtrl',
7924         templateUrl: 'app/scripts/ng_js_att_tpls/accordion/attAccordHeader.html',
7925         link: function(scope,element,attr, ctrls){
7926             var attAccordCtrl = ctrls[0];
7927             var attAccordHeaderCtrl = ctrls[1];
7928             attAccordCtrl.headerCtrl = attAccordHeaderCtrl;
7929
7930             scope.clickFunc = function(){
7931                 attAccordCtrl.toggleBody();
7932             };
7933
7934         }
7935     }
7936 })
7937 .controller('AttAccordBodyCtrl', ['$scope', function($scope){
7938     this.type='body';
7939
7940     this.expand = function(){
7941         $scope.expand();
7942     };
7943
7944     this.collapse = function(){
7945         $scope.collapse();
7946     };
7947
7948 }])
7949 .directive('attAccordBody', ['$timeout', '$height',function($timeout,$height){
7950     return {
7951         restrict: 'EA',
7952         transclude: true,
7953         replace:true,
7954         require: ['^attAccord','attAccordBody'],
7955         controller: 'AttAccordBodyCtrl',
7956         templateUrl: 'app/scripts/ng_js_att_tpls/accordion/attAccordBody.html',
7957         link: function(scope,element,attr,ctrls){
7958
7959             var attAccordCtrl = ctrls[0];
7960             var attAccordBodyCtrl = ctrls[1];
7961             attAccordCtrl.bodyCtrl = attAccordBodyCtrl;
7962
7963             var originalHeight; 
7964             $timeout(function(){
7965                 originalHeight = element[0].offsetHeight;
7966                 $height(element,0,0,0);
7967             });
7968
7969             scope.expand = function(){
7970                 $height(element,0.05,originalHeight,1);
7971             };
7972
7973             scope.collapse = function(){
7974                 $height(element,0.25,0,0);
7975             };
7976
7977         } 
7978     }
7979 }])
7980 angular.module('att.abs.alert', [])
7981 .directive('attAlert', [function()
7982 {
7983     return {
7984         restrict: 'EA',        
7985         replace : true,
7986         transclude : true,
7987         scope: {
7988             alertType : "@type",
7989             showTop : "@topPos",
7990             showAlert : "="
7991         },
7992        templateUrl : 'app/scripts/ng_js_att_tpls/alert/alert.html',
7993        link: function(scope, elem, attr, ctrl)
7994         {
7995             if(scope.showTop === 'true'){
7996                 scope.cssStyle = {'top':'50px'};
7997             }
7998             else{
7999                scope.cssStyle = {'top':'0px'};
8000             }
8001            scope.close = function(){
8002                scope.showAlert = false;
8003             };
8004         }
8005     };
8006 }]);
8007
8008 angular.module('att.abs.breadCrumbs', [])
8009     .constant("classConstant",{
8010             "defaultClass" : "breadcrumbs__link",
8011             "activeClass": "breadcrumbs__link--active"
8012         })
8013 .directive('attCrumb', ['classConstant', function(classConstant)
8014 {
8015     return {
8016         restrict: 'A',        
8017         replace : true,
8018         transclude : true,
8019         scope: {},
8020         link: function(scope, elem, attr, ctrl)
8021         {
8022             elem.addClass(classConstant.defaultClass);
8023             if(attr.attCrumb === 'active'){
8024                  elem.addClass(classConstant.activeClass);
8025             }
8026            if(!elem.hasClass('last')){
8027                elem.append('<i class="breadcrumbs__item"></i>');
8028            }
8029         }
8030     };
8031 }
8032 ]);
8033
8034 angular.module('att.abs.utilities', [])
8035
8036 .filter('highlight', function () {
8037     function escapeRegexp(queryToEscape) {
8038         return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1');
8039     }
8040     return function (matchItem, query, className) {
8041         return query && matchItem ? matchItem.replace(new RegExp(escapeRegexp(query), 'gi'), '<span class=\"' + className + '\">$&</span>') : matchItem;
8042     };
8043 })
8044
8045 .filter('attLimitTo', function() {
8046     return function(actualArray, _limit, _begin) {
8047         var finalArray = [];
8048         var limit = _limit;
8049         var begin = _begin;
8050         if(isNaN(begin)) {
8051             begin = 0;
8052         }
8053         if(actualArray && !isNaN(limit)) {
8054            // finalArray = actualArray.slice(begin, begin+limit);
8055                 //slice is not a function. need to find out why 06/17/2015
8056                 finalArray = actualArray;
8057         } else {
8058             finalArray = actualArray;
8059         }
8060         return finalArray;
8061     }
8062 })
8063
8064 .directive('attInputDeny', [function() {
8065     return {
8066         restrict: 'A',
8067         require: 'ngModel',
8068         link: function (scope, elem, attr, ctrl) {
8069             var regexExpression = null;
8070             attr.$observe('attInputDeny', function (value) {
8071                 if (value) {
8072                     regexExpression = new RegExp(value, 'g');
8073                 }
8074             });
8075             elem.bind('input', function () {
8076                 var inputString = ctrl.$viewValue && ctrl.$viewValue.replace(regexExpression, '');
8077                 if (inputString !== ctrl.$viewValue) {
8078                     ctrl.$setViewValue(inputString);
8079                     ctrl.$render();
8080                     scope.$apply();
8081                 }
8082             });
8083         }
8084     };
8085 }])
8086
8087 .directive('attAccessibilityClick', [function() {
8088     return {
8089         restrict: 'A',
8090         link: function (scope, elem, attr, ctrl) {
8091             var keyCode = [];
8092             attr.$observe('attAccessibilityClick', function (value) {
8093                 if (value) {
8094                     keyCode = value.split(',');
8095                 }
8096             });
8097             elem.bind('keydown', function (ev) {
8098                 if(keyCode.length > 0 && ((ev.charCode && keyCode.indexOf(ev.charCode.toString()) > -1) || (ev.keyCode && keyCode.indexOf(ev.keyCode.toString()) > -1) || (ev.which && keyCode.indexOf(ev.which.toString()) > -1))) {
8099                     elem[0].click();
8100                     ev.preventDefault();
8101                 }
8102             });
8103         }
8104     };
8105 }])
8106
8107 .directive('attElementFocus', [function() {
8108     return {
8109         restrict: 'A',
8110         link: function(scope, elem, attr, ctrl) {
8111             scope.$watch(attr.attElementFocus, function (value) {
8112                 if (value === true) {
8113                     elem[0].focus();
8114                 }
8115             });
8116         }
8117     };
8118 }])
8119 .factory('events', function(){
8120     var s =  function(e){
8121         if(e.stopPropagation) {
8122             e.stopPropagation();
8123         } else {
8124             e.returnValue = false;
8125         }    
8126     };
8127
8128     return {
8129         stopPropagation: s
8130     };
8131 })
8132 .factory('$documentBind', ['$document', '$timeout', function($document, $timeout) {
8133     var _click = function (flag, callbackFunc, scope) {
8134         scope.$watch(flag, function (val) {
8135             $timeout(function () {
8136                 if (val) {
8137                     $document.bind('click', callbackFunc);
8138                 } else {
8139                     $document.unbind('click', callbackFunc);
8140                 }
8141             });
8142         });
8143     };
8144
8145     return {
8146         click: _click
8147     };
8148 }]);
8149
8150 (function () {
8151     String.prototype.toSnakeCase = function () {
8152         return this.replace(/([A-Z])/g, function ($1) {
8153             return "-" + $1.toLowerCase();
8154         });
8155     };
8156     
8157     var concat = function (character, times) {
8158         character = character || '';
8159         times = (!isNaN(times) && times) || 0;
8160         var finalChar = '';
8161         for (var i = 0; i < times; i++) {
8162             finalChar += character;
8163         }
8164
8165         return finalChar;
8166     };
8167     
8168     var pad = function (actualString, width, character, direction) { // direction: true for left and false for right
8169         actualString = actualString || '';
8170         width = (!isNaN(width) && width) || 0;
8171         character = character || '';
8172         direction = (direction !== undefined && direction) || true;
8173
8174         if (width > actualString.length) {
8175             if (direction) {
8176                 return concat(character, (width - actualString.length)) + actualString;
8177             } else {
8178                 return actualString + concat(character, (width - actualString.length));
8179             }
8180         }
8181         return actualString;
8182     };
8183
8184     String.prototype.lPad = function (width, character) {
8185         return pad(this, width, character, true);
8186     };
8187
8188     String.prototype.rPad = function (width, character) {
8189         return pad(this, width, character, false);
8190     };
8191
8192     if (!Array.prototype.indexOf) {
8193         Array.prototype.indexOf = function (val) {
8194             for (var index = 0; index < this.length; index++) {
8195                 if (this[index] === val) {
8196                     return index;
8197                 }
8198             }
8199             return -1;
8200         };
8201     }
8202 })();
8203
8204 angular.module('att.abs.buttons', ['att.abs.position', 'att.abs.utilities'])
8205 .constant('btnConfig', {
8206     btnClass: 'button',
8207     btnPrimaryClass: 'button--primary',
8208     btnSecondaryClass: 'button--secondary',
8209     btnDisabledClass: 'button--inactive',
8210     btnSmallClass: 'button--small'
8211 })
8212 .directive('attButton', ['btnConfig', function(btnConfig) {
8213     return {
8214         restrict: 'A',
8215         link: function (scope, element, attrs, ctrl) {
8216             element.addClass(btnConfig.btnClass);
8217             if (attrs.size === 'small') {
8218                 element.addClass(btnConfig.btnSmallClass);
8219             }
8220             attrs.$observe('btnType', function(value) {
8221                 if (value === 'primary') {
8222                     element.addClass(btnConfig.btnPrimaryClass);
8223                     element.removeClass(btnConfig.btnSecondaryClass);
8224                     element.removeClass(btnConfig.btnDisabledClass);
8225                     element.removeAttr('disabled');
8226                 } else if (value === 'secondary') {
8227                     element.addClass(btnConfig.btnSecondaryClass);
8228                     element.removeClass(btnConfig.btnPrimaryClass);
8229                     element.removeClass(btnConfig.btnDisabledClass);
8230                     element.removeAttr('disabled');
8231                 } else if (value === 'disabled') {
8232                     element.addClass(btnConfig.btnDisabledClass);
8233                     element.removeClass(btnConfig.btnPrimaryClass);
8234                     element.removeClass(btnConfig.btnSecondaryClass);
8235                     element.attr('disabled', 'disabled');
8236                 }
8237             });
8238         }
8239     };
8240 }])
8241 .directive('attButtonLoader', [function () {
8242     return {
8243         restrict: 'A',
8244         replace: false,
8245         scope: {
8246             size: '@'
8247         },
8248         template: '<div ng-class="{\'button--loading\': size === \'large\',\'button--loading__small\': size === \'small\'}"><i></i><i></i><i></i></div>',
8249         link: function (scope, element, attrs, ctrl) {
8250             element.addClass('button button--inactive');
8251         }
8252     };
8253 }]).directive('attButtonHero', [function () {
8254     return {
8255         restrict: 'A',
8256         replace: false,
8257         transclude: true,
8258         scope: {
8259             icon: '@'
8260         },
8261         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>',
8262         link: function (scope, element, attrs, ctrl) {
8263             element.addClass('button button--hero');
8264             element.attr("tabindex", "0");
8265         }
8266     };
8267 }]).directive('attBtnDropdown',['$document', '$isElement', '$documentBind', function($document, $isElement, $documentBind){
8268        return {
8269             restrict: 'EA',
8270             transclude:true,
8271             scope:{
8272                 type: "@dropdowntype"
8273             },
8274             replace: true,
8275             template: '<div class="att-btn-dropdown"> <div class="buttons-dropdown--small btn-group" ng-class="{\'open\': isOpen}" ng-click="toggleDropdown($event)"> <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($event)"></div> <div class="circle" ng-click="toggleDropdownCircle($event)"></div> <div class="circle" ng-click="toggleDropdownCircle($event)"></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"> <div ng-transclude> </div> </ul> </div></div>',
8276             link: function(scope,element,attrs){
8277                 
8278                 scope.isOpen = false;
8279
8280                 var toggle = scope.toggle = function (show) {
8281                     if(show === true || show === false) {
8282                         scope.isOpen = show;
8283                     } else {
8284                         scope.isOpen = !scope.isOpen;
8285                     }
8286                 };
8287
8288                 scope.toggleDropdownCircle = function($event){
8289                     toggle(false);
8290                 };
8291
8292                 scope.toggleDropdown = function($event){
8293                     toggle();
8294                 };
8295
8296                 var outsideClick = function (e) {
8297                     var isElement = $isElement(angular.element(e.target), element, $document);
8298                     if(!isElement) {
8299                         toggle(false);
8300                         scope.$apply();
8301                     }
8302                 };
8303
8304                 $documentBind.click('isOpen', outsideClick, scope);
8305             }
8306         };
8307 }]);
8308
8309 angular.module('att.abs.checkbox', [])
8310 .constant("attCheckboxConfig", {
8311     activeClass : "att-checkbox--on",
8312     disabledClass : "att-checkbox--disabled"
8313 })
8314 .directive('checkboxLimit', ['$compile', "attCheckboxConfig", function ($compile, attCheckboxConfig) {
8315 return {
8316     scope: {
8317         checkboxLimit:'=',
8318         selectLimit:'@?',
8319         maxSelected:'&?'
8320     },
8321     restrict: 'A',
8322     require:'checkboxLimit',
8323      controller: ['$scope', '$element', '$attrs', function($scope, $element, $attrs) 
8324     {
8325         $scope.limit=true;
8326         this.getMaxLimits=function(){
8327             return $scope.limit;
8328         };
8329         this.setMaxLimits=function(value){
8330             $scope.limit=value;
8331         };
8332         this.maxCheckboxSelected=function(){
8333             $scope.maxSelected();
8334         };
8335     }],
8336     link: function (scope, element, attribute, ctrl) {
8337         scope.$watch('checkboxLimit', function()
8338         {
8339             var countTrue = 0;
8340             for (var keys in scope.checkboxLimit) {
8341                 if (scope.checkboxLimit.hasOwnProperty(keys)) {
8342                     if (scope.checkboxLimit[keys] === true) {
8343                         countTrue = countTrue + 1;
8344                     }
8345                 }
8346             };
8347             if(countTrue>=parseInt(scope.selectLimit)){
8348                 ctrl.setMaxLimits(false);
8349             }
8350             else{
8351                 ctrl.setMaxLimits(true);
8352             }
8353             }, true);
8354     }
8355 };
8356 }])
8357 .directive('attCheckbox', ['$compile', "attCheckboxConfig", function ($compile, attCheckboxConfig) {
8358     return {
8359         scope: {},
8360         restrict: 'A',
8361         require: ['ngModel','^?checkboxLimit'],
8362         link: function (scope, element, attribute, ctrl) {
8363             var ngCtrl = ctrl[0];
8364             var checkboxLimitCtrl = ctrl[1];
8365             var parentDiv = $compile('<div tabindex="0" role="checkbox" att-accessibility-click="13,32" ng-click="updateModel($event)" class="att-checkbox"></div>')(scope);
8366             element.css({display:'none'});
8367             element.wrap(parentDiv);
8368             element.parent().append('<div class="att-checkbox__indicator"></div>');
8369             element.parent().attr("title", attribute.title);
8370             element.parent().attr("id", attribute.id);
8371             element.removeAttr("id");
8372             //model -> UI
8373             ngCtrl.$render = function () {
8374                 var selected = ngCtrl.$modelValue ? true : false;
8375                 element.parent().toggleClass(attCheckboxConfig.activeClass, selected);
8376                 element.parent().attr("aria-checked", selected);
8377             };
8378
8379             //ui->model
8380             scope.updateModel = function (evt) {
8381                 if (!scope.disabled) {
8382                     ngCtrl.$setViewValue(element.parent().hasClass(attCheckboxConfig.activeClass) ? false : true);
8383                     if(checkboxLimitCtrl && !(checkboxLimitCtrl.getMaxLimits())){
8384                         if(ngCtrl.$modelValue===false){
8385                             ngCtrl.$render();
8386                         }
8387                         else{
8388                             checkboxLimitCtrl.maxCheckboxSelected();
8389                             ngCtrl.$setViewValue(element.parent().hasClass(attCheckboxConfig.activeClass) ? true : false);
8390                         }
8391                     }
8392                     else{
8393                         ngCtrl.$render();
8394                     }
8395                 }
8396                 evt.preventDefault();
8397             };
8398
8399             attribute.$observe('disabled', function(val) {
8400                 scope.disabled = (val === true || val === "disabled" || val === "true");
8401                 element.parent().toggleClass(attCheckboxConfig.disabledClass, scope.disabled);
8402                 element.parent().attr("tabindex", scope.disabled ? "-1" : "0");
8403             });
8404         }
8405     };
8406 }])
8407 .directive('checkboxGroup', ['$compile',function($compile) {
8408     return {
8409         scope:
8410             {
8411                 checkboxGroup: "=",
8412                 checkboxGroupValue: "=?"
8413             },
8414         restrict: 'A',
8415         link: function(scope, element, attribute, ctrl)
8416             {
8417                 scope.checkboxState = 'none';
8418                 scope.checkboxGroupValue="indeterminate";
8419                 element.css({display:'none'});
8420                 element.wrap($compile('<div tabindex="0" role="checkbox" att-accessibility-click="13,32" ng-click="updateModel($event)" class="att-checkbox"></div>')(scope));
8421                 element.parent().append('<div class="att-checkbox__indicator"></div>');
8422                 element.parent().attr("title", attribute.title);
8423                 scope.$watch('checkboxState', function(val) {
8424                     if (val === 'all') {
8425                         element.parent().addClass('att-checkbox--on');
8426                         element.parent().removeClass('att-checkbox--indeterminate');
8427                         element.parent().attr("aria-checked", true);
8428                     }
8429                     else if (val === 'none') {
8430                         element.parent().removeClass('att-checkbox--on');
8431                         element.parent().removeClass('att-checkbox--indeterminate');
8432                         element.parent().attr("aria-checked", false);
8433                     }
8434                     else if (val === 'indeterminate') {
8435                         element.parent().removeClass('att-checkbox--on');
8436                         element.parent().addClass('att-checkbox--indeterminate');
8437                         element.parent().attr("aria-checked", true);
8438                     }
8439                 });
8440
8441                 scope.updateModel = function(evt)
8442                 {
8443                     if (element.parent().hasClass('att-checkbox--on')) {
8444                             element.parent().removeClass('att-checkbox--on');
8445                             for (var keys in scope.checkboxGroup) {
8446                                 if (scope.checkboxGroup.hasOwnProperty(keys)) {
8447                                     scope.checkboxGroup[keys] = false;
8448                                 }
8449                             };
8450                             }
8451                     else {
8452                         element.parent().addClass('att-checkbox--on');
8453                         for (var keys in scope.checkboxGroup) {
8454                             if (scope.checkboxGroup.hasOwnProperty(keys)) {
8455                                 scope.checkboxGroup[keys] = true;
8456                             }
8457                         };
8458                     }
8459                     evt.preventDefault();
8460                 };
8461                 scope.$watch('checkboxGroupValue', function (value) {
8462                     if (value === false) {
8463                             element.parent().removeClass('att-checkbox--on');
8464                             for (var keys in scope.checkboxGroup) {
8465                                 if (scope.checkboxGroup.hasOwnProperty(keys)) {
8466                                         scope.checkboxGroup[keys] = false;
8467                                 }
8468                             };
8469                             }
8470                     else if (value === true){
8471                         element.parent().addClass('att-checkbox--on');
8472                         for (var keys in scope.checkboxGroup) {
8473                             if (scope.checkboxGroup.hasOwnProperty(keys)) {
8474                                     scope.checkboxGroup[keys] = true;
8475                             }
8476                         };
8477                     }
8478                 });
8479             scope.$watch('checkboxGroup', function()
8480             {
8481                 var countTrue = 0;
8482                 var countFalse = 0;
8483                 var count = 0;
8484                 for (var keys in scope.checkboxGroup) {
8485                     if (scope.checkboxGroup.hasOwnProperty(keys)) {
8486                         count = count + 1;
8487                         if (scope.checkboxGroup[keys] === true) {
8488                             countTrue = countTrue + 1;
8489                         }
8490                         else if (scope.checkboxGroup[keys] === false) {
8491                             countFalse = countFalse + 1;
8492                         }
8493                     }
8494                 };
8495                 if (count === countTrue) {
8496                     scope.checkboxState = "all";
8497                      scope.checkboxGroupValue=true;
8498                 }
8499                 else if (count === countFalse) {
8500                     scope.checkboxState = "none";
8501                     scope.checkboxGroupValue=false;
8502                 }
8503                 else {
8504                     scope.checkboxState = "indeterminate";
8505                     scope.checkboxGroupValue="indeterminate";
8506                 }
8507                 }, true);
8508         }
8509     };
8510 }]);
8511
8512 angular.module('att.abs.colorselector', [])
8513     .directive('colorSelectorWrapper', [function() {
8514         return {
8515             scope: {
8516                 selected: '=',
8517                 iconColor: '@'
8518             },
8519             restrict: 'AE',
8520             transclude: true,
8521             templateUrl: 'app/scripts/ng_js_att_tpls/colorselector/colorselector.html',
8522             link: function(scope, element, attr) {
8523                 scope.applycolor = {'background-color': scope.iconColor};
8524                 scope.selectedcolor = function(iconColor) {
8525                     scope.selected = iconColor;
8526                 };
8527             }
8528         };
8529      }])
8530     .directive('colorSelector', ['$compile', function($compile) {
8531         return{
8532             restrict: 'A',
8533             scope: {
8534                 colorSelector: '@',
8535                 ngModel: '='
8536             },
8537             link: function(scope, element, attr) {
8538                 element.removeAttr('color-selector');
8539                 var wrapcont = angular.element('<color-selector-wrapper selected="ngModel" icon-color="{{colorSelector}}">' + element.prop('outerHTML') + '</color-selector-wrapper>');
8540                 var newWrapcont = $compile(wrapcont)(scope);
8541                 element.replaceWith(newWrapcont);
8542             }
8543         };
8544     }]);
8545 angular.module('att.abs.datepicker', ['att.abs.position', 'att.abs.utilities'])
8546
8547 .constant('datepickerConfig', {
8548     dateFormat: 'MM/dd/yyyy',
8549     dayFormat: 'd',
8550     monthFormat: 'MMMM',
8551     yearFormat: 'yyyy',
8552     dayHeaderFormat: 'EEEE',
8553     dayTitleFormat: 'MMMM yyyy',
8554     disableWeekend: false,
8555     disableSunday: false,
8556     startingDay: 0,
8557     minDate: null,
8558     maxDate: null,
8559     mode: 0,
8560     dateFilter: {
8561         defaultText: 'Select from list'
8562     },
8563     datepickerEvalAttributes: ['dateFormat', 'dayFormat', 'monthFormat', 'yearFormat', 'dayHeaderFormat', 'dayTitleFormat', 'disableWeekend', 'disableSunday', 'startingDay', 'mode'],
8564         datepickerWatchAttributes: ['min', 'max']
8565 })
8566
8567 .factory('datepickerService', ['datepickerConfig', 'dateFilter', function (datepickerConfig, dateFilter) {
8568     var setAttributes = function (attr, elem) {
8569         if (angular.isDefined(attr) && attr !== null && angular.isDefined(elem) && elem !== null) {
8570             var attributes = datepickerConfig.datepickerEvalAttributes.concat(datepickerConfig.datepickerWatchAttributes);
8571             for (var key in attr) {
8572                 var val = attr[key];
8573                 if (attributes.indexOf(key) !== -1 && angular.isDefined(val)) {
8574                     elem.attr(key.toSnakeCase(), key);
8575                 }
8576             }
8577         }
8578     };
8579
8580     var bindScope = function (attr, scope) {
8581         if (angular.isDefined(attr) && attr !== null && angular.isDefined(scope) && scope !== null) {
8582             var evalFunction = function (key, val) {
8583                 scope[key] = scope.$parent.$eval(val);
8584             };
8585             
8586             var watchFunction = function (key, val) {
8587                 scope.$parent.$watch(val, function (value) {
8588                     scope[key] = value;
8589                 });
8590                 scope.$watch(key, function (value) {
8591                     scope.$parent[val] = value;
8592                 });
8593             };
8594
8595             var evalAttributes = datepickerConfig.datepickerEvalAttributes;
8596             var watchAttributes = datepickerConfig.datepickerWatchAttributes;
8597             for (var key in attr) {
8598                 var val = attr[key];
8599                 if (evalAttributes.indexOf(key) !== -1 && angular.isDefined(val)) {
8600                     evalFunction(key, val);
8601                 } else if (watchAttributes.indexOf(key) !== -1 && angular.isDefined(val)) {
8602                     watchFunction(key, val);
8603                 }
8604             }
8605         }
8606     };
8607
8608     var validateDateString = function (dateString, dateFormat) {
8609         if (dateString && dateFormat) {
8610             var delimiter;
8611             if (dateFormat.indexOf('/') !== -1) {
8612                 delimiter = '/';
8613             } else if (dateFormat.indexOf('-') !== -1) {
8614                 delimiter = '-';
8615             } else if (dateFormat.indexOf('.') !== -1) {
8616                 delimiter = '.';
8617             }
8618
8619             var dateStringArray = dateString.split(delimiter);
8620             var dateFormatArray = dateFormat.split(delimiter);
8621             if (dateStringArray.length !== dateFormatArray.length) {
8622                 return false;
8623             }
8624
8625             for (var i = 0; i < dateStringArray.length; i++) {
8626                 dateStringArray[i] = dateStringArray[i].lPad(dateFormatArray[i].length, '0');
8627             }
8628             var intermediateDateString = dateStringArray.join(delimiter);
8629
8630             var actualDateString = dateFilter(new Date(intermediateDateString), dateFormat);
8631             if (intermediateDateString === actualDateString) {
8632                 return true;
8633             } else {
8634                 return false;
8635             }
8636         }
8637     };
8638
8639     return {
8640         setAttributes: setAttributes,
8641         bindScope: bindScope,
8642         validateDateString: validateDateString
8643     };
8644 }])
8645
8646 .controller('DatepickerController', ['$scope', '$attrs', 'dateFilter', 'datepickerConfig', function($scope, $attrs, dateFilter, dtConfig) {
8647     var format = {
8648         date: getValue($attrs.dateFormat, dtConfig.dateFormat),
8649         day: getValue($attrs.dayFormat, dtConfig.dayFormat),
8650         month: getValue($attrs.monthFormat, dtConfig.monthFormat),
8651         year: getValue($attrs.yearFormat, dtConfig.yearFormat),
8652         dayHeader: getValue($attrs.dayHeaderFormat, dtConfig.dayHeaderFormat),
8653         dayTitle: getValue($attrs.dayTitleFormat, dtConfig.dayTitleFormat),
8654         disableWeekend: getValue($attrs.disableWeekend, dtConfig.disableWeekend),
8655         disableSunday: getValue($attrs.disableSunday, dtConfig.disableSunday)
8656     },
8657     startingDay = getValue($attrs.startingDay, dtConfig.startingDay);
8658     $scope.mode = getValue($attrs.mode, dtConfig.mode);
8659
8660     $scope.minDate = dtConfig.minDate ? $scope.resetTime(dtConfig.minDate) : null;
8661     $scope.maxDate = dtConfig.maxDate ? $scope.resetTime(dtConfig.maxDate) : null;
8662
8663     function getValue(value, defaultValue) {
8664         return angular.isDefined(value) ? $scope.$parent.$eval(value) : defaultValue;
8665     }
8666
8667     function getDaysInMonth(year, month) {
8668         return new Date(year, month, 0).getDate();
8669     }
8670
8671     function getDates(startDate, n) {
8672         var dates = new Array(n);
8673         var current = startDate, i = 0;
8674         while (i < n) {
8675             dates[i++] = new Date(current);
8676             current.setDate(current.getDate() + 1);
8677         }
8678         return dates;
8679     }
8680     
8681     function isSelected(dt) {
8682         if (dt && angular.isDate($scope.currentDate) && compare(dt, $scope.currentDate) === 0) {
8683             return true;
8684         }
8685         return false;
8686     }
8687     
8688     function isFromDate(dt) {
8689         if (dt && angular.isDate($scope.fromDate) && compare(dt, $scope.fromDate) === 0) {
8690             return true;
8691         }
8692         return false;
8693     }
8694
8695     function isToDate(dt) {
8696         if (dt && angular.isDate($scope.fromDate) && angular.isDate($scope.currentDate) && compare(dt, $scope.currentDate) === 0) {
8697             return true;
8698         }
8699         return false;
8700     }
8701
8702     function isDateRange(dt) {
8703         if (dt && angular.isDate($scope.fromDate) && angular.isDate($scope.currentDate) && (compare(dt, $scope.fromDate) >= 0) && (compare(dt, $scope.currentDate) <= 0)) {
8704             return true;
8705         }
8706         return false;
8707     }
8708
8709     function isWeekend(date) {
8710         if (dateFilter(date, format.dayHeader) === "Saturday" || dateFilter(date, format.dayHeader) === "Sunday") {
8711             return true;
8712         }
8713         return false;
8714     }
8715
8716     function isToday(date) {
8717         if (compare(date, $scope.resetTime(new Date())) === 0) {
8718             return true;
8719         }
8720         return false;
8721     }   
8722     function isFocused(date) {
8723         if (date && angular.isDate($scope.focusedDate) && compare(date, $scope.focusedDate) === 0) {
8724             return true;
8725         }
8726         return false;
8727     }
8728
8729     var isDisabled = this.isDisabled = function(date) {
8730         if (format.disableWeekend === true && (dateFilter(date, format.dayHeader) === "Saturday" || dateFilter(date, format.dayHeader) === "Sunday")) {
8731             return true;
8732         }
8733         if (format.disableSunday === true && (dateFilter(date, format.dayHeader) === "Sunday")) {
8734             return true;
8735         }
8736         return (($scope.minDate && compare(date, $scope.minDate) < 0) || ($scope.maxDate && compare(date, $scope.maxDate) > 0));
8737     };
8738     
8739     var compare = this.compare = function(date1, date2) {
8740         return (new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate()));
8741     };
8742         
8743         
8744     function isMinDateAvailable(startDate, endDate) {
8745         if(($scope.minDate && $scope.minDate.getTime() >= startDate.getTime()) && ($scope.minDate.getTime() <= endDate.getTime())) {
8746             return true;
8747         }
8748         else {
8749             return false;
8750         }
8751     }
8752     
8753     function isMaxDateAvailable(startDate, endDate) {
8754         if(($scope.maxDate && $scope.maxDate.getTime() >= startDate.getTime()) && ($scope.maxDate.getTime() <= endDate.getTime())) {
8755             return true;
8756         }
8757         else {
8758             return false;
8759         }
8760     }
8761
8762     function getLabel(label) {
8763         if (label)
8764         {
8765             var labelObj = {
8766                 pre: label.substr(0, 3),
8767                 post: label
8768             };
8769             return labelObj;
8770         }
8771         return;
8772     }
8773
8774     function makeDate(date, dayFormat, dayHeaderFormat, isFocused, isSelected, isFromDate, isToDate, isDateRange, isOld, isNew, isDisabled, isToday, isWeekend) {
8775         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};
8776     }
8777
8778     this.modes = [
8779         {
8780             name: 'day',
8781             getVisibleDates: function(date, calendar) {
8782                 var year = date.getFullYear(), month = date.getMonth(), firstDayOfMonth = new Date(year, month, 1), lastDayOfMonth = new Date(year, month+1, 0);
8783                 var difference = startingDay - firstDayOfMonth.getDay(),
8784                         numDisplayedFromPreviousMonth = (difference > 0) ? 7 - difference : -difference,
8785                         firstDate = new Date(firstDayOfMonth), numDates = 0;
8786
8787                 if (numDisplayedFromPreviousMonth > 0) {
8788                     firstDate.setDate(-numDisplayedFromPreviousMonth + 1);
8789                     numDates += numDisplayedFromPreviousMonth; // Previous
8790                 }
8791                 numDates += getDaysInMonth(year, month + 1); // Current
8792                 numDates += (7 - numDates % 7) % 7; // Next
8793
8794                 var days = getDates(firstDate, numDates), labels = new Array(7);
8795                 for (var i = 0; i < numDates; i++) {
8796                     var dt = new Date(days[i]);
8797                     days[i] = makeDate(dt,
8798                                 format.day,
8799                                 format.dayHeader,
8800                                 isFocused(dt),
8801                                 isSelected(dt),
8802                                 isFromDate(dt),
8803                                 isToDate(dt),
8804                                 isDateRange(dt),
8805                                 (new Date(dt.getFullYear(), dt.getMonth(), 1, 0, 0, 0).getTime() < new Date(year, month, 1, 0, 0, 0).getTime()),
8806                                 (new Date(dt.getFullYear(), dt.getMonth(), 1, 0, 0, 0).getTime() > new Date(year, month, 1, 0, 0, 0).getTime()),
8807                                 isDisabled(dt),
8808                                 isToday(dt),
8809                                 isWeekend(dt));
8810                 }
8811                 for (var j = 0; j < 7; j++) {
8812                     labels[j] = getLabel(dateFilter(days[j].date, format.dayHeader));
8813                 }
8814                 if (calendar === 'top') {
8815                     $scope.disablePrevTop = isMinDateAvailable(firstDayOfMonth, lastDayOfMonth);
8816                     $scope.disableNextTop = isMaxDateAvailable(firstDayOfMonth, lastDayOfMonth);
8817                 } else if (calendar === 'bottom') {
8818                     $scope.disablePrevBottom = isMinDateAvailable(firstDayOfMonth, lastDayOfMonth);
8819                     $scope.disableNextBottom = isMaxDateAvailable(firstDayOfMonth, lastDayOfMonth);
8820                 } else {
8821                     $scope.disablePrevTop = $scope.disablePrevBottom = isMinDateAvailable(firstDayOfMonth, lastDayOfMonth);
8822                     $scope.disableNextTop = $scope.disableNextBottom = isMaxDateAvailable(firstDayOfMonth, lastDayOfMonth);
8823                 }
8824                 $scope.disablePrev = $scope.disablePrevTop || $scope.disablePrevBottom;
8825                 $scope.disableNext = $scope.disableNextTop || $scope.disableNextBottom;
8826                 return {objects: days, title: dateFilter(date, format.dayTitle), labels: labels};
8827             },                                          
8828             split: 7,           
8829             step: {months: 1}
8830         },              
8831                 {
8832             name: 'month',
8833             getVisibleDates: function(date, calendar) {
8834                 var months = new Array(12), labels = [], year = date.getFullYear(), month = date.getMonth();
8835                 for (var i = 0; i < 12; i++) {
8836                    var dt = new Date(year,i,1);
8837                     months[i] = makeDate(dt,
8838                                                                 format.month,
8839                                                                 format.month,                                                           
8840                                 isFocused(dt),
8841                                 isSelected(dt),
8842                                 isFromDate(dt),
8843                                 isToDate(dt),
8844                                 isDateRange(dt),
8845                                 false,
8846                                 false,          
8847                                 isDisabled(dt),
8848                                                                 isToday(dt),
8849                                                                 false
8850                                                                 );
8851                 }                                               
8852                                 return {objects: months, title: dateFilter(date, format.year), labels: labels};
8853             },         
8854                         split:3,
8855             step: {years: 1}
8856         }
8857     ];
8858         
8859 }])
8860
8861 .directive('datepicker', ['$timeout', function ($timeout) {
8862     return {
8863         restrict: 'EA',
8864         replace: true,
8865         transclude: true,
8866         templateUrl: 'app/scripts/ng_js_att_tpls/datepicker/datepicker.html',
8867         scope: {
8868             currentDate: "=?current",
8869             fromDate: "=?from"
8870         },
8871         require: 'datepicker',
8872         controller: 'DatepickerController',
8873         link: function(scope, element, attrs, ctrl) {
8874             var datepickerCtrl = ctrl;
8875             var selected, calendarSelected = false;
8876             scope.focusedDate;
8877            
8878             scope.resetTime = function(date) {
8879                 var dt;
8880                 if (!isNaN(new Date(date))) {
8881                     dt = new Date(date);
8882                                         if(scope.mode === 1){
8883                                                 dt = new Date(dt.getFullYear(), dt.getMonth());
8884                                         }else{
8885                                                 dt = new Date(dt.getFullYear(), dt.getMonth(), dt.getDate());
8886                                         }
8887                 } else {
8888                     return null;
8889                 }                               
8890                 return dt;
8891             };
8892
8893             if (attrs.min) {
8894                 scope.$parent.$watch(attrs.min, function(value) {
8895                     scope.minDate = value ? scope.resetTime(value) : null;
8896                     refill();
8897                 });
8898             }
8899             if (attrs.max) {
8900                 scope.$parent.$watch(attrs.max, function(value) {
8901                     scope.maxDate = value ? scope.resetTime(value) : null;
8902                     refill();
8903                 });
8904             }
8905             
8906             // Split array into smaller arrays
8907             function split(arr, size) {
8908                 var arrays = [];
8909                 while (arr.length > 0) {
8910                     arrays.push(arr.splice(0, size));
8911                 }
8912                 return arrays;
8913             }
8914
8915             function refill(date) {
8916                 if (angular.isDate(date) && !isNaN(date)) {
8917                     selected = new Date(date);
8918                 } else {
8919                     if (!selected) {
8920                         selected = new Date();
8921                     }
8922                 }
8923                                 
8924                                 if (selected) {
8925                                         var selectedCalendar;
8926                                         if(scope.mode === 1){
8927                                                 selected = new Date();
8928                                                 selectedCalendar = moveMonth(angular.copy(selected), -1);
8929                                         } else {
8930                                                 selectedCalendar = angular.copy(selected);
8931                                         }
8932                                         
8933                                         var currentMode = datepickerCtrl.modes[scope.mode];
8934                                         var currentData = currentMode.getVisibleDates(selectedCalendar, 'top');
8935                     scope.currentRows = split(currentData.objects, currentMode.split);
8936                     scope.currentTitle = currentData.title;
8937                     scope.labels = currentData.labels || [];
8938
8939                     var nextData = currentMode.getVisibleDates(moveMonth(angular.copy(selectedCalendar), 1), 'bottom');
8940                     scope.nextRows = split(nextData.objects, currentMode.split);
8941                     scope.nextTitle = nextData.title;                                   
8942                                 }
8943             }
8944         
8945             scope.select = function(date) {
8946                 calendarSelected = true;
8947                 if(attrs.from) {
8948                     if(!(angular.isDate(scope.fromDate) && angular.isDate(scope.currentDate))) {
8949                         if(angular.isDate(scope.fromDate)) {
8950                             selectCurrentDate(date);
8951                         } else if(!angular.isDate(scope.fromDate)) {
8952                             selectFromDate(date);
8953                         }
8954                     }
8955                 } else {
8956                     selectCurrentDate(date);
8957                 }
8958                 scope.focusedDate = date;
8959             };
8960             
8961             var selectCurrentDate = function(date) {
8962                 var dt = new Date(date.getFullYear(), date.getMonth(), date.getDate());
8963                 scope.currentDate = dt;
8964             };
8965             
8966             var selectFromDate = function(date) {
8967                 var dt = new Date(date.getFullYear(), date.getMonth(), date.getDate());
8968                 scope.fromDate = dt;
8969             };
8970
8971             var swapDate = function(fromDate, currentDate) {
8972                 selectFromDate(currentDate);
8973                 $timeout(function () {
8974                     calendarSelected = true;
8975                     scope.focusedDate = currentDate;
8976                     selectCurrentDate(fromDate);
8977                 });
8978             }                   
8979             var moveMonth = function(selectedDate, direction) {
8980                 var step = datepickerCtrl.modes[scope.mode].step;
8981                 selectedDate.setDate(1);
8982                 selectedDate.setMonth(selectedDate.getMonth() + direction * (step.months || 0));
8983                 selectedDate.setFullYear(selectedDate.getFullYear() + direction * (step.years || 0));
8984
8985                 return selectedDate;
8986             };
8987
8988             scope.move = function(direction) {
8989                 selected = moveMonth(angular.copy(selected), direction);
8990                 refill();
8991             };
8992
8993             scope.$watch('currentDate', function (value) {
8994                 if(angular.isDate(value) && !isNaN(value) && datepickerCtrl.isDisabled(value)) {
8995                     scope.currentDate = null;
8996                     return;
8997                 }
8998                 if (attrs.from) {
8999                     if (!isNaN(value) && !isNaN(scope.fromDate) && datepickerCtrl.compare(value, scope.fromDate) < 0) {
9000                         swapDate(scope.fromDate, value);
9001                         return;
9002                     }
9003                 }
9004                 if (calendarSelected) {
9005                     refill();
9006                     calendarSelected = false;
9007                 } else {
9008                     if (angular.isDefined(value) && value !== null) {
9009                         refill(value);
9010                     } else {
9011                         refill();
9012                     }
9013                 }
9014                 scope.focusedDate = undefined;
9015             });
9016             
9017             scope.$watch('fromDate', function (value) {
9018                 if(angular.isDate(value) && !isNaN(value) && datepickerCtrl.isDisabled(value)) {
9019                     scope.fromDate = null;
9020                     return;
9021                 }
9022                 if (attrs.from) {
9023                     if (!isNaN(scope.currentDate) && !isNaN(value) && datepickerCtrl.compare(scope.currentDate, value) < 0) {
9024                         swapDate(value, scope.currentDate);
9025                         return;
9026                     }
9027                     if (calendarSelected) {
9028                         refill();
9029                         calendarSelected = false;
9030                     } else {
9031                         if (angular.isDefined(value) && value !== null) {
9032                             refill(value);
9033                         } else {
9034                             refill();
9035                         }
9036                     }
9037                 }
9038                 scope.focusedDate = undefined;
9039             });
9040         }
9041     };
9042 }])
9043 .directive('datepickerPopup', ['$document', 'datepickerService', '$isElement', '$documentBind', function($document, datepickerService, $isElement, $documentBind) {
9044     var link = function (scope, elem, attr, ctrl) {
9045         datepickerService.bindScope(attr, scope);
9046
9047         scope.isOpen = false;
9048
9049         var toggle = scope.toggle = function (show) {
9050             if(show === true || show === false) {
9051                 scope.isOpen = show;
9052             } else {
9053                 scope.isOpen = !scope.isOpen;
9054             }
9055         };
9056
9057         scope.$watch('current', function () {
9058             toggle(false);
9059         });
9060
9061         var outsideClick = function (e) {
9062             var isElement = $isElement(angular.element(e.target), elem, $document);
9063             if(!isElement) {
9064                 toggle(false);
9065                 scope.$apply();
9066             }
9067         };
9068
9069         $documentBind.click('isOpen', outsideClick, scope);
9070     };
9071
9072     return {
9073         restrict: 'EA',
9074         replace: true,
9075         transclude: true,
9076         templateUrl: 'app/scripts/ng_js_att_tpls/datepicker/datepickerPopup.html',
9077         scope: {
9078             current: "=current"
9079         },
9080         compile: function (elem, attr) {
9081             var wrapperElement = elem.find('span').eq(1);
9082             wrapperElement.attr('current', 'current');
9083             datepickerService.setAttributes(attr, wrapperElement);
9084
9085             return link;
9086         }
9087     };
9088 }])
9089
9090 .directive('attDatepicker', ['$log', function($log) {
9091     return {
9092         restrict: 'A',
9093         require: 'ngModel',
9094         scope: {},
9095         controller: ['$scope', '$element', '$attrs', '$compile', 'datepickerConfig', 'datepickerService', function($scope, $element, $attrs, $compile, datepickerConfig, datepickerService) {
9096             var dateFormatString = angular.isDefined($attrs.dateFormat) ? $scope.$parent.$eval($attrs.dateFormat) : datepickerConfig.dateFormat;
9097             var selectedDateMessage = '<div class="sr-focus hidden-spoken" tabindex="-1">the date you selected is {{$parent.current | date : \'' + dateFormatString + '\'}}</div>';
9098
9099             $element.removeAttr('att-datepicker');
9100             $element.removeAttr('ng-model');
9101             $element.attr('ng-model', '$parent.current');
9102             $element.attr('aria-describedby', 'datepicker');
9103             $element.attr('format-date', dateFormatString);
9104             $element.attr('att-input-deny', '[^0-9\/-]');
9105             $element.attr('maxlength', 10);
9106
9107             var wrapperElement = angular.element('<div></div>');
9108             wrapperElement.attr('datepicker-popup', '');
9109             wrapperElement.attr('current', 'current');
9110             
9111             datepickerService.setAttributes($attrs, wrapperElement);
9112             datepickerService.bindScope($attrs, $scope);
9113             
9114             wrapperElement.html('');
9115             wrapperElement.append($element.prop('outerHTML'));
9116             if (navigator.userAgent.match(/MSIE 8/) === null) {
9117                 wrapperElement.append(selectedDateMessage);
9118             }
9119             var elm = wrapperElement.prop('outerHTML');
9120             elm = $compile(elm)($scope);
9121             $element.replaceWith(elm);
9122         }],
9123         link: function(scope, elem, attr, ctrl) {
9124             if (!ctrl) {
9125                 $log.error("ng-model is required.");
9126                 return; // do nothing if no ng-model
9127             }
9128
9129             scope.$watch('current', function(value) {
9130                 ctrl.$setViewValue(value);
9131             });
9132             ctrl.$render = function() {
9133                 scope.current = ctrl.$viewValue;
9134             };
9135         }
9136     };
9137 }])
9138
9139 .directive('formatDate', ['dateFilter', 'datepickerService', function(dateFilter, datepickerService) {
9140     return {
9141         restrict: 'A',
9142         require: 'ngModel',
9143         link: function(scope, elem, attr, ctrl) {
9144             var formatDate = "";
9145             attr.$observe('formatDate', function (value) {
9146                 formatDate = value;
9147             });
9148             var dateToString = function(value) {
9149                 if (value) {
9150                     ctrl.$setValidity('invalidDate', true);
9151                     return dateFilter(value, formatDate);
9152                 } else {
9153                     ctrl.$setValidity('invalidDate', false);
9154                     return elem.val();
9155                 }
9156             };
9157             var stringToDate = function(value) {
9158                 if(datepickerService.validateDateString(value, formatDate)) {
9159                     ctrl.$setValidity('invalidDate', true);
9160                     return new Date(value);
9161                 } else {
9162                     ctrl.$setValidity('invalidDate', false);
9163                     return null;
9164                 }
9165             };
9166             ctrl.$formatters.unshift(dateToString);
9167             ctrl.$parsers.unshift(stringToDate);
9168         }
9169     };
9170 }])
9171
9172 .directive('attDateFilter', ['$document', 'dateFilter', 'datepickerConfig', 'datepickerService', '$isElement', '$documentBind', function($document, dateFilter, datepickerConfig, datepickerService, $isElement, $documentBind) {
9173         
9174     var link = function (scope, elem, attr, ctrl) {
9175         datepickerService.bindScope(attr, scope);
9176
9177         scope.selectedOption = datepickerConfig.dateFilter.defaultText;
9178         scope.showDropdownList = false;
9179         scope.showCalendar = false;
9180         scope.applyButtonType = "disabled";
9181
9182         scope.currentSelection = "";
9183         var dateFormatString = angular.isDefined(attr.dateFormat) ? scope.$parent.$eval(attr.dateFormat) : datepickerConfig.dateFormat;
9184         var inputChange = false;
9185
9186         
9187
9188         var showDropdown = scope.showDropdown = function (show) {
9189             if(show === true || show === false) {
9190                 scope.showDropdownList = show;
9191             } else {
9192                 scope.showDropdownList = !scope.showDropdownList;
9193             }
9194
9195             if (!scope.showDropdownList) {
9196                 hideCalendar();
9197             } else {
9198                 if (scope.currentSelection === 'Custom Single Date' || scope.currentSelection === 'Custom Range') {
9199                     showCalendar();
9200                 }
9201             }
9202         };
9203
9204         var resetTime = scope.resetTime = function(date) {
9205             var dt;
9206             if (!isNaN(new Date(date))) {
9207                 dt = new Date(date);
9208             } else {
9209                 return null;
9210             }
9211             return new Date(dt.getFullYear(), dt.getMonth(), dt.getDate());
9212         };
9213
9214         var addDays = scope.addDays = function (date, days) {
9215             var dt;
9216             if (!isNaN(new Date(date)) && !isNaN(days)) {
9217                 dt = new Date(date);
9218                 dt.setDate(dt.getDate() + days);
9219             } else {
9220                 dt = new Date();
9221             }
9222             return dt;
9223         };
9224                 var addMonth = scope.addMonth = function (date, months) {
9225             var dt;
9226             if (!isNaN(new Date(date)) && !isNaN(months)) {
9227                 dt = new Date(date);
9228                 dt.setMonth(dt.getMonth() + months);
9229             } else {
9230                 dt = new Date();
9231             }
9232             return dt;
9233         };      
9234
9235         var showCalendar = function() {
9236             scope.showCalendar = true;
9237         };
9238
9239         var hideCalendar = function() {
9240             scope.showCalendar = false;
9241             if(scope.currentSelection !== 'Custom Single Date' && scope.currentSelection !== 'Custom Range') {
9242                 clear(true);
9243             }
9244         };
9245
9246         var setDropdownText = function(value) {
9247             if(inputChange) {
9248                 return;
9249             }
9250
9251             var fromDateText = dateFormatString.toUpperCase();
9252             var currentDateText = dateFormatString.toUpperCase();
9253
9254             if(!isNaN(new Date(scope.fromDate))) {
9255                 fromDateText = dateFilter(scope.fromDate, dateFormatString);
9256             }
9257             if(!isNaN(new Date(scope.currentDate))) {
9258                 currentDateText = dateFilter(scope.currentDate, dateFormatString);
9259             }
9260
9261             if(value === 'Custom Single Date') {
9262                 ctrl.$setValidity('invalidDate', true);
9263                 scope.maxLength = 10;
9264                 scope.selectedOption = currentDateText;
9265             } else if(value === 'Custom Range') {
9266                 ctrl.$setValidity('invalidDate', true);
9267                 ctrl.$setValidity('invalidDateRange', true);
9268                 scope.maxLength = 21;
9269                 scope.selectedOption = fromDateText + '-' + currentDateText;
9270             }
9271         };
9272
9273         scope.getDropdownText = function () {
9274             inputChange = true;
9275             var dropdownText = scope.selectedOption;
9276
9277             if (scope.currentSelection === 'Custom Single Date') {
9278                 if (!isNaN(new Date(dropdownText)) && datepickerService.validateDateString(dropdownText, dateFormatString)) {
9279                     ctrl.$setValidity('invalidDate', true);
9280                     scope.fromDate = undefined;
9281                     scope.currentDate = new Date(dropdownText);
9282                 } else {
9283                     ctrl.$setValidity('invalidDate', false);
9284                     clear(true);
9285                 }
9286             } else if (scope.currentSelection === 'Custom Range') {
9287                 if (dropdownText.indexOf('-') !== -1 && (dropdownText.split('-').length === 2 || dropdownText.split('-').length === 6)) {
9288                     ctrl.$setValidity('invalidDateRange', true);
9289                     var resultDropdownText = dropdownText.split('-');
9290                     if (resultDropdownText.length === 2) {
9291                         resultDropdownText[0] = resultDropdownText[0].trim();
9292                         resultDropdownText[1] = resultDropdownText[1].trim();
9293                     } else if (resultDropdownText.length === 6) {
9294                         var firstDateString = resultDropdownText[0].trim() + '-' + resultDropdownText[1].trim() + '-' + resultDropdownText[2].trim();
9295                         var secondDateString = resultDropdownText[3].trim() + '-' + resultDropdownText[4].trim() + '-' + resultDropdownText[5].trim();
9296                         resultDropdownText[0] = firstDateString;
9297                         resultDropdownText[1] = secondDateString;
9298                     }
9299
9300                     if (!isNaN(new Date(resultDropdownText[0])) && !isNaN(new Date(resultDropdownText[1])) && datepickerService.validateDateString(resultDropdownText[0], dateFormatString) && datepickerService.validateDateString(resultDropdownText[1], dateFormatString)) {
9301                         ctrl.$setValidity('invalidDate', true);
9302                         var fromDate = new Date(resultDropdownText[0]);
9303                         var currentDate = new Date(resultDropdownText[1]);
9304                         if(fromDate.getTime() < currentDate.getTime()) {
9305                             ctrl.$setValidity('invalidDateRange', true);
9306                             scope.fromDate = fromDate;
9307                             scope.currentDate = currentDate;
9308                         } else {
9309                             ctrl.$setValidity('invalidDateRange', false);
9310                             clear(true);
9311                         }
9312                     } else {
9313                         ctrl.$setValidity('invalidDate', false);
9314                         clear(true);
9315                     }
9316                 } else {
9317                     ctrl.$setValidity('invalidDateRange', false);
9318                     clear(true);
9319                 }
9320             }
9321         };
9322
9323         scope.untrackInputChange = function(ev) {
9324             inputChange = false;
9325         };
9326
9327         scope.selectAdvancedOption = function (value) {
9328             scope.currentSelection = value;
9329             showCalendar();
9330             clear();
9331             scope.$watch('currentDate', function(val) {
9332                 if(!isNaN(new Date(val))) {
9333                     scope.applyButtonType = "primary";
9334                     setDropdownText(value);
9335                     if (!inputChange) {
9336                         scope.focusApplyButton = true;
9337                     }
9338                 }
9339             });
9340             scope.$watch('fromDate', function(val) {
9341                 if(!isNaN(new Date(val))) {
9342                     setDropdownText(value);
9343                 }
9344             });
9345             if (value === 'Custom Single Date') {
9346                 scope.focusSingleDateCalendar = true;
9347             } else if (value === 'Custom Range') {
9348                 scope.focusRangeCalendar = true;
9349             }
9350         };
9351         
9352         scope.resetFocus = function (ev) {
9353             scope.focusSingleDateCalendar = false;
9354             scope.focusRangeCalendar = false;
9355             scope.focusApplyButton = false;
9356         };
9357
9358         scope.apply = function() {
9359             scope.dateRange.selection = scope.selectedOption;
9360             if(!isNaN(new Date(scope.fromDate))) {
9361                 scope.from = scope.fromDate;
9362                 scope.dateRange.from = scope.fromDate;
9363             } else {
9364                 scope.from = undefined;
9365                 scope.dateRange.from = undefined;
9366             }
9367             if(!isNaN(new Date(scope.currentDate))) {
9368                 scope.current = scope.currentDate;
9369                 scope.dateRange.current = scope.currentDate;
9370             } else {
9371                 scope.current = undefined;
9372                 scope.dateRange.current = undefined;
9373             }
9374
9375             showDropdown();
9376         };
9377
9378         scope.$watchCollection(function() {
9379             return scope.dateRange;
9380         }, function(value) {
9381             if(ctrl) {
9382                 var finalDateRange = angular.copy(value);
9383                 ctrl.$setViewValue(finalDateRange);
9384             }
9385         });
9386
9387         ctrl.$render = function() {
9388             if (ctrl.$viewValue) {
9389                 var inputRange = ctrl.$viewValue;
9390                 scope.selectedOption = inputRange.selection;
9391                 scope.fromDate = inputRange.from;
9392                 scope.currentDate = inputRange.current;
9393             }
9394         };
9395
9396         scope.cancel = function() {
9397             scope.currentSelection = "";
9398             scope.selectedOption = datepickerConfig.dateFilter.defaultText;
9399                         showDropdown();
9400         };
9401
9402         var clear = scope.clear = function(partial) {
9403             scope.fromDate = undefined;
9404             scope.currentDate = undefined;
9405             scope.applyButtonType = "disabled";
9406             if(!partial) {
9407                 ctrl.$setValidity('invalidDate', true);
9408                 ctrl.$setValidity('invalidDateRange', true);
9409                 setDropdownText(scope.currentSelection);
9410             }
9411         };
9412
9413         var outsideClick = function (e) {
9414             var isElement = $isElement(angular.element(e.target), elem, $document);
9415             if(!isElement) {
9416                 showDropdown(false);
9417                 scope.$apply();
9418             }
9419         };
9420
9421         $documentBind.click('showDropdownList', outsideClick, scope);
9422     };
9423
9424     return {
9425         restrict: 'EA',
9426         scope: {
9427             from: '=?from',
9428             current: "=?current"
9429         },
9430         replace: true,
9431         require: '?ngModel',
9432                 transclude:true,
9433         templateUrl: 'app/scripts/ng_js_att_tpls/datepicker/dateFilter.html',
9434                 controller:['$scope', '$element', '$attrs',function($scope, $element, $attrs){
9435                         $scope.dateRange = {
9436                                 selection: undefined,
9437                                 from: undefined,
9438                                 current: undefined
9439                         };
9440                         this.selectOption = function (fromDate,toDate,caption) {
9441                                 $scope.selectedOption = caption;
9442                                 $scope.currentSelection =caption;
9443                                 $scope.dateRange.selection = caption;
9444                                 $scope.dateRange.current = $scope.resetTime(toDate);
9445                                 $scope.dateRange.from = $scope.resetTime(fromDate);
9446                                 $scope.showDropdown();
9447         };
9448                  $scope.checkCurrentSelection=this.checkCurrentSelection = function(value) {    
9449             if(value === $scope.currentSelection) {
9450                 return true;
9451             }
9452             return false;
9453         };
9454                 }],
9455         compile: function(elem, attr) {
9456             var singleDateCalendar = elem.find('span').eq(4);
9457             var rangeCalendar = elem.find('span').eq(5);
9458             rangeCalendar.attr('from', 'fromDate');
9459             singleDateCalendar.attr('current', 'currentDate');
9460             rangeCalendar.attr('current', 'currentDate');
9461
9462             datepickerService.setAttributes(attr, singleDateCalendar);
9463             datepickerService.setAttributes(attr, rangeCalendar);
9464
9465             return link;
9466         }
9467     };
9468 }])
9469 .directive('attDateFilterList',function(){
9470         return{
9471                 restrict:'EA',
9472                 scope:{
9473                         fromDate:'=fromDate',
9474                         toDate:'=toDate',
9475                         caption:'=caption',
9476                         disabled:'=disabled'
9477                 },
9478                 require:'^attDateFilter',
9479                 transclude:true,
9480                 replace:true,
9481                 templateUrl:'app/scripts/ng_js_att_tpls/datepicker/dateFilterList.html',
9482                 link:function(scope,elem,attr,ctrl){
9483                         scope.selectOption=function(fromDate,toDate,caption){                           
9484                                 ctrl.selectOption(fromDate,toDate,caption);
9485                         }
9486                         scope.checkCurrentSelection=ctrl.checkCurrentSelection;
9487                         
9488                 }               
9489         }
9490 });
9491
9492 angular.module('att.abs.devNotes', [])
9493
9494   .directive('attDevNotes', function() {
9495     return {
9496       restrict: 'EA',
9497       transclude: true,
9498       scope: {},
9499       
9500       controller: function($scope, $element){
9501         var panes = $scope.panes = [];
9502         $scope.select = function(pane) 
9503         {           
9504             angular.forEach(panes, function(pane) 
9505             {
9506                 pane.selected = false;
9507             });
9508             pane.selected = true;                     
9509         };
9510
9511         this.addPane = function(pane) {
9512           if (panes.length === 0) $scope.select(pane);
9513           panes.push(pane);
9514         };
9515       },
9516       template:'<div>'+
9517         '<ul class="tabs">' +
9518             '<li ng-repeat="pane in panes" ng-class="{active:pane.selected}">'+
9519               '<a href="javascript:void(0)" ng-click="select(pane)">{{pane.title}}</a>' +
9520             '</li>' +
9521           '</ul>' +
9522           '<div ng-transclude></div>'+
9523           '</div>',
9524           replace: true
9525     };
9526   })
9527
9528   .directive('pane', function() {
9529     return {
9530       require: '^attDevNotes',
9531       restrict: 'EA',
9532       transclude: true,
9533       scope: {
9534           title: '@'
9535       },
9536       link: function(scope, element, attrs, tabsCtrl) {
9537         tabsCtrl.addPane(scope);
9538       },
9539       template:
9540         '<div class="tab-pane" ng-class="{active: selected}">' + 
9541         '<pre ng-class="{\'language-markup\':title==\'HTML\',\'language-javascript\':title==\'JavaScript\'}"  class=" line-numbers">' +
9542          '<code ng-transclude></code>' +
9543          '</pre>' +
9544         '</div>',
9545       replace: true
9546     };
9547   });
9548
9549 angular.module('att.abs.dividerLines', [])
9550         .directive('attDividerLines', [function()
9551             {
9552                 return {
9553                     scope: {
9554                         attDividerLines: '@'
9555                     },
9556                     restrict: 'A',
9557                     replace: true,
9558                     templateUrl: 'app/scripts/ng_js_att_tpls/dividerLines/dividerLines.html',
9559                     link: function(scope, element, attribute, ctrl)
9560                     {
9561                         scope.lightContainer = attribute.attDividerLines;
9562                     }
9563                 };
9564             }]);
9565
9566 angular.module('att.abs.dragdrop', [])
9567         .directive('attFileDrop', ['$parse', function($parse) {
9568                 return {
9569                     restrict: 'A',
9570                     scope: {
9571                         fileModel : '=',
9572                         onDrop : '&',
9573                         attFileDrop : '&'
9574                     },
9575                     controller: ['$scope', '$attrs', function($scope, $attrs){
9576                         if($attrs.attFileDrop!==""){
9577                             $scope.onDrop=$scope.attFileDrop;
9578                         }
9579                             
9580                         this.onDrop = $scope.onDrop;
9581                     }],
9582                     link: function(scope, element, attr, ctrl) {
9583                         
9584                         element.addClass('dragdrop');
9585                         
9586                         element.bind(
9587                             'dragover',
9588                             function(e) {
9589                                 
9590                                 if(e.originalEvent){
9591                                     e.dataTransfer = e.originalEvent.dataTransfer;
9592                                 }
9593                                 
9594                                 e.dataTransfer.dropEffect = 'move';
9595                                 // allows us to drop
9596                                 if (e.preventDefault) e.preventDefault();
9597                                 element.addClass('dragdrop-over');
9598                                 return false;
9599                             }
9600                         );
9601                         
9602                         element.bind(
9603                             'dragenter',
9604                             function(e) {
9605                                 // allows us to drop
9606                                 if (e.preventDefault) e.preventDefault();
9607                                 element.addClass('dragdrop-over');
9608                                 return false;
9609                             }
9610                         );
9611
9612                         element.bind(
9613                             'dragleave',
9614                             function(e) {
9615                                 element.removeClass('dragdrop-over');
9616                                 return false;
9617                             }
9618                         );
9619                         
9620                         element.bind(
9621                             'drop',
9622                             function(e) {
9623                                 // Stops some browsers from redirecting.
9624                                 if(e.preventDefault) { e.preventDefault(); } ;
9625                                 if (e.stopPropagation) { e.stopPropagation(); };
9626                                 
9627                                 if(e.originalEvent){
9628                                     e.dataTransfer = e.originalEvent.dataTransfer;
9629                                 }
9630                                 
9631                                 element.removeClass('dragdrop-over');
9632                                 
9633                                 if(e.dataTransfer.files && e.dataTransfer.files.length > 0){
9634                                     scope.fileModel = e.dataTransfer.files[0];
9635                                     scope.$apply();
9636                                     
9637                                     if(typeof scope.onDrop === "function"){
9638                                         scope.onDrop = $parse(scope.onDrop);
9639                                         scope.onDrop();
9640                                     }
9641                                 }
9642                                 return false;
9643                             }
9644                         );
9645                     }
9646                 };
9647             }])
9648         .directive('attFileLink', [ function() {
9649                 return {
9650                     restrict: 'EA',
9651                     require: '^?attFileDrop',
9652                     replace: true,
9653                     transclude: true,
9654                     templateUrl: 'app/scripts/ng_js_att_tpls/dragdrop/fileUpload.html',
9655                     scope: {
9656                         fileModel : '=?',
9657                         onFileSelect : '&',
9658                         attFileLink : '&'
9659                     },
9660                     controller: ['$scope', '$parse', function($scope, $parse){
9661                         
9662                         this.setFileModel= function(fileModel){
9663                             if($scope.takeFileModelFromParent){
9664                                 $scope.$parent.fileModel = fileModel;
9665                                 $scope.$parent.$apply();
9666                             }
9667                             else{
9668                                 $scope.fileModel = fileModel;
9669                                 $scope.$apply();
9670                             }
9671                         };
9672                         
9673                         this.callbackFunction= function(){
9674                             if(typeof $scope.onFileSelect === "function"){
9675                                 $scope.onFileSelect = $parse($scope.onFileSelect);
9676                                 $scope.onFileSelect();
9677                             }
9678                         };
9679                         
9680                     }],
9681                     link: function(scope, element, attr, attFileDropCtrl) {
9682                         
9683                         scope.takeFileModelFromParent = false;
9684                         
9685                         if(!(attr.fileModel)){
9686                             if(attFileDropCtrl){
9687                                 scope.takeFileModelFromParent = true;
9688                             }
9689                         }
9690                         
9691                         if(attr.attFileLink!==""){
9692                             scope.onFileSelect=scope.attFileLink;
9693                         }
9694                         else if(!(attr.onFileSelect)){
9695                             if(attFileDropCtrl){
9696                                 scope.onFileSelect = attFileDropCtrl.onDrop;
9697                             }
9698                         }
9699                         
9700                     }
9701                 };
9702             }])
9703         .directive('attFileChange', ['$parse', function($parse) {
9704                 return {
9705                     restrict: 'A',
9706                     require: '^attFileLink',
9707                     link: function(scope, element, attr, attFileLinkCtrl) {
9708                         element.bind(
9709                             "change", 
9710                             function (e) {
9711                                 if(e.target.files && e.target.files.length > 0){
9712                                     attFileLinkCtrl.setFileModel(e.target.files[0]);
9713                                     attFileLinkCtrl.callbackFunction();
9714                                 }
9715                                 else{
9716                                     var strFileName = e.target.value;
9717                                     var objFSO = new ActiveXObject("Scripting.FileSystemObject");
9718                                     
9719                                     attFileLinkCtrl.setFileModel(objFSO.getFile(strFileName));
9720                                     attFileLinkCtrl.callbackFunction();
9721                                 }
9722                             }
9723                         );
9724                     }
9725                 };
9726             }]);
9727 angular.module("att.abs.drawer", [])
9728 .directive('attDrawer', ['$document', '$timeout', function ($document, $timeout) {
9729         return {
9730             restrict: 'EA',
9731             replace: true,
9732             transclude: true,
9733             scope: {
9734                 drawerOpen: "=?",
9735                 drawerAutoClose: "=?"
9736             },
9737             template: '<div><div class="att-drawer" ng-transclude></div><div ng-class="{\'drawer-backdrop\':drawerOpen}"></div></div>',
9738             link: function ($scope, element, attrs) {
9739                 var param = {};
9740
9741                 // Override default parameters
9742                 param.side = attrs.drawerSlide || 'top';
9743                 param.speed = attrs.drawerSpeed || '0.25';
9744                 param.size = attrs.drawerSize || '300px';
9745                 param.zindex = attrs.drawerZindex || 1000;
9746                 param.className = attrs.drawerClass || 'att-drawer';
9747                 
9748                 var slider = element.eq(0).children()[0];
9749                 var content = angular.element(slider).children()[0];
9750
9751                 slider.className = param.className;
9752
9753                 /* Style setup */
9754                 slider.style.transitionDuration = param.speed + 's';
9755                 slider.style.webkitTransitionDuration = param.speed + 's';
9756                 slider.style.zIndex = param.zindex;
9757                 slider.style.position = 'fixed';
9758                 slider.style.width = 0;
9759                 slider.style.height = 0;
9760                 slider.style.transitionProperty = 'width, height';
9761
9762                 switch (param.side) {
9763                     case 'right':
9764                         slider.style.height = attrs.drawerCustomHeight || '100%'; 
9765                         slider.style.top = attrs.drawerCustomTop ||  '0px';
9766                         slider.style.bottom = attrs.drawerCustomBottom ||  '0px';
9767                         slider.style.right = attrs.drawerCustomRight ||  '0px';
9768                         break;
9769                     case 'left':
9770                         slider.style.height = attrs.drawerCustomHeight || '100%';   
9771                         slider.style.top = attrs.drawerCustomTop || '0px';
9772                         slider.style.bottom = attrs.drawerCustomBottom || '0px';
9773                         slider.style.left = attrs.drawerCustomLeft || '0px';
9774                         break;
9775                     case 'top':
9776                         slider.style.width = attrs.drawerCustomWidth || '100%';   
9777                         slider.style.left = attrs.drawerCustomLeft || '0px';
9778                         slider.style.top = attrs.drawerCustomTop || '0px';
9779                         slider.style.right = attrs.drawerCustomRight || '0px';
9780                         break;
9781                     case 'bottom':
9782                         slider.style.width = attrs.drawerCustomWidth || '100%'; 
9783                         slider.style.bottom = attrs.drawerCustomBottom || '0px';
9784                         slider.style.left = attrs.drawerCustomLeft || '0px';
9785                         slider.style.right = attrs.drawerCustomRight || '0px';
9786                         break;
9787                 }
9788
9789
9790
9791                 /* Closed */
9792                 function drawerClose(slider, param) {
9793                     if (slider && slider.style.width !== 0 && slider.style.width !== 0){ 
9794                         content.style.display = 'none';
9795                         switch (param.side){
9796                             case 'right':
9797                                 slider.style.width = '0px'; 
9798                                 break;
9799                             case 'left':
9800                                 slider.style.width = '0px';
9801                                 break;
9802                             case 'top':
9803                                 slider.style.height = '0px'; 
9804                                 break;
9805                             case 'bottom':
9806                                 slider.style.height = '0px'; 
9807                                 break;
9808                         }
9809                     }
9810                     $scope.drawerOpen = false;
9811                 }
9812
9813                 /* Open */
9814                 function drawerOpen(slider, param) {
9815                     if (slider.style.width !== 0 && slider.style.width !== 0){ 
9816                         switch (param.side){
9817                             case 'right':
9818                                 slider.style.width = param.size; 
9819                                 break;
9820                             case 'left':
9821                                 slider.style.width = param.size; 
9822                                 break;
9823                             case 'top':
9824                                 slider.style.height = param.size; 
9825                                 break;
9826                             case 'bottom':
9827                                 slider.style.height = param.size; 
9828                                 break;
9829                         }
9830                         $timeout(function() {
9831                             content.style.display = 'block';
9832                         },(param.speed * 1000));
9833
9834                     }
9835                 }
9836
9837                 function isFunction(functionToCheck) {
9838                     var getType = {};
9839                     return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
9840                 }
9841
9842                 /*
9843                 * Watchers
9844                 * */
9845
9846                 if(attrs.drawerSize) {
9847                     $scope.$watch(function() {
9848
9849                         return attrs.drawerSize;
9850                     }, function(newVal,oldVal) {
9851                         param.size = newVal;
9852
9853                         if($scope.drawerOpen) {
9854                             drawerOpen(slider,param);
9855                         }
9856                     });
9857                 }
9858
9859                 $scope.$watch("drawerOpen", function (value){
9860                     if (!!value) {
9861                         // Open
9862                         drawerOpen(slider,param);
9863                     } else {
9864                         // Close
9865                         drawerClose(slider,param);
9866                     }
9867                 });
9868
9869                 // close panel on location change
9870                 if($scope.drawerAutoClose) {
9871                     $scope.$on("$locationChangeStart", function(){
9872                         drawerClose(slider, param);
9873                         if(isFunction($scope.drawerAutoClose)) {
9874                             $scope.drawerAutoClose();
9875                         }
9876                     });
9877                     $scope.$on("$stateChangeStart", function(){
9878                         drawerClose(slider, param);
9879                         if(isFunction($scope.drawerAutoClose)) {
9880                             $scope.drawerAutoClose();
9881                         }
9882                     });
9883                 }
9884             }
9885         };
9886     }
9887 ]);
9888 angular.module('att.abs.message', [])
9889
9890 .directive('attMessages', [function() {
9891     return {
9892         restrict: 'EA',
9893         scope: true,
9894         controller: ['$scope', '$element', '$attrs', function($scope, $element, $attrs) {
9895             $scope.messageType;
9896             $scope.$watchCollection($attrs['for'], function(errors) {
9897                 for (var key in errors) {
9898                     if (errors[key] === true) {
9899                         $scope.error = key;
9900                         break;
9901                     } else {
9902                         $scope.error = null;
9903                     }
9904                 };
9905                 if ($scope.error === null) {
9906                     $scope.messageType = null;
9907                     $element.removeAttr('message-type');
9908                 }
9909             });
9910             this.setMessageType = function(messageType) {
9911                 $scope.messageType = messageType;
9912             };
9913             $scope.$watch('messageType', function(value) {
9914                 if (angular.isDefined(value) && value !== null) {
9915                     $element.attr('message-type', value);
9916                 }
9917             });
9918         }]
9919     };
9920 }])
9921
9922 .directive('attMessage', [function() {
9923     return {
9924         restrict: 'EA',
9925         scope: {},
9926         require: '^attMessages',
9927         link: function(scope, elem, attr, ctrl) {
9928             scope.when = attr.when || attr.attMessage;
9929             scope.type = attr.type;
9930             elem.css({display: 'none'});
9931             scope.$parent.$watch('error', function(value) {
9932                 if (value === scope.when) {
9933                     elem.css({display: 'block'});
9934                     ctrl.setMessageType(scope.type);
9935                 } else {
9936                     elem.css({display: 'none'});
9937                 }
9938             });
9939         }
9940     };
9941 }]);
9942
9943 angular.module('att.abs.formField', ['att.abs.message'])
9944
9945 .directive('attFormField', [function() {
9946     return {
9947         priority: 101,
9948         restrict: 'A',
9949         controller: ['$scope', function($scope) {
9950         }],
9951         link: function(scope, elem, attr, ctrl) {
9952             elem.wrap('<div class="form-field"></div>');
9953             elem.parent().append('<label class="form-field__label">' + attr.placeholder || attr.attFormField + '</label>');
9954             elem.wrap('<div class="form-field-input-container"></div>');
9955
9956             elem.bind('keyup', function() {
9957                 if (this.value !== '') {
9958                     elem.parent().parent().find('label').addClass('form-field__label--show').removeClass('form-field__label--hide');
9959                 } else {
9960                     elem.parent().parent().find('label').addClass('form-field__label--hide').removeClass('form-field__label--show');                    
9961                 }
9962             });
9963
9964             elem.bind('blur', function() {
9965                 if (this.value === '') {
9966                     elem.parent().parent().find('label').removeClass('form-field__label--hide');
9967                 }
9968             });
9969         }
9970     };
9971 }])
9972
9973 .directive('attFormFieldValidation', ['$compile', '$log', function($compile, $log) {
9974     return {
9975         priority: 102,
9976         scope: {},
9977         restrict: 'A',
9978         require: ['?ngModel', '?attFormField'],
9979         link: function(scope, elem, attr, ctrl) {
9980             var ngCtrl = ctrl[0];
9981             var attFormFieldCtrl = ctrl[1];
9982             scope.valid = "";
9983             
9984             if (!ngCtrl) {
9985                 $log.error("att-form-field-validation :: ng-model directive is required.");
9986                 return;
9987             }
9988             if (!attFormFieldCtrl) {
9989                 $log.error("att-form-field-validation :: att-form-field directive is required.");
9990                 return;
9991             }
9992
9993             elem.parent().append($compile(angular.element('<i class="icon-info-alert error" ng-show="valid===false">&nbsp;</i>'))(scope));
9994             elem.parent().append($compile(angular.element('<i class="icon-info-success success" ng-show="valid===true">&nbsp;</i>'))(scope));
9995
9996             scope.$watch('valid', function(value) {
9997                 if (value === true) {
9998                     elem.parent().parent().addClass('success');
9999                 } else if (value === false) {
10000                     elem.parent().parent().addClass('error');
10001                 } else {
10002                     elem.parent().parent().removeClass('success').removeClass('error');
10003                 }
10004             });
10005
10006             elem.bind('keyup', function() {
10007                 if (ngCtrl.$valid === true) {
10008                     scope.valid = true;
10009                 } else if (ngCtrl.$invalid === true) {
10010                     scope.valid = false;
10011                 } else {
10012                     scope.valid = "";
10013                 }
10014                 scope.$apply();
10015             });
10016         }
10017     };
10018 }])
10019
10020 .directive('attFormFieldValidationAlert', ['$timeout', function($timeout) {
10021         return {
10022         scope: {},
10023         restrict: 'EA',
10024         replace: true,
10025         transclude: true,
10026         templateUrl: 'app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlert.html',
10027         link: function(scope, elem, attr, ctrl) {
10028             scope.showLabel = false;
10029             scope.hideLabel = false;
10030             scope.errorMessage = false;
10031             scope.warningMessage = false;
10032             
10033             var checkMessageType = function() {
10034                 if (elem.find('att-messages').attr('message-type') === 'error') {
10035                     scope.errorMessage = true;
10036                     scope.warningMessage = false;
10037                 } else if (elem.find('att-messages').attr('message-type') === 'warning') {
10038                     scope.errorMessage = false;
10039                     scope.warningMessage = true;
10040                 } else {
10041                     scope.errorMessage = false;
10042                     scope.warningMessage = false;
10043                 }
10044             };
10045
10046             elem.find('label').text(elem.find('input').attr('placeholder'));
10047             elem.find('input').bind('keyup', function() {
10048                 if (this.value !== '') {
10049                     scope.showLabel = true;
10050                     scope.hideLabel = false;
10051                 } else {
10052                     scope.showLabel = false;
10053                     scope.hideLabel = true;
10054                 }
10055                 checkMessageType();
10056                 scope.$apply();
10057             });
10058
10059             elem.find('input').bind('blur', function() {
10060                 if (this.value === '') {
10061                     scope.showLabel = false;
10062                     scope.hideLabel = false;
10063                 }
10064                 scope.$apply();
10065             });
10066             
10067             $timeout(function() {
10068                 checkMessageType();
10069             }, 100);
10070         }
10071     };
10072 }]);
10073
10074 'use strict';
10075 angular.module('att.abs.hourpicker', ['att.abs.utilities'])
10076   .constant('hourpickerConfig', {
10077             days: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
10078             customOption: 'Custom'
10079         })
10080
10081         .controller('hourPickerController', ['$scope', function($scope) {
10082
10083                 $scope.options = [];
10084                 this.setOptions = 
10085                 function(value, fromtime, totime, preselect, uncheckedFromTime,uncheckedToTime) {
10086                     
10087                     $scope.options.push(value);
10088                     if (preselect !== undefined) {
10089                         $scope.preselect = preselect;
10090                     }
10091                     
10092                     if (fromtime !== undefined) {
10093                         $scope.fromtime = fromtime;
10094                         for (var daycount in $scope.days) {
10095                            $scope.FrtimeList[$scope.days[daycount]] = {};
10096                            
10097                             if(uncheckedFromTime !== undefined){
10098                                 $scope.FrtimeList[$scope.days[daycount]].value = uncheckedFromTime;
10099                                 $scope.selectedFromOption[$scope.days[daycount]] = uncheckedFromTime;
10100                             }else{
10101                                 $scope.FrtimeList[$scope.days[daycount]].value = fromtime[0].value;
10102                                 $scope.selectedFromOption[$scope.days[daycount]] = fromtime[0].value;
10103                             }
10104                         }
10105                     }
10106                     if (totime !== undefined) {
10107                         $scope.totime = totime;
10108                         for (var daycount in $scope.days) {
10109                             $scope.TotimeList[$scope.days[daycount]] = {};
10110                             
10111                             if(uncheckedToTime !== undefined){
10112                                 $scope.TotimeList[$scope.days[daycount]].value = uncheckedToTime;
10113                                 $scope.selectedToOption[$scope.days[daycount]] = uncheckedToTime;
10114                             }else{
10115                                 $scope.TotimeList[$scope.days[daycount]].value = totime[0].value;
10116                                 $scope.selectedToOption[$scope.days[daycount]] = totime[0].value;
10117                             }
10118                         }
10119                     }
10120
10121
10122                     if(uncheckedFromTime !== undefined)
10123                         $scope.uncheckedFromTime = uncheckedFromTime;
10124
10125                     if(uncheckedToTime !== undefined)
10126                         $scope.uncheckedToTime = uncheckedToTime;
10127                 };
10128             }])
10129
10130         .directive('attHourpickerOption', [function() {
10131                 return {
10132                     restrict: 'EA',
10133                     require: '^attHourpicker',
10134                     scope: {
10135                         option: "=option",
10136                         fromtime: "=fromtime",
10137                         totime: "=totime",
10138                         preselect: "=preselect",
10139                         uncheckedFromTime: "=",
10140                         uncheckedToTime: "="
10141                     },
10142                     link: function(scope, element, attr, ctrl) {
10143                         ctrl.setOptions(scope.option, 
10144                             scope.fromtime,
10145                             scope.totime, 
10146                             scope.preselect, 
10147                             scope.uncheckedFromTime,
10148                             scope.uncheckedToTime);
10149                     }
10150                 };
10151             }])
10152
10153         .directive('attHourpicker', ["hourpickerConfig", "$document", "$log", "$documentBind", "$timeout", function(hourpickerConfig, $document, $log, $documentBind, $timeout) {
10154                 return{
10155                     require: 'ngModel',
10156                     restrict: 'EA',
10157                     controller: 'hourPickerController',
10158                     transclude: true,
10159                     scope:{
10160                       model: "=ngModel",
10161                       resetFlag: "=?"
10162                     },
10163                     templateUrl: 'app/scripts/ng_js_att_tpls/hourpicker/hourpicker.html',
10164                     link: function(scope, element, attr, ctrl) {
10165                         var flag = false;
10166                         scope.isFromDropDownOpen = false;
10167                         scope.isToDropDownOpen = false;
10168                         var dropDownOpenValue = "";
10169                         var custTime = {};
10170                         scope.days = hourpickerConfig.days;
10171                         scope.daysList = {};
10172                         scope.FrtimeList = {};
10173                         scope.FrtimeListDay = {};
10174                         scope.TotimeListDay = {};
10175                         scope.selectedFromOption = {};
10176                         scope.selectedToOption = {};
10177                         scope.TotimeList = {};
10178                         scope.selectedIndex = 0;
10179                         scope.selectedOption = "Select from list";
10180                         scope.customTime = [];
10181                         
10182                         scope.resetFlag = false;
10183                         
10184                         scope.$watch('resetFlag', function(newVal, oldVal){
10185                             if(newVal !== oldVal){
10186                                 if( newVal === true && scope.selectedOption === hourpickerConfig.customOption ){
10187                                     //disable and reset all days checkbox
10188                                     for (day in scope.daysList) {
10189                                         scope.daysList[day] = false;
10190                                         scope.addSelectedValue(day);
10191                                     }
10192                                     scope.preselectUpdateFxn(scope.preselect);
10193                                 }
10194                                 scope.resetFlag = false;
10195                             }
10196                         });
10197
10198                         scope.$watch('selCategory', function(value) {
10199                             if (value){
10200                                 ctrl.$setViewValue(value);                                
10201                             }
10202                         });
10203                         scope.$watch('model', function(value,oldValue) {
10204                             if (value && oldValue && angular.toJson(value) !== angular.toJson(oldValue)) {
10205                                scope.updateData(value)
10206                             }});
10207                         
10208                         scope.updateData = function(value)
10209                         {                        
10210                         if (value.constructor === Array) {
10211                                     scope.showDaysSelector = true;
10212                                     scope.selectedOption = hourpickerConfig.customOption;
10213                                     for (var arry in value) {
10214                                         var day = value[arry].day;
10215                                         scope.daysList[day] = true;
10216
10217                                         for (var fromcount in scope.fromtime) {
10218                                             if (scope.fromtime[fromcount].value === value[arry].FromTime) {
10219                                                 scope.FrtimeList[day].value = scope.fromtime[fromcount].value;
10220                                                 scope.selectedFromOption[day] = scope.FrtimeList[day].value;
10221                                             }
10222                                         }
10223                                         for (var tocount in scope.totime) {
10224                                             if (scope.totime[tocount].value === value[arry].ToTime) {
10225                                                 scope.TotimeList[day].value = scope.totime[tocount].value;
10226                                                 scope.selectedToOption[day] = scope.TotimeList[day].value;
10227                                             }
10228                                         }
10229                                         scope.addSelectedValue(day, value[arry].FromTime, value[arry].ToTime);
10230                                         //for IE8 Fix
10231                                         if (parseInt(arry) + 1 === value.length) {
10232                                             break;
10233                                         }
10234                                     }
10235                                 }
10236                                 else {
10237                                     scope.selectOption(value.day);
10238                                 }
10239                             }
10240                             
10241                         scope.$watch('preselect', function(value) {
10242                             scope.preselectUpdateFxn(value);
10243                         });
10244                         
10245                         scope.preselectUpdateFxn = function(value){
10246                             if (value !== undefined) {
10247                                 
10248                                 if(scope.options){
10249                                     value = scope.validatePreselectData(value);                                    
10250                                 }
10251                                 if (value === "") {
10252                                     return;
10253                                 }
10254                                 scope.updateData(value);                               
10255                             }
10256                         }
10257
10258                         scope.validatePreselectData = function(value)
10259                         {
10260                             if (value.constructor === Array) {
10261                                 for (var arry in value) {
10262                                     var day = value[arry].day;
10263                                     var isDayFound = false;
10264                                     var isFrmFound = false;
10265                                     var isToFound = false;
10266                                     for (var daycount in scope.days) {
10267                                         if (scope.days[daycount] === day) {
10268                                             isDayFound = true;
10269                                             break;
10270                                         }
10271                                     }
10272                                     if (!isDayFound) {
10273                                         value.splice(arry, 1);
10274                                         continue;
10275                                     }
10276                                     for (var fromcount in scope.fromtime) {
10277                                         if (scope.fromtime[fromcount].value === value[arry].FromTime) {
10278                                             isFrmFound = true;
10279                                             break;
10280                                         }
10281                                     }
10282                                     if (!isFrmFound) {
10283                                         value[arry].FromTime = scope.fromtime[0].value;
10284                                     }
10285                                     for (var tocount in scope.totime) {
10286                                         if (scope.totime[tocount].value === value[arry].ToTime) {
10287                                             isToFound = true;
10288                                             break;
10289                                         }
10290                                     }
10291                                     if (!isToFound) {
10292                                         value[arry].ToTime = scope.totime[0].value;
10293                                     }
10294                                     //for IE8 Fix
10295                                     if (parseInt(arry) + 1 === value.length) {
10296                                         break;
10297                                     }
10298                                 }
10299                             }
10300                             else {
10301                                 var isOptionFound = false;
10302                                 for (var optcount in scope.options) {
10303                                     if (scope.options[optcount] === value.day) {
10304                                         isOptionFound = true;
10305                                         break;
10306                                     }
10307                                 }
10308                                 if (!isOptionFound) {
10309                                     value = "";
10310                                 }
10311                             }
10312                             return value;
10313                         };
10314
10315                         scope.selectPrevNextValue = function($event, arrayValues, currValue) {
10316
10317                             var value;
10318                             var index = 0;
10319                             if ($event.keyCode === 38) {
10320                                 value = -1;
10321                             } else if ($event.keyCode === 40) {
10322                                 value = 1;
10323                             } else {
10324                                 return currValue;
10325                             }
10326
10327                             if (arrayValues.indexOf(currValue) !== -1) {
10328                                 index = arrayValues.indexOf(currValue) + value;
10329                             } else {
10330                                 for (var count in arrayValues) {
10331                                     if (arrayValues[count].value === currValue) {
10332                                         index = parseInt(count) + value;
10333                                         break;
10334                                     }
10335                                 }
10336                             }
10337
10338                             if (index === arrayValues.length) {
10339                                 index = index - 1;
10340                             } else if (index === -1) {
10341                                 index = index + 1;
10342                             }
10343
10344                             $event.preventDefault();
10345                             if (arrayValues[index].value)
10346                                 return arrayValues[index].value;
10347                             else
10348                                 return arrayValues[index];
10349                         };
10350
10351                         scope.showDropdown = function()
10352                         {
10353                             scope.showlist = !scope.showlist;
10354                             flag = !flag;
10355                         };
10356
10357                         scope.showfromDayDropdown = function(value)
10358                         {
10359                             //close dropdown if any other From drop down is opened
10360                             for (count in scope.FrtimeListDay) {
10361                                 if (count !== value && scope.FrtimeListDay[count] === true) {
10362                                     scope.FrtimeListDay[count] = false;
10363                                 }
10364                             }
10365                             for (count in scope.TotimeListDay) {
10366                                 if (scope.TotimeListDay[count] === true) {
10367                                     scope.TotimeListDay[count] = false;
10368                                 }
10369                             }
10370                             scope.FrtimeListDay[value] = !scope.FrtimeListDay[value];
10371                             flag = !flag;
10372                             scope.showlist = false;
10373
10374                             //save model value so we can close current dropdown on click of other part of the document
10375                             if (scope.FrtimeListDay[value]) {
10376                                 scope.isFromDropDownOpen = true;
10377                                 dropDownOpenValue = value;
10378
10379                             } else {
10380                                 scope.isFromDropDownOpen = false;
10381                             }
10382                             
10383                             $timeout(function () {
10384                                 if(scope.FrtimeListDay[value]){
10385                                     var daysContainerDIV = angular.element(element)[0].querySelector(".customdays-width");
10386                                     var containerUL = angular.element(daysContainerDIV.querySelector('.select2-container-active')).parent()[0].querySelector("ul");
10387                                     var selectedElemTopPos = angular.element(containerUL.querySelector('.selectedItemInDropDown'))[0].offsetTop;
10388                                     angular.element(containerUL)[0].scrollTop = selectedElemTopPos;
10389                                 }
10390                             });
10391                             
10392                         };
10393
10394                         scope.showtoDayDropdown = function(value)
10395                         {
10396                             //close dropdown if any other To drop down is opened
10397                             for (count in scope.TotimeListDay) {
10398                                 if (count !== value && scope.TotimeListDay[count] === true) {
10399                                     scope.TotimeListDay[count] = false;
10400                                 }
10401                             }
10402                             for (count in scope.FrtimeListDay) {
10403                                 if (scope.FrtimeListDay[count] === true) {
10404                                     scope.FrtimeListDay[count] = false;
10405                                 }
10406                             }
10407                             scope.TotimeListDay[value] = !scope.TotimeListDay[value];
10408                             flag = !flag;
10409                             scope.showlist = false;
10410
10411                             //save model value so we can close current dropdown on click of other part of the document
10412                             if (scope.TotimeListDay[value]) {
10413                                 scope.isToDropDownOpen = true;
10414                                 dropDownOpenValue = value;
10415
10416                             } else {
10417                                 scope.isToDropDownOpen = false;
10418                             }
10419                             
10420                             $timeout(function () {
10421                                 if(scope.FrtimeListDay[value]){
10422                                     var daysContainerDIV = angular.element(element)[0].querySelector(".customdays-width");
10423                                     var containerUL = angular.element(daysContainerDIV.querySelector('.select2-container-active')).parent()[0].querySelector("ul");
10424                                     var selectedElemTopPos = angular.element(containerUL.querySelector('.selectedItemInDropDown'))[0].offsetTop;
10425                                     angular.element(containerUL)[0].scrollTop = selectedElemTopPos;
10426                                 }
10427                             });
10428                             
10429                         };
10430
10431                         scope.selectFromDayOption = function(day, value)
10432                         {
10433                             scope.selectedFromOption[day] = value;
10434                             scope.FrtimeList[day].value = value;
10435                             scope.FrtimeListDay[day] = false;
10436                             scope.isFromDropDownOpen = false;
10437                         };
10438
10439                         scope.selectToDayOption = function(day, value)
10440                         {
10441                             scope.selectedToOption[day] = value;
10442                             scope.TotimeList[day].value = value;
10443                             scope.TotimeListDay[day] = false;
10444                             scope.isToDropDownOpen = false;
10445                         };
10446
10447                         scope.addSelectedValue = function(value, fromtime, totime)
10448                         {
10449                             if (scope.daysList[value] !== undefined && !scope.daysList[value]) {
10450
10451                                for (var count = 0, len = scope.customTime.length; count < len; count++) {
10452                                     if (scope.customTime[count].day === value) {
10453
10454                                         if(scope.uncheckedFromTime)
10455                                             scope.selectedFromOption[scope.customTime[count].day] = scope.uncheckedFromTime;
10456                                         else
10457                                             scope.selectedFromOption[scope.customTime[count].day]  = scope.FrtimeList[scope.customTime[count].day].value;
10458
10459                                         if(scope.uncheckedToTime)
10460                                             scope.selectedToOption[scope.customTime[count].day] = scope.uncheckedToTime;
10461                                         else
10462                                             scope.selectedToOption[scope.customTime[count].day] = scope.TotimeList[scope.customTime[count].day].value;
10463                                         
10464                                         scope.customTime.splice(count, 1);
10465                                         break;
10466                                     }
10467                                 }
10468
10469                             }
10470                             else {
10471                                 
10472                                 if(scope.selectedFromOption[value] == scope.uncheckedFromTime){
10473                                     scope.selectedFromOption[value] = scope.fromtime[0].value;
10474                                     fromtime = scope.fromtime[0].value;
10475                                     scope.FrtimeList[value].value = scope.fromtime[0].value;
10476                                 }
10477
10478                                 if(scope.selectedToOption[value]  == scope.uncheckedToTime){
10479                                     scope.selectedToOption[value]= scope.totime[0].value;
10480                                     totime = scope.totime[0].value;
10481                                     scope.TotimeList[value].value = scope.totime[0].value;
10482                                 }
10483                              
10484                                 custTime["day"] = value;
10485                                 custTime["FromTime"] =  scope.FrtimeList[value].value;
10486                                 custTime["ToTime"] = scope.TotimeList[value].value;
10487
10488                                 var count = 0, len = scope.customTime.length;
10489                                 for (; count < len; count++) {
10490                                     if (scope.customTime[count].day === value) {
10491                                         scope.customTime[count].FromTime = custTime["FromTime"];
10492                                         scope.customTime[count].ToTime = custTime["ToTime"];
10493                                         break;
10494                                     }
10495                                 }
10496                                 if (count === len) {
10497                                     var x = angular.copy(custTime);
10498                                     scope.customTime.push(x);
10499                                 }
10500                             }
10501                             scope.selCategory = scope.customTime;
10502                         };
10503
10504
10505                         var outsideClick = function(e) {
10506                             if (scope.showlist) {
10507                                 scope.$apply(function() {
10508                                     scope.showlist = false;
10509                                 });
10510                             }
10511                         };
10512
10513                         $documentBind.click('showlist', outsideClick, scope);
10514
10515                         var outsideClickFromDropdown = function(e) {
10516                             scope.$apply(function() {
10517                                 if (scope.isFromDropDownOpen) {
10518                                     scope.FrtimeListDay[dropDownOpenValue] = false;
10519                                     scope.isFromDropDownOpen = false;
10520                                 }
10521                             });
10522                         };
10523
10524                         $documentBind.click('isFromDropDownOpen', outsideClickFromDropdown, scope);
10525
10526                         var outsideClickToDropdown = function(e) {
10527                             scope.$apply(function() {
10528                                 if (scope.isToDropDownOpen) {
10529                                     scope.TotimeListDay[dropDownOpenValue] = false;
10530                                     scope.isToDropDownOpen = false;
10531                                 }
10532                             });
10533                         };
10534
10535                         $documentBind.click('isToDropDownOpen', outsideClickToDropdown, scope);
10536
10537                         scope.selectOption = function(sItem)
10538                         {
10539
10540                             if (sItem === hourpickerConfig.customOption) {
10541                                 scope.showDaysSelector = true;
10542                                 scope.selCategory = scope.customTime;
10543                             } else {
10544                                 scope.showDaysSelector = false;
10545                                 var fromTime = /[0-9]\s?am/i.exec(sItem);
10546                                 var toTime = /[0-9]\s?pm/i.exec(sItem);
10547                                 scope.selCategory = {day: sItem, FromTime: fromTime === null ? 'NA' : fromTime[0], ToTime: toTime === null ? 'NA' : toTime[0]};
10548                             }
10549
10550                             scope.showlist = false;
10551                             flag = false;
10552                             scope.selectedOption = sItem;
10553                         };
10554                     }
10555                 };
10556             }]);
10557
10558 angular.module('att.abs.iconButtons', [])
10559
10560         .constant('buttonConfig', {
10561             activeClass: 'active--button',
10562             toggleEvent: 'click'
10563         })
10564
10565         .directive('attIconBtnRadio', ['buttonConfig', function(buttonConfig) {
10566                 var activeClass = buttonConfig.activeClass || 'active--button';
10567                 var toggleEvent = buttonConfig.toggleEvent || 'click';
10568
10569                 return {
10570                     require: 'ngModel',
10571                     link: function(scope, element, attrs, ngModelCtrl) {
10572
10573                         element.attr("role","button");
10574                         element.attr("tabindex","0");
10575                         element.append("<span class='hidden-spoken'>"+attrs.attIconBtnRadio+"</span>");
10576                         
10577                         //model -> UI
10578                         ngModelCtrl.$render = function() {
10579                             element.parent().toggleClass(activeClass, angular.equals(ngModelCtrl.$modelValue, attrs.attIconBtnRadio));
10580                             /*if(ngModelCtrl.$modelValue!==undefined){
10581                                 if (angular.equals(ngModelCtrl.$modelValue, attrs.attIconBtnRadio)) {
10582                                     element.attr("aria-selected", true);
10583                                 }
10584                                 else {
10585                                     element.attr("aria-selected", false);
10586                                 }
10587                             }*/
10588                         };
10589
10590                         //ui->model
10591                         element.parent().bind(toggleEvent, function() {
10592                             if (!element.parent().hasClass(activeClass)) {
10593                                 scope.$apply(function() {
10594                                     ngModelCtrl.$setViewValue(attrs.attIconBtnRadio);
10595                                     ngModelCtrl.$render();
10596                                 });
10597                             }
10598                         });
10599
10600
10601                     }
10602                 };
10603             }])
10604         .directive('attIconBtnCheckbox', ['buttonConfig', function(buttonConfig) {
10605                 var activeClass = buttonConfig.activeClass || 'active--button';
10606                 var toggleEvent = buttonConfig.toggleEvent || 'click';
10607
10608                 return {
10609                     require: 'ngModel',
10610                     link: function(scope, element, attrs, ngModelCtrl) {
10611
10612                         element.attr("role","button");
10613                         element.attr("tabindex","0");
10614                         element.append("<span class='hidden-spoken'>"+attrs.attIconBtnCheckbox+"</span>");
10615                         
10616                         function getTrueValue() {
10617                             var trueValue = scope.$eval(attrs.btnCheckboxTrue);
10618                             return angular.isDefined(trueValue) ? trueValue : true;
10619                         }
10620
10621                         function getFalseValue() {
10622                             var falseValue = scope.$eval(attrs.btnCheckboxFalse);
10623                             return angular.isDefined(falseValue) ? falseValue : false;
10624                         }
10625
10626                         //model -> UI
10627                         ngModelCtrl.$render = function() {
10628                             element.parent().toggleClass(activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue()));
10629                             /*if(ngModelCtrl.$modelValue!==undefined){
10630                                 if ((angular.equals(ngModelCtrl.$modelValue, getTrueValue()))) {
10631                                     element.attr("aria-selected", true);
10632                                 }
10633                                 else {
10634                                     element.attr("aria-selected", false);
10635                                 }
10636                             }*/
10637                         };
10638
10639                         //ui->model
10640                         element.parent().bind(toggleEvent, function() {
10641                             scope.$apply(function() {
10642                                 ngModelCtrl.$setViewValue(element.parent().hasClass(activeClass) ? getFalseValue() : getTrueValue());
10643                                 ngModelCtrl.$render();
10644                             });
10645                         });
10646                     }
10647                 };
10648             }]);
10649
10650 angular.module('att.abs.links', [])
10651         .directive('attLink', ['$compile',function($compile) {
10652                 return {
10653                     restrict: 'A',
10654                     link: function(scope, elem, attr) {
10655                         elem.addClass('link');
10656                         if(!(elem.attr('href'))){
10657                             elem.attr("tabindex", "0");
10658                         }
10659                     }
10660                 };
10661             }])
10662         .directive('attLinkVisited', ['$compile',function($compile) {
10663                 return {
10664                     restrict: 'A',
10665                     link: function(scope, elem, attr) {
10666                         elem.addClass('link--visited');
10667                         if(!(elem.attr('href'))){
10668                             elem.attr("tabindex", "0");
10669                         }
10670                     }
10671                 };
10672             }])
10673         .directive('attReadmore', ['$timeout',function($timeout) {
10674                 return {
10675                     restrict: 'A',
10676                     scope: {
10677                         lines:"@noOfLines",
10678                         textModel: "=",
10679                         isOpen: "=" //attribute to use readmore inside accordion
10680                     },
10681                     templateUrl: 'app/scripts/ng_js_att_tpls/links/readMore.html',
10682                     link: function(scope, elem, attr, ctrl) {
10683                         var height = 1;
10684                         scope.$watch('textModel', function(val){
10685                             if(!val){
10686                                 scope.textToDisplay = '';
10687                                 scope.readMoreLink = false;
10688                                 scope.readLessLink = false;
10689                                 scope.readFlag = false;
10690                             }
10691                             else{
10692                                 if (typeof String.prototype.trim !== 'function') {
10693                                     String.prototype.trim = function() {
10694                                        return this.replace(/^\s+|\s+$/g, '');
10695                                     };
10696                                 }
10697                                 scope.textToDisplay = val.trim();
10698                                 scope.readFlag = true;
10699                                 $timeout(function() {
10700                                     var readElem = elem[0].children[0].children[0];
10701                                     if(height===1){
10702                                         if(window.getComputedStyle){
10703                                             height = parseInt(scope.lines) * parseFloat(window.getComputedStyle(readElem,null).getPropertyValue("height"));
10704                                         }
10705                                         else {
10706                                             height = parseInt(scope.lines) * parseFloat(readElem.currentStyle.height);
10707                                         }
10708                                         scope.elemHeight = height;
10709                                         scope.readLinkStyle = {'height': scope.elemHeight + 'px'};
10710                                     }
10711                                 });
10712                                 scope.readMoreLink = true;
10713                                 scope.readLessLink = false;
10714                             }
10715                         });
10716                                               
10717                         // Code to use readmore inside accordion 
10718                         var parentElem = elem.parent();
10719                         if (parentElem.hasClass('att-accordion__body')) {
10720                             scope.$watch('isOpen', function(val) {
10721                                 if (!val) {
10722                                     scope.readLess();
10723                                 }
10724                             });
10725                         }
10726                         
10727                         scope.readMore = function() {
10728                             scope.readMoreLink = false;
10729                             scope.readLessLink = true;
10730                             scope.readLinkStyle = {'height': 'auto'};
10731                             scope.readFlag = false;
10732                         };
10733                         
10734                         scope.readLess = function() {
10735                             scope.readMoreLink = true;
10736                             scope.readLessLink = false;
10737                             scope.readLinkStyle = {'height': scope.elemHeight + 'px'};
10738                             scope.readFlag = true;
10739                         };
10740                     }
10741                 };
10742             }])
10743         .directive('attLinksList', [function() {
10744                 return {
10745                     restrict: 'A',
10746                     controller: function() {
10747                     },
10748                     link: function(scope, elem, attr) {
10749                         elem.addClass('links-list');
10750                     }
10751                 };
10752             }])
10753         .directive('attLinksListItem', ['$compile',function($compile) {
10754                 return {
10755                     restrict: 'A',
10756                     require: '^attLinksList',
10757                     link: function(scope, elem, attr, attLinksListCtrl) {
10758                         elem.addClass('links-list__item');
10759                         if(!(elem.attr('href'))){
10760                             elem.attr("tabindex", "0");
10761                         }
10762                     }
10763                 };
10764             }]);
10765 'use strict'
10766 angular.module('att.abs.loading', [])
10767         .directive('attLoading', [
10768             function() {
10769                 return {
10770                     restrict: 'A',
10771                     replace: true,
10772                     scope: {
10773                         icon: '@attLoading',
10774                         progressStatus: '=?',
10775                         colorClass: '=?'
10776                     },
10777                     templateUrl: 'app/scripts/ng_js_att_tpls/loading/loading.html',
10778                     link: function(scope, element, attr) {
10779                         var progressvalue = scope.progressStatus;
10780                         scope.progressStatus = Math.min(100, Math.max(0, progressvalue));
10781                         if(navigator.userAgent.indexOf("MSIE 8.")!=-1){
10782                                                         var shiftX = 0,
10783                                                                 shiftY = scope.progressStatus * 36;
10784                                                         
10785                                                 if (element.hasClass('att-loading--blue')) {
10786                                                         shiftX = -36;
10787                                                 }
10788                                                 else if (element.hasClass('att-loading--white')) {
10789                                                         shiftX = -72;
10790                                                 }
10791                                                 //element.eq(1).children().find('att-loading-inset__percentage').html(scope.progressStatus);
10792                                                 element.css({
10793                                                 'background-position-x' : shiftX,
10794                                                 'background-position-y' : -shiftY
10795                                                 });
10796                 
10797                       }
10798
10799                     }
10800                 };
10801             }
10802         ]);
10803
10804 angular.module('att.abs.modal', [])
10805 /**
10806  * A helper, internal data structure that acts as a map but also allows getting / removing
10807  * elements in the LIFO order
10808  */
10809   .factory('$$stackedMap', function () {
10810     return {
10811       createNew: function () {
10812         var stack = [];
10813
10814         return {
10815           add: function (key, value) {
10816             stack.push({
10817               key: key,
10818               value: value
10819             });
10820           },
10821           get: function (key) {
10822             for (var i = 0; i < stack.length; i++) {
10823               if (key == stack[i].key) {
10824                 return stack[i];
10825               }
10826             }
10827           },
10828           keys: function() {
10829             var keys = [];
10830             for (var i = 0; i < stack.length; i++) {
10831               keys.push(stack[i].key);
10832             }
10833             return keys;
10834           },
10835           top: function () {
10836             return stack[stack.length - 1];
10837           },
10838           remove: function (key) {
10839             var idx = -1;
10840             for (var i = 0; i < stack.length; i++) {
10841               if (key == stack[i].key) {
10842                 idx = i;
10843                 break;
10844               }
10845             }
10846             return stack.splice(idx, 1)[0];
10847           },
10848           removeTop: function () {
10849             return stack.splice(stack.length - 1, 1)[0];
10850           },
10851           length: function () {
10852             return stack.length;
10853           }
10854         };
10855       }
10856     };
10857   })
10858
10859 /**
10860  * A helper directive for the $modal service. It creates a backdrop element.
10861  */
10862   .directive('modalBackdrop', ['$timeout', function ($timeout) {
10863     return {
10864       restrict: 'EA',
10865       replace: true,
10866       templateUrl: 'app/scripts/ng_js_att_tpls/modal/backdrop.html',
10867       link: function (scope) {
10868         scope.animate = false;
10869         //trigger CSS transitions
10870         $timeout(function () {
10871           scope.animate = true;
10872         });      
10873       }
10874     };
10875   }])
10876
10877   .directive('modalWindow', ['$modalStack','$timeout','$document', function ($modalStack,$timeout,$document) {
10878     return {
10879       restrict: 'EA',
10880       scope: {
10881         index: '@'
10882       },
10883       replace: true,
10884       transclude: true,
10885       templateUrl: 'app/scripts/ng_js_att_tpls/modal/window.html',
10886       link: function (scope, element, attrs) {
10887         scope.windowClass = attrs.windowClass || '';
10888         
10889                 
10890         $timeout(function () {
10891           // trigger CSS transitions
10892                   scope.focusModalFlag=true;
10893           scope.animate = true;
10894                    
10895         });
10896                 $document.on('focus keydown', function(e) {             
10897                         if (e.which ===9) {
10898                         String.prototype.contains = function(it) { return this.indexOf(it) != -1; };
10899                         if (element[0] !== e.target && !element[0].contains( e.target )) {
10900                                 element[0].focus();
10901                         }
10902                         }
10903                 });
10904         scope.close = function (evt) {             
10905           var modal = $modalStack.getTop();         
10906           if (modal && modal.value.backdrop && modal.value.backdrop != 'static'  && (evt.target === evt.currentTarget)) {
10907             // Check if preventDefault exists due to lack of support for IE8
10908             if (evt.preventDefault) {
10909               evt.preventDefault();
10910               evt.stopPropagation();  
10911             } else {
10912               evt.returnValue = false;
10913             }
10914             
10915             $modalStack.dismiss(modal.key, 'backdrop click');
10916           }
10917         };
10918       }
10919     };
10920   }])
10921
10922   .factory('$modalStack', ['$document', '$compile', '$rootScope', '$$stackedMap',
10923     function ($document, $compile, $rootScope, $$stackedMap) {
10924
10925       var OPENED_MODAL_CLASS = 'modal-open';
10926
10927       var backdropjqLiteEl, backdropDomEl;
10928       var backdropScope = $rootScope.$new(true);
10929       var openedWindows = $$stackedMap.createNew();
10930       var $modalStack = {};
10931
10932       function backdropIndex() {
10933         var topBackdropIndex = -1;
10934         var opened = openedWindows.keys();
10935         for (var i = 0; i < opened.length; i++) {
10936           if (openedWindows.get(opened[i]).value.backdrop) {
10937             topBackdropIndex = i;
10938           }
10939         }
10940         return topBackdropIndex;
10941       }
10942
10943       $rootScope.$watch(backdropIndex, function(newBackdropIndex){
10944         backdropScope.index = newBackdropIndex;
10945       });
10946
10947       function removeModalWindow(modalInstance) {
10948
10949         var body = $document.find('body').eq(0);
10950         var modalWindow = openedWindows.get(modalInstance).value;
10951
10952         //clean up the stack
10953         openedWindows.remove(modalInstance);
10954
10955         //remove window DOM element
10956         modalWindow.modalDomEl.remove();
10957         body.toggleClass(OPENED_MODAL_CLASS, openedWindows.length() > 0);
10958
10959         //remove backdrop if no longer needed
10960         if (backdropDomEl && backdropIndex() == -1) {
10961           backdropDomEl.remove();
10962           backdropDomEl = undefined;
10963         }
10964
10965         //destroy scope
10966         modalWindow.modalScope.$destroy();
10967       }
10968
10969       $document.bind('keydown', function (evt) {
10970         var modal;
10971
10972         if (evt.which === 27) {
10973           modal = openedWindows.top();
10974           if (modal && modal.value.keyboard) {
10975             $rootScope.$apply(function () {
10976               $modalStack.dismiss(modal.key);
10977             });
10978           }
10979         }
10980       });
10981
10982       $modalStack.open = function (modalInstance, modal) {
10983
10984         openedWindows.add(modalInstance, {
10985           deferred: modal.deferred,
10986           modalScope: modal.scope,
10987           backdrop: modal.backdrop,
10988           keyboard: modal.keyboard
10989         });
10990
10991         var body = $document.find('body').eq(0);
10992
10993         if (backdropIndex() >= 0 && !backdropDomEl) {
10994             backdropjqLiteEl = angular.element('<div modal-backdrop></div>');
10995             backdropDomEl = $compile(backdropjqLiteEl)(backdropScope);
10996             body.append(backdropDomEl);
10997         }
10998           
10999         var angularDomEl = angular.element('<div modal-window></div>');
11000         angularDomEl.attr('window-class', modal.windowClass);
11001         angularDomEl.attr('index', openedWindows.length() - 1);
11002         angularDomEl.html(modal.content);
11003
11004         var modalDomEl = $compile(angularDomEl)(modal.scope);
11005         openedWindows.top().value.modalDomEl = modalDomEl;
11006         body.append(modalDomEl);
11007         body.addClass(OPENED_MODAL_CLASS);
11008       };
11009
11010       $modalStack.close = function (modalInstance, result) {
11011         var modal = openedWindows.get(modalInstance);
11012         if (modal) {
11013           modal.value.deferred.resolve(result);
11014           removeModalWindow(modalInstance);
11015         }
11016       };
11017
11018       $modalStack.dismiss = function (modalInstance, reason) {
11019         var modalWindow = openedWindows.get(modalInstance).value;
11020         if (modalWindow) {
11021           modalWindow.deferred.reject(reason);
11022           removeModalWindow(modalInstance);
11023         }
11024       };
11025
11026       $modalStack.getTop = function () {
11027         return openedWindows.top();
11028       };
11029
11030       return $modalStack;
11031     }])
11032
11033   .provider('$modal', function () {
11034
11035     var $modalProvider = {
11036       options: {
11037         backdrop: true, //can be also false or 'static'
11038         keyboard: true
11039       },
11040       $get: ['$injector', '$rootScope', '$q', '$http', '$templateCache', '$controller', '$modalStack',
11041         function ($injector, $rootScope, $q, $http, $templateCache, $controller, $modalStack) {
11042
11043           var $modal = {};
11044
11045           function getTemplatePromise(options) {
11046             return options.template ? $q.when(options.template) :
11047               $http.get(options.templateUrl, {cache: $templateCache}).then(function (result) {
11048                 return result.data;
11049               });
11050           }
11051
11052           function getResolvePromises(resolves) {
11053             var promisesArr = [];
11054             angular.forEach(resolves, function (value, key) {
11055               if (angular.isFunction(value) || angular.isArray(value)) {
11056                 promisesArr.push($q.when($injector.invoke(value)));
11057               }
11058             });
11059             return promisesArr;
11060           }
11061
11062           $modal.open = function (modalOptions) {
11063
11064             var modalResultDeferred = $q.defer();
11065             var modalOpenedDeferred = $q.defer();
11066
11067             //prepare an instance of a modal to be injected into controllers and returned to a caller
11068             var modalInstance = {
11069               result: modalResultDeferred.promise,
11070               opened: modalOpenedDeferred.promise,
11071               close: function (result) {
11072                 $modalStack.close(modalInstance, result);
11073               },
11074               dismiss: function (reason) {
11075                 $modalStack.dismiss(modalInstance, reason);
11076               }
11077             };
11078
11079             //merge and clean up options
11080             modalOptions = angular.extend({}, $modalProvider.options, modalOptions);
11081             modalOptions.resolve = modalOptions.resolve || {};
11082
11083             //verify options
11084             if (!modalOptions.template && !modalOptions.templateUrl) {
11085               throw new Error('One of template or templateUrl options is required.');
11086             }
11087
11088             var templateAndResolvePromise =
11089               $q.all([getTemplatePromise(modalOptions)].concat(getResolvePromises(modalOptions.resolve)));
11090
11091
11092             templateAndResolvePromise.then(function resolveSuccess(tplAndVars) {
11093
11094               var modalScope = (modalOptions.scope || $rootScope).$new();
11095               modalScope.$close = modalInstance.close;
11096               modalScope.$dismiss = modalInstance.dismiss;
11097
11098               var ctrlInstance, ctrlLocals = {};
11099               var resolveIter = 1;
11100
11101               //controllers
11102               if (modalOptions.controller) {
11103                 ctrlLocals.$scope = modalScope;
11104                 ctrlLocals.$modalInstance = modalInstance;
11105                 angular.forEach(modalOptions.resolve, function (value, key) {
11106                   ctrlLocals[key] = tplAndVars[resolveIter++];
11107                 });
11108
11109                 ctrlInstance = $controller(modalOptions.controller, ctrlLocals);
11110               }
11111
11112               $modalStack.open(modalInstance, {
11113                 scope: modalScope,
11114                 deferred: modalResultDeferred,
11115                 content: tplAndVars[0],
11116                 backdrop: modalOptions.backdrop,
11117                 keyboard: modalOptions.keyboard,
11118                 windowClass: modalOptions.windowClass
11119               });
11120
11121             }, function resolveError(reason) {
11122               modalResultDeferred.reject(reason);
11123             });
11124
11125             templateAndResolvePromise.then(function () {
11126               modalOpenedDeferred.resolve(true);
11127             }, function () {
11128               modalOpenedDeferred.reject(false);
11129             });
11130
11131             return modalInstance;
11132           };
11133
11134           return $modal;
11135         }]
11136     };
11137
11138     return $modalProvider;
11139   })
11140
11141 .directive("simpleModal", ["$modal", "$log", '$scrollTo', function($modal, $log, $scrollTo) {
11142         return {
11143             restrict: 'EA',
11144             scope: {
11145                 simpleModal: '@',
11146                 backdrop:'@',
11147                 keyboard:'@',
11148                 modalOk:'&',
11149                 modalCancel:'&',
11150                 windowClass:'@',
11151                 controller:'@'
11152             },
11153             link: function(scope, elm, attr) {
11154                 elm.bind('click', function(ev) {
11155                     var currentPosition = ev.pageY - ev.clientY;
11156                     ev.preventDefault();
11157                     if (angular.isDefined(elm.attr("href")) && elm.attr("href") !== "") {
11158                         scope.simpleModal = elm.attr("href");
11159                     }
11160                    scope.backdrop === "false" ? scope.backdropclick='static':scope.backdropclick=true;
11161                    scope.keyboard === "false" ? scope.keyboardev=false:scope.keyboardev=true;
11162                     $modal.open({
11163                         templateUrl: scope.simpleModal,
11164                         backdrop:scope.backdropclick,
11165                         keyboard:scope.keyboardev,
11166                         windowClass:scope.windowClass,
11167                         controller: scope.controller
11168                     }).result.then(scope.modalOk, scope.modalCancel);
11169                 });
11170             }
11171         };     
11172     }]);
11173
11174 angular.module('att.abs.pagination', ['att.abs.utilities'])
11175 .directive('attPagination', ['$timeout', function($timeout) {
11176      return {
11177         restrict: 'EA',
11178         scope: {
11179             totalPages: '=',
11180             currentPage: '=',
11181             showInput: '=',
11182             clickHandler: '=?'
11183         },
11184         replace: true,
11185         templateUrl: 'app/scripts/ng_js_att_tpls/pagination/pagination.html',
11186         link: function(scope, elem, attr, ctrl) {
11187             scope.focusedPage;
11188
11189             scope.$watch('totalPages', function(value) {
11190                 if(angular.isDefined(value) && value !== null){
11191                     scope.pages = [];
11192                     if (value < 1) {
11193                         scope.totalPages = 1;
11194                         return;
11195                     }
11196
11197                     if (value <= 7) {
11198                         for (var i = 1; i <= value; i++) {
11199                             scope.pages.push(i);
11200                         }
11201                     } else if (value > 7) {
11202                         var midVal = Math.ceil(value / 2);
11203                         scope.pages = [midVal - 1, midVal, midVal + 1];
11204                     }
11205
11206                     currentPageChanged(1);
11207                 }               
11208             });
11209
11210             scope.$watch('currentPage', function(value) {
11211                 currentPageChanged(value);
11212             });
11213
11214             function currentPageChanged(value) {
11215                 if (angular.isDefined(value) && value !== null) {
11216                     if (!value) {
11217                         value = 1;
11218                     } else if (!angular.isNumber(value)) {
11219                         value = parseInt(value, 10);
11220                     }
11221
11222                     if (value > scope.totalPages) {
11223                         value = scope.totalPages;
11224                     } else if (value < 1) {
11225                         value = 1;
11226                     }
11227                     
11228                     if(scope.currentPage !== value) {
11229                         scope.currentPage = value;
11230                         callbackHandler(scope.currentPage);
11231                     }
11232                     
11233                     if (scope.totalPages > 7) {
11234                         if (value < scope.pages[0] && value > 3) {
11235                             scope.pages = [value, value + 1, value + 2];
11236                         } else if (value > scope.pages[2] && value < scope.totalPages - 2) {
11237                             scope.pages = [value - 2, value - 1, value];
11238                         } else if (value <= 3) {
11239                             scope.pages = [1, 2, 3];
11240                         } else if (value >= scope.totalPages - 2) {
11241                             scope.pages = [scope.totalPages - 2, scope.totalPages - 1, scope.totalPages];
11242                         }
11243                     }
11244                 }
11245             }
11246             
11247             scope.next = function(event) {
11248                 event.preventDefault();
11249                 if (scope.currentPage < scope.totalPages) {
11250                     scope.currentPage += 1;
11251                     callbackHandler(scope.currentPage);
11252                 }
11253             };
11254
11255             scope.prev = function(event) {
11256                 event.preventDefault();
11257                 if (scope.currentPage > 1) {
11258                     scope.currentPage -= 1;
11259                     callbackHandler(scope.currentPage);
11260                 }
11261             };
11262
11263             scope.selectPage = function(value, event) {
11264                 event.preventDefault();
11265                 scope.currentPage = value;
11266                 scope.focusedPage = value;
11267                 callbackHandler(scope.currentPage);
11268             };
11269             
11270             var callbackHandler = function(num) {
11271                 if (angular.isFunction(scope.clickHandler))
11272                 {
11273                     scope.clickHandler(num);
11274                 }
11275             };
11276
11277             scope.checkSelectedPage = function(value) {
11278                 if(scope.currentPage === value) {
11279                     return true;
11280                 }
11281                 return false;
11282             };
11283
11284             scope.isFocused = function(page) {
11285                 if(scope.focusedPage === page) {
11286                     return true;
11287                 } else {
11288                     return false;
11289                 }
11290             };
11291         }
11292     };
11293 }]);
11294
11295 angular.module('att.abs.paneSelector',[])
11296 .constant('paneGroupConstants',{
11297         SIDE_WIDTH_DEFAULT: '33%',
11298         INNER_PANE_DEFAULT: '67%',
11299         SIDE_PANE_ID: 'sidePane',
11300         NO_DRILL_DOWN: 'none'
11301 })
11302 .factory('animation', function(){
11303         return TweenLite;
11304 })
11305 .directive('sideRow', ['$parse',function($parse){
11306         return {
11307                 restrict: 'A',
11308                 replace:true,
11309                 require: ['^sidePane','^paneGroup'],
11310                 link: function(scope,element,attr,ctrls){
11311                         var sidePaneCtrl = ctrls[0];
11312                         var paneGroupCtrl = ctrls[1];
11313                         if(scope.$first){
11314                                 /*
11315                                         Reset the sidePaneId array if a new
11316                                         set of ngRepeat data appeared
11317                                 */
11318                                 sidePaneCtrl.sidePaneIds = [];
11319                         }
11320  
11321                         var paneId =attr['paneId'];
11322                         var drillDownTo = attr['drillDownTo'];
11323
11324                         sidePaneCtrl.sidePaneRows.push({'paneId':paneId, 'drillDownTo':drillDownTo});
11325                         element.on('click', function(evnt){
11326                                 sidePaneCtrl.currentSelectedRowPaneId = paneId;
11327                                 paneGroupCtrl.slideOutPane(paneId,true);
11328                         });
11329                 }
11330         }
11331 }])
11332 .controller('SidePaneCtrl',['$scope', '$element','animation', 'paneGroupConstants',
11333  function($scope,$element,animation, paneGroupConstants){
11334         
11335         this.sidePaneTracker = {};
11336         this.currentWidth = paneGroupConstants.SIDE_WIDTH_DEFAULT;
11337         this.paneId = paneGroupConstants.SIDE_PANE_ID;
11338         this.currentSelectedRowPaneId;
11339
11340         this.drillDownToMapper = {};
11341
11342         this.sidePaneRows = [];
11343
11344         this.init = function(){
11345
11346                 var sidePaneRows = this.sidePaneRows;
11347
11348                 if(sidePaneRows){
11349                         for(var index in sidePaneRows){
11350                                 var paneId = sidePaneRows[index].paneId;
11351                                 var drillDownTo = sidePaneRows[index].drillDownTo; 
11352
11353                                 this.drillDownToMapper[paneId] = drillDownTo;
11354
11355                                 if(index == 0){
11356                                         this.currentSelectedRowPaneId = paneId;
11357                                         this.sidePaneTracker[paneId] = [];
11358                                 }
11359                         }
11360                 }
11361                 
11362                 
11363         }
11364
11365         this.getSidePanesList = function(){
11366                 return this.sidePaneTracker[this.currentSelectedRowPaneId];
11367         };
11368
11369         this.addToSidePanesList = function(newPaneId){
11370                 if(this.sidePaneTracker[this.currentSelectedRowPaneId] == undefined)
11371                         this.sidePaneTracker[this.currentSelectedRowPaneId] = [];
11372                 else{
11373                         if(newPaneId)
11374                                 this.sidePaneTracker[this.currentSelectedRowPaneId].push(newPaneId);
11375                 }
11376         };
11377
11378         this.setWidth = function(val){
11379                 if(val)
11380                         this.currentWidth = val;
11381                 animation.set($element,{width:this.currentWidth});
11382         };
11383
11384         this.resizeWidth = function(val){
11385                 if(val)
11386                         this.currentWidth = val;
11387                 animation.to($element,.5,{width:val});
11388         };
11389
11390 }])
11391 .directive('sidePane', ['paneGroupConstants', function(paneGroupConstants){
11392         return {
11393                 restrict: 'EA',
11394                 transclude: true,
11395                 replace: true,
11396                 templateUrl: 'app/scripts/ng_js_att_tpls/paneSelector/sidePane.html',
11397                 require: ['^paneGroup', 'sidePane'],
11398                 controller: 'SidePaneCtrl',
11399                 scope:{},
11400                 link: function(scope,element,attr, ctrls){
11401                         var paneGroupCtrl = ctrls[0];
11402                         var sidePaneCtrl = ctrls[1];
11403                         paneGroupCtrl.addPaneCtrl(paneGroupConstants.SIDE_PANE_ID, sidePaneCtrl);
11404                 }
11405         }
11406 }])
11407 .directive('drillDownRow', ['$parse', 'paneGroupConstants',function($parse,paneGroupConstants){
11408         return {
11409                 restrict: 'A',
11410                 replace:true,
11411                 require: ['^innerPane','^paneGroup'],
11412                 link: function(scope,element,attr,ctrls){
11413                         var innerPaneCtrl = ctrls[0];
11414                         var paneGroupCtrl = ctrls[1];
11415                         var sidePaneCtrl = ctrls[2];
11416
11417                         element.on('click', function(evnt){
11418                                 var drillDownTo = innerPaneCtrl.drillDownTo;
11419
11420                                 if(innerPaneCtrl.drillDownTo != paneGroupConstants.NO_DRILL_DOWN)
11421                                         paneGroupCtrl.slideOutPane(drillDownTo);
11422                         });
11423                 }
11424         }
11425 }])
11426 .controller('InnerPaneCtrl', ['$scope', '$element','animation', 'paneGroupConstants',
11427         function($scope,$element,animation,paneGroupConstants){
11428
11429         this.paneId = $scope.paneId;
11430         this.drillDownTo;
11431         this.currentWidth = paneGroupConstants.INNER_PANE_DEFAULT;
11432
11433         this.setWidth = function(val){
11434                 if(val)
11435                         this.currentWidth = val;
11436                 animation.set($element,{width:this.currentWidth});
11437         };
11438
11439         this.resizeWidth = function(val,callback){
11440                 animation.to($element,.25,{width:val,onComplete: callback});
11441         };
11442
11443         this.displayNone = function(){
11444                 animation.set($element, {display:'none'});
11445         };
11446
11447         this.displayBlock = function(){
11448                 animation.set($element,{display:'block'});
11449                 if(this)
11450                         this.hideRightBorder();
11451         };
11452
11453         this.floatLeft = function(){
11454                 animation.set($element,{float:'left'});
11455         };
11456
11457         this.hideLeftBorder = function(){
11458                 animation.set($element, {borderLeftWidth: '0px'});
11459         };
11460
11461         this.showLeftBorder = function(){
11462                 animation.set($element,{borderLeftWidth: '1px'});
11463         };
11464
11465         this.hideRightBorder = function(){
11466                 animation.set($element,{borderRightWidth: '0px'});
11467         };
11468
11469         this.showRightBorder = function(){
11470                 animation.set($element, {borderRightWidth: '1px'});
11471         };
11472
11473         this.slideFromRight = function(){
11474                 animation.set($element, {float:'right'});
11475                 animation.set($element, {width: this.currentWidth});
11476         };      
11477
11478         this.startOpen = function(){
11479                 return $scope.startOpen;
11480         };
11481
11482 }])
11483 .directive('innerPane', function(){
11484         return {
11485                 restrict: 'EA',
11486                 replace: true,
11487                 transclude: true,
11488                 templateUrl: 'app/scripts/ng_js_att_tpls/paneSelector/innerPane.html',
11489                 require: ['^paneGroup', 'innerPane'],
11490                 controller: 'InnerPaneCtrl',
11491                 scope:{
11492                         paneId:'@'
11493                 },
11494                 link: function(scope,element,attr,ctrls){
11495
11496                         if(attr.startOpen == ""){
11497                                 scope.startOpen  = true;
11498                         }
11499
11500                         var paneGroupCtrl = ctrls[0];
11501                         var innerPaneCtrl = ctrls[1];
11502                         paneGroupCtrl.addPaneCtrl(scope.paneId,innerPaneCtrl);
11503                 }
11504         }
11505 })
11506 .controller('PaneGroupCtrl', ['$scope', '$element', 'paneGroupConstants', '$timeout',function($scope,$element,paneGroupConstants,$timeout){
11507         
11508         this.panes = {};
11509         this.accountLevelPaneModel = [];
11510
11511         this.title = $scope.title;
11512
11513         this.init = function(){
11514                 var sidePane = this.panes[paneGroupConstants.SIDE_PANE_ID];
11515
11516                 if(sidePane){
11517
11518                         sidePane.init();
11519
11520                         //Show the other panes that may be set to startOpen
11521                         //numOpen starts at 1 because of the side pane
11522                         var numOpen = 1;
11523                         for(var key in this.panes){
11524                                 if(this.panes[key].startOpen && this.panes[key].startOpen())
11525                                         numOpen++;
11526                         }
11527                         var width;
11528                         if(numOpen >= 3){
11529                                 width = ((100/numOpen)) + '%';
11530                         }
11531
11532                         
11533                         if(this.panes[sidePane.currentSelectedRowPaneId])
11534                         {
11535                                 if(width){
11536                                         sidePane.setWidth(width);
11537                                         this.panes[sidePane.currentSelectedRowPaneId].setWidth(width);
11538                                 }
11539                                 else{
11540                                         sidePane.setWidth();
11541                                         this.panes[sidePane.currentSelectedRowPaneId].setWidth();
11542                                 }
11543                                 
11544                                 this.panes[sidePane.currentSelectedRowPaneId].displayBlock();
11545
11546                                 for(var key in this.panes){
11547                                         if(key != paneGroupConstants.SIDE_PANE_ID && key != sidePane.currentSelectedRowPaneId)
11548                                                         this.panes[key].displayNone();
11549                                                 
11550                                         this.panes[key].drillDownTo = sidePane.drillDownToMapper[key]; 
11551                                 }
11552                         }
11553                                 
11554                         openOtherPanesOnStart(sidePane, this.panes);
11555                         
11556                 }
11557
11558                 function openOtherPanesOnStart(sidePane, panes){
11559                         //Build an array of the panes that need to be out
11560                         var otherPanesStartOpened = [];
11561                         for(var index in sidePane.sidePaneRows){
11562                                 var pane = sidePane.sidePaneRows[index];
11563
11564                                 //Skip the first pane row since we handled it in the begining
11565                                 if(index > 0 && panes[pane.paneId].startOpen && panes[pane.paneId].startOpen()){
11566                                         otherPanesStartOpened.push(pane);
11567                                         //Remember the panes that are opened for the first pane row Index
11568                                         sidePane.addToSidePanesList(pane.paneId);
11569                                 }
11570                                 
11571                         }
11572
11573                         if(width){
11574                                 for(var index in otherPanesStartOpened){
11575                                         var paneId = otherPanesStartOpened[index].paneId;
11576                                         var paneCtrl = panes[paneId];
11577
11578                                         if(paneCtrl && paneCtrl.setWidth && paneCtrl.displayBlock){
11579                                                 paneCtrl.setWidth(width);
11580                                                 paneCtrl.displayBlock();
11581                                         }
11582
11583                                 }
11584                         }
11585
11586                 }
11587         }
11588
11589         /*
11590           Resets all the panels to their original positions at the end of a sidebar click
11591           By setting the sideBar to its default width
11592           Setting all panes to float left and displaynone
11593           Setting the pane that was clicked to default width and slide right
11594         */
11595
11596         this.resetPanes = function(){
11597                 for(var key in this.panes){
11598                         var pane = this.panes[key];
11599                         if(pane && (pane.paneId != paneGroupConstants.SIDE_PANE_ID)){
11600                                 pane.floatLeft();
11601                                 pane.displayNone();
11602                         }
11603                 }
11604
11605                 if(this.panes[paneGroupConstants.SIDE_PANE_ID])
11606                         this.panes[paneGroupConstants.SIDE_PANE_ID].setWidth(paneGroupConstants.SIDE_WIDTH_DEFAULT);
11607         };
11608
11609         this.addPaneCtrl = function(paneId,paneCtrl){
11610                 this.panes[paneId] = paneCtrl;
11611         };
11612
11613         this._slideOutPane = function(paneId,isFromSidePane){
11614
11615                 this.resetPanes();
11616                 //Check current side pane stack to see how many panes are already open for that side pane choice
11617                 //then add the new pane that needs to be there 
11618                 if(isFromSidePane){
11619
11620                         //Check if the side pane id has already been clicked
11621                         var panesList; 
11622
11623
11624                         if(this.panes[paneGroupConstants.SIDE_PANE_ID])
11625                                         panesList = this.panes[paneGroupConstants.SIDE_PANE_ID].getSidePanesList();
11626
11627                         if(!panesList){
11628
11629                                 if(this.panes && this.panes[paneGroupConstants.SIDE_PANE_ID] && this.panes[paneId]){
11630                                         this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId = paneId;
11631                                         this.panes[paneGroupConstants.SIDE_PANE_ID].addToSidePanesList();
11632
11633                                         this.panes[paneId].slideFromRight();
11634                                         this.panes[paneId].displayBlock();
11635
11636                                         this.panes[paneId].setWidth(paneGroupConstants.INNER_PANE_DEFAULT);
11637                                 }       
11638
11639                         }else{
11640                                 //Restore the panes based on the panelist
11641                                 if(panesList.length == 0){
11642                                         //Only one pane is out
11643
11644                                         if(this.panes && this.panes[paneGroupConstants.SIDE_PANE_ID] && this.panes[paneId]){
11645                                                 this.panes[paneGroupConstants.SIDE_PANE_ID].setWidth(paneGroupConstants.SIDE_WIDTH_DEFAULT);
11646                                                 this.panes[paneId].displayBlock();
11647                                                 this.panes[paneId].setWidth(paneGroupConstants.INNER_PANE_DEFAULT);
11648                                         }
11649                                         
11650                                 }else{
11651
11652                                         if(this.panes && this.panes[paneGroupConstants.SIDE_PANE_ID]){
11653                                                 //Multiple panes out
11654                                                 var numPanes = panesList.length + 2;
11655                                                 var width = ((100/numPanes)) + '%';
11656                                                 this.panes[paneGroupConstants.SIDE_PANE_ID].setWidth(width);
11657
11658                                                 //Set the sidePanes pane
11659                                                 //set the panes children list
11660                                                 if(this.panes && this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId]){
11661                                                         this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId].displayBlock();
11662                                                         this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId].setWidth(width);
11663                                                 }
11664                                                 
11665                                                 for(var i in panesList){
11666                                                         if(this.panes[panesList[i]]){
11667                                                                 this.panes[panesList[i]].displayBlock();
11668                                                                 this.panes[panesList[i]].setWidth(width);
11669                                                         }
11670                                                 }
11671                                         }
11672                                         
11673                                 }
11674                         }
11675
11676                 }
11677                 else{
11678
11679                         //Have to check the paneId that was given and where it is drilling down to
11680                         var isPaneInStack = false;
11681
11682                         var stackPaneList
11683
11684                         if(this.panes[paneGroupConstants.SIDE_PANE_ID])
11685                                 stackPaneList = this.panes[paneGroupConstants.SIDE_PANE_ID].getSidePanesList();
11686
11687                         for(var i in stackPaneList){
11688                                 var pId = stackPaneList[i];
11689                                 if(pId == paneId){
11690                                         isPaneInStack = true;
11691                                         break;
11692                                 }
11693                         }
11694
11695                         if(!isPaneInStack){
11696                                 if(this.panes[paneGroupConstants.SIDE_PANE_ID])
11697                                                 this.panes[paneGroupConstants.SIDE_PANE_ID].addToSidePanesList(paneId);
11698                         }
11699
11700                         var sidePanesListLength;
11701
11702                         if(this.panes[paneGroupConstants.SIDE_PANE_ID])
11703                                 sidePanesListLength = this.panes[paneGroupConstants.SIDE_PANE_ID].getSidePanesList().length;
11704                         
11705                         var numPanes = sidePanesListLength + 2;
11706                         var width = ((100/numPanes)) + '%';
11707                         
11708                         if(this.panes[paneGroupConstants.SIDE_PANE_ID])
11709                                 this.panes[paneGroupConstants.SIDE_PANE_ID].setWidth(width);
11710                         
11711                         var slideInPaneId;
11712
11713                         if(this.panes[paneGroupConstants.SIDE_PANE_ID])
11714                                 slideInPaneId = this.panes[paneGroupConstants.SIDE_PANE_ID].getSidePanesList()[sidePanesListLength - 1];
11715
11716                         var that = this;
11717
11718                         var panesList;
11719
11720                         if(that.panes[paneGroupConstants.SIDE_PANE_ID])
11721                                 panesList = that.panes[paneGroupConstants.SIDE_PANE_ID].getSidePanesList();
11722                         
11723                         for(var p in panesList){
11724                                 var paneId = panesList[p];
11725                                 var pane = this.panes[paneId];
11726                                 if(paneId != slideInPaneId && pane){
11727                                         pane.setWidth(width);
11728                                         pane.displayBlock();
11729                                         pane.floatLeft();
11730                                 }
11731                         }
11732
11733                         if(this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId]){
11734                                 this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId].displayBlock();
11735                                 this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId].showRightBorder();
11736
11737                                 this.panes[this.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId].resizeWidth(width,function(){
11738
11739                                         if(that.panes[slideInPaneId] && that.panes[that.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId]){
11740                                                 that.panes[that.panes[paneGroupConstants.SIDE_PANE_ID].currentSelectedRowPaneId].hideRightBorder();
11741                                                 that.panes[slideInPaneId].setWidth(width);
11742                                                 that.panes[slideInPaneId].slideFromRight();
11743                                                 that.panes[slideInPaneId].displayBlock();
11744                                                 that.panes[slideInPaneId].floatLeft();
11745                                         }
11746
11747                                 });
11748                         }
11749                         
11750                 }
11751
11752         }
11753
11754         this.slideOutPane = function(paneId,isFromSidePane){
11755                 this._slideOutPane(paneId,isFromSidePane);
11756         };
11757
11758 }])
11759 .directive('paneGroup', ['$timeout',function($timeout){
11760         return {
11761                 restrict: 'EA',
11762                 transclude: true,
11763                 replace: true,
11764                 templateUrl: 'app/scripts/ng_js_att_tpls/paneSelector/paneGroup.html',
11765                 scope:{
11766                 },
11767                 controller: 'PaneGroupCtrl',
11768                 link: function(scope,element,attr,ctrl){        
11769
11770                         $timeout(initialize,100);
11771
11772                         function initialize(){
11773                                 ctrl.init();
11774                         }
11775
11776                 }
11777         }
11778 }]);
11779 angular.module('att.abs.profileCard', [])
11780            
11781             .constant('profileStatus',{
11782                 status:{
11783                     ACTIVE:{status:"Active",color:"green"},
11784                     DEACTIVATED:{status:"Deactivated",color:"red"},
11785                     LOCKED:{status:"Locked",color:"red"},
11786                     IDLE:{status:"Idle",color:"yellow"},
11787                     PENDING:{status:"Pending",color:"blue"}
11788                     },
11789                 role:"COMPANY ADMINISTRATOR"
11790                 })
11791            
11792             .directive('profileCard',['$http','$q','profileStatus', function($http,$q,profileStatus) {
11793                return  {  
11794                     restrict: 'EA',
11795                     replace:'true',
11796                     templateUrl:function(element, attrs) {
11797                         if(!attrs.addUser){
11798                             return 'app/scripts/ng_js_att_tpls/profileCard/profileCard.html';
11799                         }
11800                         else{
11801                             return 'app/scripts/ng_js_att_tpls/profileCard/addUser.html';
11802                         }
11803                     },
11804                     scope:{
11805                         profile:'='
11806                     },
11807                     link: function(scope, elem, attr){
11808
11809                         scope.image=true;
11810                         function isImage(src) {
11811                            
11812                             var deferred = $q.defer();
11813
11814                             var image = new Image();
11815                             image.onerror = function() {
11816                                 deferred.reject(false);
11817                             };
11818                             image.onload = function() {
11819                                 deferred.resolve(true);
11820                             };
11821                             
11822                             if(src!==undefined && src.length>0 ){
11823                                 image.src = src;                                
11824                             }else{
11825                                  deferred.reject(false);
11826                             }
11827
11828                             return deferred.promise;
11829                         }
11830                         if(!attr.addUser){
11831                         scope.image=false;
11832                         isImage(scope.profile.img).then(function(img) {
11833                             console.log(img);
11834                                 scope.image=img;
11835                         });
11836                        var splitName=(scope.profile.name).split(' ');
11837                                                 scope.initials='';
11838                                                 for(var i=0;i<splitName.length;i++){
11839                                                         scope.initials += splitName[i][0];
11840                                                 }
11841                         if(scope.profile.role.toUpperCase()===profileStatus.role){
11842                             scope.badge=true;
11843                         }
11844                         var profileState=profileStatus.status[scope.profile.state.toUpperCase()];
11845                         if(profileState) {
11846                             scope.profile.state=profileStatus.status[scope.profile.state.toUpperCase()].status;
11847                             scope.colorIcon=profileStatus.status[scope.profile.state.toUpperCase()].color;
11848                             if(scope.profile.state.toUpperCase()===profileStatus.status.PENDING.status.toUpperCase()||scope.profile.state.toUpperCase()===profileStatus.status.LOCKED.status.toUpperCase())
11849                                 if(scope.profile.state.toUpperCase()===profileStatus.status.LOCKED.status.toUpperCase()){
11850                                     scope.profile.lastLogin=scope.profile.state;
11851                                 }
11852                                 else{
11853                                     scope.profile.lastLogin=scope.profile.state;
11854                                 }
11855                         }
11856                         var today=new Date().getTime();
11857                         var lastlogin=new Date(scope.profile.lastLogin).getTime();
11858                         var diff=(today-lastlogin)/(1000*60*60*24);
11859                         if(diff<=1){
11860                             scope.profile.lastLogin="Today";
11861                         }
11862                         else if(diff<=2){
11863                             scope.profile.lastLogin="Yesterday";
11864                         }
11865                         } 
11866                      }                     
11867                 };              
11868             }]);
11869 angular.module('att.abs.progressBars', [])
11870
11871 .directive('attProgressBar', [ function() {
11872     return {
11873         restrict: 'A',
11874         replace: true,              
11875         templateUrl : 'app/scripts/ng_js_att_tpls/progressBars/progressBars.html'
11876     };
11877 }]);
11878 angular.module('att.abs.radio', [])
11879     .constant('attRadioConfig', {
11880         activeClass : "att-radio--on",
11881         disabledClass : "att-radio--disabled"
11882     })
11883 .directive('attRadio', ['$compile','attRadioConfig', function ($compile, attRadioConfig) {
11884     return {
11885         scope: {},
11886         restrict: 'A',
11887         require: 'ngModel',
11888         link: function (scope, element, attr, ctrl) {
11889             var ngCtrl = ctrl;
11890             var parentDiv = $compile('<div tabindex="0" role="radio" att-accessibility-click="13,32" ng-click="updateModel($event)" class="att-radio"></div>')(scope);
11891
11892             element.wrap(parentDiv);
11893             element.parent().append('<div class="att-radio__indicator"></div>');
11894             element.parent().attr("title", attr.title);
11895             element.attr("tabindex","-1");
11896
11897             ngCtrl.$render = function () {
11898                 var selected = angular.equals(ngCtrl.$modelValue, attr.attRadio);
11899                 element.parent().toggleClass(attRadioConfig.activeClass, selected);
11900                 element.parent().attr("aria-checked", selected)
11901             };
11902
11903             scope.updateModel = function (evt) {
11904                 var isActive = element.parent().hasClass(attRadioConfig.activeClass);
11905
11906                 if (!isActive && !scope.disabled) {
11907                     ngCtrl.$setViewValue(isActive ? null : attr.attRadio);
11908                     ngCtrl.$render();
11909                 }
11910                 evt.preventDefault();
11911             };
11912
11913             attr.$observe('disabled', function (val) {
11914                 scope.disabled = (val === true || val === "disabled" || val === "true");
11915                 element.parent().toggleClass(attRadioConfig.disabledClass, scope.disabled);
11916                 element.parent().attr("tabindex", scope.disabled ? "-1" : "0");
11917             });
11918         }
11919     };
11920 }]);
11921
11922 angular.module('att.abs.scrollbar', [])
11923     .directive('attScrollbar', ['$window', '$timeout', '$parse', '$animate', function ($window, $timeout, $parse, $animate) {
11924     return {
11925         restrict: 'A',
11926         transclude: true,
11927         templateUrl: 'app/scripts/ng_js_att_tpls/scrollbar/scrollbar.html',
11928         controller: ['$scope','$element','$attrs', function($scope, $element, $attrs)  {
11929             var defaults = {
11930                 axis: 'y', // Vertical or horizontal scrollbar? ( x || y ).
11931                 wheel: true, // Enable or disable the mousewheel;
11932                 wheelSpeed: 40, // How many pixels must the mouswheel scroll at a time.
11933                 wheelLock: true, // Lock default scrolling window when there is no more content.
11934                 scrollInvert: false, // Enable invert style scrolling
11935                 trackSize: false, // Set the size of the scrollbar to auto or a fixed number.
11936                 thumbSize: false, // Set the size of the thumb to auto or a fixed number.
11937                 alwaysVisible: true // Set to false to hide the scrollbar if not being used
11938             };
11939             var options = $attrs.scrollbar;
11940             if (options) {
11941                 options = $parse(options)($scope);
11942             } else {
11943                 options = {};
11944             }
11945             this.options = angular.extend({}, defaults, options);
11946             this._defaults = defaults;
11947
11948             var self = this,
11949                     $body = angular.element(document.querySelectorAll('body')[0]),
11950                     $document = angular.element(document),
11951                     $viewport = angular.element($element[0].querySelectorAll('.scroll-viewport')[0]),
11952                     $overview = angular.element($element[0].querySelectorAll('.scroll-overview')[0]),
11953                     $scrollbar = angular.element($element[0].querySelectorAll('.scroll-bar')[0]),
11954                     $thumb = angular.element($element[0].querySelectorAll('.scroll-thumb')[0]),
11955                     mousePosition = 0,
11956                     isHorizontal = this.options.axis === 'x',
11957                     hasTouchEvents=false,
11958                     wheelEvent = ("onwheel" in document ? "wheel" : // Modern browsers support "wheel"
11959                             document.onmousewheel !== undefined ? "mousewheel" : // Webkit and IE support at least "mousewheel"
11960                             "DOMMouseScroll"), // let's assume that remaining browsers are older Firefox
11961                     sizeLabel = isHorizontal ? 'width' : 'height',
11962                     sizeLabelCap = sizeLabel.charAt(0).toUpperCase() + sizeLabel.slice(1).toLowerCase(),
11963                     posiLabel = isHorizontal ? 'left' : 'top',
11964                     // moveEvent = document.createEvent('HTMLEvents'),
11965                     restoreVisibilityAfterWheel,
11966                     thumbscrolltouch=false,documnetscrolltouch=false;
11967                 if(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
11968                     hasTouchEvents = true;
11969                 }
11970
11971             //moveEvent.initEvent('move', true, true);
11972             this.contentPosition = 0;
11973             this.viewportSize = 0;
11974             this.contentSize = 0;
11975             this.contentRatio = 0;
11976             this.trackSize = 0;
11977             this.trackRatio = 0;
11978             this.thumbSize = 0;
11979             this.thumbPosition = 0;
11980
11981             this.initialize = function() {
11982                 if (!this.options.alwaysVisible) {
11983                     $scrollbar.css('opacity', 0);
11984                 }
11985                 self.update();
11986                 setEvents();
11987                 return self;
11988             };
11989
11990             this.update = function(scrollTo) {
11991                 this.viewportSize = $viewport.prop('offset' + sizeLabelCap) || 1;
11992                 this.contentSize = $overview.prop('scroll' + sizeLabelCap) || 1;
11993                 this.contentRatio = this.viewportSize / this.contentSize;
11994                 this.trackSize = this.options.trackSize || this.viewportSize;
11995                 this.thumbSize = Math.min(this.trackSize, Math.max(0, (this.options.thumbSize || (this.trackSize * this.contentRatio))));
11996                 this.trackRatio = this.options.thumbSize ? (this.contentSize - this.viewportSize) / (this.trackSize - this.thumbSize) : (this.contentSize / this.trackSize);
11997                 mousePosition = $scrollbar.prop('offsetTop');
11998
11999                 $scrollbar.toggleClass('disable', this.contentRatio >= 1 || isNaN(this.contentRatio));
12000
12001                 if (!this.options.alwaysVisible && this.contentRatio < 1 && this.viewportSize > 0) {
12002                     //flash the scrollbar when update happens
12003                     $animate.addClass($scrollbar, 'visible').then(function() {
12004                         $animate.removeClass($scrollbar, 'visible');
12005                         $scope.$digest();
12006                     });
12007                 }
12008
12009                 if (scrollTo !== null) {
12010                     switch (scrollTo) {
12011                         case 'bottom':
12012                             this.contentPosition = this.contentSize - this.viewportSize;
12013                             break;
12014                         default:
12015                             this.contentPosition = parseInt(scrollTo, 10) || 0;
12016                     }
12017                 }
12018
12019                 ensureContentPosition();
12020                 $thumb.css(posiLabel, self.contentPosition / self.trackRatio + 'px');
12021                 $scrollbar.css(sizeLabel, self.trackSize + 'px');
12022                 $thumb.css(sizeLabel, self.thumbSize + 'px');
12023                 $overview.css(posiLabel, -self.contentPosition + 'px');
12024
12025                 return this;
12026             };
12027             fireEvent = function(obj, evt) {
12028                 var fireOnThis = obj;
12029                 if (document.createEvent) {
12030                     // alert("FF");
12031                     var evtObj = document.createEvent('HTMLEvents');
12032                     evtObj.initEvent(evt, true, false);
12033                     fireOnThis.dispatchEvent(evtObj);
12034                 }
12035                 else if (document.createEventObject) {
12036                     // alert("IE8");
12037                     var evtObj = document.createEventObject();
12038                     fireOnThis.fireEvent('on' + evt, evtObj);
12039                 }
12040             };
12041             function ensureContentPosition() {
12042                 // if scrollbar is on, ensure the bottom of the content does not go above the bottom of the viewport
12043                 if (self.contentRatio <= 1 && self.contentPosition > self.contentSize - self.viewportSize) {
12044                     self.contentPosition = self.contentSize - self.viewportSize;
12045                 }
12046                 // if scrollbar is off, ensure the top of the content does not go below the top of the viewport
12047                 else if (self.contentRatio > 1 && self.contentPosition > 0) {
12048                     self.contentPosition = 0;
12049                 }
12050             }
12051
12052             function setEvents() {
12053
12054                 if (hasTouchEvents) {
12055                     $viewport.on('touchstart', touchstart);
12056                                         $thumb.on('touchstart', touchstart);
12057                 }
12058                 else {
12059                     $thumb.on('mousedown', start);
12060                     $scrollbar.on('mousedown', drag);
12061                 }
12062
12063                 angular.element($window).on('resize', resize);
12064
12065                 if (self.options.wheel) {
12066                     $element.on(wheelEvent, wheel);
12067                 }
12068             }
12069
12070             function resize() {
12071                 self.update();
12072             }
12073
12074             function touchstart(event) {
12075                 if (1 === event.touches.length) {
12076                     event.stopPropagation();
12077                     start(event.touches[0]);
12078                 }
12079             }
12080
12081             function start(event) {
12082                 $body.addClass('scroll-no-select');
12083                 $element.addClass('scroll-no-select');
12084
12085                 if (!self.options.alwaysVisible) {
12086                     $scrollbar.addClass('visible');
12087                 }
12088                 mousePosition = isHorizontal ? event.clientX : event.clientY;
12089                 self.thumbPosition = parseInt($thumb.css(posiLabel), 10) || 0;
12090
12091                 if (hasTouchEvents) {
12092                                         documnetscrolltouch=false;
12093                     thumbscrolltouch=false;
12094                                         $viewport.on('touchmove', touchdrag);
12095                     $viewport.on('touchend', end);
12096                                         $thumb.on('touchmove',touchdragthumb);
12097                     $thumb.on('touchend', end);
12098                 } else {
12099                     $document.on('mousemove', drag);
12100                     $document.on('mouseup', end);
12101                     $thumb.on('mouseup', end);
12102                 }
12103             }
12104
12105             function wheel(event) {
12106
12107                 if (self.contentRatio >= 1) {
12108                     return;
12109                 }
12110
12111                 if (!self.options.alwaysVisible) {
12112                     //cancel removing visibility if wheel event is triggered before the timeout
12113                     if (restoreVisibilityAfterWheel) {
12114                         $timeout.cancel(restoreVisibilityAfterWheel);
12115                     }
12116                     $scrollbar.addClass('visible');
12117
12118                     restoreVisibilityAfterWheel = $timeout(function() {
12119                         $scrollbar.removeClass('visible');
12120                     }, 100);
12121                 }
12122
12123
12124                 var evntObj = (event && event.originalEvent) || event || $window.event,
12125                         deltaDir = self.options.axis.toUpperCase(),
12126                         delta = {
12127                             X: evntObj.deltaX,
12128                             Y: evntObj.deltaY
12129                         },
12130                 wheelSpeed = evntObj.deltaMode === 0 ? self.options.wheelSpeed : 1;
12131
12132                 if (self.options.scrollInvert) {
12133                     wheelSpeed *= -1;
12134                 }
12135
12136                 if (wheelEvent === 'mousewheel') {
12137                     delta.Y = -1 * evntObj.wheelDelta / 40;
12138                     evntObj.wheelDeltaX && (delta.X = -1 * evntObj.wheelDeltaX / 40);
12139                 }
12140                 delta.X *= -1 / wheelSpeed;
12141                 delta.Y *= -1 / wheelSpeed;
12142
12143                 var wheelSpeedDelta = delta[deltaDir];
12144
12145                 self.contentPosition -= wheelSpeedDelta * self.options.wheelSpeed;
12146                 self.contentPosition = Math.min((self.contentSize - self.viewportSize), Math.max(0, self.contentPosition));
12147
12148
12149                 //$element[0].dispatchEvent(moveEvent);
12150                 fireEvent($element[0], 'move');
12151
12152                 ensureContentPosition();
12153                 $thumb.css(posiLabel, self.contentPosition / self.trackRatio + 'px');
12154                 $overview.css(posiLabel, -self.contentPosition + 'px');
12155
12156                 if (self.options.wheelLock || (self.contentPosition !== (self.contentSize - self.viewportSize) && self.contentPosition !== 0)) {
12157                     evntObj.preventDefault();
12158                 }
12159             }
12160
12161             function touchdrag(event) {
12162                 event.preventDefault();
12163                                 documnetscrolltouch=true;
12164                 drag(event.touches[0]);
12165             }
12166                         function touchdragthumb(event){
12167                 event.preventDefault();
12168                 thumbscrolltouch=true;
12169                 drag(event.touches[0]);         
12170             }
12171
12172             function drag(event) {
12173
12174                 if (self.contentRatio >= 1) {
12175                     return;
12176                 }
12177                 var mousePositionNew = isHorizontal ? event.clientX : event.clientY,
12178                         thumbPositionDelta = mousePositionNew - mousePosition;
12179
12180                 if ((self.options.scrollInvert && !hasTouchEvents) ||
12181                         (hasTouchEvents && !self.options.scrollInvert))
12182                 {
12183                     thumbPositionDelta = mousePosition - mousePositionNew;
12184                 }
12185                                 if(documnetscrolltouch && hasTouchEvents){
12186                         thumbPositionDelta = mousePosition - mousePositionNew;
12187                 }
12188                 if(thumbscrolltouch && hasTouchEvents){
12189                     thumbPositionDelta = mousePositionNew - mousePosition;
12190                 }
12191                 var thumbPositionNew = Math.min((self.trackSize - self.thumbSize), Math.max(0, self.thumbPosition + thumbPositionDelta));
12192                 self.contentPosition = thumbPositionNew * self.trackRatio;
12193
12194
12195                 // $element[0].dispatchEvent(moveEvent);
12196                 fireEvent($element[0], 'move');
12197
12198                 ensureContentPosition();
12199                 $thumb.css(posiLabel, thumbPositionNew + 'px');
12200                 $overview.css(posiLabel, -self.contentPosition + 'px');
12201             }
12202
12203             function end() {
12204
12205                 $body.removeClass('scroll-no-select');
12206                 $element.removeClass('scroll-no-select');
12207                 if (!self.options.alwaysVisible) {
12208                     $scrollbar.removeClass('visible');
12209                 }
12210                 $document.off('mousemove', drag);
12211                 $document.off('mouseup', end);
12212                 $thumb.off('mouseup', end);
12213                 $document.off('touchmove', touchdrag);
12214                 $document.off('ontouchend', end);
12215                                 $thumb.off('touchmove',touchdragthumb);
12216                 $thumb.off('touchend', end);
12217             }
12218             this.cleanup = function() {
12219                 $viewport.off('touchstart', touchstart);
12220                 $thumb.off('mousedown', start);
12221                 $scrollbar.off('mousedown', drag);
12222                                 $thumb.off('touchmove',touchdragthumb);
12223                 $thumb.off('touchend', end);
12224                 angular.element($window).off('resize', resize);
12225                 $element.off(wheelEvent, wheel);
12226                 //ensure scrollbar isn't activated
12227                 self.options.alwaysVisible = true;
12228                 end();
12229             };
12230
12231         }],
12232         link: function(scope, iElement, iAttrs, controller) {
12233             var position = iElement.css('position');
12234             if (position !== 'relative' && position !== 'absolute') {
12235                 iElement.css('position', 'relative');
12236             }
12237             scope.$watch(function() {
12238                 $timeout(function() {
12239                     var $overview = angular.element(iElement[0].querySelectorAll('.scroll-overview')[0]);
12240                     var newValue = $overview.prop('scrollHeight');
12241                     var oldValue = scope.oldValue;
12242                     if (newValue !== oldValue) {
12243                         scope.oldValue = newValue;
12244                         controller.update();
12245                     }
12246                 }, 100, false);
12247             });
12248             controller.initialize();
12249             iElement.on('$destroy', function() {
12250                 controller.cleanup();
12251             });
12252         }
12253     };
12254 }]);
12255 (function(){    
12256 var KEY = {
12257     TAB: 9,
12258     ENTER: 13,
12259     ESC: 27,
12260     SPACE: 32,
12261     LEFT: 37,
12262     UP: 38,
12263     RIGHT: 39,
12264     DOWN: 40,
12265     SHIFT: 16,
12266     CTRL: 17,
12267     ALT: 18,
12268     PAGE_UP: 33,
12269     PAGE_DOWN: 34,
12270     HOME: 36,
12271     END: 35,
12272     BACKSPACE: 8,
12273     DELETE: 46,
12274     COMMAND: 91,
12275
12276     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 : "'"
12277     },
12278
12279     isControl: function (e) {
12280         var k = e.keyCode;
12281         switch (k) {
12282         case KEY.COMMAND:
12283         case KEY.SHIFT:
12284         case KEY.CTRL:
12285         case KEY.ALT:
12286             return true;
12287         }
12288
12289         if (e.metaKey) return true;
12290
12291         return false;
12292     },
12293     isFunctionKey: function (k) {
12294         k = k.keyCode ? k.keyCode : k;
12295         return k >= 112 && k <= 123;
12296     },
12297     isVerticalMovement: function (k){
12298       return ~[KEY.UP, KEY.DOWN].indexOf(k);
12299     },
12300     isHorizontalMovement: function (k){
12301       return ~[KEY.LEFT,KEY.RIGHT,KEY.BACKSPACE,KEY.DELETE].indexOf(k);
12302     }
12303  };    
12304
12305 angular.module('att.abs.search', ['att.abs.utilities', 'att.abs.position', 'att.abs.utilities'])
12306
12307 .directive('attSearch', ["$document", "$filter", "$isElement", '$documentBind', "$timeout", function($document,$filter,$isElement,$documentBind,$timeout){
12308     return{
12309         restrict: 'A',
12310         scope:{cName: '=attSearch'},
12311         transclude: false,
12312         replace: false,       
12313         require:'ngModel',
12314         templateUrl: 'app/scripts/ng_js_att_tpls/search/search.html',
12315         link: function(scope, element, attr, ctrl) {
12316             
12317             scope.selectedIndex = -1;
12318             scope.selectedOption = attr.placeholder;
12319             scope.isDisabled = false;
12320             scope.className = "select2-match";
12321             scope.showSearch = false;
12322             scope.showlist = false;
12323
12324             if(attr.placeholderAsOption === "false")
12325             {
12326                 scope.selectMsg = "";
12327             }
12328             else
12329             {
12330                 scope.selectMsg = attr.placeholder;
12331             }
12332
12333             if(attr.showInputFilter === "true"){scope.showSearch = true;}            
12334
12335             scope.showDropdown = function(){
12336                 if(!(attr.disabled)){
12337                     scope.showlist = !scope.showlist;
12338                     scope.setSelectTop();
12339                 }
12340             };
12341             
12342              element.bind("keydown", function(e){                     
12343                 if (e.keyCode === KEY.BACKSPACE || e.keyCode === KEY.SPACE || e.keyCode === KEY.ESC || e.keyCode === KEY.ENTER || KEY.isControl(e) || KEY.isVerticalMovement(e.keyCode) || KEY.isHorizontalMovement(e.keyCode) || KEY.isFunctionKey(e.keyCode)) 
12344                 {
12345                     e.preventDefault();
12346                     e.stopPropagation(); 
12347                     
12348                     switch (e.keyCode) {
12349                         case KEY.DOWN:
12350                             scope.selectNext();
12351                             break;
12352                         case KEY.UP:
12353                             scope.selectPrev();
12354                             break;
12355                         case KEY.ENTER:
12356                             scope.selectCurrent();
12357                             break;
12358                         case KEY.BACKSPACE:
12359                             scope.title = "";
12360                             scope.$apply();
12361                             break;    
12362                         case KEY.SPACE:
12363                             scope.title += " ";
12364                             scope.$apply();
12365                             break;                            
12366                         case KEY.ESC:
12367                             if(scope.title === "")
12368                             {
12369                                 scope.showlist = false;
12370                                 scope.$apply();
12371                             }
12372                             else
12373                             {
12374                                 scope.title = "";
12375                                 scope.$apply();
12376                             }
12377                             break;        
12378                     }                                        
12379                 }
12380                 else
12381                 {
12382                     if(scope.showSearch === false && e.keyCode !== 9)
12383                     { 
12384                         scope.showlist = true;
12385                         scope.title = scope.title ? scope.title + String.fromCharCode(e.keyCode):String.fromCharCode(e.keyCode);                            
12386                         scope.$apply();
12387                     }
12388                     else if(e.keyCode === 9)
12389                     {
12390                         scope.showlist = false;
12391                         scope.title = "";
12392                         scope.$apply();
12393                     }
12394                 }
12395             });
12396
12397             scope.selectOption = function(sTitle,sIndex,keepOpen)
12398             {
12399                 if(sIndex === -1 || sIndex === "-1"){
12400                    scope.selCategory = "";                   
12401                    scope.selectedIndex = -1;      
12402                    ctrl.$setViewValue("");
12403                    scope.selectedOption = scope.selectMsg;
12404                 }
12405                 else
12406                 {
12407                     scope.selCategory = scope.cName[sIndex];
12408                     scope.selectedIndex = sIndex; 
12409                     ctrl.$setViewValue(scope.selCategory);
12410                     scope.selectedOption = scope.selCategory.title;
12411                 }                                
12412                 scope.title = "";
12413                 if(!keepOpen)
12414                 {
12415                     scope.showlist = false;
12416                 }                
12417             };
12418
12419             if(attr.disabled)
12420             {
12421                scope.isDisabled = true;
12422             }
12423
12424             scope.selectCurrent = function()
12425             {   
12426                 if(scope.showlist === true)
12427                 {
12428                     scope.selectOption(scope.selectMsg,scope.selectedIndex ,false);
12429                     scope.$apply();
12430                 }
12431                 else
12432                 {
12433                     scope.showlist = true;
12434                     scope.setSelectTop();
12435                     scope.$apply();
12436                 }
12437             };
12438             
12439             scope.hoverIn = function(cItem)
12440             {
12441                 scope.selectedIndex = cItem;
12442             }; 
12443             
12444             scope.setSelectTop = function()
12445             {            
12446                 $timeout(function () 
12447                 {
12448                     if(scope.showlist ===true)
12449                     {
12450                         var containerUL = angular.element(element)[0].querySelector(".select2-results");
12451                         var selectedElemTopPos = angular.element(containerUL.querySelector('.select2-result-current'))[0].offsetTop;
12452                         angular.element(containerUL)[0].scrollTop = selectedElemTopPos;                          
12453                     }
12454                 });                        
12455             };
12456             
12457             
12458             scope.setCurrentTop = function()
12459             {            
12460                 $timeout(function () 
12461                 {
12462                     if(scope.showlist ===true)
12463                     {
12464                         var containerUL = angular.element(element)[0].querySelector(".select2-results");
12465                         var selectedElemTopPos = angular.element(containerUL.querySelector('.hovstyle'))[0].offsetTop;
12466                         //angular.element(containerUL)[0].scrollTop = selectedElemTopPos;
12467                         if(selectedElemTopPos < (angular.element(containerUL)[0].scrollTop) )
12468                         {
12469                             angular.element(containerUL)[0].scrollTop -= 30;
12470                         }
12471                         else if((selectedElemTopPos + 30) > (angular.element(containerUL)[0].clientHeight))
12472                         {
12473                             angular.element(containerUL)[0].scrollTop += 30;                          
12474                         }
12475                         
12476                     }
12477                 });                        
12478             }; 
12479             
12480             scope.selectNext = function()
12481             {                 
12482                 if((scope.selectedIndex + 1) <= (scope.cName.length-1))
12483                 {    
12484                     scope.selectedIndex += 1;
12485                     if(scope.showlist === false)
12486                     {
12487                         scope.selectOption(scope.selectMsg,scope.selectedIndex ,false);                    
12488                     }                    
12489                     scope.$apply();
12490                 }     
12491                 scope.setCurrentTop();
12492             };
12493
12494             scope.selectPrev = function()
12495             {
12496                 if((scope.selectedIndex - 1) >= 0)
12497                 {      
12498                     scope.selectedIndex -= 1;                    
12499                     if(scope.showlist === false)
12500                     {
12501                         scope.selectOption(scope.selectMsg,scope.selectedIndex ,false);                    
12502                     }                     
12503                     scope.$apply();
12504                 }                
12505                 else if(scope.selectedIndex -1 < 0)
12506                 {
12507                     scope.selectedIndex = -1;
12508                     if(scope.showlist === false)
12509                     {
12510                         scope.selectOption(scope.selectMsg,scope.selectedIndex ,false);                    
12511                     } 
12512                     scope.$apply();
12513                 }        
12514                 scope.setCurrentTop();
12515
12516             };
12517             
12518             scope.updateSelection = function(sItem)
12519             {
12520                 scope.selectedOption = sItem.title;
12521                 //scope.selectedIndex = -1;
12522                 scope.title = "";
12523             };
12524
12525             scope.$watch('selCategory',function(value)
12526             {
12527                 if(value){
12528                     scope.updateSelection(value);
12529                 };
12530             });
12531
12532             ctrl.$viewChangeListeners.push(function(){
12533                 scope.$eval(attr.ngChange);
12534             });
12535
12536             ctrl.$render = function(){
12537                 scope.selCategory = ctrl.$viewValue;
12538             };
12539
12540             var outsideClick = function(e){
12541                 var isElement = $isElement(angular.element(e.target), element, $document);
12542                 if(!isElement) {
12543                     scope.showlist = false;
12544                     scope.$apply(); 
12545                 }
12546             };
12547
12548             $documentBind.click('showlist', outsideClick, scope);
12549         }
12550     };
12551 }]);
12552 }());
12553
12554 (function(){
12555 var KEY = {
12556     TAB: 9,
12557     ENTER: 13,
12558     ESC: 27,
12559     SPACE: 32,
12560     LEFT: 37,
12561     UP: 38,
12562     RIGHT: 39,
12563     DOWN: 40,
12564     SHIFT: 16,
12565     CTRL: 17,
12566     ALT: 18,
12567     PAGE_UP: 33,
12568     PAGE_DOWN: 34,
12569     HOME: 36,
12570     END: 35,
12571     BACKSPACE: 8,
12572     DELETE: 46,
12573     COMMAND: 91,
12574
12575     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 : "'"
12576     },
12577
12578     isControl: function (e) {
12579         var k = e.keyCode;
12580         switch (k) {
12581         case KEY.COMMAND:
12582         case KEY.SHIFT:
12583         case KEY.CTRL:
12584         case KEY.ALT:
12585             return true;
12586         }
12587
12588         if (e.metaKey) return true;
12589
12590         return false;
12591     },
12592     isFunctionKey: function (k) {
12593         k = k.keyCode ? k.keyCode : k;
12594         return k >= 112 && k <= 123;
12595     },
12596     isVerticalMovement: function (k){
12597       return ~[KEY.UP, KEY.DOWN].indexOf(k);
12598     },
12599     isHorizontalMovement: function (k){
12600       return ~[KEY.LEFT,KEY.RIGHT,KEY.BACKSPACE,KEY.DELETE].indexOf(k);
12601     }
12602  };
12603
12604 angular.module('att.abs.select', ['att.abs.utilities', 'att.abs.position', 'att.abs.utilities'])
12605
12606 .filter('startsWith', function() {
12607     if (typeof String.prototype.startsWith != 'function') {
12608         // see below for better implementation!
12609         String.prototype.startsWith = function (str){
12610             return this.indexOf(str) === 0;
12611         };
12612     }
12613
12614     return function(items, searchString) {
12615         if (searchString === undefined || searchString === "") return items;
12616
12617         var filtered = [];
12618         angular.forEach(items, function(item) {
12619             if (item.title.toLowerCase().startsWith(searchString.toLowerCase())) {
12620                 filtered.push(item);
12621             }
12622         });
12623         return filtered;
12624     };
12625 })
12626
12627 .directive('attSelect', ["$document", "$filter", "$isElement", '$documentBind', "$timeout", function($document,$filter,$isElement,$documentBind,$timeout){
12628     return{
12629         restrict: 'A',
12630         scope:{cName: '=attSelect'},
12631         transclude: false,
12632         replace: false,
12633         require:'ngModel',
12634         templateUrl: 'app/scripts/ng_js_att_tpls/select/select.html',
12635         link: function(scope, element, attr, ctrl) {
12636
12637             scope.selectedIndex = -1;
12638             scope.selectedOption = attr.placeholder;
12639             scope.isDisabled = false;
12640             scope.className = "select2-match";
12641             scope.showSearch = false;
12642             scope.showlist = false;
12643
12644             if(attr.placeholderAsOption === "false")
12645             {
12646                 scope.selectMsg = "";
12647             }
12648             else
12649             {
12650                 scope.selectMsg = attr.placeholder;
12651             }
12652
12653             if (attr.startsWithFilter === "true" || attr.startsWithFilter === true) {
12654                 scope.startsWithFilter = true;
12655             }
12656
12657             if(attr.showInputFilter === "true"){scope.showSearch = true;}
12658
12659             scope.showDropdown = function(){
12660                 if(!(attr.disabled)){
12661                     scope.showlist = !scope.showlist;
12662                     scope.setSelectTop();
12663                 }
12664             };
12665
12666              element.bind("keydown", function(e){
12667                 if (e.keyCode === KEY.BACKSPACE || e.keyCode === KEY.SPACE || e.keyCode === KEY.ESC || e.keyCode === KEY.ENTER || KEY.isControl(e) || KEY.isVerticalMovement(e.keyCode) || KEY.isHorizontalMovement(e.keyCode) || KEY.isFunctionKey(e.keyCode))
12668                 {
12669                     e.preventDefault();
12670                     e.stopPropagation();
12671
12672                     switch (e.keyCode) {
12673                         case KEY.DOWN:
12674                             scope.selectNext();
12675                             break;
12676                         case KEY.UP:
12677                             scope.selectPrev();
12678                             break;
12679                         case KEY.ENTER:
12680                             scope.selectCurrent();
12681                             break;
12682                         case KEY.BACKSPACE:
12683                             scope.title = "";
12684                             scope.$apply();
12685                             break;
12686                         case KEY.SPACE:
12687                             scope.title += " ";
12688                             scope.$apply();
12689                             break;
12690                         case KEY.ESC:
12691                             if(scope.title === "")
12692                             {
12693                                 scope.showlist = false;
12694                                 scope.$apply();
12695                             }
12696                             else
12697                             {
12698                                 scope.title = "";
12699                                 scope.$apply();
12700                             }
12701                             break;
12702                     }
12703                 }
12704                 else
12705                 {
12706                     if(scope.showSearch === false && e.keyCode !== 9)
12707                     {
12708                         scope.showlist = true;
12709                         scope.title = scope.title ? scope.title + String.fromCharCode(e.keyCode):String.fromCharCode(e.keyCode);
12710                         scope.$apply();
12711                     }
12712                     else if(e.keyCode === 9)
12713                     {
12714                         scope.showlist = false;
12715                         scope.title = "";
12716                         scope.$apply();
12717                     }
12718                 }
12719             });
12720
12721             scope.selectOption = function(sTitle,sIndex,keepOpen)
12722             {
12723                 if(sIndex === -1 || sIndex === '-1'){
12724                    scope.selCategory = "";
12725                    scope.selectedIndex = -1;
12726                    ctrl.$setViewValue("");
12727                    scope.selectedOption = scope.selectMsg;
12728                 }
12729                 else
12730                 {
12731                     scope.selCategory = scope.cName[sIndex];
12732                     scope.selectedIndex = sIndex;
12733                     ctrl.$setViewValue(scope.selCategory);
12734                     scope.selectedOption = scope.selCategory.title;
12735                 }
12736                 scope.title = "";
12737                 if(!keepOpen)
12738                 {
12739                     scope.showlist = false;
12740                 }
12741             };
12742
12743             if(attr.disabled)
12744             {
12745                scope.isDisabled = true;
12746             }
12747
12748             scope.selectCurrent = function()
12749             {
12750                 if(scope.showlist === true)
12751                 {
12752                     scope.selectOption(scope.selectMsg,scope.selectedIndex ,false);
12753                     scope.$apply();
12754                 }
12755                 else
12756                 {
12757                     scope.showlist = true;
12758                     scope.setSelectTop();
12759                     scope.$apply();
12760                 }
12761             };
12762
12763             scope.hoverIn = function(cItem)
12764             {
12765                 scope.selectedIndex = cItem;
12766             };
12767
12768             scope.setSelectTop = function()
12769             {
12770                 $timeout(function ()
12771                 {
12772                     if(scope.showlist ===true)
12773                     {
12774                         var containerUL = angular.element(element)[0].querySelector(".select2-results");
12775                         var selectedElemTopPos = angular.element(containerUL.querySelector('.select2-result-current'))[0].offsetTop;
12776                         angular.element(containerUL)[0].scrollTop = selectedElemTopPos;
12777                     }
12778                 });
12779             };
12780
12781
12782             scope.setCurrentTop = function()
12783             {
12784                 $timeout(function ()
12785                 {
12786                     if(scope.showlist ===true)
12787                     {
12788                         var containerUL = angular.element(element)[0].querySelector(".select2-results");
12789                         var selectedElemTopPos = angular.element(containerUL.querySelector('.hovstyle'))[0].offsetTop;
12790                         //angular.element(containerUL)[0].scrollTop = selectedElemTopPos;
12791                         if(selectedElemTopPos < (angular.element(containerUL)[0].scrollTop) )
12792                         {
12793                             angular.element(containerUL)[0].scrollTop -= 30;
12794                         }
12795                         else if((selectedElemTopPos + 30) > (angular.element(containerUL)[0].clientHeight))
12796                         {
12797                             angular.element(containerUL)[0].scrollTop += 30;
12798                         }
12799
12800                     }
12801                 });
12802             };
12803
12804             scope.selectNext = function()
12805             {
12806                 if((scope.selectedIndex + 1) <= (scope.cName.length-1))
12807                 {
12808                     scope.selectedIndex += 1;
12809                     if(scope.showlist === false)
12810                     {
12811                         scope.selectOption(scope.selectMsg,scope.selectedIndex ,false);
12812                     }
12813                     scope.$apply();
12814                 }
12815                 scope.setCurrentTop();
12816             };
12817
12818             scope.selectPrev = function()
12819             {
12820                 if((scope.selectedIndex - 1) >= 0)
12821                 {
12822                     scope.selectedIndex -= 1;
12823                     if(scope.showlist === false)
12824                     {
12825                         scope.selectOption(scope.selectMsg,scope.selectedIndex ,false);
12826                     }
12827                     scope.$apply();
12828                 }
12829                 else if(scope.selectedIndex -1 < 0)
12830                 {
12831                     scope.selectedIndex = -1;
12832                     if(scope.showlist === false)
12833                     {
12834                         scope.selectOption(scope.selectMsg,scope.selectedIndex ,false);
12835                     }
12836                     scope.$apply();
12837                 }
12838                 scope.setCurrentTop();
12839
12840             };
12841
12842             scope.updateSelection = function(sItem)
12843             {
12844                 scope.selectedOption = sItem.title;
12845                 //scope.selectedIndex = -1;
12846                 scope.title = "";
12847             };
12848
12849             scope.$watch('selCategory',function(value)
12850             {
12851                 if(value){
12852                     scope.updateSelection(value);
12853                 };
12854             });
12855
12856             ctrl.$viewChangeListeners.push(function(){
12857                 scope.$eval(attr.ngChange);
12858             });
12859
12860             ctrl.$render = function(){
12861                 scope.selCategory = ctrl.$viewValue;
12862             };
12863
12864             var outsideClick = function(e){
12865                 var isElement = $isElement(angular.element(e.target), element, $document);
12866                 if(!isElement) {
12867                     scope.showlist = false;
12868                     scope.$apply();
12869                 }
12870             };
12871
12872             $documentBind.click('showlist', outsideClick, scope);
12873         }
12874     };
12875 }])
12876
12877 .directive('textDropdown', ['$document', '$isElement', '$documentBind', function($document,$isElement,$documentBind) {
12878     return {
12879         restrict: 'EA',
12880         replace: true,
12881         scope: {
12882             actions: '=actions',
12883             defaultAction: '=defaultAction',
12884             onActionClicked: '=?'
12885         },
12886         templateUrl : 'app/scripts/ng_js_att_tpls/select/textDropdown.html',
12887
12888         link: function(scope, element, attr, ctrl) {
12889             scope.selectedIndex = 0;
12890             scope.selectedOption = attr.placeholder;
12891             scope.isDisabled = false;
12892             scope.isActionsShown = false;
12893
12894             if(scope.defaultAction == undefined)
12895             {
12896                 scope.currentAction = scope.actions[0];
12897                 scope.selectedIndex = 0;
12898             } else if (scope.defaultAction != undefined || scope.defaultAction != '') {
12899                 for (var act in scope.actions)
12900                 {
12901                     if (scope.actions[act] === scope.defaultAction)
12902                     {
12903                         scope.currentAction = scope.actions[act];
12904                         scope.selectedIndex = scope.actions.indexOf(act);
12905                         scope.isActionsShown = false;
12906
12907                     break;
12908                     }
12909                 }
12910
12911             } else {
12912                 scope.currentAction = scope.actions[0];
12913             }
12914
12915             scope.toggle = function() {
12916                 scope.isActionsShown = !scope.isActionsShown;
12917             }
12918
12919             scope.chooseAction = function($event, action){
12920
12921                 if ($event != null) {
12922                     scope.currentAction = action;
12923                     scope.selectedIndex = scope.actions.indexOf(action);
12924
12925                 }
12926
12927                 else {
12928                     scope.currentAction = scope.actions[scope.selectedIndex];
12929                 }
12930
12931                 if (angular.isFunction(scope.onActionClicked))
12932                 {
12933                     scope.onActionClicked(scope.currentAction);
12934                 }
12935
12936                 scope.toggle();
12937             }
12938
12939             scope.isCurrentAction = function(action) {
12940                 return (action === scope.currentAction);
12941             };
12942
12943             // cato
12944             element.bind("keydown", function(e){
12945                 if (e.which === KEY.ENTER ||  KEY.isVerticalMovement(e.which) || KEY.isHorizontalMovement(e.which))
12946                 {
12947                     e.preventDefault();
12948                     e.stopPropagation();
12949                      switch (e.keyCode) {
12950                         case KEY.DOWN:
12951                             scope.selectNext();
12952                             break;
12953                         case KEY.UP:
12954                             scope.selectPrev();
12955                             break;
12956                         case KEY.ENTER:
12957                             scope.selectCurrent();
12958                             break;
12959                         case KEY.ESC:
12960                             scope.isActionsShown = false;
12961                             scope.$apply();
12962                     }
12963                     scope.$apply();
12964                     return;
12965                 }
12966             });
12967
12968             if(attr.disabled)
12969             {
12970                scope.isDisabled = true;
12971             }
12972
12973
12974             scope.selectCurrent = function()
12975             {
12976                 if (scope.selectedIndex < 0)
12977                 {
12978                     scope.selectedIndex = 0;
12979                 }
12980
12981
12982                 if(!scope.isActionsShown) {
12983                     scope.toggle();
12984                 }
12985                 else {
12986                     scope.chooseAction(null, scope.currentAction);
12987                 }
12988             };
12989
12990             scope.selectNext = function()
12991             {
12992                 if(scope.isActionsShown)
12993                 {
12994                     if((scope.selectedIndex + 1) < scope.actions.length)
12995                     {
12996                         scope.selectedIndex += 1;
12997                         scope.$apply();
12998
12999                     }
13000                     else{
13001                         scope.selectedIndex = (scope.actions.length - 1);
13002                         scope.$apply();
13003
13004                     }
13005                 }
13006             };
13007
13008             scope.selectPrev = function()
13009             {
13010                 if(scope.isActionsShown)
13011                 {
13012                     if((scope.selectedIndex - 1) >= 0)
13013                     {
13014                         scope.selectedIndex -= 1;
13015                         scope.$apply();
13016                     }
13017                     else if(scope.selectedIndex - 1 < 0)
13018                     {
13019                         scope.selectedIndex = 0;
13020                         scope.$apply();
13021                     }
13022                 }
13023             };
13024
13025             scope.hoverIn = function(cItem)
13026             {
13027                 scope.selectedIndex = cItem;
13028             };
13029
13030
13031             //end cato
13032
13033             var outsideClick = function(e) {
13034                 var isElement = $isElement(angular.element(e.target), element, $document);
13035
13036                 if(!isElement) {
13037                     scope.toggle();
13038                     scope.$apply();
13039                 }
13040
13041             };
13042
13043             $documentBind.click('isActionsShown', outsideClick, scope);
13044
13045         }
13046     };
13047 }]);
13048
13049 }());
13050
13051 angular.module('att.abs.slider', ['att.abs.position'])
13052         .constant('sliderDefaultOptions', {
13053             width: 300,
13054             step: 1,
13055             precision: 0,
13056             disabledWidth: 116,
13057         })
13058         .directive('attSlider', ['sliderDefaultOptions','$position', function(sliderDefaultOptions,$position)
13059             {
13060                 return {
13061                     restrict: 'EA',
13062                     replace: true,
13063                     transclude: true,
13064                     scope: {
13065                         floor: "=", // the minimum possible value
13066                         ceiling: "=", // the maximum possible value
13067                         step: "@", // how wide is each step
13068                         precision: "@", // how many decimal places do we care about
13069                         width: "@", //how wide the bar would be
13070                         textDisplay: "=", // Labels of max and min values to be displayed at front End
13071                         value: "=", // Value of Current Position model
13072                         ngModelSingle: '=?',
13073                         ngModelLow: '=?',
13074                         ngModelHigh: '=?',
13075                         ngModelDisabled: '=?'
13076                     },
13077                     templateUrl: 'app/scripts/ng_js_att_tpls/slider/slider.html',
13078                     link: function(scope, elem, attr, ctrl)
13079                     {
13080                         var minOffset, maxOffset, newOffset, offsetRange, valueRange, start_x = 0, disabledRange, disabled, evFlag = false, minValue, maxValue, range, refLow, refHigh, maxPtr, minPtr, singlePtr, getHandles;
13081                         scope.minPtrOffset = 0;
13082                         scope.maxPtrOffset = 0;
13083                         var disableWidth = sliderDefaultOptions.disabledWidth;
13084                        
13085                         //Get handles 
13086                         var obj = elem.children();
13087                         disabledRange = obj[0].children;
13088                         disabledRange = angular.element(disabledRange[0]);
13089                         getHandles = obj[1].children;
13090                         singlePtr = angular.element(getHandles[0]);
13091                         minPtr = angular.element(getHandles[1]);
13092                         maxPtr = angular.element(getHandles[2]);
13093                         disabled = ((attr.ngModelSingle == null) && (attr.ngModelLow == null) && (attr.ngModelHigh == null)) && (attr.ngModelDisabled != null);
13094                         range = (attr.ngModelSingle == null) && ((attr.ngModelLow != null) && (attr.ngModelHigh != null));
13095                         refLow = 'ngModelLow';
13096                         refHigh = 'ngModelHigh';
13097                         if (!range) {
13098                             minPtr.remove();
13099                             maxPtr.remove();
13100                         }
13101                         else {
13102                             singlePtr.remove();
13103                         }
13104                         if (!disabled) {
13105                             disabledRange.remove();
13106                         }
13107                         else {
13108                             scope.disabledStyle = {width: disableWidth + 'px', zIndex: 1};
13109                             scope.handleStyle = {left: disableWidth + 'px'};
13110                         }
13111                         minValue = parseFloat(scope.floor);
13112                         maxValue = parseFloat(scope.ceiling);
13113                         valueRange = maxValue - minValue;
13114                         minOffset = 0;
13115                         if (attr.width !== undefined) {
13116                             maxOffset = attr.width;
13117                         }
13118                         else {
13119                             if (elem[0].clientWidth !== 0) {
13120                                 maxOffset = elem[0].clientWidth;
13121                             }
13122                             else {
13123                                 maxOffset = sliderDefaultOptions.width;
13124                             }
13125                         }
13126                         offsetRange = maxOffset - minOffset;
13127                         
13128                         //Key Down Event
13129                         scope.keyDown = function(ev){
13130                                if(ev.keyCode == 39){
13131                                     var elemLeft = $position.position(elem).left;
13132                                     if (newOffset){
13133                                     newOffset = sliderDefaultOptions.step + newOffset;
13134                                 }
13135                                 else{newOffset = sliderDefaultOptions.step + elemLeft;}
13136                             }
13137                             else if(ev.keyCode == 37){
13138                                 var ptrLeft = $position.position(singlePtr).left;
13139                                 var elemLeft = $position.position(elem).left;
13140                                 if(newOffset){
13141                                    if (newOffset!=0){
13142                                     newOffset = newOffset - sliderDefaultOptions.step ;
13143                                    }
13144                                 }
13145                                 else{
13146                                     newOffset = ptrLeft - sliderDefaultOptions.step ;}
13147                             }
13148                                 
13149                                 if(newOffset>=0){
13150                                   
13151                                 scope.ptrOffset(newOffset);
13152                              }
13153                             
13154                          };   
13155                          
13156                         //Mouse Down Event
13157                         scope.mouseDown = function(e, ref) {
13158                             scope.ref = ref;
13159                             evFlag = true;
13160                             if (!range){
13161                                 if (newOffset)
13162                                 {
13163                                     start_x = e.clientX - newOffset;
13164
13165                                 }
13166                                 else {
13167                                     start_x = e.clientX;
13168                                 }
13169                             } else {
13170                                 if (scope.ref == refLow) {
13171                                     start_x = e.clientX - scope.minPtrOffset;
13172
13173                                 }
13174                                 else {
13175                                     start_x = e.clientX - scope.maxPtrOffset;
13176                                 }
13177                             }
13178                             if (disabled) {
13179                                 scope.ref= 'ngModelDisabled';
13180                                 scope.disabledStyle = {width: disableWidth + 'px', zIndex: 1};
13181                             }
13182                         };
13183                                           
13184                         // Mouse Move Event
13185                         scope.moveElem = function(ev) {
13186                             if (evFlag) {
13187                                 var eventX, newPercent, newValue;
13188                                 eventX = ev.clientX;
13189                                 newOffset = eventX - start_x;
13190                                 scope.ptrOffset(newOffset);
13191                             }
13192                         };
13193
13194                         // Mouse Up Event
13195                         scope.mouseUp = function(ev) {
13196                             evFlag = false;
13197                             minPtr.removeClass('dragging');
13198                             maxPtr.removeClass('dragging');
13199                             singlePtr.removeClass('dragging');
13200                             $(document).off('mousemove');
13201                         };
13202
13203                         //Function to calculate the current PositionValue
13204                         scope.calStep = function(value, precision, step, floor) {
13205                             var decimals, remainder, roundedValue, steppedValue;
13206                             if (floor === null) {
13207                                 floor = 0;
13208                             }
13209                             if (step === null) {
13210                                 step = 1 / Math.pow(10, precision);
13211                             }
13212                             remainder = (value - floor) % step;
13213                             steppedValue = remainder > (step / 2) ? value + step - remainder : value - remainder;
13214                             decimals = Math.pow(10, precision);
13215                             roundedValue = steppedValue * decimals / decimals;
13216                             return roundedValue.toFixed(precision);
13217                         };
13218
13219                         //Function to calculate Offset Percent
13220                         scope.percentOffset = function(offset) {
13221                             return ((offset - minOffset) / offsetRange) * 100;
13222                         };
13223                         
13224                         //Function to calculate Offset position
13225                         scope.ptrOffset = function(newOffset){
13226                             var newPercent, newValue;
13227                                 newOffset = Math.max(Math.min(newOffset, maxOffset), minOffset);
13228                                 newPercent = scope.percentOffset(newOffset);
13229                                 newValue = minValue + (valueRange * newPercent / 100.0);
13230                                 if (range) {
13231                                     var rangeSliderWidth;
13232                                     if (scope.ref == refLow) {
13233                                         scope.minHandleStyle = {left: newOffset + "px"};
13234                                         scope.minNewVal = newValue;
13235                                         scope.minPtrOffset = newOffset;
13236                                         minPtr.addClass('dragging');
13237                                         if (newValue > scope.maxNewVal) {
13238                                             scope.ref = refHigh;
13239                                             scope.maxNewVal = newValue;
13240                                             scope.maxPtrOffset = newOffset;
13241                                             maxPtr.addClass('dragging');
13242                                             minPtr.removeClass('dragging');
13243                                             scope.maxHandleStyle = {left: newOffset + "px"};
13244                                         }
13245                                     }
13246                                     else {
13247                                         scope.maxHandleStyle = {left: newOffset + "px"};
13248                                         scope.maxNewVal = newValue;
13249                                         scope.maxPtrOffset = newOffset;
13250                                         maxPtr.addClass('dragging');
13251                                         if (newValue < scope.minNewVal) {
13252                                             scope.ref = refLow;
13253                                             scope.minVal = newValue;
13254                                             scope.minPtrOffset = newOffset;
13255                                             minPtr.addClass('dragging');
13256                                             maxPtr.removeClass('dragging');
13257                                             scope.minHandleStyle = {left: newOffset + "px"};
13258                                         }
13259                                     }
13260                                     rangeSliderWidth = parseInt(scope.maxPtrOffset) - parseInt(scope.minPtrOffset);
13261                                     scope.rangeStyle = {width: rangeSliderWidth + "px", left: scope.minPtrOffset + "px"};
13262                                 }
13263                                 else {
13264                                     if (disabled && newOffset > disableWidth) {
13265                                         scope.rangeStyle = {width: newOffset + "px", zIndex: 0};
13266                                     }
13267                                     else {
13268                                         singlePtr.addClass('dragging');
13269                                         scope.rangeStyle = {width: newOffset + "px"};
13270                                     }
13271                                     scope.handleStyle = {left: newOffset + "px"};
13272                                 }
13273                                 if ((scope.precision == undefined) || (scope.step == undefined)) {
13274                                     scope.precision = sliderDefaultOptions.precision;
13275                                     scope.step = sliderDefaultOptions.step;
13276                                 }
13277                                 newValue = scope.calStep(newValue, parseInt(scope.precision), parseFloat(scope.step), parseFloat(scope.floor));
13278                                 scope[scope.ref] = newValue;
13279                         }
13280                     }
13281                 };
13282             }
13283         ]).directive('attSliderMin',[function()
13284             {
13285              return{
13286                  require: '^attSlider',
13287                  restrict: 'EA',
13288                  replace: true,
13289                  transclude: true,
13290                  templateUrl: 'app/scripts/ng_js_att_tpls/slider/minContent.html'
13291                };
13292          }
13293     ]).directive('attSliderMax',[function()
13294             {
13295              return{
13296                  require: '^attSlider',
13297                  restrict: 'EA',
13298                  replace: true,
13299                  transclude: true,
13300                  templateUrl: 'app/scripts/ng_js_att_tpls/slider/maxContent.html'
13301              };
13302          }
13303     ])
13304 .constant('sliderConstants', {
13305     /*
13306         The MIT License (MIT)
13307         Copyright (c) 2013 Julien Valéry
13308     */
13309     SLIDER: {
13310       settings: {
13311         from: 1,
13312         to: 40,
13313         step: 1,
13314         smooth: true,
13315         limits: true,
13316         value: "3",
13317         dimension: "",
13318         vertical: false
13319       },
13320       className: "jslider",
13321       selector: ".jslider-"
13322     },
13323     EVENTS: {
13324     },
13325     COLORS: {
13326       GREEN: 'green',
13327       BLUE_HIGHLIGHT: 'blue',
13328       MAGENTA: 'magenta',
13329       GOLD: 'gold',
13330       PURPLE: 'purple',
13331       DARK_BLUE: 'dark-blue',
13332       REGULAR: 'regular',
13333       WHITE: 'white'
13334     }
13335  })
13336 .factory('utils', function() {
13337     /*
13338         The MIT License (MIT)
13339         Copyright (c) 2013 Julien Valéry
13340     */
13341     return {
13342       offset: function(elm) { 
13343         var rawDom = elm[0]; 
13344         var _x = 0; 
13345         var _y = 0; 
13346         var body = document.documentElement || document.body; 
13347         var scrollX = window.pageXOffset || body.scrollLeft; 
13348         var scrollY = window.pageYOffset || body.scrollTop; 
13349         _x = rawDom.getBoundingClientRect().left + scrollX; 
13350         _y = rawDom.getBoundingClientRect().top + scrollY; 
13351         return { left: _x, top:_y };
13352       },
13353
13354       roundUpToScale: function(mousePrc, scale, cutOffWidth, cutOffIndex){
13355         var lowerVal;
13356         var higherVal;
13357         var newMousePrc;
13358         var middle;
13359
13360         for(var index = 1;index < scale.length; index++){
13361           lowerVal = scale[index-1];
13362           higherVal = scale[index];
13363
13364           middle = ((higherVal - lowerVal)*.5)+lowerVal;
13365
13366           /*
13367           Handles a situation where the user clicks close to the start point of 
13368           the slider but the pointer doesn't move
13369           */
13370      
13371
13372           if(lowerVal == 0 && mousePrc <= middle){
13373             newMousePrc = lowerVal;
13374             break;
13375           }
13376           else if(checkEquality(lowerVal,mousePrc)){
13377             newMousePrc = lowerVal;
13378             break;
13379           }
13380           else if(lowerVal < mousePrc && (mousePrc < higherVal || 
13381             checkEquality(mousePrc,higherVal)))
13382           {
13383             newMousePrc = higherVal;
13384             break;
13385           }
13386           
13387         }
13388
13389         //Check if the newMousePrc is <= the cuttOffPoint
13390         if(cutOffWidth && newMousePrc < cutOffWidth){
13391           return scale[cutOffIndex];
13392         }
13393         else{
13394           return newMousePrc;
13395         }
13396
13397         /*
13398             Checks to see if 2 points are so close that they are
13399             basically equal.
13400         */
13401
13402         function checkEquality(point1, point2){
13403             var precision = 0.1;
13404             if( Math.abs(point2 - point1) <= precision)
13405                 return true;
13406             return false;
13407         }
13408       },
13409
13410       valueForDifferentScale: function(from,to,prc,prcToValueMapper){
13411         var decimalPrc = prc/100;
13412         if(decimalPrc == 0)
13413             return from;
13414
13415         return prcToValueMapper[prc];
13416       },
13417
13418       getConversionFactorValue: function(value, conversion,firstDimension){
13419         /*
13420             Loop through the conversion array and keep checking the
13421             startVal
13422         */
13423
13424         if(value <= conversion[0].startVal){
13425             return{
13426                 scaledVal:value,
13427                 scaledDimension:firstDimension
13428             };
13429         }
13430
13431
13432         var endIndex = 0;
13433         for(var index in conversion){
13434             var c = conversion[index];
13435
13436             if(value > c.startVal)
13437                 endIndex = index;
13438         }
13439
13440         var scaleFactor = conversion[endIndex].scaleFactor;
13441         var scaledVal = value/scaleFactor;
13442         var scaledDimension=conversion[endIndex].dimension;
13443
13444         return {
13445             scaledVal:scaledVal,
13446             scaledDimension:scaledDimension
13447         };
13448
13449       }
13450
13451     };
13452 })
13453
13454 .factory('sliderDraggable', ['utils', function(utils) {
13455    
13456     /*
13457         The MIT License (MIT)
13458         Copyright (c) 2013 Julien Valéry
13459     */
13460
13461     function Draggable(){
13462       this._init.apply( this, arguments );
13463     }
13464
13465     Draggable.prototype.oninit = function(){
13466     };
13467
13468     Draggable.prototype.events = function(){
13469     };
13470
13471     Draggable.prototype.onmousedown = function(){
13472       this.ptr.css({ position: "absolute" });
13473     };
13474
13475     Draggable.prototype.onmousemove = function( evt, x, y ){
13476       this.ptr.css({ left: x, top: y });
13477     };
13478
13479     Draggable.prototype.onmouseup = function(){};
13480
13481     Draggable.prototype.isDefault = {
13482       drag: false,
13483       clicked: false,
13484       toclick: true,
13485       mouseup: false
13486     };
13487
13488     Draggable.prototype._init = function() {
13489       if( arguments.length > 0 ){
13490         this.ptr = arguments[0];
13491         this.parent = arguments[2];
13492
13493         if (!this.ptr)
13494           return;
13495
13496         this.is = {};
13497         angular.extend( this.is, this.isDefault );
13498         var offset = utils.offset(this.ptr);
13499
13500         this.d = {
13501           left: offset.left,
13502           top: offset.top,
13503           width: this.ptr[0].clientWidth,
13504           height: this.ptr[0].clientHeight
13505         };
13506
13507         this.oninit.apply( this, arguments );
13508
13509         this._events();
13510       }
13511     };
13512
13513     Draggable.prototype._getPageCoords = function( event ){
13514
13515       var value = {};
13516
13517       if( event.targetTouches && event.targetTouches[0] ){
13518         value= { x: event.targetTouches[0].pageX, y: event.targetTouches[0].pageY };
13519       } else{
13520         value= { x: event.pageX, y: event.pageY };
13521       }
13522
13523
13524       return value;
13525     };
13526
13527     Draggable.prototype._bindEvent = function( ptr, eventType, handler ){
13528       var self = this;
13529
13530       if( this.supportTouches_ ){
13531         ptr[0].attachEvent( this.events_[ eventType ], handler);
13532       }
13533       else{
13534         if(ptr.bind){
13535           ptr.bind( this.events_[ eventType ], handler );
13536         }
13537       }
13538     };
13539
13540     Draggable.prototype._events = function(){
13541       var self = this;
13542
13543       this.supportTouches_ = 'ontouchend' in document;
13544       this.events_ = {
13545         "click": this.supportTouches_ ? "touchstart" : "click",
13546         "down": this.supportTouches_ ? "touchstart" : "mousedown",
13547         "move": this.supportTouches_ ? "touchmove" : "mousemove",
13548         "up"  : this.supportTouches_ ? "touchend" : "mouseup",
13549         "mousedown"  : this.supportTouches_ ? "mousedown" : "mousedown"
13550       };
13551
13552       var documentElt = angular.element(window.document);
13553
13554       this._bindEvent(documentElt, "move", function(event) {        
13555         if(self.is.drag) {
13556           event.stopPropagation();
13557           event.preventDefault();
13558           if (!self.parent.disabled) {
13559             self._mousemove(event);
13560           }  
13561         }
13562       });
13563       this._bindEvent(documentElt, "down", function(event) {
13564         if(self.is.drag) {
13565           event.stopPropagation();
13566           event.preventDefault();
13567         }
13568       });
13569       this._bindEvent(documentElt, "up", function(event) {        
13570         self._mouseup(event);        
13571       });
13572
13573       this._bindEvent( this.ptr, "down", function(event) {
13574         self._mousedown( event );
13575         return false;
13576       });
13577       this._bindEvent( this.ptr, "up", function(event) {
13578         self._mouseup( event );
13579       });      
13580      
13581       this.events();
13582     };
13583
13584     Draggable.prototype._mousedown = function( evt ){
13585       this.is.drag = true;
13586       this.is.clicked = false;
13587       this.is.mouseup = false;   
13588
13589       var coords = this._getPageCoords( evt );
13590       this.cx = coords.x - this.ptr[0].offsetLeft;
13591       this.cy = coords.y - this.ptr[0].offsetTop;
13592
13593       angular.extend(this.d, {
13594         left: this.ptr[0].offsetLeft,
13595         top: this.ptr[0].offsetTop,
13596         width: this.ptr[0].clientWidth,
13597         height: this.ptr[0].clientHeight
13598       });
13599
13600       if( this.outer && this.outer.get(0) ){
13601         this.outer.css({ height: Math.max(this.outer.height(), $(document.body).height()), overflow: "hidden" });
13602       }
13603
13604       this.onmousedown( evt );
13605     };
13606
13607     Draggable.prototype._mousemove = function( evt ){
13608
13609       if(this.uid==0)
13610         return;
13611
13612       this.is.toclick = false;
13613       var coords = this._getPageCoords( evt );
13614       this.onmousemove( evt, coords.x - this.cx, coords.y - this.cy );
13615     };    
13616
13617     Draggable.prototype._mouseup = function( evt ){
13618       var oThis = this;
13619
13620       if( this.is.drag ){
13621         this.is.drag = false;
13622
13623         if( this.outer && this.outer.get(0) ) {
13624
13625           if( $.browser.mozilla ){
13626             this.outer.css({ overflow: "hidden" });
13627           } else {
13628             this.outer.css({ overflow: "visible" });
13629           }
13630
13631           if( $.browser.msie && $.browser.version == '6.0' ){
13632             this.outer.css({ height: "100%" });
13633           } else {
13634             this.outer.css({ height: "auto" });
13635           }
13636         }
13637
13638         this.onmouseup( evt );
13639       }
13640     };
13641
13642     return Draggable;
13643   }])
13644 .factory('sliderPointer', ['sliderDraggable', 'utils', function(Draggable, utils) {
13645
13646     /*
13647         The MIT License (MIT)
13648         Copyright (c) 2013 Julien Valéry
13649     */
13650     function SliderPointer() {
13651       Draggable.apply(this, arguments);
13652     }
13653
13654     SliderPointer.prototype = new Draggable();
13655
13656     SliderPointer.prototype.oninit = function(ptr, id, _constructor) {
13657       this.uid = id;
13658       this.parent = _constructor;
13659       this.value = {};
13660       this.settings = angular.copy(_constructor.settings);
13661     };
13662
13663     SliderPointer.prototype.onmousedown = function(evt) {
13664       
13665       var off = utils.offset(this.parent.domNode);
13666
13667       var offset = {
13668         left: off.left,
13669         top: off.top,
13670         width: this.parent.domNode[0].clientWidth,
13671         height: this.parent.domNode[0].clientHeight
13672       };
13673
13674       this._parent = {
13675         offset: offset,
13676         width: offset.width,
13677         height: offset.height
13678       };      
13679
13680       this.ptr.addClass("jslider-pointer-hover");
13681       this.setIndexOver();
13682     };
13683
13684     SliderPointer.prototype.onmousemove = function(evt, x, y) {
13685       var coords = this._getPageCoords( evt ); 
13686
13687       //val is the percent where the slider pointer is located
13688       var val = this.calc(coords.x);
13689       
13690       if(!this.parent.settings.smooth){
13691
13692         val = utils.roundUpToScale(val,
13693           this.parent.settings.scale, 
13694           this.parent.settings.cutOffWidth,
13695           this.parent.settings.cutOffIndex);
13696
13697       }
13698
13699       var cutOffWidth = this.parent.settings.cutOffWidth;
13700
13701       var valPrc = val  + (4/5000);
13702     
13703       if(cutOffWidth && val < cutOffWidth)
13704         val = cutOffWidth;
13705
13706       this._set(val);
13707     };
13708
13709     SliderPointer.prototype.onmouseup = function(evt) {
13710
13711       if( this.settings.callback && angular.isFunction(this.settings.callback) ){
13712         var val = this.parent.getValue();
13713         this.settings.callback.call( this.parent, val);
13714       }
13715
13716       this.ptr.removeClass("jslider-pointer-hover");
13717     };
13718
13719     SliderPointer.prototype.setIndexOver = function() {
13720       this.parent.setPointersIndex(1);
13721       this.index(2);
13722     };
13723
13724     SliderPointer.prototype.index = function(i) {
13725     };
13726
13727     SliderPointer.prototype.limits = function(x) {
13728       return this.parent.limits(x, this);
13729     };
13730
13731     SliderPointer.prototype.calc = function(coords) {
13732         var diff = coords-this._parent.offset.left;
13733         var val = this.limits(  (diff*100)/this._parent.width);
13734         return val;
13735     };
13736
13737     SliderPointer.prototype.set = function(value, opt_origin) {
13738       this.value.origin = this.parent.round(value);
13739       this._set(this.parent.valueToPrc(value,this), opt_origin);
13740     };
13741
13742     SliderPointer.prototype._set = function(prc, opt_origin) {
13743       if(!opt_origin){
13744         this.value.origin = this.parent.prcToValue(prc);
13745       }
13746       this.value.prc = prc;
13747
13748       //Sets the location of the SliderPointer
13749       this.ptr.css({left:prc+'%'});
13750       this.parent.redraw(this);
13751     };
13752
13753     return SliderPointer;
13754 }])
13755 .factory('slider', ['sliderPointer', 'sliderConstants', 'utils', function(SliderPointer, sliderConstants, utils) {
13756
13757     /*
13758         The MIT License (MIT)
13759         Copyright (c) 2013 Julien Valéry
13760     */
13761     var cutOffDom;
13762
13763     function Slider() {
13764       return this.init.apply( this, arguments );
13765     }
13766
13767     function changeCutOffWidth(width){
13768       cutOffDom.css('width',width);
13769     };
13770
13771     Slider.prototype.changeCutOffWidth = changeCutOffWidth;
13772
13773     Slider.prototype.init = function( inputNode, templateNode, settings ){
13774       this.settings = sliderConstants.SLIDER.settings;
13775       angular.extend(this.settings, angular.copy(settings));
13776
13777       this.inputNode = inputNode;
13778       this.inputNode.addClass("ng-hide");
13779
13780       this.settings.interval = this.settings.to-this.settings.from;
13781       
13782       if( this.settings.calculate && $.isFunction( this.settings.calculate ) )
13783         this.nice = this.settings.calculate;
13784
13785       if( this.settings.onstatechange && $.isFunction( this.settings.onstatechange ) )
13786         this.onstatechange = this.settings.onstatechange;
13787
13788       this.is = { init: false };
13789       this.o = {};
13790
13791       this.create(templateNode);
13792     };
13793
13794     Slider.prototype.create = function(templateNode){
13795       var $this = this;
13796
13797       this.domNode = templateNode;
13798
13799       var off = utils.offset(this.domNode);
13800
13801       var offset = {
13802         left: off.left,
13803         top: off.top,
13804         width: this.domNode[0].clientWidth,
13805         height: this.domNode[0].clientHeight
13806       };      
13807
13808       this.sizes = { domWidth: this.domNode[0].clientWidth, domOffset: offset };
13809
13810       angular.extend(this.o, {
13811         pointers: {},
13812         labels: {
13813           0: {            
13814             o : angular.element(this.domNode.find('div')[5])
13815           },
13816           1: {            
13817             o : angular.element(this.domNode.find('div')[6])
13818           }
13819         },
13820         limits: {          
13821           0: angular.element(this.domNode.find('div')[3]),          
13822           1: angular.element(this.domNode.find('div')[5])
13823         }
13824       });
13825
13826       angular.extend(this.o.labels[0], {
13827         value: this.o.labels[0].o.find("span")
13828       });
13829
13830       angular.extend(this.o.labels[1], {
13831         value: this.o.labels[1].o.find("span")
13832       });
13833
13834       if( !$this.settings.value.split(";")[1] ) {
13835         this.settings.single = true;
13836       }
13837
13838       var clickPtr;
13839
13840       var domNodeDivs = this.domNode.find('div');
13841       cutOffDom = angular.element(domNodeDivs[8]);
13842       if(cutOffDom && cutOffDom.css)
13843         cutOffDom.css('width','0%');
13844
13845       var pointers = [ angular.element(domNodeDivs[1]), angular.element(domNodeDivs[2]) ];
13846
13847       angular.forEach(pointers, function(pointer, key ) {
13848         $this.settings = angular.copy($this.settings);
13849         var value = $this.settings.value.split(';')[key];
13850         if( value ) {
13851           $this.o.pointers[key] = new SliderPointer( pointer, key, $this );
13852
13853           var prev = $this.settings.value.split(';')[key-1];
13854           if( prev && parseInt(value, 10) < parseInt(prev, 10 )) value = prev;
13855
13856           var value1 = value < $this.settings.from ? $this.settings.from : value;
13857           value1 = value > $this.settings.to ? $this.settings.to : value;
13858
13859           $this.o.pointers[key].set( value1, true );
13860
13861           if (key === 0) {
13862             $this.domNode.bind('mousedown', $this.clickHandler.apply($this));
13863           }
13864         }
13865       });
13866
13867       this.o.value = angular.element(this.domNode.find("i")[2]);
13868       this.is.init = true;
13869
13870       angular.forEach(this.o.pointers, function(pointer, key){
13871         $this.redraw(pointer);
13872       });
13873
13874     };
13875
13876     Slider.prototype.clickHandler = function() {
13877
13878       var self = this;
13879      
13880       return function(evt) {
13881
13882         if (self.disabled)
13883           return;
13884
13885         var className = evt.target.className;
13886         var targetIdx = 0;
13887
13888         if (className.indexOf('jslider-pointer-to') > 0) {
13889           targetIdx = 1;
13890         }
13891
13892         var _off = utils.offset(self.domNode);
13893
13894         var offset = {
13895           left: _off.left,
13896           top: _off.top,
13897           width: self.domNode[0].clientWidth,
13898           height: self.domNode[0].clientHeight
13899         };              
13900
13901         targetIdx = 1;
13902         var targetPtr = self.o.pointers[targetIdx];
13903
13904         targetPtr._parent = { offset: offset, width: offset.width, height: offset.height};
13905         targetPtr._mousemove(evt);
13906         targetPtr.onmouseup();
13907
13908         return false;
13909       };
13910
13911     };
13912
13913     Slider.prototype.disable = function(bool) {   
13914       this.disabled = bool;
13915     };    
13916
13917     Slider.prototype.nice = function( value ){
13918       return value;
13919     };
13920
13921     Slider.prototype.onstatechange = function(){};
13922
13923     Slider.prototype.limits = function( x, pointer ){
13924
13925       if( !this.settings.smooth ){
13926         var step = this.settings.step*100 / ( this.settings.interval );
13927         x = Math.round( x/step ) * step;
13928       }
13929
13930       var another = this.o.pointers[1-pointer.uid];
13931       if( another && pointer.uid && x < another.value.prc ) 
13932         x = another.value.prc;
13933       if( another && !pointer.uid && x > another.value.prc ) 
13934         x = another.value.prc;
13935
13936       if( x < 0 ) x = 0;
13937       if( x > 100 ) x = 100;
13938
13939       var val = Math.round( x*10) / 10;
13940       return val;
13941     };
13942
13943     Slider.prototype.setPointersIndex = function( i ){
13944       angular.forEach(this.getPointers(), function(pointer, i) {
13945         pointer.index( i );
13946       });
13947     };
13948
13949     Slider.prototype.getPointers = function(){
13950       return this.o.pointers;
13951     };
13952
13953     Slider.prototype.onresize = function(){
13954       var self = this;
13955
13956       this.sizes = {
13957         domWidth: this.domNode[0].clientWidth,
13958         domHeight: this.domNode[0].clientHeight,
13959         domOffset: {
13960           left: this.domNode[0].offsetLeft,
13961           top: this.domNode[0].offsetTop,
13962           width: this.domNode[0].clientWidth,
13963           height: this.domNode[0].clientHeight
13964         }
13965       };
13966
13967       angular.forEach(this.o.pointers, function(ptr, key) {
13968         self.redraw(ptr);
13969       });
13970     };
13971
13972     Slider.prototype.update = function(){
13973       this.onresize();
13974       this.drawScale();
13975     };
13976
13977     Slider.prototype.drawScale = function(){
13978     };
13979
13980     Slider.prototype.redraw = function( pointer ){
13981
13982       if(!this.settings.smooth){
13983
13984         var newMousePrc = utils.roundUpToScale(pointer.value.prc,
13985           this.settings.scale, 
13986           this.settings.cutOffWidth,
13987           this.settings.cutOffIndex);
13988
13989         pointer.value.origin = newMousePrc;
13990         pointer.value.prc = newMousePrc;
13991       }
13992
13993       if( !this.is.init ) 
13994         return false;
13995
13996       this.setValue();
13997
13998       var width = this.o.pointers[1].value.prc;
13999       var newPos = {left:'0%', width:width + '%'};
14000
14001       this.o.value.css(newPos);
14002
14003       var htmlValue = this.nice(pointer.value.origin);
14004       var scaledDimension=this.settings.firstDimension;
14005
14006       if(this.settings.stepWithDifferentScale && !this.settings.smooth){
14007         htmlValue = utils.valueForDifferentScale(this.settings.from,
14008          this.settings.to,htmlValue, this.settings.prcToValueMapper);
14009       }
14010
14011       //This is the base value before the conversion
14012       if( this.settings.realtimeCallback && angular.isFunction(this.settings.realtimeCallback)
14013         && this.settings.cutOffVal != undefined && pointer.uid == 1){
14014
14015         this.settings.realtimeCallback(htmlValue);
14016       }
14017       
14018       //Need to change this to the correct value for the scale
14019       if(this.settings.conversion){
14020         var conversionObj = utils.getConversionFactorValue(parseInt(htmlValue), 
14021             this.settings.conversion,
14022             this.settings.firstDimension);
14023
14024         htmlValue = conversionObj.scaledVal;
14025         scaledDimension = conversionObj.scaledDimension;
14026       }
14027
14028       //Check if we need to round the decimal places
14029       if(this.settings.decimalPlaces || this.settings.decimalPlaces == 0){
14030         if(typeof htmlValue == 'number'){
14031             htmlValue = htmlValue.toFixed(this.settings.decimalPlaces);
14032         }
14033       }
14034
14035       this.o.labels[pointer.uid].value.html(htmlValue+' '+scaledDimension);
14036
14037       //Top tooltip label
14038       this.redrawLabels(pointer);
14039     };
14040
14041     Slider.prototype.redrawLabels = function( pointer ) {
14042
14043       function setPosition( label, sizes, prc ){
14044         sizes.margin = -sizes.label/2;
14045         var domSize = self.sizes.domWidth;
14046
14047         var label_left = sizes.border + sizes.margin;
14048         if( label_left < 0 )
14049           sizes.margin -= label_left;
14050
14051         if( sizes.border+sizes.label / 2 > domSize ){
14052           sizes.margin = 0;
14053           sizes.right = true;
14054         } else
14055         sizes.right = false;
14056         
14057         //Adjust the tooltip location
14058         sizes.margin = -((label.o[0].clientWidth/2) - label.o[0].clientWidth/20);
14059
14060         label.o.css({ left: prc + "%", marginLeft: sizes.margin, right: "auto" });
14061
14062         if( sizes.right ) 
14063           label.o.css({ left: "auto", right: 0 });
14064
14065         return sizes;
14066       }
14067
14068       var self = this;
14069       var label = this.o.labels[pointer.uid];
14070       var prc = pointer.value.prc;
14071
14072       var sizes = {
14073         label: label.o[0].offsetWidth,
14074         right: false,
14075         border: ( prc * domSize ) / 100
14076       };
14077
14078       var another_label = null;
14079       var another = null;
14080
14081       if (!this.settings.single){
14082         another = this.o.pointers[1-pointer.uid];
14083         another_label = this.o.labels[another.uid];
14084
14085         switch( pointer.uid ){
14086           case 0:
14087           if( sizes.border+sizes.label / 2 > another_label.o[0].offsetLeft-this.sizes.domOffset.left ){
14088             another_label.o.css({ visibility: "hidden" });
14089
14090             another_label.value.html( this.nice( another.value.origin ) );
14091
14092             label.o.css({ visibility: "hidden" });
14093
14094             prc = ( another.value.prc - prc ) / 2 + prc;
14095             if( another.value.prc != pointer.value.prc ){
14096               label.value.html( this.nice(pointer.value.origin) + "&nbsp;&ndash;&nbsp;" + this.nice(another.value.origin) );
14097               
14098               sizes.label = label.o[0].clientWidth;
14099               sizes.border = ( prc * domSize ) / 100;
14100             }
14101           } else {
14102             another_label.o.css({ visibility: "visible" });
14103           }
14104           break;
14105           case 1:
14106           if( sizes.border - sizes.label / 2 < another_label.o[0].offsetLeft - this.sizes.domOffset.left + another_label.o[0].clientWidth ){
14107             another_label.o.css({ visibility: "hidden" });
14108             another_label.value.html( this.nice(another.value.origin) );
14109
14110             label.o.css({ visibility: "visible" });
14111
14112             prc = ( prc - another.value.prc ) / 2 + another.value.prc;
14113
14114             if( another.value.prc != pointer.value.prc ){
14115               label.value.html( this.nice(another.value.origin) + "&nbsp;&ndash;&nbsp;" + this.nice(pointer.value.origin) );
14116               sizes.label = label.o[0].clientWidth;
14117               sizes.border = ( prc * domSize ) / 100;
14118             }
14119           } else {
14120             another_label.o.css({ visibility: "visible" });
14121           }
14122           break;
14123         }
14124       }
14125
14126       sizes = setPosition( label, sizes, prc );
14127
14128       var domSize = self.sizes.domWidth;
14129
14130       //This is the 0th pointer
14131       if( another_label ){
14132
14133         sizes = {
14134           label: another_label.o[0].clientWidth,
14135           right: false,
14136           border: ( another.value.prc * this.sizes.domWidth ) / 100
14137         };
14138
14139         sizes = setPosition( another_label, sizes, another.value.prc );
14140       }
14141     };
14142
14143     Slider.prototype.redrawLimits = function() {
14144
14145       if( this.settings.limits ) {
14146
14147         var limits = [ true, true ];
14148
14149         for( var key in this.o.pointers ){
14150
14151           if( !this.settings.single || key === 0 ){
14152
14153             var pointer = this.o.pointers[key];
14154             var label = this.o.labels[pointer.uid];
14155             var label_left = label.o[0].offsetLeft - this.sizes.domOffset.left;
14156
14157             var limit = this.o.limits[0];
14158             if( label_left < limit[0].clientWidth )
14159               limits[0] = false;
14160
14161             limit = this.o.limits[1];
14162             if( label_left + label.o[0].clientWidth > this.sizes.domWidth - limit[0].clientWidth )
14163               limits[1] = false;
14164           }
14165         }
14166
14167         for( var i=0; i < limits.length; i++ ){
14168           if( limits[i] ) 
14169             angular.element(this.o.limits[i]).addClass("animate-show");          
14170           else
14171             angular.element(this.o.limits[i]).addClass("animate-hidde");          
14172         }
14173       }
14174     };
14175
14176     Slider.prototype.setValue = function(){
14177       var value = this.getValue();
14178       this.inputNode.attr( "value", value );
14179       this.onstatechange.call( this, value, this.inputNode );
14180     };
14181
14182     Slider.prototype.getValue = function(){
14183       if(!this.is.init) 
14184         return false;
14185
14186       var $this = this;
14187
14188       var value = "";
14189       angular.forEach( this.o.pointers, function(pointer, key){
14190         if( pointer.value.prc !== undefined && !isNaN(pointer.value.prc) ) {
14191
14192           var pointerPrc = pointer.value.prc;
14193     
14194           var myValue =  $this.prcToValue(pointerPrc);
14195
14196           if(!$this.settings.smooth){
14197             var myValue = utils.valueForDifferentScale($this.settings.from, 
14198             $this.settings.to, 
14199             pointerPrc,
14200             $this.settings.prcToValueMapper);
14201          }
14202
14203           value += (key > 0 ? ";" : "") +myValue;
14204         }
14205       });
14206
14207       
14208       return value;
14209     };
14210
14211     Slider.prototype.getPrcValue = function(){
14212       if(!this.is.init) return false;
14213       var $this = this;
14214
14215       var value = "";
14216       $.each( this.o.pointers, function(i){
14217         if( this.value.prc !== undefined && !isNaN(this.value.prc) )
14218          value += (i > 0 ? ";" : "") + this.value.prc;
14219       });
14220       return value;
14221     };
14222
14223     Slider.prototype.prcToValue = function( prc ){
14224       var value;
14225       if( this.settings.heterogeneity && this.settings.heterogeneity.length > 0 ){
14226         var h = this.settings.heterogeneity;
14227
14228         var _start = 0;
14229         var _from = this.settings.from;
14230
14231         for( var i=0; i <= h.length; i++ ){
14232           var v;
14233           if( h[i] ) 
14234             v = h[i].split("/");
14235           else
14236             v = [100, this.settings.to];        
14237
14238           if( prc >= _start && prc <= v[0] ) {
14239             value = _from + ( (prc-_start) * (v[1]-_from) ) / (v[0]-_start);
14240           }
14241
14242           _start = v[0];
14243           _from = v[1];
14244         }
14245       } 
14246       else {
14247         value = this.settings.from + ( prc * this.settings.interval ) / 100;
14248       }   
14249
14250       var roundedValue = this.round(value);
14251       return roundedValue;
14252     };
14253
14254     Slider.prototype.valueToPrc = function( value, pointer ){
14255
14256       var prc;
14257       if( this.settings.heterogeneity && this.settings.heterogeneity.length > 0 ){
14258         var h = this.settings.heterogeneity;
14259
14260         var _start = 0;
14261         var _from = this.settings.from;
14262
14263         for (var i=0; i <= h.length; i++) {
14264           var v;
14265           if(h[i])
14266             v = h[i].split("/");
14267           else
14268             v = [100, this.settings.to];        
14269
14270           if(value >= _from && value <= v[1]){
14271             prc = pointer.limits(_start + (value-_from)*(v[0]-_start)/(v[1]-_from));
14272           }
14273
14274           _start = v[0]; _from = v[1];
14275         }
14276
14277       } else {
14278         prc = pointer.limits((value-this.settings.from)*100/this.settings.interval);
14279       }
14280
14281       return prc;
14282     };
14283
14284     Slider.prototype.round = function( value ){
14285
14286       value = Math.round( value / this.settings.step ) * this.settings.step;
14287
14288       if( this.settings.round ) 
14289         value = Math.round( value * Math.pow(10, this.settings.round) ) / Math.pow(10, this.settings.round);
14290       else 
14291         value = Math.round( value );
14292       return value;
14293     };
14294
14295     return Slider;
14296
14297   }])
14298 .directive('attStepSlider', [
14299       '$compile', '$templateCache','$timeout', '$window', 'slider', 'sliderConstants','utils',
14300       function(compile, templateCache, timeout, win, Slider, sliderConstants,utils) {
14301
14302         /*
14303             The MIT License (MIT)
14304             Copyright (c) 2013 Julien Valéry
14305         */
14306
14307         var templateUrl = 'app/scripts/ng_js_att_tpls/slider/attStepSlider.html';
14308
14309         return {
14310           restrict : 'AE',
14311           require: '?ngModel',
14312           scope: { 
14313             options:'=',
14314             cutOff: '=' 
14315           },
14316           priority: 1,
14317           templateUrl: templateUrl,
14318           link : function(scope, element, attrs, ngModel) {
14319             if(!ngModel) return;
14320
14321           scope.mainSliderClass = 'step-slider';
14322
14323           element.after(compile(templateCache.get(templateUrl))(scope, function(clonedElement, scope) {          
14324             scope.tmplElt = clonedElement;
14325           }));        
14326
14327           ngModel.$render = function () {
14328             var singleValue = false;
14329
14330             if(ngModel.$viewValue.split && ngModel.$viewValue.split(";").length == 1){
14331                 ngModel.$viewValue = '0;'+ngModel.$viewValue;
14332             }else if(typeof(ngModel.$viewValue) === 'number'){
14333               ngModel.$viewValue = '0;'+ngModel.$viewValue;
14334             }
14335
14336             if (!ngModel.$viewValue && ngModel.$viewValue !== 0) {
14337               return;
14338             }
14339
14340             if (typeof(ngModel.$viewValue) === 'number') {
14341               ngModel.$viewValue = ''+ngModel.$viewValue;
14342             }
14343
14344             if (scope.slider) {
14345               var firstPointer ='0';
14346               var secondPointer =ngModel.$viewValue.split(";")[1];
14347
14348               scope.slider.getPointers()[0].set(firstPointer, true);
14349               
14350               if (ngModel.$viewValue.split(";")[1]) {
14351                 var value = ngModel.$viewValue.split(";")[1];
14352                 if(value.length >= 4){
14353                   value = value.substring(0,2);
14354                 }
14355
14356                 if(!scope.options.realtime)
14357                     scope.options.callback(parseFloat(ngModel.$viewValue.split(";")[1]));
14358                 
14359                 scope.slider.getPointers()[1].set(ngModel.$viewValue.split(";")[1], true);
14360               }
14361             }
14362           };
14363
14364           var init = function() {
14365
14366             scope.from = ''+scope.options.from;
14367             scope.to = ''+scope.options.to;
14368
14369             if (scope.options.calculate && typeof scope.options.calculate === 'function') {
14370               scope.from = scope.options.calculate(scope.from);
14371               scope.to = scope.options.calculate(scope.to);
14372             }
14373
14374             scope.showDividers = scope.options.showDividers;
14375             scope.COLORS = sliderConstants.COLORS;
14376
14377             scope.sliderColor = scope.options.sliderColor;
14378             if(!scope.sliderColor)
14379               scope.sliderColor = sliderConstants.COLORS.REGULAR;
14380
14381             var scaleArray = scope.options.scale;
14382
14383
14384             //Make a copy of the scaleArray before converting it to percentage for the bars
14385             var nonPercentScaleArray = [];
14386
14387             //Create Mapper for the percentage to value
14388             var prcToValueMapper = {};
14389
14390             for(var i in scaleArray){
14391                 var s = scaleArray[i];
14392                 nonPercentScaleArray.push(s);
14393             }
14394
14395             function addScaleArrayStartAndEnd(){
14396               if(scaleArray[0] != 0){
14397                 scaleArray.splice(0,0,0);
14398               } 
14399
14400               if(scaleArray[scaleArray.length - 1] != 100){
14401                 scaleArray.splice(scaleArray.length, 0, 100);
14402               }
14403             }
14404
14405             function convertScaleArrayToPercentage(){
14406
14407                 if(scaleArray[scaleArray.length - 1] != scope.options.to){
14408                  scaleArray.splice(scaleArray.length, 0, scope.options.to);
14409                 }
14410
14411                 for(var i in scaleArray){
14412
14413                     var fromValueCheck = (scaleArray[i]/scope.options.from);
14414                     var toValueCheck = (scaleArray[i]/scope.options.to);
14415
14416                     var prcValue =  ( (scaleArray[i] - scope.options.from)/ (scope.options.to - scope.options.from))*100;
14417                     var realValue = scaleArray[i];
14418
14419                     if(toValueCheck == 1){
14420                         prcValue = 100;
14421                     }
14422                     else if(fromValueCheck == 1){
14423                         prcValue = 0;   
14424                     }
14425
14426                     scaleArray[i] = prcValue;
14427
14428                     prcToValueMapper[''+prcValue] = realValue;
14429                 
14430                 }
14431
14432             }
14433
14434             if( (scope.options.from != 0 || scope.options.to != 100)
14435              && scope.options.smooth){
14436               /*
14437                 scale array is in real values.
14438                */
14439               addScaleArrayStartAndEnd();
14440               scope.options.stepWithDifferentScale = true;
14441               /*
14442               for(var i in scaleArray){
14443                 scaleArray[i] = (scaleArray[i]/100)*scope.options.to;
14444               }
14445               */
14446             }
14447             else if( (scope.options.from != 0 || scope.options.to != 100) 
14448               && !scope.options.smooth){
14449               /*
14450                 Case for different from and to values other than 0 and 100
14451                 so we have to do some different calculations
14452               */
14453               scope.options.stepWithDifferentScale = true;
14454               convertScaleArrayToPercentage();
14455               addScaleArrayStartAndEnd();
14456             }
14457             else{
14458               /*
14459                This is the normal case where the from and to values are 0 and
14460                100 respectively.        
14461               */
14462               //Check that the scale starts at 0 and 100
14463               convertScaleArrayToPercentage();
14464               addScaleArrayStartAndEnd();
14465             }
14466
14467             var decimalPlaces = 0;
14468             if(scope.options.decimalPlaces){
14469                 decimalPlaces = scope.options.decimalPlaces;
14470             }
14471
14472             //Modify the endDimension based on whether converison was passed in
14473             //Also change the toStr value to scale to the last factor
14474             scope.endDimension = scope.options.dimension;
14475
14476             if(scope.options.conversion){
14477                 //Get the dimension of the last conversion
14478                 var lastIndex = scope.options.conversion.length - 1;
14479                 var lastDimension = scope.options.conversion[lastIndex].dimension;
14480                 var lastScaleFactor = scope.options.conversion[lastIndex].scaleFactor;
14481                 scope.endDimension = " "+lastDimension;
14482
14483                 var toVal = (scope.to/lastScaleFactor).toFixed(decimalPlaces);
14484                 scope.toStr = toVal;
14485             }else{
14486                 scope.toStr = scope.options.to;
14487             }
14488
14489             var OPTIONS = {
14490               from: scope.options.from,
14491               to: scope.options.to,
14492               step: scope.options.step,
14493               smooth: scope.options.smooth,
14494               limits: true,
14495               stepWithDifferentScale: scope.options.stepWithDifferentScale,
14496               round: scope.options.round || false,
14497               value: ngModel.$viewValue,
14498               scale: scope.options.scale,
14499               nonPercentScaleArray: nonPercentScaleArray,
14500               prcToValueMapper: prcToValueMapper,
14501               firstDimension:scope.options.dimension,
14502               decimalPlaces: decimalPlaces,
14503               conversion: scope.options.conversion,
14504               realtimeCallback: scope.options.callback
14505             };
14506
14507             if(angular.isFunction(scope.options.realtime)){
14508                 OPTIONS.realtimeCallback = function(value){
14509                     ngModel.$setViewValue(value);
14510                     scope.options.callback(value);
14511                 };
14512             }
14513             else{
14514                 OPTIONS.callback = forceApply;
14515             }
14516             
14517             OPTIONS.calculate = scope.options.calculate || undefined;
14518             OPTIONS.onstatechange = scope.options.onstatechange || undefined;
14519             
14520
14521             //timeout(function() {
14522
14523               var scaleDiv = scope.tmplElt.find('div')[7];
14524                 if(!OPTIONS.conversion){
14525                 
14526                     scope.tmplElt.find('div').eq(6).find('span').eq(0).css('padding-left', '10px');
14527                     scope.tmplElt.find('div').eq(6).find('span').eq(0).css('padding-right', '15px');
14528             
14529                 }
14530
14531               scope.slider = angular.element.slider(element, scope.tmplElt, OPTIONS);
14532               angular.element(scaleDiv).html(scope.generateScale());
14533               scope.drawScale(scaleDiv);
14534               initListener();
14535
14536               scope.$watch('options.disable',function(val){
14537                 if  (scope.slider) {
14538                   scope.tmplElt.toggleClass('disabled',val);              
14539                   scope.slider.disable(val);
14540                 }  
14541               });
14542
14543               scope.$watch('cutOff', function(cutOffVal){
14544
14545                 
14546
14547                 if(cutOffVal && cutOffVal > 0){
14548
14549                   var cutOffPrc = (cutOffVal - scope.slider.settings.from)/(scope.slider.settings.to -
14550                     scope.slider.settings.from);
14551                   cutOffPrc = cutOffPrc*100;
14552
14553                   scope.isCutOffSlider = true;
14554                   scope.slider.settings.cutOffWidth = cutOffPrc;
14555
14556                   //cutOffVal is the actual value of the cutoff point
14557                   scope.cutOffVal = cutOffVal;
14558                   if(scope.options.conversion){
14559                     var convertedVal = utils.getConversionFactorValue(cutOffVal, scope.options.conversion, scope.options.dimension);
14560                     convertedVal.scaledVal = parseFloat(convertedVal.scaledVal).toFixed(scope.options.decimalPlaces);
14561                     scope.cutOffVal = convertedVal.scaledVal +' '+convertedVal.scaledDimension;
14562                   }
14563                   scope.slider.settings.cutOffVal = cutOffVal;
14564                   //Calculate the cutOff percentage
14565                   scope.slider.changeCutOffWidth(cutOffPrc + '%');
14566
14567                   var scale = scope.slider.settings.nonPercentScaleArray;
14568
14569                   //Calculate where the cutOff point in relation to the scale array
14570                   for(var i in scale){
14571                     if(i >= 1){
14572                       var lowerVal = scale[i - 1];
14573                       var higherVal = scale[i];
14574
14575                       if(cutOffVal > lowerVal && cutOffVal <= higherVal){
14576                         scope.slider.settings.cutOffIndex = i;
14577                       }
14578
14579                     }
14580                   }
14581
14582                 }else{
14583                     scope.slider.settings.cutOffVal = 0;
14584                 }
14585
14586               });
14587
14588             //});           
14589           };
14590
14591           function initListener() {
14592             angular.element(win).bind('resize', function(event) {
14593               scope.slider.onresize();
14594             });
14595           }
14596      
14597           scope.generateScale = function(){
14598             if( scope.options.scale && scope.options.scale.length > 0 ){
14599               var str = "";
14600               var s = scope.options.scale;
14601               var position = 'left';
14602
14603               for(var i=0; i < s.length; i++){
14604                 if(i != 0 && i != s.length - 1){
14605
14606                     var scaledPosition = ( (s[i] - scope.from)/(scope.to - scope.from))*100;
14607                     if(scope.options.stepWithDifferentScale && !scope.options.smooth){
14608                       scaledPosition = s[i];
14609                     }
14610                     str += '<span style="'+ position + ': ' +  scaledPosition+ '%"></span>';
14611                 }
14612               }
14613               return str;
14614             } else return "";
14615
14616             return "";
14617           };
14618
14619           scope.drawScale = function(scaleDiv){
14620             angular.forEach(angular.element(scaleDiv).find('ins'), function(scaleLabel, key) {
14621               scaleLabel.style.marginLeft = - scaleLabel.clientWidth / 2;
14622             });
14623           };
14624
14625           var forceApply = function(value) {
14626             var val = value.split(";")[1];
14627            
14628             scope.$apply(function() {
14629                ngModel.$setViewValue(parseInt(val));
14630             });
14631             if (scope.options.callback){
14632                scope.options.callback(parseInt(val));
14633             }
14634
14635           };
14636
14637           scope.$watch('options', function(value) {
14638               init();
14639           });
14640
14641           angular.element.slider = function( inputElement, element, settings) {
14642             if(!element.data('jslider'))
14643               element.data('jslider', new Slider( inputElement, element, settings ));
14644             var sliderObj = element.data('jslider');
14645             return sliderObj;
14646           };
14647
14648         }
14649       };
14650 }]);
14651 angular.module('att.abs.splitButtonDropdown', ['att.abs.utilities'])
14652         .directive('attButtonDropdown', ['$document', '$parse', '$documentBind', function($document, $parse, $documentBind) {
14653                 return {
14654                     restrict: 'EA',
14655                     replace: true,
14656                     transclude: true,
14657                     templateUrl: 'app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdown.html',
14658                     scope: {
14659                         btnText: "@",
14660                         btnType: "@",
14661                         btnLink: "@",
14662                         btnClick: "&"
14663                     },
14664                     link: function(scope, element, attr) {
14665                         scope.isSmall = false;
14666                         scope.isDropDownOpen = false;
14667                         scope.isActionDropdown = false;
14668                         var flag = false;
14669
14670                         if (attr.small === "") {
14671                             scope.isSmall = true;
14672                         }
14673
14674                         if (!(scope.btnText)) {
14675                             scope.isActionDropdown = true;
14676                         }
14677                         
14678                         scope.clickFxn = function() {
14679                             if(typeof scope.btnClick === "function" && !scope.btnLink){
14680                                 scope.btnClick = $parse(scope.btnClick);
14681                                 scope.btnClick();
14682                             }
14683                         };
14684
14685                         scope.toggleDropdown = function() {
14686                             if (!(scope.btnType === 'disabled')) {
14687                                 flag = scope.isDropDownOpen = !scope.isDropDownOpen;
14688                             }
14689                         };
14690
14691                         scope.showDropdown = function() {
14692                             if (!(scope.btnType === 'disabled')) {
14693                                 scope.isDropDownOpen = true;
14694                                 flag = true;
14695                             }
14696                         };
14697
14698                         scope.hideDropdown = function() {
14699                             if (!(scope.btnType === 'disabled')) {
14700                                 scope.isDropDownOpen = false;
14701                                 flag = false;
14702                             }
14703                         };
14704
14705                         var outsideClick = function(e) {
14706                             if (!flag) {
14707                                 scope.$apply(function() {
14708                                     scope.isDropDownOpen = false;
14709                                 });
14710                             }
14711                             flag = false;
14712                         };
14713
14714                         $documentBind.click('isDropDownOpen', outsideClick, scope);
14715
14716                         attr.$observe('btnType', function(val) {
14717                             scope.btnType = val;
14718                         });
14719                     }
14720                 };
14721
14722             }])
14723 .constant('iconStateConstants', {
14724     MIDDLE: 'middle',
14725     LEFT: 'left',
14726     RIGHT: 'right',
14727     NEXT_TO_DROPDOWN:'next-to-dropdown',
14728     LEFT_NEXT_TO_DROPDOWN:'left-next-to-dropdown',
14729     DIR_TYPE: {
14730         LEFT: 'left',
14731         RIGHT:  'right',
14732         BUTTON: 'button'
14733     },
14734     KEYBOARD: {
14735         UP: 38,
14736         DOWN:40,
14737         ENTER: 13,
14738         ESC: 27
14739     },
14740     SPLIT_ICON_BTN_EVENT_EMITTER_KEY: 'splitIconButtonTap'
14741 })
14742 .directive('expandableLine', ['$document',function($document){
14743     return {
14744         restrict: 'EA',
14745         replace: true,
14746         priority: 300,
14747         require: ['^attSplitIconButton', 'expandableLine'],
14748         controller: ['$scope', function($scope){
14749             $scope.isActive = false;
14750             this.setActiveState = function(isActive){
14751                 $scope.isActive = isActive;
14752             }
14753
14754             this.isActive = $scope.isActive;
14755             this.dirType = $scope.dirType;
14756         }],
14757         template: '<div ng-class="{\'expand-line-container\': !isActive, \'expand-line-container-active\': isActive}"> <div ng-class="{\'hovered-line\':isActive, \'vertical-line\':!isActive}"> </div></div>',
14758         scope:{
14759             dirType: '@'
14760         },
14761         link: function(scope,element,attr,ctrls){
14762             var attSplitIconButtonCtrl = ctrls[0];
14763             var expandableLineCtrl = ctrls[1];
14764             attSplitIconButtonCtrl.addSubCtrl(expandableLineCtrl);
14765         }
14766     }
14767 }])
14768 .controller('AttSplitIconCtrl', ['$scope', function($scope){
14769     this.setType = function(type){
14770         $scope.type = type;
14771     };
14772     
14773     this.isDropdown = function(isDropdown){
14774          $scope.isDropdown = isDropdown;
14775     };
14776
14777     this.dropDownClicked = function(){
14778         if($scope.dropDownClicked)
14779             $scope.dropDownClicked();
14780     }
14781
14782     this.dirType = $scope.dirType;
14783
14784 }])
14785 .directive('attSplitIcon', ['$document', '$timeout','iconStateConstants','$documentBind','events',
14786  function($document,$timeout,iconStateConstants,$documentBind, events){
14787     return {
14788         restrict: 'EA',
14789         replace: true,
14790         priority: 200,
14791         transclude: true,
14792         require: ['^attSplitIconButton','attSplitIcon'],
14793         templateUrl: 'app/scripts/ng_js_att_tpls/splitButtonDropdown/splitIcon.html',
14794         scope:{
14795             icon: '@',
14796             hoverWatch: '=',
14797             dropDownWatch: '=',
14798             dirType: '@'
14799         },
14800         controller:'AttSplitIconCtrl',
14801         link: function(scope,element,attr,ctrls){
14802
14803             var attSplitIconButtonCtrl = ctrls[0];
14804             var attSplitIconCtrl = ctrls[1];
14805             attSplitIconButtonCtrl.addSubCtrl(attSplitIconCtrl);
14806
14807             scope.iconStateConstants = iconStateConstants;
14808
14809             var currentIndex = 0;
14810             var isMyElement = false;
14811             var listElements;
14812
14813             scope.isDropdown = false;
14814             scope.isDropdownOpen = false;
14815
14816
14817             scope.$on(iconStateConstants.SPLIT_ICON_BTN_EVENT_EMITTER_KEY, function(evnt, data){
14818                 if(typeof data == 'boolean' && data){
14819                     scope.dropDownClicked();    
14820                     
14821                     /*
14822                         Check if the dropdown is open and if we are selecting one
14823                         of the items, so that when pressing enter it will trigger it.
14824                     */
14825                     if(scope.isDropDownOpen){
14826                         listElements[currentIndex].eq(0).find('a')[0].click();
14827                     }
14828                 }
14829                 else{
14830                     var e = data;
14831                     //Only trigger the keyboard event if the icon button is a dropdown type
14832                     if(scope.isDropdown)
14833                         triggerKeyboardEvents(e);   
14834                 }
14835
14836                 function triggerKeyboardEvents(e){
14837                     if(e.which == iconStateConstants.KEYBOARD.ESC){
14838                         outsideClick();
14839                     }
14840                     if( e.which == iconStateConstants.KEYBOARD.UP ||  
14841                         e.which == iconStateConstants.KEYBOARD.DOWN){
14842
14843                         e.preventDefault();
14844                         events.stopPropagation(e);
14845                         //e.stopPropagation();
14846
14847                         if(e.which == iconStateConstants.KEYBOARD.DOWN){
14848                             //Dropdown is open and the user taps down again
14849
14850                             if(scope.isDropDownOpen){
14851                                 //Now we need to go through the rows in the dropdown
14852                                 scope.nextItemInDropdown();
14853                             }
14854                             //Dropdown is not open
14855                             else{
14856                                 isMyElement = true;
14857                                 outsideClick();
14858                                 listElementsInit();
14859                             }
14860                         }
14861                         else if(e.which  == iconStateConstants.KEYBOARD.UP){
14862                             if(scope.isDropDownOpen){
14863                                 scope.previousItemInDropdown();
14864                             }else{
14865                             }
14866                         }
14867                         
14868                         else{
14869                             isMyElement = false;
14870                             outsideClick();
14871                         }
14872                     }else if(e.which == iconStateConstants.KEYBOARD.ENTER){
14873                         if(scope.isDropDownOpen){
14874                             listElementsInit();
14875                         }else{
14876                         }
14877                     }
14878                 }
14879
14880                 function listElementsInit(){
14881                     if(listElements == undefined){
14882                         listElements = [];
14883                         var liTemps = element.find('li');
14884                         for(var i = 0; i < liTemps.length; i++){
14885                             listElements.push(liTemps.eq(i));
14886                         }
14887                         listElements[currentIndex].children().eq(0).addClass('selected-item');
14888                     }
14889                 }
14890             
14891             });
14892         
14893             scope.nextItemInDropdown = function(){
14894                 if(listElements && currentIndex < listElements.length - 1){
14895                     currentIndex++;
14896                     listElements[currentIndex - 1].children().eq(0).removeClass('selected-item');
14897                     listElements[currentIndex].children().eq(0).addClass('selected-item');
14898                 }
14899             };
14900
14901             scope.previousItemInDropdown = function(){
14902                 if(currentIndex > 0){
14903                     currentIndex--;
14904                     listElements[currentIndex].children().eq(0).addClass('selected-item');
14905
14906                     if(currentIndex + 1 < listElements.length)
14907                         listElements[currentIndex + 1].children().eq(0).removeClass('selected-item');
14908                 }
14909             };
14910
14911             scope.$watch('isIconHovered', function(val){
14912                 scope.hoverWatch = val;
14913             });
14914
14915             scope.$watch('type', function(val){
14916
14917                 function toggleValues(isMiddle,isNextToDropDown,isRight,isLeft,isLeftNextDropdown){
14918                     scope['isMiddle']  = isMiddle;
14919                     scope['isNextToDropDown'] = isNextToDropDown;
14920                     scope['isRight']  = isRight;
14921                     scope['isLeft'] = isLeft;
14922                     scope['isLeftNextDropdown'] = isLeftNextDropdown;
14923                 };
14924
14925                 if(val == scope.iconStateConstants.MIDDLE){
14926                     toggleValues(true,false,false,true,false);
14927                 }
14928                 else if(val ==  scope.iconStateConstants.LEFT){
14929                     toggleValues(false,false,false,true,false);
14930                 }
14931                 else if(val == scope.iconStateConstants.RIGHT){
14932                     toggleValues(false,false,true,false,false);
14933                 }else if(val == scope.iconStateConstants.NEXT_TO_DROPDOWN){
14934                     toggleValues(false,true,true,true,false);
14935                 }else  if(val == scope.iconStateConstants.LEFT_NEXT_TO_DROPDOWN){
14936                     toggleValues(false,false,false,true,true);
14937                 }
14938             });
14939
14940             if(attr.dropDownId && attr.dropDownId != ''){
14941                 scope.dropDownId = attr.dropDownId;
14942                 scope.isDropdown = true;
14943             }
14944
14945             scope.dropDownClicked = function(){
14946                 isMyElement = true;
14947             };
14948
14949             scope.toggleDropdown = function(val) {
14950                 if(val != undefined)
14951                     scope.isDropDownOpen=val;
14952                 else
14953                     scope.isDropDownOpen = !scope.isDropDownOpen; 
14954
14955                 scope.dropDownWatch = scope.isDropDownOpen;
14956             };
14957
14958             var outsideClick = function(e) {
14959                 if(scope.isDropdown){
14960                     if (isMyElement) {
14961                         isMyElement = false;
14962                         scope.toggleDropdown();
14963                     }else{
14964                         scope.toggleDropdown(false);
14965                     }
14966                     scope.$apply();
14967                 }
14968             };
14969
14970             $documentBind.click('isDropdown', outsideClick, scope);
14971         }
14972     }
14973 }])
14974 .controller('AttSplitIconButtonCtrl',['$scope', 'iconStateConstants',function($scope,iconStateConstants){
14975
14976     this.subCtrls = [];
14977
14978     $scope.isLeftLineShown=true;
14979     $scope.isRightLineShown=true;
14980     $scope.childrenScopes = [];
14981
14982     var origLeftLineShown = $scope.isLeftLineShown;
14983     var origRightLineShown = $scope.isRightLineShown;
14984
14985     var that = this;
14986
14987     function getDirIndex(dirType){
14988         var index = -1;
14989         for(var c in that.subCtrls){
14990             var ctrl = that.subCtrls[c];
14991             if(ctrl.dirType==dirType){
14992                 index = c;
14993                 break;
14994             }
14995         }
14996         return index;
14997     }
14998
14999     this.addSubCtrl =  function(sub){
15000         this.subCtrls.push(sub);
15001     };
15002
15003     this.isLeftLineShown = function(isShown){
15004         if(isShown == undefined)
15005             return $scope.isLeftLineShown;
15006         else
15007             $scope.isLeftLineShown = isShown;
15008     };
15009
15010     this.isRightLineShown = function(isShown){
15011         if(isShown == undefined)
15012             return $scope.isRightLineShown;
15013         else
15014             $scope.isRightLineShown = isShown;
15015     };
15016
15017     this.setLeftLineHover = function(isHovered){
15018         var leftLineIndex = getDirIndex(iconStateConstants.DIR_TYPE.LEFT);
15019
15020         if($scope.isLeftLineShown){
15021             if(this.subCtrls[leftLineIndex] && this.subCtrls[leftLineIndex].setActiveState){
15022                 this.subCtrls[leftLineIndex].setActiveState(isHovered);
15023             }
15024         }
15025     };
15026
15027     this.setRightLineHover = function(isHovered){
15028         var rightLineIndex = getDirIndex(iconStateConstants.DIR_TYPE.RIGHT);
15029         if($scope.isRightLineShown){
15030             if(this.subCtrls[rightLineIndex]  && this.subCtrls[rightLineIndex].setActiveState){
15031                 this.subCtrls[rightLineIndex].setActiveState(isHovered);
15032             }
15033         }
15034     };
15035
15036     this.toggleLines = function(isHovered,buttonGroupCtrl,buttonCtrl,isDropDownOpen){  
15037
15038         var subIconButtons = buttonGroupCtrl.subIconButtons;
15039         var subIconButtonsLength = subIconButtons.length;
15040
15041         var leftLineIndex =  getDirIndex(iconStateConstants.DIR_TYPE.LEFT);
15042         var rightLineIndex =  getDirIndex(iconStateConstants.DIR_TYPE.RIGHT);
15043
15044         function noVerticalLineToggle(){
15045             for(var i =0; i < subIconButtonsLength; i++){
15046                 if(subIconButtons[i] == buttonCtrl){
15047                     if(i + 1 <= subIconButtonsLength - 1){
15048                         if(subIconButtons[i+1].isLeftLineShown() && subIconButtons[i+1].subCtrls[leftLineIndex] 
15049                             && subIconButtons[i+1].subCtrls[leftLineIndex].setActiveState)
15050                             subIconButtons[i+1].subCtrls[leftLineIndex].setActiveState(isHovered);
15051                     }
15052                     if(i - 1 >= 0){
15053                         if(subIconButtons[i-1].isRightLineShown() && subIconButtons[i-1].subCtrls[rightLineIndex] 
15054                             && subIconButtons[i-1].subCtrls[rightLineIndex].setActiveState)
15055                             subIconButtons[i-1].subCtrls[rightLineIndex].setActiveState(isHovered);
15056                     }
15057                     break;
15058                 }
15059             }
15060         }   
15061
15062         if(isDropDownOpen){
15063             /*
15064               If the button is next to the dropdown button then just keep the 
15065               buttons left line or its left neighbors right line toggled on
15066               If the button is the dropdown button don't do anything
15067               else do things normally witht the button
15068             */
15069             if(subIconButtons[subIconButtonsLength-1] == buttonCtrl){
15070
15071             }
15072             else if(subIconButtons[subIconButtonsLength-2]==buttonCtrl){
15073                 if(subIconButtons[subIconButtonsLength-2].isLeftLineShown())
15074                     subIconButtons[subIconButtonsLength-2].subCtrls[leftLineIndex].setActiveState(isHovered);
15075                 else if(subIconButtonsLength  - 3 >= 0){
15076                     if(subIconButtons[subIconButtonsLength-3].isRightLineShown())
15077                         subIconButtons[subIconButtonsLength-3].subCtrls[rightLineIndex].setActiveState(isHovered);
15078                 }
15079             }else{
15080                
15081                 noVerticalLineToggle();
15082
15083                 if($scope.isLeftLineShown){
15084                     this.subCtrls[leftLineIndex].setActiveState(isHovered);
15085                 }
15086
15087                 if($scope.isRightLineShown){
15088                     this.subCtrls[rightLineIndex].setActiveState(isHovered);
15089                 }
15090             }
15091         }
15092         else{
15093             //Handle Special cases where they aren't showing any vertical lines
15094             //and the dropdown isn't down
15095             if(!$scope.isLeftLineShown && !$scope.isRightLineShown){
15096                 noVerticalLineToggle();
15097             }   
15098
15099             if($scope.isLeftLineShown){
15100                 if(this.subCtrls[leftLineIndex].setActiveState)
15101                 this.subCtrls[leftLineIndex].setActiveState(isHovered);
15102             }
15103
15104             if($scope.isRightLineShown){
15105                 if(this.subCtrls[rightLineIndex].setActiveState)
15106                 this.subCtrls[rightLineIndex].setActiveState(isHovered);
15107             }
15108         }
15109     };
15110   
15111     this.setButtonType = function(type){
15112         var buttonIndex = getDirIndex(iconStateConstants.DIR_TYPE.BUTTON);
15113         if(this.subCtrls[buttonIndex] && this.subCtrls[buttonIndex].setType)
15114             this.subCtrls[buttonIndex].setType(type);
15115     };
15116
15117 }])
15118 .directive('attSplitIconButton', ['$document', 'iconStateConstants',
15119     function($document,iconStateConstants){
15120     return {
15121         restrict: 'EA',
15122         replace: true,
15123         priority: 100,
15124         transclude: true,
15125         require: ['^attSplitIconButtonGroup', 'attSplitIconButton'],
15126         controller: 'AttSplitIconButtonCtrl',
15127         templateUrl: 'app/scripts/ng_js_att_tpls/splitButtonDropdown/splitIconButton.html',
15128         scope:{
15129             icon: '@',
15130             dropDownId: '@'
15131         },
15132         link: function(scope,element,attr,ctrls){
15133
15134           
15135             var attSplitButtonGroupCtrl = ctrls[0];
15136             var attSplitIconButtonCtrl = ctrls[1];
15137
15138             attSplitButtonGroupCtrl.addIconButton(attSplitIconButtonCtrl);
15139
15140             element.bind('keydown', function(e){
15141                 //Check if the key is the up or down key
15142                 //if()
15143                 if(e.which == iconStateConstants.KEYBOARD.UP ||
15144                     e.which == iconStateConstants.KEYBOARD.DOWN ||
15145                     e.which == iconStateConstants.KEYBOARD.ENTER ||
15146                     e.which == iconStateConstants.KEYBOARD.ESC ) {
15147
15148                     scope.clickHandler();
15149                     scope.$broadcast(iconStateConstants.SPLIT_ICON_BTN_EVENT_EMITTER_KEY, e);
15150                 }
15151             });
15152
15153             scope.dropDownWatch = false;
15154
15155             scope.iconStateConstants = iconStateConstants;
15156
15157             scope.clickHandler = function(){
15158                 attSplitButtonGroupCtrl.hideLeftLineRightButton(attSplitIconButtonCtrl);
15159             };
15160             
15161             scope.$watch('isHovered', function(val){
15162                 if(val){
15163                     attSplitIconButtonCtrl.toggleLines(val,attSplitButtonGroupCtrl,attSplitIconButtonCtrl,attSplitButtonGroupCtrl.isDropDownOpen);
15164                 }else{
15165                     attSplitIconButtonCtrl.toggleLines(val,attSplitButtonGroupCtrl,attSplitIconButtonCtrl,attSplitButtonGroupCtrl.isDropDownOpen);
15166                 }
15167             });
15168
15169             scope.$watch('dropDownWatch', function(val){
15170                 attSplitButtonGroupCtrl.isDropDownOpen = val;
15171                 attSplitButtonGroupCtrl.toggleDropdownState(val);
15172             });
15173         }
15174     }
15175 }])
15176 .controller('AttSplitIconButtonGroupCtrl',   ['$scope','iconStateConstants',function($scope,iconStateConstants){
15177     
15178     this.subIconButtons = [];
15179     this.addIconButton = function(iconButton){
15180        this.subIconButtons.push(iconButton);
15181     };
15182
15183     this.isDropDownOpen = false;
15184
15185     this.hideLeftLineRightButton = function(btn){
15186         var numButtons = this.subIconButtons.length;
15187         var buttonLeftOfRightMost = this.subIconButtons[numButtons - 2];
15188         var rightMostButton = this.subIconButtons[numButtons -1];
15189
15190         if (btn != buttonLeftOfRightMost && btn != rightMostButton ){
15191             rightMostButton.setLeftLineHover(false);
15192         }
15193     };
15194
15195     this.toggleDropdownState = function(isDropDownOpen){
15196
15197         var numButtons = this.subIconButtons.length;
15198    
15199         if(numButtons > 2){
15200         
15201             if(isDropDownOpen){
15202
15203                 if(this.subIconButtons[numButtons - 2].isRightLineShown())
15204                     this.subIconButtons[numButtons - 2].setRightLineHover(true);
15205                 else
15206                     this.subIconButtons[numButtons - 1].setLeftLineHover(true);
15207
15208                 this.subIconButtons[numButtons - 2].setButtonType(iconStateConstants.NEXT_TO_DROPDOWN);
15209             }else{
15210                 
15211                 this.subIconButtons[numButtons - 1].setLeftLineHover(false);
15212                 this.subIconButtons[numButtons - 2].setButtonType(iconStateConstants.MIDDLE);
15213             }
15214
15215         }else{
15216
15217             if(isDropDownOpen){
15218                 this.subIconButtons[0].setRightLineHover(true);
15219                 this.subIconButtons[0].setButtonType(iconStateConstants.LEFT_NEXT_TO_DROPDOWN);
15220             }else{
15221                 this.subIconButtons[0].setButtonType(iconStateConstants.LEFT);
15222             }
15223         }
15224
15225     };
15226
15227 }])
15228 .directive('attSplitIconButtonGroup', ['$document', '$timeout',  'iconStateConstants' ,function($document,$timeout,iconStateConstants){
15229     return {
15230         restrict: 'EA',
15231         replace: true,
15232         priority: 50,
15233         transclude: true,
15234         require: 'attSplitIconButtonGroup',
15235         controller: 'AttSplitIconButtonGroupCtrl',
15236         templateUrl: 'app/scripts/ng_js_att_tpls/splitButtonDropdown/splitIconButtonGroup.html',
15237         scope:{},
15238         link: function(scope,element,attr,ctrls){
15239
15240             $timeout(initialize,100);
15241          
15242             function initialize(){
15243
15244                 var subIconButtonCtrls = ctrls.subIconButtons;
15245                 var leftMostButtonIndex = 0;
15246                 var rightMostButtonIndex =subIconButtonCtrls.length-1;
15247
15248                 //left most button config
15249                 subIconButtonCtrls[leftMostButtonIndex].setButtonType(iconStateConstants.LEFT);
15250                 subIconButtonCtrls[leftMostButtonIndex].isLeftLineShown(false);
15251                 subIconButtonCtrls[leftMostButtonIndex].isRightLineShown(true);
15252
15253                 //right most button config
15254                 subIconButtonCtrls[rightMostButtonIndex].setButtonType(iconStateConstants.RIGHT);
15255                 subIconButtonCtrls[rightMostButtonIndex].isRightLineShown(false);
15256                 subIconButtonCtrls[rightMostButtonIndex].isLeftLineShown(false);
15257
15258                 //middle buttons config
15259                 if(rightMostButtonIndex >= 2){
15260                     var index = 1;
15261                     while(index < rightMostButtonIndex){
15262                         subIconButtonCtrls[index].setButtonType(iconStateConstants.MIDDLE);
15263                         subIconButtonCtrls[index].isRightLineShown(false);
15264                         subIconButtonCtrls[index].isLeftLineShown(false);
15265                         index++;
15266                     }
15267
15268                     var skipIndex = 2;
15269                     while(skipIndex <= rightMostButtonIndex){
15270                         if(skipIndex == rightMostButtonIndex){
15271                             subIconButtonCtrls[skipIndex].isLeftLineShown(true);
15272                         }else{
15273                             subIconButtonCtrls[skipIndex].isRightLineShown(true);
15274                             subIconButtonCtrls[skipIndex].isLeftLineShown(true); 
15275                         } 
15276                         skipIndex = skipIndex + 2;
15277                     }
15278                 }
15279
15280                 //reposition the dropdown
15281                 var ulElem = element.find('ul');
15282                 if(ulElem.length > 0){
15283                     var numButtons = rightMostButtonIndex+1;
15284                     if(numButtons > 2){
15285                         var offset = (numButtons)*34-70+(numButtons/1.5) + 0.5;
15286                         var offSetStr = offset+'px';
15287                         angular.element(ulElem).css('left',offSetStr);
15288                         angular.element(ulElem).css('border-top-left-radius','0px');
15289                     }else{
15290                         angular.element(ulElem).css('left','0px');
15291                     }
15292                 }
15293             }
15294         }
15295     }
15296 }]);
15297
15298 angular.module('att.abs.steptracker', ['att.abs.transition'])
15299     .directive('steptracker', ['$timeout', function($timeout) {
15300         return {
15301             priority: 100, // This allows dev's clickHandler to cancel an operation
15302             scope: {
15303                 sdata: "=sdata",
15304                 cstep:"=currentStep",
15305                 clickHandler: '=?',
15306                 disableClick: '=?'
15307             },
15308             restrict: 'EA',
15309             replace: true,
15310             templateUrl: 'app/scripts/ng_js_att_tpls/steptracker/step-tracker.html',
15311             link: function(scope, elem, attr, ctrl) {
15312                 if (scope.disableClick === undefined) {
15313                     scope.disableClick = false;
15314                 }
15315
15316                 $timeout(function() {
15317                     if(scope.cstep < 1){
15318                         scope.cstep = 1;
15319                     }
15320                     else if(scope.cstep > scope.sdata.length){
15321                         scope.cstep = scope.sdata.length;
15322                     }
15323
15324                     var divs = elem.find('div');
15325                     var slidertracks = [];
15326                     for(var i in divs){
15327                         if(divs.eq(i)[0]){
15328                             var el = divs.eq(i)[0].className;
15329                             if(el.indexOf('track ng-scope') > -1){
15330                                 slidertracks.push(divs.eq(i));
15331                             }
15332                         }
15333                     }
15334
15335                     var currentPage;
15336                     var totalPage;
15337                     var currentTrack = updateCurrentTrack(scope.cstep);
15338
15339                     function updateCurrentTrack(step) {
15340                         // Always return the step-1 because array starts at 0
15341                         return angular.element(slidertracks[step-1]);
15342                     };
15343
15344                     function updateTrackWidth() {
15345                         if (scope.cstep > 0 && scope.cstep <= scope.sdata.length-1 && currentPage > 0) {
15346                             var newWidth = ((currentPage/totalPage)*100) + "%";
15347                             currentTrack = updateCurrentTrack(scope.cstep);
15348                             currentTrack.css('width', newWidth);
15349                         }
15350                     };
15351
15352                     function updatePages() {
15353                         if (scope.cstep <= scope.sdata.length) {
15354                             currentPage = scope.sdata[scope.cstep-1]['currentPage'];
15355                             totalPage = scope.sdata[scope.cstep-1]['totalPages'];
15356                         }
15357                     };
15358
15359                     // dynamically add width for steps, depending on the number of steps.
15360                     scope.set_width = function(indexval) {
15361                         var setwidth = (100 / (scope.sdata.length - 1)) + "%";
15362
15363                         // skip last element and add width for all other element
15364                         if ((scope.sdata.length - 1) > indexval) {
15365                             return {'width': setwidth};
15366                         }
15367                     };
15368
15369                     scope.$watch('sdata', function(current, previous) {
15370                         updatePages();
15371                         var prevStep = scope.cstep;
15372
15373                         // Before anything, ensure currentPage is never below 1
15374                         if (currentPage < 1) {
15375                             currentPage = 1;
15376
15377                             if (scope.cstep != 1) {
15378                                 // Decrease step, current track width is 0%, new step width updates
15379                                 scope.cstep--;
15380                                 updatePages();
15381                             }
15382                         }
15383                         // Move to next step, reset currentPage, totalPage, and ensure previous steps are completed
15384                         if (currentPage > totalPage) {
15385                             if (scope.cstep > scope.sdata.length-1) {
15386                                 scope.cstep++;
15387                                 return;
15388                             } else {
15389                                 currentPage = totalPage;
15390                                 updateTrackWidth();
15391                                 scope.cstep++;
15392                                 updatePages();
15393                                 updateTrackWidth();
15394                             }
15395                         }
15396
15397                         if (currentPage < 1 && prevStep === scope.cstep) {
15398                             currentPage = 1;
15399                             if (scope.cstep > 1) {
15400                                 scope.cstep--;
15401                                 scope.sdata[scope.cstep-1]['currentPage'] = scope.sdata[scope.cstep-1]['totalPages'];
15402                                 scope.sdata[scope.cstep]['currentPage'] = 1;
15403                             }
15404                         }
15405
15406                         updateTrackWidth();
15407                     }, true);
15408
15409
15410                     //add the active class for current step
15411                     scope.activestep = function(index) {
15412                         if (index === scope.cstep-1)
15413                             return true;
15414                         else
15415                             return false;
15416                     };
15417                     //add the done class for finished step
15418                     scope.donesteps = function(index) {
15419                         if (index < scope.cstep-1)
15420                             return true;
15421                         else
15422                             return false;
15423                     };
15424                     //add the last class for final step
15425                     scope.laststep = function(index) {
15426                         if (index === scope.sdata.length-1)
15427                             return true;
15428                         else
15429                             return false;
15430                     };
15431
15432                     scope.isIncomplete = function(index) {
15433                         if (index === scope.cstep-1) return false;
15434
15435                         if (index >= 0 && index < scope.sdata.length-1) {
15436                             // If currentPage <= totalPage then return true
15437                             var step = scope.sdata[index];
15438                             if (step['currentPage'] <= step['totalPages']) return true; else return false;
15439                         }
15440                     };
15441
15442                     //click event
15443                     scope.stepclick = function($event, steps) {
15444
15445                         // If we are decreasing steps, reset all currentPage counts to 1
15446                         if (steps < scope.cstep) {
15447                             for (var i = scope.cstep-1; i > steps; i--) {
15448                                 scope.sdata[i]['currentPage'] = 1;
15449                             }
15450                             scope.sdata[steps]['currentPage']--;
15451                         }
15452
15453                         if (angular.isFunction(scope.clickHandler)) {
15454                             scope.clickHandler($event, steps);
15455                         }
15456
15457                         scope.cstep=steps+1;
15458
15459                         // In the case we decremented previously from this step, we need to reset currentpage to default
15460                         if (scope.cstep <= scope.sdata.length && scope.sdata[scope.cstep]['currentPage'] < 1) {
15461                             scope.sdata[scope.cstep]['currentPage'] = 1;
15462                         }
15463                         updatePages();
15464                         updateTrackWidth();
15465                     };
15466                 }, 100);
15467             }
15468         };
15469     }
15470     ])
15471 .constant('timelineConstants',{
15472     STEP_TYPE:{
15473         ALERT:'alert',
15474         COMPLETED:'completed',
15475         CANCELLED: 'cancelled'
15476     }
15477 })
15478 .controller('AttTimelineCtrl' , ['$scope', '$timeout', function($scope,$timeout){
15479
15480     var timelineBarCtrls = [];
15481     var timelineDotCtrls = [];
15482
15483     this.numSteps = 0;
15484
15485     this.isAlternate = function(){
15486         return $scope.alternate;
15487     }
15488
15489     this.addTimelineBarCtrls = function(t){
15490         timelineBarCtrls.push(t);       
15491     };
15492
15493     this.addTimelineDotCtrls = function(b){
15494         timelineDotCtrls.push(b);
15495     };
15496
15497     $timeout(init,200);
15498     
15499     function init(){
15500  
15501         function compare(a,b) {
15502           if (a.order < b.order)
15503              return -1;
15504           if (a.order > b.order)
15505             return 1;
15506           return 0;
15507         }
15508
15509         timelineDotCtrls.sort(compare);
15510         timelineBarCtrls.sort(compare);
15511
15512         if($scope.$parent.animate)
15513             animateSequence();
15514         
15515         $scope.$watch('trigger', function(val){
15516             if(val){
15517                 $scope.resetTimeline();
15518             }else{
15519                 $scope.$parent.animate = false;
15520             }
15521         });
15522     }
15523
15524     function animateSequence(){
15525
15526         var dotsDuration = .25;
15527         var timelineBarProgressDuration = .25;
15528
15529         if(typeof $scope.barAnimateDuration == 'number')
15530             timelineBarProgressDuration = $scope.barAnimateDuration;
15531         
15532         var start = createAnimation(0,timelineBarProgressDuration);
15533
15534         function setToInactiveStates(){
15535
15536             for(var i in timelineDotCtrls){
15537                 var dotCtrl = timelineDotCtrls[i];
15538
15539                 if(i%2 == 0){
15540                     dotCtrl.unhoveredStateForBelow(.25);
15541                 }else{
15542                     dotCtrl.unhoveredStateForAbove(.25);
15543                 }
15544
15545                 if(dotCtrl.isStop())
15546                     break;
15547             }
15548
15549         }
15550
15551         function createAnimation(i, duration){
15552             if(i == 0){
15553                 return function(){
15554                     if(timelineDotCtrls[i+1].isStop() && timelineDotCtrls[i+1].isCancelled()){
15555                         timelineBarCtrls[i].isCancelled(true);
15556                     }
15557                     timelineBarCtrls[i].animate(createAnimation(i+1, duration), duration);
15558                 }
15559             }else if(i == timelineBarCtrls.length - 1){
15560                 return function(){
15561
15562                     //Removes the bolded text from the start
15563                     if(timelineDotCtrls[0].isCurrentStep()){
15564                         timelineDotCtrls[0].isCurrentStep(false);
15565                     }
15566
15567                     if(timelineDotCtrls[i].isStop()){
15568                         timelineDotCtrls[i-1].shrinkAnimate(dotsDuration);
15569                         timelineDotCtrls[i].isCurrentStep(true);
15570                     }else{
15571                         timelineDotCtrls[i-1].shrinkAnimate(dotsDuration);
15572                         timelineBarCtrls[i].animate(createAnimation(i+1, duration), duration);
15573                     }
15574
15575                     timelineDotCtrls[i].expandedAnimate(dotsDuration);
15576
15577                     $timeout(function(){
15578                         setToInactiveStates();
15579                     },500);
15580                 }
15581             }
15582             //End Dot
15583             else if(i == timelineBarCtrls.length){
15584                 return function(){
15585
15586                     //Removes the bolded text from the start
15587                     if(timelineDotCtrls[0].isCurrentStep()){
15588                         timelineDotCtrls[0].isCurrentStep(false);
15589                     }
15590
15591                     timelineDotCtrls[i-1].shrinkAnimate(dotsDuration);
15592                     timelineDotCtrls[i].expandedAnimate(dotsDuration);
15593                     timelineDotCtrls[i].isCurrentStep(true);
15594
15595                     $timeout(function(){
15596                         setToInactiveStates();
15597                     },500);
15598                     
15599                 }
15600             }
15601             else{
15602                 return function(){
15603                     //Removes the bolded text from the start
15604                     if(timelineDotCtrls[0].isCurrentStep()){
15605                         timelineDotCtrls[0].isCurrentStep(false);
15606                     }
15607
15608                     //timelineDotCtrls[i].setColor();
15609                     if(timelineDotCtrls[i].isStop()){
15610                         timelineDotCtrls[i-1].shrinkAnimate(dotsDuration);
15611                         timelineDotCtrls[i].expandedAnimate(dotsDuration);
15612                         timelineDotCtrls[i].isCurrentStep(true);
15613
15614                         $timeout(function(){
15615                             setToInactiveStates();
15616                         },500);
15617
15618                     }else{
15619
15620                         if(timelineDotCtrls[i+1].isStop() && timelineDotCtrls[i+1].isCancelled()){
15621                             timelineBarCtrls[i].isCancelled(true);
15622                         }
15623                     
15624                         timelineDotCtrls[i-1].shrinkAnimate(dotsDuration);
15625                         timelineBarCtrls[i].animate(createAnimation(i+1, duration), duration);
15626                         timelineDotCtrls[i].expandedAnimate(dotsDuration);
15627                     }
15628                     
15629                 }
15630             }
15631         }
15632
15633         start();
15634     }
15635
15636 }])
15637 .directive('attTimeline', ['$timeout', '$compile', function($timeout,$compile){
15638     return {
15639         restrict: 'EA',
15640         replace: true,
15641         scope: {
15642             steps: '=',
15643             trigger:'=',
15644             alternate: '=',
15645             barAnimateDuration: '='
15646         },
15647         templateUrl: 'app/scripts/ng_js_att_tpls/steptracker/timeline.html',
15648         controller: 'AttTimelineCtrl',
15649         link: function(scope,element,attrs,ctrl){
15650             var init = function(){
15651                 var tempCtrls = [];
15652                 var steps = scope.steps;
15653
15654                 var middleSteps = [];
15655                 for(var i = 1; i < steps.length; i++){
15656                     var aStep = steps[i];
15657                     middleSteps.push(aStep);
15658                 }
15659
15660                 scope.middleSteps = middleSteps;
15661
15662                 //Used in calculating the width of the loading bars
15663                 ctrl.numSteps = steps.length - 1;
15664             };
15665             
15666             init();
15667
15668             //Recompile in case of scope changes
15669             scope.resetTimeline = function(){
15670                scope.animate = true;
15671                $compile(element)(scope);
15672             };
15673         }
15674     }
15675 }])
15676 .controller('TimelineBarCtrl', ['$scope', function($scope){
15677     this.type  = 'timelinebar';
15678     this.order = parseInt($scope.order);
15679
15680     this.animate = function(callback,duration){
15681         $scope.loadingAnimation(callback,duration);
15682     };
15683
15684     this.isCancelled = function(isCancelled){
15685         $scope.isCancelled = isCancelled;
15686     }
15687
15688 }])
15689 .directive('timelineBar', ['animation', '$progressBar', function(animation, $progressBar){
15690     return {
15691         restrict: 'EA',
15692         replace: true,
15693         templateUrl: 'app/scripts/ng_js_att_tpls/steptracker/timelineBar.html',
15694         scope: {
15695             order: '@'
15696         },
15697         require: ['^attTimeline', 'timelineBar'],
15698         controller: 'TimelineBarCtrl',
15699         link: function(scope,element,attrs, ctrls){
15700
15701             var attTimelineCtrl = ctrls[0];
15702             var timelineBarCtrl = ctrls[1];
15703
15704             attTimelineCtrl.addTimelineBarCtrls(timelineBarCtrl);
15705
15706             scope.isCompleted = true;
15707
15708             var widthPerc = (100/attTimelineCtrl.numSteps)-3;
15709
15710             element.css('width', widthPerc+'%');
15711         
15712             var elem = element.find('div').eq(0);
15713
15714             animation.set(elem, {opacity: 0.0});
15715
15716             var updateCallback = function(selfElement){
15717                 animation.set(elem, {opacity:1.0});
15718                 animation.set(elem,{
15719                     scaleX:selfElement.progress(),
15720                     transformOrigin: "left"
15721                 });
15722             };
15723             
15724             scope.loadingAnimation = $progressBar(updateCallback);
15725         }
15726     }
15727 }])
15728 .controller('TimelineDotCtrl', ['$scope','$timeout', 'timelineConstants',function($scope,$timeout,timelineConstants){
15729     this.type = 'dot';
15730
15731     this.order = parseInt($scope.order);
15732     var self = this;
15733
15734     $timeout(function(){
15735
15736         if(self.order != 0){
15737             if(self.order %2 != 0){
15738                 $scope.initializeAboveForAnimation();
15739             }
15740             else{
15741                 $scope.initializeBelowForAnimation();
15742             }
15743         }
15744
15745     });
15746
15747     this.expandedAnimate  = function(duration){
15748
15749         $scope.setColor();
15750         $scope.expandedAnimate(duration);
15751
15752         if(self.order != 0 && !$scope.isStepsLessThanFive()){
15753             if(self.order % 2 != 0){
15754                 $scope.expandContentForAbove(duration);
15755             }else{
15756                 $scope.expandContentForBelow(duration);
15757             }
15758         }
15759         
15760     };
15761
15762     this.unhoveredStateForAbove = function(duration){
15763         $scope.unhoveredStateForAbove(duration);
15764     };
15765
15766     this.unhoveredStateForBelow = function(duration){
15767         $scope.unhoveredStateForBelow(duration);
15768     };
15769
15770     this.shrinkAnimate = function(duration){
15771         $scope.shrinkAnimate(duration);
15772     };
15773
15774     this.setExpanded = function(){
15775         $scope.setSize(3);
15776     };
15777
15778     this.isStop = function(){
15779         return $scope.isStop;
15780     };
15781
15782     this.isCancelled = function(){
15783         if($scope.type == timelineConstants.STEP_TYPE.CANCELLED)
15784             return true;
15785         else
15786             return false;
15787     };
15788
15789     this.isAlert = function(){
15790         if($scope.type == timelineConstants.STEP_TYPE.ALERT)
15791             return true;
15792         else
15793             return false;
15794     };
15795
15796     //Sets the bolded text
15797     this.isCurrentStep = function(isCurrentStep){
15798         if(isCurrentStep != undefined){
15799             $scope.isCurrentStep = isCurrentStep;
15800         }
15801         return $scope.isCurrentStep;
15802     };
15803
15804 }])
15805 .directive('timelineDot', ['$timeout', 'animation', 'timelineConstants', 
15806     function($timeout,animation,timelineConstants){
15807     return {
15808         restrict: 'EA',
15809         replace: true,
15810         scope:{
15811             order:'@',
15812             title:'@',
15813             description: '@',
15814             by: '@',
15815             date: '@',
15816             type: '@'
15817         },
15818         templateUrl: 'app/scripts/ng_js_att_tpls/steptracker/timelineDot.html',
15819         require: ['^attTimeline', 'timelineDot'],
15820         controller: 'TimelineDotCtrl',
15821         link: function(scope,element,attrs,ctrls){
15822
15823             var attTimelineCtrl = ctrls[0];
15824             var timelineDotCtrl = ctrls[1];
15825             attTimelineCtrl.addTimelineDotCtrls(timelineDotCtrl);
15826
15827             scope.numSteps = attTimelineCtrl.numSteps + 1;
15828
15829             scope.isCurrentStep = false;
15830             scope.isCompleted = false;
15831             scope.isStop = false;
15832
15833             if(scope.type == timelineConstants.STEP_TYPE.ALERT || scope.type == timelineConstants.STEP_TYPE.CANCELLED){
15834                 scope.isStop = true;
15835             }
15836
15837             scope.isInactive = true;
15838
15839             var divs = element.find('div');
15840             
15841             var biggerCircleElem = divs.eq(0);
15842             var expandableCircleElem = divs.eq(2);
15843             var infoboxElem = divs.eq(3);
15844             var titleElem = divs.eq(5);
15845             var contentElem = divs.eq(6);
15846             var dateElem = divs.eq(9);
15847         
15848             
15849             function isEmptyStep(){
15850                 if(!scope.description && !scope.by  && !scope.date)
15851                     return true;
15852                 return false;
15853             }
15854
15855             scope.isStepsLessThanFive = function(){
15856                 if(scope.numSteps < 5)
15857                     return true;
15858                 return false;
15859             }
15860
15861
15862
15863             scope.titleMouseover=function(num){
15864
15865                 if(!scope.isStepsLessThanFive()){
15866                     if(!isEmptyStep()){
15867                         if(num == 1 && scope.order%2 == 0){
15868                             scope.expandContentForBelow(.25);
15869                         }
15870
15871                         if(num == 2 && scope.order%2 != 0){
15872                             scope.expandContentForAbove(.25);
15873                         }
15874                     }
15875                 }
15876                 
15877             };
15878
15879             scope.titleMouseleave = function(num){
15880                 if(scope.order%2 == 0){
15881                     scope.unhoveredStateForBelow(.25);
15882                 }
15883                 else{       
15884                     scope.unhoveredStateForAbove(.25);
15885                 }
15886             };
15887
15888             scope.initializeAboveForAnimation = function(){
15889                 if(!scope.isStepsLessThanFive() && attTimelineCtrl.isAlternate()){
15890                     animation.set(contentElem,{opacity:0});
15891                     animation.set(dateElem,{opacity:0});
15892
15893                     if(!isEmptyStep()){
15894                         var yOffset = contentElem[0].offsetHeight + dateElem[0].offsetHeight;
15895
15896                         animation.set(titleElem,{'top':yOffset });
15897                     }
15898                 }
15899             };
15900
15901             scope.expandContentForAbove = function(duration){
15902
15903                 if(!scope.isStepsLessThanFive() && attTimelineCtrl.isAlternate()){
15904                     animation.to(titleElem,duration, {'top':0});
15905                     animation.to(contentElem,duration,{opacity:1});
15906                     animation.to(dateElem,duration,{opacity:1});
15907                 }
15908                     
15909             };
15910
15911             scope.unhoveredStateForAbove = function(duration){
15912
15913                 if(!scope.isStepsLessThanFive() && attTimelineCtrl.isAlternate()){
15914                     animation.set(contentElem,{opacity:0});
15915                     animation.set(dateElem,{opacity:1});
15916                     var yOffset = contentElem[0].offsetHeight;
15917                     animation.to(titleElem,duration,{'top':yOffset});
15918                 }
15919         
15920             };
15921
15922             scope.initializeBelowForAnimation = function(){
15923                 if(!scope.isStepsLessThanFive() && attTimelineCtrl.isAlternate()){
15924                     animation.set(contentElem,{height:'0%',opacity:0, top:'-20px'});
15925                     animation.set(dateElem,{opacity:0});
15926                 }  
15927             };
15928
15929             scope.expandContentForBelow = function(duration){
15930
15931                 if(!scope.isStepsLessThanFive() && attTimelineCtrl.isAlternate()){
15932                     animation.set(dateElem,{opacity:1});
15933                     animation.to(contentElem,duration,{ height:'auto',opacity:1, top:'0px'});   
15934                 }
15935                 
15936             };
15937
15938             scope.unhoveredStateForBelow = function(duration){
15939
15940                 if(!scope.isStepsLessThanFive() && attTimelineCtrl.isAlternate()){
15941                     animation.to(contentElem,duration,{height:'0%',opacity:0, top:'-20px', position:'relative'});
15942                     animation.set(dateElem,{opacity:1});
15943                 }
15944                 
15945             };  
15946
15947             /*
15948                 Default Initializaztion
15949             */
15950
15951             //If the info box is above and the description and date and by are empty then we have do reset its position
15952             if(isEmptyStep()){
15953                 //IT has to be an alternating version for it to be above
15954                 if(scope.order%2 != 0 && attTimelineCtrl.isAlternate())
15955                     infoboxElem.css('top', '-47px');
15956             }
15957
15958
15959             //Check if the order is odd and set the appropiate above or below and other effects
15960             //scope.isAboveInfoBoxShown = true;
15961             if(scope.order%2 == 0 || !attTimelineCtrl.isAlternate()){
15962                 scope.isBelowInfoBoxShown=true;
15963             }
15964             else{               
15965                 scope.isBelowInfoBoxShown=false;
15966             }
15967
15968             //modify some css for steps less than 5 and not alternating
15969             if(scope.isStepsLessThanFive() && !attTimelineCtrl.isAlternate()){
15970                 animation.set(dateElem,{marginTop:10});
15971             }
15972
15973             //For IE 8 fix
15974             animation.set(biggerCircleElem,{opacity: '.5'});
15975
15976             //shrink the expandableCircle to we can expand it later
15977             animation.set(expandableCircleElem, {opacity: '0.0'});
15978             animation.set(expandableCircleElem, {scale: .10});
15979
15980             if(scope.order == 0){
15981                 animation.set(expandableCircleElem, {opacity: '1.0'});
15982                 animation.set(expandableCircleElem,{scale: 1});
15983                 animation.set(biggerCircleElem,{scale:3});
15984
15985                 scope.isCurrentStep = true;
15986                 scope.isInactive=false;
15987                 scope.isCompleted = true;
15988             }
15989
15990             scope.setColor = function(){
15991                 scope.isInactive=false;
15992                 if(scope.type == timelineConstants.STEP_TYPE.CANCELLED){
15993                     scope.isCancelled=true;
15994                 }
15995                 else if(scope.type == timelineConstants.STEP_TYPE.ALERT){
15996                     scope.isAlert=true;
15997                 }
15998                 else{
15999                     scope.isCompleted = true;
16000                 }
16001                 
16002                 if(!scope.$phase)
16003                     scope.$apply();
16004             };
16005
16006             scope.setSize = function(size){
16007                 animation.set(biggerCircle,{scale:size});
16008             };
16009
16010             scope.setExpandedCircle = function(){
16011                 animation.set(expandableCircleElem, {opacity: '1.0'});
16012                 animation.set(expandableCircleElem,{scale: 1});
16013             };
16014
16015             scope.expandedAnimate = function(duration){
16016                 animation.to(biggerCircleElem,duration,{scale:3});
16017                 animation.set(expandableCircleElem, {opacity: '1.0'});
16018                 animation.to(expandableCircleElem,duration,{scale: 1});
16019             };
16020
16021             scope.shrinkAnimate = function(duration){
16022                 animation.to(biggerCircleElem,duration,{scale:1});
16023             };
16024             
16025         }
16026     }
16027 }]);
16028 angular.module('att.abs.table', ['att.abs.utilities'])
16029 .constant('tableConfig', {
16030     defaultSortPattern: false, //true for descending & false for ascending
16031     highlightSearchStringClass: 'tablesorter-search-highlight'
16032 })
16033
16034 .directive('attTable', ['$filter', function($filter) {
16035     return {
16036         restrict: 'EA',
16037         replace: true,
16038         transclude: true,
16039         scope: {
16040             tableData: "=",
16041             viewPerPage: "=",
16042             currentPage: "=",
16043             totalPage: "=",
16044             searchCategory: "=",
16045             searchString: "="
16046         },
16047         require: 'attTable',
16048         templateUrl: 'app/scripts/ng_js_att_tpls/table/attTable.html',
16049         controller: ['$scope', function($scope) {
16050             this.headers = [];
16051             this.currentSortIndex = null;
16052             this.setIndex = function(headerScope) {
16053                 this.headers.push(headerScope);
16054             };
16055             this.getIndex = function(headerName) {
16056                 for (var i = 0; i < this.headers.length; i++) {
16057                     if (this.headers[i].headerName === headerName) {
16058                         return this.headers[i].index;
16059                     }
16060                 }
16061                 return null;
16062             };
16063             this.sortData = function(columnIndex, reverse) {
16064                 $scope.$parent.columnIndex = columnIndex;
16065                 $scope.$parent.reverse = reverse;
16066                 this.currentSortIndex = columnIndex;
16067                 $scope.currentPage = 1;
16068                 this.resetSortPattern();
16069             };
16070             this.getSearchString = function() {
16071                 return $scope.searchString;
16072             };
16073             this.resetSortPattern = function() {
16074                 for(var i = 0; i < this.headers.length; i++) {
16075                     var currentScope = this.headers[i];
16076                     if(currentScope.index !== this.currentSortIndex) {
16077                         currentScope.resetSortPattern();
16078                     }
16079                 }
16080             };
16081         }],
16082         link: function(scope, elem, attr, ctrl) {
16083             scope.searchCriteria = {};
16084             scope.$watchCollection('tableData', function(value) {
16085                 if(value && !isNaN(value.length)) {
16086                     scope.totalRows = value.length;
16087                 }
16088             });
16089             scope.$watch('currentPage', function(val) {
16090                 scope.$parent.currentPage = val;
16091             });
16092             scope.$watch('viewPerPage', function(val) {
16093                 scope.$parent.viewPerPage = val;
16094             });
16095             scope.$watch(function() {
16096                 return scope.totalRows / scope.viewPerPage;
16097             }, function(value) {
16098                 if(!isNaN(value)) {
16099                     scope.totalPage = Math.ceil(value);
16100                     scope.currentPage = 1;
16101                 }
16102             });
16103             var resetSearchCriteria = function() {
16104                 scope.searchCriteria = {};
16105             };
16106             scope.$watch('searchCategory', function(value) {
16107                 if (angular.isDefined(value) && value !== null && value !== "" && angular.isDefined(scope.searchString) && scope.searchString !== null && scope.searchString !== "") {
16108                     var index = ctrl.getIndex(value);
16109                     if (index !== null) {
16110                         resetSearchCriteria();
16111                         scope.searchCriteria[index] = scope.searchString;
16112                     } else {
16113                         resetSearchCriteria();
16114                     }
16115                 } else if (angular.isDefined(scope.searchString) && scope.searchString !== null && scope.searchString !== "" && (!angular.isDefined(value) || value === null || value === "")) {
16116                     scope.searchCriteria = {
16117                         $: scope.searchString
16118                     };
16119                 } else {
16120                     resetSearchCriteria();
16121                 }
16122             });
16123             scope.$watch('searchString', function(value) {
16124                 if (angular.isDefined(value) && value !== null && value !== "" && angular.isDefined(scope.searchCategory) 
16125                     && scope.searchCategory !== null && scope.searchCategory !== "") {
16126                     var index = ctrl.getIndex(scope.searchCategory);
16127                     if (index !== null) {
16128                         resetSearchCriteria();
16129                         scope.searchCriteria[index] = value;
16130                     } else {
16131                         resetSearchCriteria();
16132                     }
16133                 } else if (angular.isDefined(value) && value !== null && value !== ""
16134                  && (!angular.isDefined(scope.searchCategory) || scope.searchCategory === null || scope.searchCategory === ""))
16135                   {
16136                     scope.searchCriteria = {
16137                         $: value
16138                     };
16139                 } else {
16140                     resetSearchCriteria();
16141                 }
16142             });
16143             scope.$watchCollection('searchCriteria', function(val) {
16144                 scope.$parent.searchCriteria = val;
16145                 scope.totalRows = ($filter('filter')(scope.tableData, val, false)).length;
16146                 scope.currentPage = 1;
16147             });
16148         }
16149     };
16150 }])
16151
16152 .directive('attTableRow', [function() {
16153     return {
16154         restrict: 'EA',
16155         compile: function (elem, attr) {
16156             if (attr.type === 'header') {
16157                 elem.find('tr').eq(0).addClass('tablesorter-headerRow');
16158             } else if (attr.type === 'body') {
16159                 var html = elem.children();
16160
16161                 if(attr.rowRepeat)
16162                     html.attr('ng-repeat', attr.rowRepeat.concat(" | orderBy : columnIndex : reverse | filter : searchCriteria : false | attLimitTo : viewPerPage : viewPerPage*(currentPage-1)"));
16163                 
16164                 html.attr('ng-class', "{'alt-row': $even,'normal-row': $odd}");
16165                 elem.append(html);
16166             }
16167         }
16168     };
16169 }])
16170
16171 .directive('attTableHeader', ['tableConfig', function(tableConfig) {
16172     return {
16173         restrict: 'EA',
16174         replace: true,
16175         transclude: true,
16176         scope: {
16177             sortable: '@',
16178             defaultSort: '@',
16179             index: '@key',
16180             arrowDirection: '=',
16181             clickFunc: '&'
16182         },
16183         require: '^attTable',
16184         templateUrl: 'app/scripts/ng_js_att_tpls/table/attTableHeader.html',
16185         link: function(scope, elem, attr, ctrl) {
16186             var reverse = tableConfig.defaultSortPattern;
16187             scope.headerName = elem.text();
16188             scope.sortPattern = null;
16189             ctrl.setIndex(scope);
16190
16191             scope.$watch('arrowDirection', function(val){
16192                 if(val)
16193                     scope.sortPattern = 'asc';
16194                 else
16195                     scope.sortPattern = 'desc';
16196             });
16197
16198             scope.$watch(function() {
16199                 return elem.text();
16200             }, function(value) {
16201                 scope.headerName = value;
16202             });
16203             scope.sort = function(sortType) {
16204                 if(sortType === true || sortType === false) {
16205                     reverse = sortType;
16206                 }
16207                 ctrl.sortData(scope.index, reverse);
16208                 scope.sortPattern = reverse ? 'desc' : 'asc';
16209                 reverse = !reverse;
16210             };
16211             scope.$watch(function() {
16212                 return ctrl.currentSortIndex;
16213             }, function(value) {
16214                 if (value !== scope.index) {
16215                     scope.sortPattern = null;
16216                 }
16217             });
16218             if(scope.sortable !== 'false') {
16219                 if(scope.defaultSort === 'A' || scope.defaultSort === 'a') {
16220                     scope.sort(false);
16221                 } else if(scope.defaultSort === 'D' || scope.defaultSort === 'd') {
16222                     scope.sort(true);
16223                 }
16224             }
16225             scope.resetSortPattern = function() {
16226                 reverse = tableConfig.defaultSortPattern;
16227             };
16228         }
16229     };
16230 }])
16231
16232 .directive('attTableBody', ['$filter', '$timeout', 'tableConfig', function($filter, $timeout, tableConfig) {
16233     return {
16234         restrict: 'EA',
16235         require: '^attTable',
16236         replace: true,
16237         transclude: true,
16238         templateUrl: 'app/scripts/ng_js_att_tpls/table/attTableBody.html',
16239         link: function (scope, elem, attr, ctrl) {
16240             var highlightSearchStringClass = tableConfig.highlightSearchStringClass;
16241             var searchString = "";
16242             $timeout(function () {
16243                 var actualHtml = elem.children();
16244                 scope.$watch(function () {
16245                     return ctrl.getSearchString();
16246                 }, function (val) {
16247                     searchString = val;
16248                     clearWrap(elem);
16249                     if (actualHtml.length > 0) {
16250                         traverse(elem);
16251                     } else {
16252                         wrapElement(elem);
16253                     }
16254                 });
16255             }, 50);
16256
16257             var traverse = function (elem) {
16258                 var innerHtml = elem.children();
16259                 if (innerHtml.length > 0) {
16260                     for (var i = 0; i < innerHtml.length; i++) {
16261                         traverse(innerHtml.eq(i));
16262                     }
16263                 } else {
16264                     wrapElement(elem);
16265                     return;
16266                 }
16267             };
16268
16269             var wrapElement = function (elem) {
16270                 var text = elem.text();
16271                 elem.html('');
16272                 elem.append($filter('highlight')(text, searchString, highlightSearchStringClass));
16273             };
16274
16275             var clearWrap = function (elem) {
16276                 var elems = elem.find('*');
16277                 for (var i = 0; i < elems.length; i++) {
16278                     if (elems.eq(i).attr('class') && elems.eq(i).attr('class').indexOf(highlightSearchStringClass) !== -1) {
16279                         var text = elems.eq(i).text();
16280                         elems.eq(i).replaceWith(text);
16281                     }
16282                 }
16283             };
16284         }
16285     };
16286 }]);
16287
16288 angular.module('att.abs.tabs', [])
16289         .directive('attTabs', function() {
16290             return{
16291                 restrict: 'EA',
16292                 transclude: false,
16293                 replace: true,
16294                 scope: {
16295                     tabs: "=title"
16296                 },
16297                 controller: ['$scope', function($scope) {
16298                         this.getData = function() {
16299                             return $scope.tabs;
16300                         };
16301                         this.onClickTab = function(tab) {
16302
16303                             return $scope.currentTab = tab.url;
16304                         };
16305                         this.isActiveTab = function(tab) {
16306                             return tab === $scope.currentTab;
16307                         };
16308                     }],
16309                 link: function(scope, elem, attr, ctrl) {
16310                     for (var i = 0; i < scope.tabs.length; i++) {
16311                         if (scope.tabs[i].selected) {
16312                             if (scope.tabs[i].url) {
16313                                 scope.currentTab = scope.tabs[i].url;
16314                             }
16315                         }
16316                     }
16317                 }
16318             };
16319         })
16320         .directive('floatingTabs', function() {
16321             return {
16322                 require: '^attTabs',
16323                 restrict: 'EA',
16324                 transclude: false,
16325                 replace: true,
16326                 scope: {
16327                     size: "@"
16328                 },
16329                 templateUrl: 'app/scripts/ng_js_att_tpls/tabs/floatingTabs.html',
16330                 link: function(scope, elem, attr, attTabsCtrl) {
16331                     scope.tabs = attTabsCtrl.getData();
16332                     scope.onClickTab = attTabsCtrl.onClickTab;
16333                     scope.isActiveTab = attTabsCtrl.isActiveTab;
16334                 }
16335             };
16336         })
16337         .directive('simplifiedTabs', function() {
16338             return {
16339                 require: '^attTabs',
16340                 restrict: 'EA',
16341                 transclude: false,
16342                 replace: true,
16343                 scope: {
16344                     ctab: "=ngModel"
16345                 },
16346                 templateUrl: 'app/scripts/ng_js_att_tpls/tabs/simplifiedTabs.html',
16347                 link: function(scope, elem, attr, attTabsCtrl) {
16348                     scope.tabs = attTabsCtrl.getData();
16349                     scope.clickTab = function(tab) {
16350                         return scope.ctab = tab.id;
16351                     };
16352                     scope.isActive = function(tab) {
16353                         return tab === scope.ctab;
16354                     };
16355                 }
16356             };
16357         })
16358         
16359     .directive('genericTabs', function() {
16360             return {
16361                 require: '^attTabs',
16362                 restrict: 'EA',
16363                 transclude: false,
16364                 replace: true,
16365                 scope: {
16366                     ctab: "=ngModel"
16367                 },
16368                 templateUrl: 'app/scripts/ng_js_att_tpls/tabs/genericTabs.html',
16369                 link: function(scope, elem, attr, attTabsCtrl) {
16370                     scope.tabs = attTabsCtrl.getData();
16371                     scope.clickTab = function(tab) {
16372                         return scope.ctab = tab.id;
16373                     };
16374                     scope.isActive = function(tab) {
16375                         return tab === scope.ctab;
16376                     };
16377                 }
16378             };
16379         })
16380     .directive('parentTab',[ function() {
16381         return {
16382             restrict: 'EA',
16383             scope: {
16384                 menuItems:'=',
16385                 activeSubMenu:'=',
16386                 activeMenu:'='
16387             },
16388             controller: ['$scope',function($scope){
16389                     $scope.megaMenu=$scope.menuItems;
16390                     $scope.megaMenuTab;
16391                     $scope.megaMenuHoverTab;
16392                     this.setMenu=function(index){
16393                             $scope.menuItems=$scope.megaMenu;
16394                             for(var i=0; i<$scope.menuItems.length; i++){
16395                                     if($scope.menuItems[i].active == true){                                                     
16396                                             $scope.activeMenu=$scope.menuItems[i];
16397                                     };
16398                             };
16399                             this.setSubMenuStatus(false);
16400
16401                             $scope.$apply();
16402                     };  
16403                     this.setActiveMenu=function(){
16404                     if(!($scope.megaMenuTab=="undefined" || $scope.megaMenuTab==null)){
16405                             $scope.menuItems=[$scope.megaMenuTab];
16406                             $scope.activeMenu={};
16407                             $scope.activeSubMenu=$scope.megaMenuTab;
16408                             this.setSubMenuStatus(true);                                
16409                     }
16410                     else{
16411                             for(var i=0; i<$scope.menuItems.length; i++){
16412                                     ($scope.menuItems[i].active = false);
16413                                     if($scope.menuItems[i].subItems)
16414                                     for(var j=0; j<$scope.menuItems[i].subItems.length; j++){
16415                                                     $scope.menuItems[i].subItems[j].active = false;     
16416                                             };
16417                             };
16418                             $scope.menuItems=$scope.megaMenu;
16419                     }   
16420                     $scope.$apply();    
16421                     };
16422                     var checkSubMenuStatus = false;
16423
16424                     this.setSubMenuStatus = function(value){
16425                             checkSubMenuStatus = value;
16426                     };
16427                     this.getSubMenuStatus = function(){
16428                             return checkSubMenuStatus;
16429                     };
16430                     this.setActiveMenuTab=function(tab){
16431                     $scope.megaMenuTab=tab;
16432                     };
16433                     this.setActiveMenuHoverTab=function(tab){
16434                     $scope.megaMenuHoverTab=tab;
16435                     };
16436                     this.setActiveSubMenuTab=function(){
16437                     $scope.megaMenuTab=$scope.megaMenuHoverTab;
16438                     };
16439                     this.resetMenuTab=function(){
16440                     $scope.megaMenuTab='undefined';
16441                     };
16442             }]
16443         }
16444      }])
16445     .directive('parentmenuTabs',[ function() {
16446         return {
16447             restrict: 'EA',
16448             transclude: true,
16449             replace: true,
16450             scope: {
16451                 megaMenu:'@',
16452                 menuItems:'='
16453             },
16454             controller: ['$scope',function($scope){
16455                     this.getMenu=function(){
16456                             return $scope.menuItems;
16457                     };
16458                     this.setMenu=function(menuItem){
16459                              $scope.menuItems=menuItem;
16460                     };                                  
16461             }],
16462             templateUrl: 'app/scripts/ng_js_att_tpls/tabs/parentmenuTab.html'   
16463         }               
16464     }])
16465     .directive('menuTabs',["$window","$document",  function(win,$document) {
16466      return {
16467          restrict: 'EA',
16468          transclude: true,
16469          replace: true,
16470          require: ['^parentTab', '^?parentmenuTabs'],
16471          scope: {
16472              activeMenu:"=",
16473              menuItem: "=",
16474              subMenu: "@",
16475              subItemActive: "@"
16476          },
16477          templateUrl:function(element, attrs) {
16478              if(attrs.megaMenu){
16479                  return 'app/scripts/ng_js_att_tpls/tabs/menuTab.html';
16480              }
16481              else{
16482                  return 'app/scripts/ng_js_att_tpls/tabs/submenuTab.html';
16483              }
16484          },
16485          link: function(scope, elem, attr,ctrl) {
16486              var parentCtrl = ctrl[0];
16487              var parentmenuCtrl = ctrl[1];
16488              scope.clickInactive=true;
16489              scope.showHoverChild = function(e){                
16490                  scope.clickInactive=false;
16491                  scope.hoverChild=ctrl[0].getSubMenuStatus();   
16492                          if(e.type=="mouseover" && ctrl[0].getSubMenuStatus())
16493                          {
16494                                  scope.showChildren(e);
16495                          }                                      
16496              }          
16497              scope.showChildren = function(e){
16498                  scope.parentMenuItems=parentmenuCtrl.getMenu();
16499                  for(var i=0; i<scope.parentMenuItems.length; i++){
16500                          scope.parentMenuItems[i].active = false;
16501                          if(scope.parentMenuItems[i].subItems){                                                 
16502                                  for(var j=0; j<scope.parentMenuItems[i].subItems.length; j++){
16503                                          scope.parentMenuItems[i].subItems[j].active = false;   
16504                                  };
16505                          };
16506                          scope.clickInactive=true;
16507                  };
16508                  scope.menuItem.active = true;
16509                  scope.activeMenu=scope.menuItem;
16510                  e.stopPropagation();
16511              };
16512              scope.$watch("subItemActive",function(value){
16513                  if(value=="true" && scope.subMenu=='true'){
16514                  parentCtrl.setActiveMenuHoverTab(scope.menuItem);      
16515                  }
16516              });
16517
16518              scope.showMenuClick=function(){
16519                      parentCtrl.setActiveMenuTab(scope.menuItem);               
16520              };
16521              scope.showSubMenuClick=function(){
16522                      parentCtrl.setActiveSubMenuTab();          
16523              };
16524              scope.resetMenu=function(){
16525                      parentCtrl.resetMenuTab();         
16526              };
16527
16528              function debounce(method, delay) {
16529                      clearTimeout(method._tId);
16530                      method._tId= setTimeout(function(){
16531                              parentCtrl.setMenu();
16532                      }, delay);
16533              }
16534              function debounce1(method, delay) {
16535                      clearTimeout(method._tId);
16536                      method._tId= setTimeout(function(){
16537                              parentCtrl.setActiveMenu();
16538                      }, delay);
16539              }
16540              $document.bind('scroll', function() {
16541                      if(win.pageYOffset===0){
16542                              debounce(parentCtrl.setMenu, 100);
16543                      }
16544                      else if(win.pageYOffset>1 && win.pageYOffset<1500){
16545                              debounce1(parentCtrl.setActiveMenu, 100);
16546                      }
16547              });
16548          }
16549      };
16550  }]);
16551 angular.module('att.abs.tagBadges', [])
16552         .directive('tagBadges', ['$parse', '$timeout', function($parse, $timeout) {
16553                 return {
16554                     restrict: 'EA',
16555                     replace: false,
16556                     transclude: true,
16557                     templateUrl: 'app/scripts/ng_js_att_tpls/tagBadges/tagBadges.html',
16558                     scope: {
16559                         styleType: "@",
16560                         onClose: "&"
16561                     },
16562                     link: function(scope, elem, attr, ctrl) {
16563                         scope.isSmall = false;
16564                         scope.isIcon = false;
16565                         scope.isColor = false;
16566                         scope.display = true;
16567                         scope.isClosable = false;
16568                         scope.isHighlight = false;
16569                         scope.customColor = false;
16570
16571                         if (attr.small === "") {
16572                             scope.isSmall = true;
16573                         }
16574                         
16575                         if (scope.styleType === "icon") {
16576                             scope.isIcon = true;
16577                         }
16578                         else if (scope.styleType === "color") {
16579                             scope.isColor = true;
16580                             if(attr.color != undefined && attr.color != "") {
16581                                 scope.customColor = true;
16582                                 attr.$observe("color", function(val) {
16583                                     scope.border_type_borderColor = val;
16584                                     scope.background_type_backgroundColor = val;
16585                                     scope.background_type_borderColor = val;
16586                                 });
16587                             }
16588                         }
16589                         
16590                         scope.activeHighlight = function(state){
16591                             if(scope.customColor){
16592                                 if(state){
16593                                     scope.isHighlight = true;
16594                                 }
16595                                 else{
16596                                     scope.isHighlight = false;
16597                                 }
16598                             }
16599                         };
16600                         
16601                         if (attr.closable === "") {
16602                             scope.isClosable = true;
16603                             
16604                             scope.closeMe = function() {
16605                                 scope.display = false;
16606                                 
16607                                 $timeout(function(){
16608                                     elem.attr("tabindex", "0");
16609                                     elem[0].focus();
16610                                     elem.bind('blur', function(){
16611                                         elem.remove();
16612                                     });
16613                                 });
16614                                 
16615                                 if(attr['onClose']){
16616                                     scope.onClose = $parse(scope.onClose);
16617                                     scope.onClose();
16618                                 }
16619                             };
16620                         }
16621                     }
16622                 }
16623             }]);
16624 angular.module('att.abs.textOverflow', [])
16625         .constant('textDefaultOptions', {
16626             width: '50%'
16627         })
16628 .directive('attTextOverflow', ['textDefaultOptions','$compile',function(textDefaultOptions,$compile)
16629 {
16630     return {
16631         restrict: 'A',
16632         link: function(scope, elem, attrs, ctrl)
16633         {
16634             var tooltipText = elem.text();
16635             elem.addClass('text-ellipsis');
16636             attrs.$observe('attTextOverflow', function(val){
16637                 if(val)
16638                     elem.css({"width":val});
16639                 else
16640                     elem.css({"width":textDefaultOptions.width});
16641             });
16642             if(!(elem.attr('tooltip'))){
16643                 elem.attr("tooltip", tooltipText);
16644                 elem.attr("tooltip-placement", 'above');
16645                 var newElem =  angular.element(elem);
16646                 $compile(newElem)(scope);
16647             }
16648         }
16649     };
16650 }]);
16651
16652 angular.module('att.abs.toggle', ['angular-gestures', 'att.abs.position'])
16653         .directive('attToggleTemplate', ['$compile', '$log', '$position',  function($compile, $log, $position)
16654             {
16655                 return{
16656                     restrict: 'A',
16657                     require: 'ngModel',
16658                     transclude: true,
16659                     scope: {
16660                         modelVal: "=ngModel"
16661                     },
16662                     templateUrl: 'app/scripts/ng_js_att_tpls/toggle/demoToggle.html',
16663                     link: function(scope, element, attr, ctrl) {
16664                         var ngCtrl = ctrl;
16665                         scope.initialDragPosition = 0;
16666                         var dragStatus = 0;
16667                         var switchMovementPath = ($position.offset(element.children().eq(1).children().eq(0)).width -1);
16668                         scope.drag = function(e) {
16669                             var self = this;
16670                             dragStatus = 1;
16671                             if (e.type === 'dragstart') {
16672                                 scope.initialDragPosition = $position.position(element.children().eq(1)).left;
16673
16674                                 element.children().eq(1).addClass('dragging');
16675                             } else if (e.type === 'drag') {
16676                                 var left = Math.min(0, Math.max(scope.initialDragPosition + e.gesture.deltaX, -switchMovementPath));
16677                                 element.children().eq(1).css({
16678                                     left: left + 'px'
16679                                 });
16680                             } else if (e.type === 'dragend') {
16681                                 var isOn = $position.position(element.children().eq(1)).left > (switchMovementPath*-1)/2;
16682                                 element.children().eq(1).removeClass('dragging');
16683                                 TweenMax.to(element.children().eq(1), .1, {left: isOn ? 0 : (switchMovementPath*-1), ease: Power4.easeOut, onComplete: function(){element.children().eq(1).css({left: ''}) } });
16684                                 if(isOn === true){
16685                                 updateModelVal();
16686                             }
16687                             else if(isOn === false && e.gesture.direction === "left"){
16688                                 updateModelVal();
16689                             }                             
16690                             dragStatus = 0;
16691                             }
16692
16693                             return false;
16694                         };
16695
16696                         scope.directiveValue = attr.attToggleTemplate;
16697                         scope.on = attr.trueValue;
16698                         scope.off = attr.falseValue;
16699                         var switchMovementPathPixels = ((switchMovementPath)*-1) + 'px';
16700                         scope.$watch('modelVal', function(newVal) {
16701                             scope.attrValue = newVal;
16702                             if (newVal === attr.ngTrueValue || newVal === true) {
16703                                 element.children().eq(1).css({
16704                                     left : '0px'
16705                                 });
16706                                 element.addClass('att-checkbox--on'); 
16707                                 element.attr("aria-checked", true);
16708                                 dragStatus = 0;
16709                             } else {
16710                                 element.children().eq(1).css({
16711                                     left : switchMovementPathPixels
16712                                 });
16713                                 element.removeClass('att-checkbox--on'); 
16714                                 element.attr("aria-checked", false);
16715                                 dragStatus = 0;
16716                             }
16717                             element.children().eq(1).css({
16718                                     left : ''
16719                                 });
16720                             
16721                         });
16722
16723                         var updateModelVal = function() {
16724                             if (scope.attrValue === attr.ngTrueValue || scope.attrValue === true)
16725                             {
16726                                 scope.modelVal = false;
16727                             }
16728                             else
16729                             {
16730                                 scope.modelVal = true;
16731                             }
16732                         };
16733                         scope.updateModel = function(env){
16734                            {
16735                             if (dragStatus !== 1) {
16736                                 updateModelVal();
16737                                 dragStatus = 0;
16738                             }
16739                             }; 
16740                             env.preventDefault();
16741                         };
16742                         
16743
16744                     }
16745                 };
16746             }
16747
16748         ])
16749
16750         .directive('attToggleMain', ['$compile', '$log', function($compile, $log)
16751             {
16752                 return{
16753                     restrict: 'A',
16754                     require: 'ngModel',
16755                     transclude: true,
16756                     replace: true,
16757                     scope: {
16758                         modelValue: "=ngModel",
16759                         trueValue: "=ngTrueValue",
16760                         falseValue: "=ngFalseValue"
16761                     },
16762                     link: function(scope, element, attr, ctrl) {
16763                         var ngCtrl = ctrl;
16764                         var html = "";
16765                         var attrVal = "";
16766                         element.removeAttr('att-toggle-main');
16767                         scope.on = attr.ngTrueValue;
16768                         scope.off = attr.ngFalseValue;
16769                         scope.largeValue = attr.attToggleMain;
16770                         if (angular.isDefined(attr.ngTrueValue)) {
16771                             html += ' true-value="{{on}}" false-value="{{off}}"';
16772                         }
16773                         if (scope.largeValue !== undefined)
16774                         {
16775                             attrVal += ' ="{{largeValue}}"';
16776                         }
16777
16778                         element.css({display:'none'});
16779                         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>');                        elm = $compile(elm)(scope);
16780                         element.replaceWith(elm);
16781                     }
16782                 };
16783             }]
16784                 );
16785 angular.module('att.abs.tooltip', ['att.abs.position', 'att.abs.utilities', 'ngSanitize'])
16786         
16787         // The default options tooltip and popover.
16788         .constant('tooltipDefaultOptions', {
16789             placement: 'above',
16790             animation: false,
16791             popupDelay: 0,
16792             stylett: 'dark',
16793             appendToBody: true
16794         })
16795         
16796         /**
16797          * The $tooltip service creates tooltip- and popover-like directives as well as
16798          * houses global options for them.
16799          */
16800         .provider('$tooltip', ['tooltipDefaultOptions', function(tooltipDefaultOptions) {
16801
16802             // Default hide triggers for each show trigger
16803             var triggerMap = {
16804                 'mouseenter': 'mouseleave',
16805                 'click': 'click',
16806                 'focus': 'blur',
16807                 'mouseover':'mouseout'
16808             };
16809
16810             // The options specified to the provider globally.
16811             var globalOptions = {};
16812
16813             this.options = function(value) {
16814                 angular.extend(globalOptions, value);
16815             };
16816
16817             /**
16818              * This allows you to extend the set of trigger mappings available. E.g.:
16819              *
16820              *   $tooltipProvider.setTriggers( 'openTrigger': 'closeTrigger' );
16821              */
16822             this.setTriggers = function setTriggers(triggers) {
16823                 angular.extend(triggerMap, triggers);
16824             };
16825
16826             /**
16827              * This is a helper function for translating camel-case to snake-case.
16828              */
16829             function snake_case(name) {
16830                 var regexp = /[A-Z]/g;
16831                 var separator = '-';
16832                 return name.replace(regexp, function(letter, pos) {
16833                     return (pos ? separator : '') + letter.toLowerCase();
16834                 });
16835             }
16836
16837             /**
16838              * Returns the actual instance of the $tooltip service.
16839              */
16840             this.$get = ['$window', '$compile', '$timeout', '$parse', '$document', '$position', '$interpolate', function($window, $compile, $timeout, $parse, $document, $position, $interpolate) {
16841                     return function $tooltip(type, prefix, defaultTriggerShow) {
16842                         var options = angular.extend({}, tooltipDefaultOptions, globalOptions);
16843                         
16844                         /**
16845                          * Returns an object of show and hide triggers.
16846                          *
16847                          * If a trigger is supplied,
16848                          * it is used to show the tooltip; otherwise, it will use the `trigger`
16849                          * option passed to the `$tooltipProvider.options` method; else it will
16850                          * default to the trigger supplied to this directive factory.
16851                          *
16852                          * The hide trigger is based on the show trigger. If the `trigger` option
16853                          * was passed to the `$tooltipProvider.options` method, it will use the
16854                          * mapped trigger from `triggerMap` or the passed trigger if the map is
16855                          * undefined; otherwise, it uses the `triggerMap` value of the show
16856                          * trigger; else it will just use the show trigger.
16857                          */
16858                         function getTriggers(trigger) {
16859                             var show = trigger || options.trigger || defaultTriggerShow;
16860                             var hide = triggerMap[show] || show;
16861                             return {
16862                                 show: show,
16863                                 hide: hide
16864                             };
16865                         }
16866
16867                         var directiveName = snake_case(type);
16868
16869                         var startSym = $interpolate.startSymbol();
16870                         var endSym = $interpolate.endSymbol();
16871                         var template =
16872                                 '<div ' + directiveName + '-popup ' +
16873                                 'title="' + startSym + 'tt_title' + endSym + '" ' +
16874                                 'content="' + startSym + 'tt_content' + endSym + '" ' +
16875                                 'placement="' + startSym + 'tt_placement' + endSym + '" ' +
16876                                 'animation="tt_animation()" ' +
16877                                 'is-open="tt_isOpen" ' +
16878                                 'stylett="' + startSym + 'tt_style' + endSym + '" ' +
16879                                 '>' +
16880                                 '</div>';
16881                                
16882                         return {
16883                             restrict: 'EA',
16884                             scope: true,
16885                             link: function link(scope, element, attrs) {
16886                                 
16887                                 element.attr("tabindex", "0");
16888                                 element.bind('mouseenter', function(){
16889                                     element.removeAttr("title");
16890                                 });
16891                                 element.bind('mouseleave', function(){
16892                                     element.attr("title", scope.tt_content);
16893                                 });
16894                                 
16895                                 var tooltip = $compile(template)(scope);
16896                                 var transitionTimeout;
16897                                 var popupTimeout;
16898                                 var $body;
16899                                 var appendToBody = angular.isDefined(options.appendToBody) ? options.appendToBody : false;
16900                                 var triggers = getTriggers(undefined);
16901                                 var hasRegisteredTriggers = false;
16902                                 var hasEnableExp = angular.isDefined(attrs[prefix + 'Enable']);
16903
16904                                 // By default, the tooltip is not open.
16905                                 // TODO add ability to start tooltip opened
16906                                 scope.tt_isOpen = false;
16907                                 
16908                                 //Adding a scope watch, to remove the created popup from DOM, incase it is updated outside the provider code.
16909                                 scope.$watch('tt_isOpen', function(newVal, oldVal){
16910                                     if(newVal !== oldVal){
16911                                        if( newVal === false ){
16912                                            // remove code
16913                                            tooltip.remove();
16914                                        }
16915                                     }
16916                                 });
16917
16918                                 function toggleTooltipBind() {
16919                                     if (!scope.tt_isOpen) {
16920                                         showTooltipBind();
16921                                     } else {
16922                                         hideTooltipBind();
16923                                     }
16924                                 }
16925
16926                                 // Show the tooltip with delay if specified, otherwise show it immediately
16927                                 function showTooltipBind() {
16928                                     tooltip = $compile(template)(scope);
16929                                     scope.$digest();
16930                                     if (hasEnableExp && !scope.$eval(attrs[prefix + 'Enable'])) {
16931                                         return;
16932                                     }
16933                                     if (scope.tt_popupDelay) {
16934                                         popupTimeout = $timeout(show, scope.tt_popupDelay);
16935                                     } else {
16936                                         scope.$apply(show);
16937                                     }
16938                                 }
16939
16940                                 function hideTooltipBind() {
16941                                     scope.$apply(function() {
16942                                         hide();
16943                                     });
16944                                 }
16945
16946                                 // Show the tooltip popup element.
16947                                 function show() {
16948                                     var position,
16949                                             ttWidth,
16950                                             ttHeight,
16951                                             ttPosition;
16952
16953                                     // Don't show empty tooltips.
16954                                     if (!scope.tt_content) {
16955                                         return;
16956                                     }
16957
16958                                     // If there is a pending remove transition, we must cancel it, lest the
16959                                     // tooltip be mysteriously removed.
16960                                     if (transitionTimeout) {
16961                                         $timeout.cancel(transitionTimeout);
16962                                     }
16963
16964                                     // Set the initial positioning.
16965                                     tooltip.css({top: 0, left: 0, display: 'block', 'z-index': 9999});
16966
16967                                     // Now we add it to the DOM because need some info about it. But it's not 
16968                                     // visible yet anyway.
16969                                     
16970                                     if (appendToBody) {
16971                                         $body = $body || $document.find('body');
16972                                         $body.append(tooltip);
16973                                     } else {
16974                                         element.after(tooltip);
16975                                     }
16976
16977                                     // Get the position of the directive element.
16978                                     position = appendToBody ? $position.offset(element) : $position.position(element);
16979 //                                    alert(JSON.stringify(position));
16980                                     
16981                                     // Get the height and width of the tooltip so we can center it.
16982                                     ttWidth = tooltip.prop('offsetWidth');
16983                                     ttHeight = tooltip.prop('offsetHeight');
16984
16985                                     // Calculate the tooltip's top and left coordinates to center it with
16986                                     // this directive.
16987                                     var ttArrowOffset = 10;
16988                                     
16989                                     switch (scope.tt_placement) {
16990                                         case 'right':
16991                                             if(appendToBody){
16992                                                 ttPosition = {
16993                                                     top: position.top + position.height / 2 - ttHeight / 2,
16994                                                     left: position.left + position.width
16995                                                 };
16996                                             }else{
16997                                                 ttPosition = {
16998                                                     top: position.top + position.height / 2 - ttHeight / 2,
16999                                                     left: position.left + position.width + ttArrowOffset
17000                                                 };
17001                                             }
17002                                             break;
17003                                         case 'below':
17004                                             if(appendToBody){
17005                                                 ttPosition = {
17006                                                     top: position.top + position.height,
17007                                                     left: position.left + position.width / 2 - ttWidth / 2
17008                                                 };
17009                                             }else{
17010                                                 ttPosition = {
17011                                                     top: position.top + position.height + ttArrowOffset,
17012                                                     left: position.left + position.width / 2 - ttWidth / 2
17013                                                 };
17014                                             }
17015                                             break;
17016                                         case 'left':
17017                                             if(appendToBody){
17018                                                 ttPosition = {
17019                                                     top: position.top + position.height / 2 - ttHeight / 2,
17020                                                     left: position.left - ttWidth
17021                                                 };
17022                                             }else{
17023                                                 ttPosition = {
17024                                                     top: position.top + position.height / 2 - ttHeight / 2,
17025                                                     left: position.left - ttWidth - ttArrowOffset
17026                                                 };
17027                                             }
17028                                             break;
17029                                         default:
17030                                             if(appendToBody){
17031                                                 ttPosition = {
17032                                                     top: position.top - ttHeight,
17033                                                     left: position.left + position.width / 2 - ttWidth / 2
17034                                                 };
17035                                             }else{
17036                                                 ttPosition = {
17037                                                     top: position.top - ttHeight - ttArrowOffset,
17038                                                     left: position.left + position.width / 2 - ttWidth / 2
17039                                                 };
17040                                             }
17041                                             break;
17042                                     }
17043
17044                                     ttPosition.top += 'px';
17045                                     ttPosition.left += 'px';
17046
17047                                     // Now set the calculated positioning.
17048                                     tooltip.css(ttPosition);
17049
17050                                     // And show the tooltip.
17051                                     scope.tt_isOpen = true;
17052                                 }
17053
17054                                 // Hide the tooltip popup element.
17055                                 function hide() {
17056                                     // First things first: we don't show it anymore.
17057                                     scope.tt_isOpen = false;
17058
17059                                     //if tooltip is going to be shown after delay, we must cancel this
17060                                     $timeout.cancel(popupTimeout);
17061
17062                                     // And now we remove it from the DOM. However, if we have animation, we 
17063                                     // need to wait for it to expire beforehand.
17064                                     // FIXME: this is a placeholder for a port of the transitions library.
17065                                     if (angular.isDefined(scope.tt_animation) && scope.tt_animation()) {
17066                                         transitionTimeout = $timeout(function() {
17067                                             tooltip.remove();
17068                                         }, 500);
17069                                     } else {
17070                                         tooltip.remove();
17071                                     }
17072                                 }
17073
17074                                 /**
17075                                  * Observe the relevant attributes.
17076                                  */
17077                                 attrs.$observe(type, function(val) {
17078                                     if (val) {
17079                                         scope.tt_content = val;
17080                                         element.attr('title',val);
17081                                     } else {
17082                                         if (scope.tt_isOpen) {
17083                                             hide();
17084                                         }
17085                                     }
17086                                 });
17087
17088                                 attrs.$observe(prefix + 'Title', function(val) {
17089                                     scope.tt_title = val;
17090                                 });
17091
17092                                 attrs.$observe(prefix + 'Placement', function(val) {
17093                                     scope.tt_placement = angular.isDefined(val) ? val : options.placement;
17094                                 });
17095                                 
17096                                 attrs.$observe(prefix + 'Style', function(val) {
17097                                     scope.tt_style = angular.isDefined(val) ? val : options.stylett;
17098                                 });
17099
17100                                 attrs.$observe(prefix + 'Animation', function(val) {
17101                                     scope.tt_animation = angular.isDefined(val) ? $parse(val) : function() {
17102                                         return options.animation;
17103                                     };
17104                                 });
17105
17106                                 attrs.$observe(prefix + 'PopupDelay', function(val) {
17107                                     var delay = parseInt(val, 10);
17108                                     scope.tt_popupDelay = !isNaN(delay) ? delay : options.popupDelay;
17109                                 });
17110
17111                                 attrs.$observe(prefix + 'Trigger', function(val) {
17112
17113                                     if (hasRegisteredTriggers) {
17114                                         element.unbind(triggers.show, showTooltipBind);
17115                                         element.unbind(triggers.hide, hideTooltipBind);
17116                                     }
17117
17118                                     triggers = getTriggers(val);
17119
17120                                     if (triggers.show === triggers.hide) {
17121                                         element.bind(triggers.show, toggleTooltipBind);
17122                                     } else {
17123                                         element.bind(triggers.show, showTooltipBind);
17124                                         element.bind(triggers.hide, hideTooltipBind);
17125                                     }
17126
17127                                     hasRegisteredTriggers = true;
17128                                 });
17129
17130                                 attrs.$observe(prefix + 'AppendToBody', function(val) {
17131                                     appendToBody = angular.isDefined(val) ? $parse(val)(scope) : appendToBody;
17132                                 });
17133
17134                                 // if a tooltip is attached to <body> we need to remove it on
17135                                 // location change as its parent scope will probably not be destroyed
17136                                 // by the change.
17137                                 if (appendToBody) {
17138                                     scope.$on('$locationChangeSuccess', function closeTooltipOnLocationChangeSuccess() {
17139                                         if (scope.tt_isOpen) {
17140                                             hide();
17141                                         }
17142                                     });
17143                                 }
17144
17145                                 // Make sure tooltip is destroyed and removed.
17146                                 scope.$on('$destroy', function onDestroyTooltip() {
17147                                     if (scope.tt_isOpen) {
17148                                         hide();
17149                                     } else {
17150                                         tooltip.remove();
17151                                     }
17152                                 });
17153                             }
17154                         };
17155                     };
17156                 }];
17157         }])
17158
17159         .directive('tooltipPopup', ['$document', '$documentBind', function($document, $documentBind) {
17160             return {
17161                 restrict: 'EA',
17162                 replace: true,
17163                 transclude: true,
17164                 scope: {content: '@', placement: '@', animation: '&', isOpen: '=', stylett: '@'},
17165                 templateUrl: 'app/scripts/ng_js_att_tpls/tooltip/tooltip-popup.html',
17166                 link: function(scope, elem, attr, ctrl) {
17167                     var flag = false;
17168                     
17169                     scope.$watch("isOpen", function(value) {
17170                         flag = scope.isOpen;
17171                     });
17172                     
17173                     elem.bind('click', function (e) {
17174                         e.stopPropagation();
17175                     });
17176                     
17177                     var outsideClick = function(e) {
17178                         if (!flag) {
17179                             scope.$apply(function() {
17180                                 scope.isOpen = false;
17181                             });
17182                         }
17183                         flag = false;
17184                     };
17185
17186                     $documentBind.click('isOpen', outsideClick, scope);
17187                 }
17188             };
17189         }])
17190     
17191         .directive('tooltip', ['$tooltip', function($tooltip) {
17192             return $tooltip('tooltip', 'tooltip', 'mouseenter');
17193         }])
17194         
17195         .directive('tooltipCondition', [ '$timeout',function($timeout) {
17196                 return  {
17197                     restrict: 'EA',
17198                     replace: true,              
17199                     scope:{
17200                         tooltipCondition:"@?"
17201                     },
17202                     template:'<p><span tooltip=\"{{tooltipCondition}}\" ng-if=\"showpop\">{{tooltipCondition}}</span><span id=\"innerElement\" ng-hide=\"showpop\">{{tooltipCondition}}</span></p>',
17203                     link: function(scope, elem, attr){
17204                         scope.showpop=false;
17205                         if(attr.height==='true'){
17206                             $timeout(function () {
17207                                 var maxHeight=(elem[0].offsetHeight);
17208                                var elemHeight=elem.children(0)[0].offsetHeight;
17209                                if(elemHeight > maxHeight){
17210                                    scope.showpop=true;
17211                                }
17212                             },1000);
17213                         }
17214                         else if(scope.tooltipCondition.length>=25){
17215                         scope.showpop=true;
17216                         }
17217                    
17218                     }
17219                 };            
17220         }]);
17221
17222 angular.module('att.abs.treeview', [])
17223         .directive('treeView', function() {
17224             return{
17225                 restrict: 'A',
17226                 link: function(scope, elem, attrs) {
17227                     var el = elem.children('ul li');
17228                     var list = TweenMax.from(el, .2, {display: 'none', paused: true, reversed: true});
17229                                         elem.attr("tabindex","0");                                                                      
17230                     function toggleBranch() {
17231                         if (list.reversed())
17232                         {
17233                             list.play();
17234                         } else
17235                         {
17236                             list.reverse();
17237                         }
17238                     };
17239                                         function toggleTree(e){
17240                                         e.stopPropagation();
17241                                                 if ($(e.target).attr("tree-view") !== undefined)
17242                         {
17243                             if (elem.hasClass('minus'))
17244                             {
17245                                 elem.removeClass('minus');
17246                             }
17247                             else
17248                             {
17249                                 elem.addClass('minus');
17250                             }
17251                             toggleBranch();
17252                         }
17253                                         }
17254                     elem.on('click', function(e) {
17255                                                 toggleTree(e);
17256                     });
17257                                         elem.on('keypress', function (e) {                                              
17258                                                 var activeCode = e.keyCode ? e.keyCode : e.charCode;                            
17259                                                 var keyCode = [13,32];
17260                                                 if(keyCode.length > 0 && ((activeCode && keyCode.indexOf(activeCode) > -1))) {                                          
17261                                                         toggleTree(e);                                                  
17262                                                         e.preventDefault();
17263                                                 }
17264                                         });                                     
17265                 }
17266             };
17267         });
17268
17269 angular.module('att.abs.typeAhead', ['att.abs.tagBadges'])
17270
17271         .directive('focusMe',['$timeout', '$parse', function($timeout, $parse) {
17272             return {
17273                 link: function(scope, element, attrs) {
17274                     var model = $parse(attrs.focusMe);
17275                     
17276                     scope.$watch(model, function(value) {
17277                         if (value === true) {
17278                             $timeout(function() {
17279                                 element[0].focus();
17280                                 scope.inputActive=true;
17281                             });
17282                         }
17283                     });
17284                     
17285                     element.bind('blur', function() {
17286                         scope.$apply(model.assign(scope, false));
17287                              scope.inputActive=false;
17288                     });
17289                 }
17290             };
17291         }])
17292
17293         .directive('typeAhead', ['$timeout', function($timeout) {
17294                 return {
17295                     restrict: 'EA',
17296                     templateUrl: 'app/scripts/ng_js_att_tpls/typeAhead/typeAhead.html',
17297                     replace: true,
17298                     scope: {
17299                         items: '=',
17300                         title: '@',
17301                         subtitle: '@',
17302                         model: '=',
17303                         emailIdList:'=',
17304                         emailMessage:'='
17305                     },
17306                     link: function(scope, elem, attrs) {
17307                         scope.lineItems = [];
17308                         scope.filteredListLength = -1;
17309                         scope.filteredList = [];
17310                         scope.inputfocus = false;
17311
17312                         scope.setFocus = function() {
17313                             scope.clickFocus = true;
17314                         };
17315                        
17316                         scope.handleSelection = function(selectedItem,emailItem) {
17317                             scope.lineItems.push(selectedItem);
17318                             scope.emailIdList.push(emailItem);
17319                             scope.model = "";
17320                             scope.current = 0;
17321                             scope.selected = true;
17322                             scope.clickFocus = true;
17323                            
17324                         };
17325                          
17326                         scope.theMethodToBeCalled = function(index) {
17327                             var tempArr = scope.lineItems.slice();
17328                             scope.emailIdList.splice(index, 1);
17329                             tempArr.splice(index, 1);
17330                             $timeout(function() {
17331                                 scope.lineItems = [];
17332                                 scope.$apply();
17333                                 scope.lineItems = scope.lineItems.concat(tempArr);
17334                             });
17335                            
17336                         };
17337
17338                         scope.current = 0;
17339                         scope.selected = true;
17340
17341                         scope.isCurrent = function(index, itemName,itemEmail,dropdownLength) {
17342                             if (scope.current === index) {
17343                                 scope.itemName = itemName;
17344                                 scope.itemEmail = itemEmail;
17345                             }
17346                            
17347                             scope.dropdownLength=dropdownLength;
17348                             return scope.current === index;
17349                         };
17350
17351                         scope.setCurrent = function(index) {
17352                             scope.current = index;
17353                         };
17354
17355                         scope.selectionIndex = function(evt) {
17356
17357                             if (evt.keyCode === 38 && scope.current > 0) {
17358                                evt.preventDefault();
17359                                 scope.current = scope.current - 1;
17360                                 scope.isCurrent(scope.current);
17361                             } else if (evt.keyCode === 9) {
17362                                 scope.selected = true;
17363                             } else if (evt.keyCode === 13 && scope.dropdownLength!==scope.items.length) {
17364                                 scope.handleSelection(scope.itemName,scope.itemEmail);
17365                             } else if (evt.keyCode === 8 && scope.model.length === 0) {
17366                                 scope.theMethodToBeCalled(scope.lineItems.length - 1);
17367                             } else if (evt.keyCode === 46) {
17368                                 scope.theMethodToBeCalled(scope.lineItems.length - 1);
17369                             } else if (evt.keyCode === 40 && scope.current < scope.dropdownLength-1) {
17370                                 evt.preventDefault();
17371                                 scope.current = scope.current + 1;
17372                                 scope.isCurrent(scope.current); 
17373                             }
17374
17375                             elem[0].querySelector('.list-scrollable').scrollTop = (scope.current - 1) * 35;
17376                         };
17377                     }
17378                 };
17379             }]);
17380 angular.module('att.abs.userMessages',[])
17381 .constant('messageConstants', {
17382         TABLE_MESSAGE_TYPES: {
17383                 noMatching: 1,
17384                 errorLoading: 2,
17385                 magnifySearch: 3,
17386                 isLoading: 4
17387         },
17388         USER_MESSAGE_TYPES: {
17389                 success: 1,
17390                 error: 0
17391         }
17392 })
17393 .directive('attTableMessage', ['messageConstants',function(messageConstants) {
17394
17395         return {
17396                 restrict: 'AE',
17397                 replace: true,
17398                 transclude: true,
17399                 scope: {
17400                         msgType: '=',
17401                         onRefreshClick: '&'
17402                 },
17403                 templateUrl: 'app/scripts/ng_js_att_tpls/userMessages/attTableMessage.html',
17404                 link: function(scope,elements,attr){
17405                         scope.messageConstants = messageConstants;
17406                         scope.refreshAction= function(evt){
17407                                 scope.onRefreshClick(evt);
17408                         };
17409                 }
17410         };
17411 }]).directive('attUserMessage', ['messageConstants',function(messageConstants) {
17412
17413         return{
17414                 restrict: 'AE',
17415                 replace: true,
17416                 transclude:true,
17417                 scope: {
17418                         thetitle: '=',
17419                         type: '=',
17420                         message: '=',
17421                         trigger: '='
17422                 },
17423                 templateUrl: 'app/scripts/ng_js_att_tpls/userMessages/attUserMessage.html',
17424                 link: function(scope,element,attrs) {
17425                         scope.messageConstants= messageConstants;
17426                 }
17427         };
17428 }]);
17429 angular.module('att.abs.verticalSteptracker', [])
17430     .directive('verticalSteptracker', [
17431     function() {
17432         return {
17433         restrict: 'EA',
17434         transclude: true,
17435         replace: false,
17436         scope: {
17437         },
17438         template: '<div class="vertical-nav"><ul ng-transclude class="tickets-list-height"></ul></div>',
17439         link:function(scope,elem,attribute,ctrl)  {
17440
17441         }   
17442     };
17443      }
17444  ])
17445      .directive('verticalSteptrackerStep',[
17446         function() {
17447         return {            
17448             restrict: 'EA',
17449             transclude: true,
17450             replace: false,
17451             scope: {
17452                 type: "=type",
17453                 id: "=id"
17454             },
17455             templateUrl: 'app/scripts/ng_js_att_tpls/verticalSteptracker/vertical-step-tracker.html',
17456             link: function(scope, elem, attr, ctrl) {
17457
17458                 
17459             }
17460          };
17461      }
17462      ])
17463      
17464         .directive('attAbsLink',[function(){
17465                 return{
17466                     restrict: 'EA',
17467                     transclude: true,
17468                     replace: false,                    
17469                     template: '<span ng-transclude class="view-log"></span>',
17470                     link: function(scope, elem, attr, ctrl) {
17471                 
17472             }
17473                 };
17474         }])
17475
17476
17477
17478 angular.module('att.abs.videoControls', [])
17479         .config(['$compileProvider' , function ($compileProvider) {
17480                 $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|javascript):/);
17481             }])
17482         .directive('videoControls', [function() {
17483                 return {
17484                     restrict: 'EA',
17485                     replace: true,
17486                     transclude: true,
17487                     templateUrl: 'app/scripts/ng_js_att_tpls/videoControls/videoControls.html'
17488                 };
17489             }])
17490         .directive('photoControls', [function() {
17491                 return {
17492                     restrict: 'EA',
17493                     replace: true,
17494                     transclude: true,
17495                     templateUrl: 'app/scripts/ng_js_att_tpls/videoControls/photoControls.html',
17496                     scope: {
17497                         prevLink: "@",
17498                         nextLink: "@"
17499                     },
17500                     link: function(scope, elem, attr, ctrl) {
17501                         if(!attr['prevLink'])
17502                             scope.prevLink = 'javascript:void(0)';
17503                         
17504                         if(!attr['nextLink'])
17505                             scope.nextLink = 'javascript:void(0)';
17506                         
17507                         scope.links = {
17508                             prevLink : scope.prevLink,
17509                             nextLink : scope.nextLink
17510                         }
17511                     }
17512                 };
17513             }]);
17514 angular.module("app/scripts/ng_js_att_tpls/accordion/accordion.html", []).run(["$templateCache", function($templateCache) {
17515   $templateCache.put("app/scripts/ng_js_att_tpls/accordion/accordion.html",
17516     "<div class=\"att-accordion__group tabpanel\" ng-class=\"{'att-accordion__group att-accordion__group--open':isOpen,'att-accordion__group':!isOpen }\">\n" +
17517     "    <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" +
17518     "        <span>{{heading}}</span>\n" +
17519     "        <i ng-class=\"{'icon-chevron-down':!isOpen,'icon-chevron-up':isOpen }\" class=\"pull-right\"></i>\n" +
17520     "    </a>\n" +
17521     "    <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" +
17522     "    <div id=\"panel{{index}}\" aria-labelledby=\"tab{{index}}\" aria-hidden=\"{{!isOpen}}\" role=\"tabpanel\" collapse=\"!isOpen\" class=\"att-accordion__body\" ng-transclude>\n" +
17523     "    </div>\n" +
17524     "    <div class=\"att-accordion__bottom--border\"></div>    \n" +
17525     "</div> ");
17526 }]);
17527
17528 angular.module("app/scripts/ng_js_att_tpls/accordion/accordion_alt.html", []).run(["$templateCache", function($templateCache) {
17529   $templateCache.put("app/scripts/ng_js_att_tpls/accordion/accordion_alt.html",
17530     "<div class=\"att-accordion__group tabpanel\" ng-class=\"{'att-accordion__group att-accordion__group--open':isOpen,'att-accordion__group':!isOpen }\">\n" +
17531     "    <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" +
17532     "    </a>\n" +
17533     "    <span>{{heading}}</span>\n" +
17534     "    <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" +
17535     "    </div>\n" +
17536     "</div> ");
17537 }]);
17538
17539 angular.module("app/scripts/ng_js_att_tpls/accordion/attAccord.html", []).run(["$templateCache", function($templateCache) {
17540   $templateCache.put("app/scripts/ng_js_att_tpls/accordion/attAccord.html",
17541     "<div ng-transclude></div>");
17542 }]);
17543
17544 angular.module("app/scripts/ng_js_att_tpls/accordion/attAccordBody.html", []).run(["$templateCache", function($templateCache) {
17545   $templateCache.put("app/scripts/ng_js_att_tpls/accordion/attAccordBody.html",
17546     "<div ng-transclude></div>");
17547 }]);
17548
17549 angular.module("app/scripts/ng_js_att_tpls/accordion/attAccordHeader.html", []).run(["$templateCache", function($templateCache) {
17550   $templateCache.put("app/scripts/ng_js_att_tpls/accordion/attAccordHeader.html",
17551     "<div ng-click=\"clickFunc()\">\n" +
17552     "   <div ng-transclude>\n" +
17553     "           <i class=\"icon-chevron-down\"></i>\n" +
17554     "   </div>\n" +
17555     "</div>");
17556 }]);
17557
17558 angular.module("app/scripts/ng_js_att_tpls/alert/alert.html", []).run(["$templateCache", function($templateCache) {
17559   $templateCache.put("app/scripts/ng_js_att_tpls/alert/alert.html",
17560     "<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" +
17561     "    <div class=\"container\">\n" +
17562     "        <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" +
17563     "        <span ng-transclude> </span>\n" +
17564     "    </div>\n" +
17565     "</div>");
17566 }]);
17567
17568 angular.module("app/scripts/ng_js_att_tpls/colorselector/colorselector.html", []).run(["$templateCache", function($templateCache) {
17569   $templateCache.put("app/scripts/ng_js_att_tpls/colorselector/colorselector.html",
17570     "<div class=\"att-radio att-color-selector__item\"  \n" +
17571     "     ng-class=\"{'att-radio--on': (iconColor === selected)}\">\n" +
17572     "    <div class=\"att-radio__indicator\"  tabindex=\"0\" att-accessibility-click=\"32,13\"ng-click=\"selectedcolor(iconColor)\" \n" +
17573     "         ng-style=\"applycolor\" ng-transclude></div>\n" +
17574     "</div>");
17575 }]);
17576
17577 angular.module("app/scripts/ng_js_att_tpls/datepicker/dateFilter.html", []).run(["$templateCache", function($templateCache) {
17578   $templateCache.put("app/scripts/ng_js_att_tpls/datepicker/dateFilter.html",
17579     "<div class=\"calendar\" ng-class=\"{'monthpicker':mode === 1}\">\n" +
17580     "    <div class=\"select2-container\" ng-class=\"{'select2-container-active select2-dropdown-open': showDropdownList}\" style=\"width: 100%; z-index:0\">\n" +
17581     "        <a tabindex=\"0\" class=\"select2-choice\" href=\"javascript:void(0)\" ng-show=\"!showCalendar\" att-accessibility-click=\"13,32\" ng-click=\"showDropdown()\">\n" +
17582     "            <span class=\"select2-chosen\" ng-show=\"!showCalendar\">{{selectedOption}}</span>\n" +
17583     "            <input type=\"text\" ng-show=\"showCalendar\" ng-blur=\"untrackInputChange($event)\" att-input-deny=\"[^0-9\\/-]\" maxlength=\"{{maxLength}}\" ng-model=\"selectedOption\" ng-change=\"getDropdownText()\" />\n" +
17584     "            <abbr class=\"select2-search-choice-close\"></abbr>\n" +
17585     "            <span ng-class=\"{'select2-arrow': mode !== 1, 'calendar-icon': mode === 1}\"><b></b></span>\n" +
17586     "        </a>\n" +
17587     "        <a class=\"select2-choice\" href=\"javascript:void(0)\" ng-show=\"showCalendar\">\n" +
17588     "            <span class=\"select2-chosen\" ng-show=\"!showCalendar\">{{selectedOption}}</span>\n" +
17589     "            <input type=\"text\" ng-show=\"showCalendar\" ng-blur=\"untrackInputChange($event)\" att-input-deny=\"[^0-9\\/-]\" maxlength=\"{{maxLength}}\" ng-model=\"selectedOption\" ng-change=\"getDropdownText()\" />\n" +
17590     "            <abbr class=\"select2-search-choice-close\"></abbr>\n" +
17591     "            <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" +
17592     "        </a>\n" +
17593     "    </div>\n" +
17594     "    <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" +
17595     "        <ul class=\"select2-results options\" style=\"margin-top:0px;height:120px;overflow:auto;\" ng-transclude></ul>\n" +
17596     "           <ul class=\"select2-results sttings\" style=\"margin-top:0px\">\n" +
17597     "                   <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" +
17598     "                <div class=\"select2-result-label\" ng-if=\"mode !== 1\">Custom Single Date...</div>\n" +
17599     "                           <div class=\"select2-result-label\" ng-if=\"mode === 1\">Custom single month...</div>\n" +
17600     "            </li>                  \n" +
17601     "            <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" +
17602     "                <div class=\"select2-result-label\" ng-if=\"mode !== 1\">Custom Range...</div>\n" +
17603     "                           <div class=\"select2-result-label\" ng-if=\"mode === 1\">Custom month range...</div>\n" +
17604     "            </li>\n" +
17605     "            <li class=\"select2-result select2-highlighted btnContainer\" ng-style=\"{display: (showCalendar && 'block') || 'none'}\">\n" +
17606     "                <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" +
17607     "                <button tabindex=\"0\" att-button=\"\" btn-type=\"secondary\" size=\"small\" att-accessibility-click=\"13,32\" ng-click=\"cancel()\">Cancel</button>\n" +
17608     "                <div>\n" +
17609     "                    <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" +
17610     "                    <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" +
17611     "                </div>\n" +
17612     "            </li>\n" +
17613     "           </ul>\n" +
17614     "    </div>\n" +
17615     "    <div class=\"datepicker-wrapper show-right\" ng-style=\"{display: (showCalendar && 'block') || 'none'}\">\n" +
17616     "        <span datepicker ng-blur=\"resetFocus($event)\" att-element-focus=\"focusSingleDateCalendar\" ng-show=\"checkCurrentSelection('Custom Single Date')\"></span>\n" +
17617     "        <span datepicker ng-blur=\"resetFocus($event)\" att-element-focus=\"focusRangeCalendar\" ng-show=\"checkCurrentSelection('Custom Range')\"></span>\n" +
17618     "    </div>\n" +
17619     "</div>\n" +
17620     "");
17621 }]);
17622
17623 angular.module("app/scripts/ng_js_att_tpls/datepicker/dateFilterList.html", []).run(["$templateCache", function($templateCache) {
17624   $templateCache.put("app/scripts/ng_js_att_tpls/datepicker/dateFilterList.html",
17625     "<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" +
17626     "                <div class=\"select2-result-label\" ng-class=\"{'disabled':disabled}\" ng-transclude></div>\n" +
17627     "</li>");
17628 }]);
17629
17630 angular.module("app/scripts/ng_js_att_tpls/datepicker/datepicker.html", []).run(["$templateCache", function($templateCache) {
17631   $templateCache.put("app/scripts/ng_js_att_tpls/datepicker/datepicker.html",
17632     "<ul id=\"datepicker\" class=\"datepicker\" ng-class=\"{'monthpicker': mode === 1}\" aria-hidden=\"false\" role=\"dialog\" tabindex=\"-1\">\n" +
17633     "    <div class=\"datepicker-days\" style=\"display: block;\">\n" +
17634     "        <table class=\"table-condensed\">\n" +
17635     "            <thead>\n" +
17636     "                <tr>\n" +
17637     "                    <th id=\"month\" tabindex=\"0\" align=\"left\" class=\"datepicker-switch\" colspan=\"{{(mode !== 1) && (currentRows[0].length - 2) || (currentRows[0].length)}}\">{{currentTitle}}</th>\n" +
17638     "                    <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" +
17639     "                        <div class=\"icons-list\" data-size=\"medium\"><i class=\"icon-arrow-left-circle\" ng-class=\"{'disabled': disablePrev}\"></i>\n" +
17640     "                        </div><span class=\"hidden-spoken\">Previous Month</span>\n" +
17641     "                    </th>\n" +
17642     "                    <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" +
17643     "                        <div class=\"icons-list\" data-size=\"medium\"><i class=\"icon-arrow-right-circle\" ng-class=\"{'disabled': disableNext}\"></i>\n" +
17644     "                        </div><span class=\"hidden-spoken\">Next Month</span>\n" +
17645     "                    </th>\n" +
17646     "                </tr>\n" +
17647     "                <tr ng-if=\"labels.length > 0\">\n" +
17648     "                    <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" +
17649     "                </tr>\n" +
17650     "            </thead>\n" +
17651     "            <tbody>\n" +
17652     "                <tr>\n" +
17653     "                    <td id=\"datepickerBody\" att-scrollbar colspan=\"{{currentRows[0].length}}\" style=\"padding: 0px;\">\n" +
17654     "                        <table ng-class=\"{'table-condensed': mode === 0, 'monthtable-condensed': mode === 1}\" style=\"padding: 0px;\">\n" +
17655     "                            <tbody>\n" +
17656     "                                <tr ng-repeat=\"row in currentRows\">\n" +
17657     "                                    <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" +
17658     "                                </tr>\n" +
17659     "                                                           <tr ng-if=\"mode === 1\" class=\"divider\"><td colspan=\"{{nextRows[0].length}}\"><hr></td></tr>\n" +
17660     "                                <tr>\n" +
17661     "                                    <th id=\"month\" tabindex=\"0\" align=\"left\" class=\"datepicker-switch internal\" colspan=\"{{nextRows[0].length}}\">{{nextTitle}}</th>\n" +
17662     "                                </tr>\n" +
17663     "                                <tr ng-repeat=\"row in nextRows\">\n" +
17664     "                                    <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" +
17665     "                                </tr>\n" +
17666     "                            </tbody>\n" +
17667     "                        </table>\n" +
17668     "                    </td>\n" +
17669     "                </tr>\n" +
17670     "            </tbody>\n" +
17671     "        </table>\n" +
17672     "    </div>\n" +
17673     "</ul>\n" +
17674     "");
17675 }]);
17676
17677 angular.module("app/scripts/ng_js_att_tpls/datepicker/datepickerPopup.html", []).run(["$templateCache", function($templateCache) {
17678   $templateCache.put("app/scripts/ng_js_att_tpls/datepicker/datepickerPopup.html",
17679     "<div class=\"calendar\">\n" +
17680     "    <div class=\"box\" ng-class=\"{'active': isOpen}\">\n" +
17681     "        <span ng-transclude></span>\n" +
17682     "        <i class=\"calendar-icon\" tabindex=\"0\" att-accessibility-click=\"13,32\" ng-click=\"toggle()\"></i>\n" +
17683     "    </div>\n" +
17684     "    <div class=\"datepicker-wrapper datepicker-wrapper-display-none\" ng-style=\"{display: (isOpen && 'block') || 'none'}\" aria-hidden=\"false\" role=\"dialog\" tabindex=\"-1\">\n" +
17685     "        <span datepicker></span>\n" +
17686     "    </div>\n" +
17687     "</div>\n" +
17688     "");
17689 }]);
17690
17691 angular.module("app/scripts/ng_js_att_tpls/dividerLines/dividerLines.html", []).run(["$templateCache", function($templateCache) {
17692   $templateCache.put("app/scripts/ng_js_att_tpls/dividerLines/dividerLines.html",
17693     "<div class=\"divider-container\" ng-class=\"{'divider-container-light': lightContainer}\">\n" +
17694     "    <hr ng-class=\"{'divider-light': lightContainer}\">\n" +
17695     "</div>\n" +
17696     "\n" +
17697     "");
17698 }]);
17699
17700 angular.module("app/scripts/ng_js_att_tpls/dragdrop/fileUpload.html", []).run(["$templateCache", function($templateCache) {
17701   $templateCache.put("app/scripts/ng_js_att_tpls/dragdrop/fileUpload.html",
17702     "<label class=\"fileContainer\"><span ng-transclude></span><input type=\"file\" att-file-change></label>");
17703 }]);
17704
17705 angular.module("app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlert.html", []).run(["$templateCache", function($templateCache) {
17706   $templateCache.put("app/scripts/ng_js_att_tpls/formField/attFormFieldValidationAlert.html",
17707     "<div class=\"form-field\" ng-class=\"{'error': errorMessage, 'warning': warningMessage}\">\n" +
17708     "    <label class=\"form-field__label\" ng-class=\"{'form-field__label--show': showLabel, 'form-field__label--hide': hideLabel}\"></label>\n" +
17709     "    <div class=\"form-field-input-container\" ng-transclude></div>\n" +
17710     "</div>");
17711 }]);
17712
17713 angular.module("app/scripts/ng_js_att_tpls/hourpicker/hourpicker.html", []).run(["$templateCache", function($templateCache) {
17714   $templateCache.put("app/scripts/ng_js_att_tpls/hourpicker/hourpicker.html",
17715     "<div class=\"hourpicker\">\n" +
17716     "    <div class=\"dropdown-width\">\n" +
17717     "        <div ng-model=\"showlist\" class=\"select2-container topDropDownWidth\" ng-class=\"{'select2-dropdown-open select2-container-active': showlist}\" >\n" +
17718     "            <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" +
17719     "                <span class=\"select2-chosen\">{{selectedOption}}</span>\n" +
17720     "                <span class=\"select2-arrow\"><b></b></span>\n" +
17721     "            </a>\n" +
17722     "        </div>             \n" +
17723     "        <div class=\"select2-display-none select2-with-searchbox select2-drop-active show-search resultTopWidth\" ng-show=\"showlist\">       \n" +
17724     "        <ul class=\"select2-results resultTopMargin\" >                       \n" +
17725     "            <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" +
17726     "        </ul>\n" +
17727     "        </div>\n" +
17728     "    </div>\n" +
17729     "    <div ng-show=\"showDaysSelector\" class=\"customdays-width\">\n" +
17730     "        <div att-divider-lines class=\"divider-margin-f\"></div>  \n" +
17731     "        <div class=\"col-md-3 fromto-margin\">\n" +
17732     "            <div>From</div> <br>\n" +
17733     "            <div>To</div>\n" +
17734     "        </div>\n" +
17735     "        <div ng-repeat=\"day in days\">\n" +
17736     "            <div class=\"col-md-3 col-md-days\">\n" +
17737     "                <div  class=\"col-md-1 daysselect-margin\">\n" +
17738     "                    <input type=\"checkbox\" ng-model=\"daysList[day]\" title=\"Day selection\" att-checkbox ng-change=\"addSelectedValue(day)\">    \n" +
17739     "                </div>\n" +
17740     "                <span>{{day}}</span><br>\n" +
17741     "                \n" +
17742     "                <div class=\"dropDownMarginBottom\">\n" +
17743     "                    <div class=\"select2-container topDropDownWidth\" ng-class=\"{'select2-dropdown-open select2-container-active': FrtimeListDay[day]}\" >\n" +
17744     "                        <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" +
17745     "                            <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" +
17746     "                        </a>\n" +
17747     "                    </div>             \n" +
17748     "                    \n" +
17749     "                    <div class=\"select2-display-none select2-with-searchbox select2-drop-active show-search resultFromDropDown\"  ng-show=\"FrtimeListDay[day]\">       \n" +
17750     "                    <ul class=\"select2-results resultTopMargin\" >                       \n" +
17751     "                        <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" +
17752     "                    </ul>\n" +
17753     "                    </div>\n" +
17754     "                </div>\n" +
17755     "                \n" +
17756     "                <div class=\"dropDownMarginBottom\">\n" +
17757     "                    <div class=\"select2-container topDropDownWidth\" ng-class=\"{'select2-dropdown-open select2-container-active': TotimeListDay[day]}\" >\n" +
17758     "                        <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" +
17759     "                            <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" +
17760     "                        </a>\n" +
17761     "                    </div>\n" +
17762     "                    \n" +
17763     "                    <div class=\"select2-display-none select2-with-searchbox select2-drop-active show-search resultToDropDown\" ng-show=\"TotimeListDay[day]\">       \n" +
17764     "                    <ul class=\"select2-results resultTopMargin\" >                       \n" +
17765     "                        <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" +
17766     "                    </ul>\n" +
17767     "                    </div>\n" +
17768     "                </div>\n" +
17769     "            </div>  \n" +
17770     "        </div>    \n" +
17771     "        <div att-divider-lines class=\"divider-margin-s\"></div>    \n" +
17772     "    </div>\n" +
17773     "    <div ng-transclude></div>\n" +
17774     "</div>");
17775 }]);
17776
17777 angular.module("app/scripts/ng_js_att_tpls/links/readMore.html", []).run(["$templateCache", function($templateCache) {
17778   $templateCache.put("app/scripts/ng_js_att_tpls/links/readMore.html",
17779     "<div>\n" +
17780     "    <div ng-bind-html=\"textToDisplay\" ng-class=\"{'att--readMore': readFlag, 'att--readLess': !readFlag}\" ng-style=\"readLinkStyle\"></div>\n" +
17781     "    <span class=\"att--readmore__link\" ng-show=\"readMoreLink\">\85 <a href=\"#\" ng-click=\"readMore()\" att-accessbility-click=\"32,13\">Read More</a>\n" +
17782     "    </span>\n" +
17783     "</div>\n" +
17784     "<span class=\"att--readless__link\" ng-show=\"readLessLink\">\n" +
17785     "    <a href=\"#\" ng-click=\"readLess()\" att-accessbility-click=\"32,13\">Read Less</a>\n" +
17786     "</span>");
17787 }]);
17788
17789 angular.module("app/scripts/ng_js_att_tpls/loading/loading.html", []).run(["$templateCache", function($templateCache) {
17790   $templateCache.put("app/scripts/ng_js_att_tpls/loading/loading.html",
17791     "<div data-progress=\"{{progressStatus}}\" class=\"{{colorClass}}\" ng-class=\"{'att-loading-count':icon == 'count','loading--small':icon == 'small','loading': icon != 'count'}\">\n" +
17792     "   <div class=\"att-loading-circle\" ng-if=\"icon == 'count'\">\n" +
17793     "           <div class=\"att-loading-circle__mask att-loading-circle__full\">\n" +
17794     "                   <div class=\"att-loading-circle__fill\"></div>\n" +
17795     "           </div>\n" +
17796     "           <div class=\"att-loading-circle__mask att-loading-circle__half\">\n" +
17797     "                   <div class=\"att-loading-circle__fill\"></div>\n" +
17798     "                   <div class=\"att-loading-circle__fill att-loading-circle__fix\"></div>\n" +
17799     "           </div>\n" +
17800     "   </div>\n" +
17801     "   <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" +
17802     "</div>\n" +
17803     "\n" +
17804     "");
17805 }]);
17806
17807 angular.module("app/scripts/ng_js_att_tpls/modal/backdrop.html", []).run(["$templateCache", function($templateCache) {
17808   $templateCache.put("app/scripts/ng_js_att_tpls/modal/backdrop.html",
17809     "<div class=\"overlayed\" ng-class=\"{show: animate}\" \n" +
17810     "     ng-style=\"{'z-index': 2000 + index*10,'overflow':'scroll'}\">         \n" +
17811     "</div>");
17812 }]);
17813
17814 angular.module("app/scripts/ng_js_att_tpls/modal/window.html", []).run(["$templateCache", function($templateCache) {
17815   $templateCache.put("app/scripts/ng_js_att_tpls/modal/window.html",
17816     "<div tabindex=\"-1\" role=\"dialog\" att-element-focus=\"focusModalFlag\" class=\"modals {{ windowClass }}\" ng-class=\"{show: animate}\" \n" +
17817     "     ng-style=\"{'z-index': 2010 + index*10}\"  ng-click=\"close($event)\" ng-transclude>         \n" +
17818     "</div>\n" +
17819     "");
17820 }]);
17821
17822 angular.module("app/scripts/ng_js_att_tpls/pagination/pagination.html", []).run(["$templateCache", function($templateCache) {
17823   $templateCache.put("app/scripts/ng_js_att_tpls/pagination/pagination.html",
17824     "<div class=\"pager\">\n" +
17825     "    <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" +
17826     "    <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" +
17827     "    <span class=\"pager__item\" ng-if=\"totalPages > 7 && currentPage > 3\">...</span>\n" +
17828     "    <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" +
17829     "    <span class=\"pager__item\" ng-if=\"totalPages > 7 && currentPage < totalPages - 2 && showInput !== true\">...</span>\n" +
17830     "    <span ng-show=\"totalPages > 7 && showInput === true\"><input class=\"pager__item--input\" type=\"text\" placeholder=\"...\" maxlength=\"2\" ng-model=\"currentPage\"/></span>\n" +
17831     "    <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" +
17832     "    <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" +
17833     "</div>");
17834 }]);
17835
17836 angular.module("app/scripts/ng_js_att_tpls/paneSelector/innerPane.html", []).run(["$templateCache", function($templateCache) {
17837   $templateCache.put("app/scripts/ng_js_att_tpls/paneSelector/innerPane.html",
17838     "<div class='inner-pane'>\n" +
17839     "   <div ng-transclude>\n" +
17840     "   </div>\n" +
17841     "</div>");
17842 }]);
17843
17844 angular.module("app/scripts/ng_js_att_tpls/paneSelector/paneGroup.html", []).run(["$templateCache", function($templateCache) {
17845   $templateCache.put("app/scripts/ng_js_att_tpls/paneSelector/paneGroup.html",
17846     "<div class='pane-group'>\n" +
17847     "   <div ng-transclude>\n" +
17848     "   </div>\n" +
17849     "</div>");
17850 }]);
17851
17852 angular.module("app/scripts/ng_js_att_tpls/paneSelector/sidePane.html", []).run(["$templateCache", function($templateCache) {
17853   $templateCache.put("app/scripts/ng_js_att_tpls/paneSelector/sidePane.html",
17854     "<div class='side-pane'>    \n" +
17855     "   <div ng-transclude>\n" +
17856     "   </div>\n" +
17857     "</div>");
17858 }]);
17859
17860 angular.module("app/scripts/ng_js_att_tpls/profileCard/addUser.html", []).run(["$templateCache", function($templateCache) {
17861   $templateCache.put("app/scripts/ng_js_att_tpls/profileCard/addUser.html",
17862     "<div  class=\"col-md-9 profile-card add-user\">\n" +
17863     "    <div class=\"atcenter\">\n" +
17864     "        <div><i class=\"icon-add\"></i></div>\n" +
17865     "        <span>add User</span>\n" +
17866     "    </div>\n" +
17867     "</div>");
17868 }]);
17869
17870 angular.module("app/scripts/ng_js_att_tpls/profileCard/profileCard.html", []).run(["$templateCache", function($templateCache) {
17871   $templateCache.put("app/scripts/ng_js_att_tpls/profileCard/profileCard.html",
17872     "<div class=\"col-md-9 profile-card\">\n" +
17873     "    <div class=\"top-block\">\n" +
17874     "       <div class=\"profile-image\">\n" +
17875     "            <img ng-if=\"image\" profile-name=\"{{profile.name}}\" ng-src=\"{{profile.img}}\">\n" +
17876     "            <span ng-hide=\"image\" class=\"default-img\">{{initials}}</span>\n" +
17877     "            <p class=\"name\" tooltip-condition=\"{{profile.name}}\" height=\"true\"></p>\n" +
17878     "            <p class=\"status\">\n" +
17879     "                <span class=\"status-icon\" ng-class=\"{'icon-green':colorIcon==='green','icon-red':colorIcon==='red','icon-blue':colorIcon==='blue','icon-yellow':colorIcon==='yellow'}\">   \n" +
17880     "                </span>\n" +
17881     "                <span>{{profile.state}}<span ng-if=\"badge\" class=\"status-badge\">Admin</span></span>\n" +
17882     "            </p>\n" +
17883     "        </div>\n" +
17884     "    </div>\n" +
17885     "    <div class=\"bottom-block\">\n" +
17886     "         <div class=\"profile-details\">\n" +
17887     "            <label>Username</label>\n" +
17888     "            <p att-text-overflow=\"92%\" tooltip-condition=\"{{profile.userName}}\">{{profile.userName}}</p>\n" +
17889     "            <label>Email</label>\n" +
17890     "            <p att-text-overflow=\"92%\" tooltip-condition=\"{{profile.email}}\">{{profile.email}}</p>\n" +
17891     "            <label>Role</label>\n" +
17892     "            <p att-text-overflow=\"92%\" tooltip-condition=\"{{profile.role}}\">{{profile.role}}</p>\n" +
17893     "            <label>Last Login</label>\n" +
17894     "            <p att-text-overflow=\"92%\" tooltip-condition=\"{{profile.lastLogin}}\">{{profile.lastLogin}}</p>\n" +
17895     "         </div>\n" +
17896     "    </div>\n" +
17897     "</div>");
17898 }]);
17899
17900 angular.module("app/scripts/ng_js_att_tpls/progressBars/progressBars.html", []).run(["$templateCache", function($templateCache) {
17901   $templateCache.put("app/scripts/ng_js_att_tpls/progressBars/progressBars.html",
17902     "<div class=\"att-progress\">\n" +
17903     "    <div class=\"att-progress-value\">&nbsp;</div>\n" +
17904     "</div>");
17905 }]);
17906
17907 angular.module("app/scripts/ng_js_att_tpls/scrollbar/scrollbar.html", []).run(["$templateCache", function($templateCache) {
17908   $templateCache.put("app/scripts/ng_js_att_tpls/scrollbar/scrollbar.html",
17909     "<div class=\"scroll-bar\">\n" +
17910     "   <div class=\"scroll-thumb\"></div>\n" +
17911     "</div>\n" +
17912     "<div class=\"scroll-viewport\">\n" +
17913     "   <div class=\"scroll-overview\" ng-transclude></div>\n" +
17914     "</div>");
17915 }]);
17916
17917 angular.module("app/scripts/ng_js_att_tpls/search/search.html", []).run(["$templateCache", function($templateCache) {
17918   $templateCache.put("app/scripts/ng_js_att_tpls/search/search.html",
17919     "<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" +
17920     "   <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" +
17921     "           <span class=\"select2-chosen needsclick\">{{selectedOption}}</span>\n" +
17922     "           <abbr class=\"select2-search-choice-close needsclick\"></abbr>   \n" +
17923     "           <span class=\"select2-arrow needsclick\" role=\"presentation\">\n" +
17924     "                   <b role=\"presentation\" class=\"needsclick\"></b>\n" +
17925     "           </span>\n" +
17926     "        </a>\n" +
17927     "   <label class=\"select2-offscreen\"></label>\n" +
17928     "        <input class=\"select2-focusser select2-offscreen\" tabindex=\"-1\" type=\"text\" aria-haspopup=\"true\" role=\"button\">\n" +
17929     "</div>\n" +
17930     "<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" +
17931     "   <div class=\"select2-search\">       \n" +
17932     "           <label class=\"select2-offscreen\"></label>       \n" +
17933     "           <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-expanded=\"true\" \n" +
17934     "                   aria-autocomplete=\"list\" placeholder=\"\">   \n" +
17935     "   </div>   \n" +
17936     "   <ul class=\"select2-results\" role=\"listbox\">\n" +
17937     "                <li ng-show=\"filteredName.length === 0\" class=\"select2-no-results\">No matches found</li>\n" +
17938     "           <li class=\"select2-results-dept-0 select2-result select2-result-selectable\" role=\"presentation\"\n" +
17939     "                    ng-model=\"ListType\" ng-show=\"selectMsg && filteredName.length > 0\" \n" +
17940     "                    ng-click=\"selectOption(selectMsg, '-1')\" \n" +
17941     "                    ng-class=\"{'select2-result-current': selectedOption === selectMsg, 'hovstyle': selectedIndex === -1}\" \n" +
17942     "                    ng-mouseover=\"hoverIn(-1)\">\n" +
17943     "                   <div class=\"select2-result-label\"  ng-bind-html=\"selectMsg | highlight:title:className\" role=\"option\">\n" +
17944     "                           <span class=\"select2-match\" ></span>\n" +
17945     "                   </div>\n" +
17946     "           </li>                        \n" +
17947     "           <li class=\"select2-results-dept-0 select2-result select2-result-selectable\" role=\"presentation\"\n" +
17948     "                    ng-model=\"ListType\" ng-repeat=\"(fIndex, item) in filteredName = (cName | filter:title)\" \n" +
17949     "                    ng-class=\"{'select2-result-current': selectedOption === item.title,'hovstyle': selectedIndex === item.index}\"\n" +
17950     "                    ng-click=\"selectOption(item.title,item.index)\"\n" +
17951     "                    ng-mouseover=\"hoverIn(item.index)\">\n" +
17952     "                   <div class=\"select2-result-label\" ng-bind-html=\"item.title | highlight:title:className\" role=\"option\">\n" +
17953     "                           <span class=\"select2-match\" ></span>\n" +
17954     "                   </div>\n" +
17955     "           </li>\n" +
17956     "           \n" +
17957     "   </ul>\n" +
17958     "</div>");
17959 }]);
17960
17961 angular.module("app/scripts/ng_js_att_tpls/search/search_2.html", []).run(["$templateCache", function($templateCache) {
17962   $templateCache.put("app/scripts/ng_js_att_tpls/search/search_2.html",
17963     "<div ng-model=\"showlist\" class=\"select2-container\" ng-class=\"{'select2-dropdown-open select2-container-active': showlist}\" style=\"width: 100%; z-index:0\">\n" +
17964     "    <a tabindex=\"-1\" class=\"select2-choice\" href=\"javascript:void(0)\" ng-click=\"showDropdown()\">\n" +
17965     "        <span class=\"select2-chosen\">{{selectedOption}}</span>\n" +
17966     "        <abbr class=\"select2-search-choice-close\"></abbr>\n" +
17967     "        <span class=\"select2-arrow\"><b></b></span>\n" +
17968     "    </a>\n" +
17969     "    <input type=\"text\" class=\"select2-focusser select2-offscreen\">\n" +
17970     "</div>\n" +
17971     "<select ng-model=\"value\" ng-options=\"c.title for c in cName\" class=\"select2-offscreen\"></select>\n" +
17972     "<div class=\"select2-drop select2-display-none select2-with-searchbox select2-drop-active show-search\" style=\"display: block; width: 100%;\" ng-show=\"showlist\">\n" +
17973     "    <div ng-show=\"showSearch\" class=\"select2-search\">\n" +
17974     "        <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" +
17975     "    </div>\n" +
17976     "    <ul class=\"select2-results\" style=\"margin-top:0px;max-height:205px\">\n" +
17977     "        <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" +
17978     "            <div class=\"select2-result-label\" ng-bind-html=\"country.title | highlight:title:className\"><span class=\"select2-match\"></span>\n" +
17979     "            </div>\n" +
17980     "        </li>\n" +
17981     "    </ul>\n" +
17982     "</div>\n" +
17983     "");
17984 }]);
17985
17986 angular.module("app/scripts/ng_js_att_tpls/select/select.html", []).run(["$templateCache", function($templateCache) {
17987   $templateCache.put("app/scripts/ng_js_att_tpls/select/select.html",
17988     "<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" +
17989     "   <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" +
17990     "           <span class=\"select2-chosen needsclick\">{{selectedOption}}</span>\n" +
17991     "           <abbr class=\"select2-search-choice-close needsclick\"></abbr>\n" +
17992     "           <span class=\"select2-arrow needsclick\" role=\"presentation\">\n" +
17993     "                   <b role=\"presentation\" class=\"needsclick\"></b>\n" +
17994     "           </span>\n" +
17995     "        </a>\n" +
17996     "   <label class=\"select2-offscreen\"></label>\n" +
17997     "        <input class=\"select2-focusser select2-offscreen\" tabindex=\"-1\" type=\"text\" aria-haspopup=\"true\" role=\"button\">\n" +
17998     "</div>\n" +
17999     "<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" +
18000     "   <div class=\"select2-search\">\n" +
18001     "           <label class=\"select2-offscreen\"></label>\n" +
18002     "           <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-expanded=\"true\"  \n" +
18003     "                   aria-autocomplete=\"list\" placeholder=\"\">\n" +
18004     "   </div>\n" +
18005     "   <ul class=\"select2-results\" role=\"listbox\">\n" +
18006     "                <li ng-show=\"filteredName.length === 0\" class=\"select2-no-results\">No matches found</li>\n" +
18007     "           <li class=\"select2-results-dept-0 select2-result select2-result-selectable\" role=\"presentation\"\n" +
18008     "                    ng-model=\"ListType\" ng-show=\"selectMsg && filteredName.length > 0\"\n" +
18009     "                    ng-click=\"selectOption(selectMsg, '-1')\"\n" +
18010     "                    ng-class=\"{'select2-result-current': selectedOption === selectMsg, 'hovstyle': selectedIndex === -1}\"\n" +
18011     "                    ng-mouseover=\"hoverIn(-1)\"\n" +
18012     "                    >\n" +
18013     "                   <div ng-if=\"startsWithFilter\" class=\"select2-result-label\"  ng-bind-html=\"selectMsg\" role=\"option\">\n" +
18014     "                           <span class=\"select2-match\" ></span>\n" +
18015     "           </div>\n" +
18016     "            <div ng-if=\"!startsWithFilter\" class=\"select2-result-label\"  ng-bind-html=\"selectMsg | highlight:title:className\" role=\"option\">\n" +
18017     "                <span class=\"select2-match\" ></span>\n" +
18018     "            </div>\n" +
18019     "           </li>\n" +
18020     "           <li ng-if=\"startsWithFilter\" class=\"select2-results-dept-0 select2-result select2-result-selectable\" role=\"presentation\"\n" +
18021     "                    ng-model=\"ListType\" ng-repeat=\"(fIndex, item) in filteredName = (cName | startsWith:title:item)\"\n" +
18022     "                    ng-class=\"{'select2-result-current': selectedOption === item.title,'hovstyle': selectedIndex === item.index}\"\n" +
18023     "                    ng-click=\"selectOption(item.title,item.index)\"\n" +
18024     "                    ng-mouseover=\"hoverIn(item.index)\"\n" +
18025     "                    >\n" +
18026     "                   <div class=\"select2-result-label\" ng-bind-html=\"item.title\" role=\"option\">\n" +
18027     "                           <span class=\"select2-match\" ></span>\n" +
18028     "                   </div>\n" +
18029     "           </li>\n" +
18030     "\n" +
18031     "        <li ng-if=\"!startsWithFilter\" class=\"select2-results-dept-0 select2-result select2-result-selectable\" role=\"presentation\"\n" +
18032     "            ng-model=\"ListType\" ng-repeat=\"(fIndex, item) in filteredName = (cName | filter:title)\"\n" +
18033     "            ng-class=\"{'select2-result-current': selectedOption === item.title,'hovstyle': selectedIndex === item.index}\"\n" +
18034     "            ng-click=\"selectOption(item.title,item.index)\"\n" +
18035     "            ng-mouseover=\"hoverIn(item.index)\"\n" +
18036     "            >\n" +
18037     "            <div class=\"select2-result-label\" ng-bind-html=\"item.title | highlight:title:className\" role=\"option\">\n" +
18038     "                <span class=\"select2-match\" ></span>\n" +
18039     "            </div>\n" +
18040     "        </li>\n" +
18041     "\n" +
18042     "   </ul>\n" +
18043     "</div>\n" +
18044     "");
18045 }]);
18046
18047 angular.module("app/scripts/ng_js_att_tpls/select/textDropdown.html", []).run(["$templateCache", function($templateCache) {
18048   $templateCache.put("app/scripts/ng_js_att_tpls/select/textDropdown.html",
18049     "<div tabindex=\"0\" class=\"text-dropdown\">\n" +
18050     "   <div class=\"dropdown\" ng-class=\"{'not-visible': isActionsShown}\" ng-click=\"toggle()\" >\n" +
18051     "           <span class=\"action--selected\" ng-bind=\"currentAction\"></span>\n" +
18052     "           <i ng-class=\"isActionsShown ? 'icon-dropdown-up' : 'icon-dropdown-down'\"></i>\n" +
18053     "   </div>\n" +
18054     "\n" +
18055     "   <ul ng-class=\"isActionsShown ? 'actionsOpened' : 'actionsClosed'\" ng-show=\"isActionsShown\">\n" +
18056     "           <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" +
18057     "   </ul>\n" +
18058     "\n" +
18059     "</div>");
18060 }]);
18061
18062 angular.module("app/scripts/ng_js_att_tpls/slider/attStepSlider.html", []).run(["$templateCache", function($templateCache) {
18063   $templateCache.put("app/scripts/ng_js_att_tpls/slider/attStepSlider.html",
18064     "<span ng-class=\"mainSliderClass\">\n" +
18065     "    <table>\n" +
18066     "        <tr>\n" +
18067     "            <td>\n" +
18068     "                <div class=\"jslider-bg\">\n" +
18069     "                    <i class=\"l\"></i>\n" +
18070     "                    <i class=\"r\"></i>\n" +
18071     "                    <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" +
18072     "                </div>\n" +
18073     "                <div class=\"jslider-pointer\" id=\"left-pointer\"></div>\n" +
18074     "                <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" +
18075     "                <div class=\"jslider-label\"><span ng-bind=\"from\"></span><span ng-bind=\"options.dimension\"></span></div>\n" +
18076     "                <div class=\"jslider-label jslider-label-to\"><span ng-bind=\"toStr\"></span><span ng-bind=\"endDimension\"></span></div>\n" +
18077     "                <div class=\"jslider-value\" id=\"jslider-value-left\"><span></span>{{options.dimension}}</div>\n" +
18078     "                <div class=\"jslider-value jslider-value-to\"><span></span>{{toolTipDimension}}</div>\n" +
18079     "                <div class=\"jslider-scale\" ng-class=\"{'show-dividers': showDividers, 'cutoff-slider-dividers':isCutOffSlider}\">\n" +
18080     "                </div>\n" +
18081     "                <div class=\"jslider-cutoff\">\n" +
18082     "                    <div class=\"jslider-label jslider-label-cutoff\">\n" +
18083     "                        <span ng-bind=\"cutOffVal\"></span>\n" +
18084     "                    </div>\n" +
18085     "                </div>\n" +
18086     "            </td>\n" +
18087     "        </tr>\n" +
18088     "    </table>\n" +
18089     "</span>\n" +
18090     "");
18091 }]);
18092
18093 angular.module("app/scripts/ng_js_att_tpls/slider/maxContent.html", []).run(["$templateCache", function($templateCache) {
18094   $templateCache.put("app/scripts/ng_js_att_tpls/slider/maxContent.html",
18095     "<div class=\"att-slider__label att-slider__label--max att-slider__label--below\" ng-transclude></div>");
18096 }]);
18097
18098 angular.module("app/scripts/ng_js_att_tpls/slider/minContent.html", []).run(["$templateCache", function($templateCache) {
18099   $templateCache.put("app/scripts/ng_js_att_tpls/slider/minContent.html",
18100     "<div class=\"att-slider__label att-slider__label--min att-slider__label--below\" ng-transclude></div>");
18101 }]);
18102
18103 angular.module("app/scripts/ng_js_att_tpls/slider/slider.html", []).run(["$templateCache", function($templateCache) {
18104   $templateCache.put("app/scripts/ng_js_att_tpls/slider/slider.html",
18105     "<div class=\"att-slider\" ng-mousemove=\"moveElem($event)\" ng-mouseup=\"mouseUp($event)\">\n" +
18106     "    <div class=\"att-slider__track\">\n" +
18107     "        <div class=\"att-slider__range att-slider__range--disabled\" ng-style=\"disabledStyle\"></div>\n" +
18108     "        <div class=\"att-slider__range\" ng-style=\"rangeStyle\"></div>\n" +
18109     "    </div>\n" +
18110     "    <div class=\"att-slider__handles-container\">\n" +
18111     "       <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" +
18112     "       <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" +
18113     "       <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" +
18114     "    </div>\n" +
18115     "    <div ng-transclude></div>\n" +
18116     "</div>");
18117 }]);
18118
18119 angular.module("app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdown.html", []).run(["$templateCache", function($templateCache) {
18120   $templateCache.put("app/scripts/ng_js_att_tpls/splitButtonDropdown/splitButtonDropdown.html",
18121     "<div class=\" btn-group\" \n" +
18122     "     ng-class=\"{'buttons-dropdown--large':!isSmall, \n" +
18123     "                 'buttons-dropdown--small':isSmall, \n" +
18124     "                 'action-dropdown':isActionDropdown, \n" +
18125     "                 'open':isDropDownOpen}\">\n" +
18126     "    <a tabindex=\"0\" href=\"javascript:void(0)\" class=\"button btn buttons-dropdown__split\" \n" +
18127     "       ng-class=\"{'button--primary':(btnType==undefined || btnType=='primary'), \n" +
18128     "                   'button--secondary':btnType=='secondary', \n" +
18129     "                   'button--disabled':btnType=='disabled', \n" +
18130     "                   'button--small':isSmall}\" \n" +
18131     "       ng-if=\"!isActionDropdown\"\n" +
18132     "       ng-click=\"btnType==='disabled'?undefined:clickFxn()\" att-accessibility-click=\"13,32\">{{btnText}}</a>\n" +
18133     "    <a tabindex=\"0\" href=\"javascript:void(0)\" role=\"button\" aria-label=\"Toggle Dropdown\" class=\"button buttons-dropdown__drop dropdown-toggle\" \n" +
18134     "       ng-class=\"{'button--primary':(btnType==undefined || btnType=='primary'), \n" +
18135     "               'button--secondary':btnType=='secondary', \n" +
18136     "               'button--disabled':btnType=='disabled', \n" +
18137     "               'button--small':isSmall}\" ng-click=\"toggleDropdown()\" att-accessibility-click=\"13,32\"></a>\n" +
18138     "    <ul class=\"dropdown-menu\" ng-click=\"hideDropdown()\" ng-transclude></ul>\n" +
18139     "</div>");
18140 }]);
18141
18142 angular.module("app/scripts/ng_js_att_tpls/splitButtonDropdown/splitIcon.html", []).run(["$templateCache", function($templateCache) {
18143   $templateCache.put("app/scripts/ng_js_att_tpls/splitButtonDropdown/splitIcon.html",
18144     "<div class='split-icon-button-container'>\n" +
18145     "\n" +
18146     "   <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" +
18147     "           <a class='{{icon}}' aria-label='{{icon}}' role='button' tabindex=\"0\"></a>\n" +
18148     "           <i ng-if=\"isRight && !isMiddle && !isLeftNextDropdown && !isNextToDropDown\" \n" +
18149     "                   ng-class=\"isDropDownOpen ? 'icon-dropdown-up' : 'icon-dropdown-down'\"> </i>\n" +
18150     "   </div> \n" +
18151     "\n" +
18152     "    <ul ng-if='isDropdown' class='dropdown-menu {{dropDownId}}' ng-show='\n" +
18153     "    isDropDownOpen' ng-click='toggleDropdown(false)' ng-transclude>\n" +
18154     "    </ul>\n" +
18155     "\n" +
18156     "</div>");
18157 }]);
18158
18159 angular.module("app/scripts/ng_js_att_tpls/splitButtonDropdown/splitIconButton.html", []).run(["$templateCache", function($templateCache) {
18160   $templateCache.put("app/scripts/ng_js_att_tpls/splitButtonDropdown/splitIconButton.html",
18161     "<div>\n" +
18162     "   <div ng-if='isLeftLineShown' dir-type='{{iconStateConstants.DIR_TYPE.LEFT}}' expandable-line></div>\n" +
18163     "   <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" +
18164     "           <div ng-transclude>\n" +
18165     "           </div>\n" +
18166     "   </div>\n" +
18167     "   <div ng-if='isRightLineShown' dir-type='{{iconStateConstants.DIR_TYPE.RIGHT}}' expandable-line></div>\n" +
18168     "</div>");
18169 }]);
18170
18171 angular.module("app/scripts/ng_js_att_tpls/splitButtonDropdown/splitIconButtonGroup.html", []).run(["$templateCache", function($templateCache) {
18172   $templateCache.put("app/scripts/ng_js_att_tpls/splitButtonDropdown/splitIconButtonGroup.html",
18173     "<div ng-transclude>\n" +
18174     "</div>");
18175 }]);
18176
18177 angular.module("app/scripts/ng_js_att_tpls/steptracker/step-tracker.html", []).run(["$templateCache", function($templateCache) {
18178   $templateCache.put("app/scripts/ng_js_att_tpls/steptracker/step-tracker.html",
18179     "<div class=\"steptracker1\">\n" +
18180     "    <div class=\"steptracker-bg\">\n" +
18181     "        <div class=\"steptracker-track size-onethird\" ng-repeat=\"step in sdata\"\n" +
18182     "             ng-style=\"set_width($index)\"\n" +
18183     "             ng-class=\"{'last':laststep($index),'done':donesteps($index),'active':activestep($index), 'incomplete': isIncomplete($index), 'disabled': disableClick}\">\n" +
18184     "            <div class=\"circle\" tabindex=\"0\"\n" +
18185     "                 ng-click=\"stepclick($event, $index);\"\n" +
18186     "                 att-accessibility-click=\"13,23\">{{($index) + 1}}<span>{{step.title}}</span></div>\n" +
18187     "            <div ng-if=\"!laststep($index)\" class=\"track\"></div>\n" +
18188     "        </div>\n" +
18189     "    </div>\n" +
18190     "</div>\n" +
18191     "");
18192 }]);
18193
18194 angular.module("app/scripts/ng_js_att_tpls/steptracker/step.html", []).run(["$templateCache", function($templateCache) {
18195   $templateCache.put("app/scripts/ng_js_att_tpls/steptracker/step.html",
18196     "<div class=\"steptracker1\">\n" +
18197     "    <div class=\"steptracker-bg\">\n" +
18198     "        <div class=\"steptracker-track size-onethird\" \n" +
18199     "             ng-class=\"{'last':laststep($index),'done':donesteps($index),'active':activestep($index)}\">\n" +
18200     "            <div class=\"circle\" tabindex=\"0\" \n" +
18201     "                 ng-click=\"stepclick($event, $index);\" \n" +
18202     "                 att-accessibility-click=\"13,23\">{{($index) + 1}}<span>{{step.title}}</span></div>\n" +
18203     "            <div ng-if=\"!laststep($index)\" class=\"track\"></div>\n" +
18204     "        </div>\n" +
18205     "    </div>\n" +
18206     "</div>\n" +
18207     "");
18208 }]);
18209
18210 angular.module("app/scripts/ng_js_att_tpls/steptracker/timeline.html", []).run(["$templateCache", function($templateCache) {
18211   $templateCache.put("app/scripts/ng_js_att_tpls/steptracker/timeline.html",
18212     "<div class='att-timeline'>\n" +
18213     "   <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" +
18214     "\n" +
18215     "   <div ng-repeat=\"m in middleSteps track by $index\">\n" +
18216     "           <div timeline-bar order='{{$index}}'></div>\n" +
18217     "           <div timeline-dot order='{{$index + 1}}' title='{{m.title}}' description='{{m.description}}' by='{{m.by}}' date='{{m.date}}' type='{{m.type}}'>\n" +
18218     "           </div>\n" +
18219     "   </div>\n" +
18220     "\n" +
18221     "</div>");
18222 }]);
18223
18224 angular.module("app/scripts/ng_js_att_tpls/steptracker/timelineBar.html", []).run(["$templateCache", function($templateCache) {
18225   $templateCache.put("app/scripts/ng_js_att_tpls/steptracker/timelineBar.html",
18226     "<div class='timeline-bar'>\n" +
18227     "   <div class='progress-bar' ng-class=\"{'completed-color':isCompleted,'cancelled-color':isCancelled,'alert-color':isAlert}\">\n" +
18228     "   </div>\n" +
18229     "   <hr></hr>\n" +
18230     "</div>");
18231 }]);
18232
18233 angular.module("app/scripts/ng_js_att_tpls/steptracker/timelineDot.html", []).run(["$templateCache", function($templateCache) {
18234   $templateCache.put("app/scripts/ng_js_att_tpls/steptracker/timelineDot.html",
18235     "<div class='timeline-dot'>\n" +
18236     "\n" +
18237     "   <div class='bigger-circle' ng-class=\"{'completed-color':isCompleted,'cancelled-color':isCancelled,'alert-color':isAlert}\">\n" +
18238     "   </div>\n" +
18239     "\n" +
18240     "   <div class='inactive-circle'>\n" +
18241     "   </div>\n" +
18242     "\n" +
18243     "   <div class='expandable-circle' ng-class=\"{'completed-color':isCompleted,'cancelled-color':isCancelled,'alert-color':isAlert}\">\n" +
18244     "   </div>\n" +
18245     "\n" +
18246     "   <div ng-class=\"{'below-info-box':isBelowInfoBoxShown, 'above-info-box': !isBelowInfoBoxShown}\">\n" +
18247     "           \n" +
18248     "           <div ng-if='isBelowInfoBoxShown' class='vertical-line'>\n" +
18249     "           </div>\n" +
18250     "\n" +
18251     "           <div class='info-container' ng-init='isContentShown=false'>\n" +
18252     "                   <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(1)' ng-bind='title' ></div>\n" +
18253     "                   <div class='content'>\n" +
18254     "                           <div class='description' ng-bind='description'></div>\n" +
18255     "                           <div class='submitter' ng-bind='by'></div>\n" +
18256     "                   </div>\n" +
18257     "                   <div class='date' ng-mouseover='titleMouseover(2)' ng-mouseleave='titleMouseleave(2)' ng-bind='date'></div>\n" +
18258     "           </div>\n" +
18259     "\n" +
18260     "           <div ng-if='!isBelowInfoBoxShown' class='vertical-line'>\n" +
18261     "           </div>\n" +
18262     "   </div>\n" +
18263     "\n" +
18264     "</div>");
18265 }]);
18266
18267 angular.module("app/scripts/ng_js_att_tpls/table/attTable.html", []).run(["$templateCache", function($templateCache) {
18268   $templateCache.put("app/scripts/ng_js_att_tpls/table/attTable.html",
18269     "<table class=\"tablesorter tablesorter-default\" ng-transclude></table>\n" +
18270     "");
18271 }]);
18272
18273 angular.module("app/scripts/ng_js_att_tpls/table/attTableBody.html", []).run(["$templateCache", function($templateCache) {
18274   $templateCache.put("app/scripts/ng_js_att_tpls/table/attTableBody.html",
18275     "<td ng-transclude></td>\n" +
18276     "");
18277 }]);
18278
18279 angular.module("app/scripts/ng_js_att_tpls/table/attTableHeader.html", []).run(["$templateCache", function($templateCache) {
18280   $templateCache.put("app/scripts/ng_js_att_tpls/table/attTableHeader.html",
18281     "<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" +
18282     "");
18283 }]);
18284
18285 angular.module("app/scripts/ng_js_att_tpls/tabs/floatingTabs.html", []).run(["$templateCache", function($templateCache) {
18286   $templateCache.put("app/scripts/ng_js_att_tpls/tabs/floatingTabs.html",
18287     "<ul ng-class=\"{'tabsbid': size === 'large', 'tabsbid--small': size === 'small'}\">\n" +
18288     " <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" +
18289     "        <a class=\"tabsbid__item-link\" href=\"{{tab.url}}\" tabindex=\"0\" att-accessibility-click=\"32,13\">{{tab.title}}</a>\n" +
18290     "  </li>\n" +
18291     "</ul>");
18292 }]);
18293
18294 angular.module("app/scripts/ng_js_att_tpls/tabs/genericTabs.html", []).run(["$templateCache", function($templateCache) {
18295   $templateCache.put("app/scripts/ng_js_att_tpls/tabs/genericTabs.html",
18296     "<ul ng-class=\"{'tabsbid': size === 'large', 'tabsbid--small': size === 'small'}\">\n" +
18297     "    <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" +
18298     "           <a class=\"tabsbid__item-link\" href=\"{{tab.url}}\" tabindex=\"0\" att-accessibility-click=\"32,13\">{{tab.title}}</a>\n" +
18299     "    </li>\n" +
18300     "</ul>\n" +
18301     "");
18302 }]);
18303
18304 angular.module("app/scripts/ng_js_att_tpls/tabs/menuTab.html", []).run(["$templateCache", function($templateCache) {
18305   $templateCache.put("app/scripts/ng_js_att_tpls/tabs/menuTab.html",
18306     "<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>");
18307 }]);
18308
18309 angular.module("app/scripts/ng_js_att_tpls/tabs/parentmenuTab.html", []).run(["$templateCache", function($templateCache) {
18310   $templateCache.put("app/scripts/ng_js_att_tpls/tabs/parentmenuTab.html",
18311     "<div ng-class=\"{'megamenu-tabs': megaMenu,'submenu-tabs': !megaMenu}\">\n" +
18312     "    <ul class=\"megamenu__items\" ng-transclude>\n" +
18313     "    </ul>\n" +
18314     "</div>");
18315 }]);
18316
18317 angular.module("app/scripts/ng_js_att_tpls/tabs/simplifiedTabs.html", []).run(["$templateCache", function($templateCache) {
18318   $templateCache.put("app/scripts/ng_js_att_tpls/tabs/simplifiedTabs.html",
18319     "<div class=\"simplified-tabs\">\n" +
18320     "<ul class=\"simplified-tabs__items\">\n" +
18321     "    <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" +
18322     "    <li class=\"tabs__pointer\"></li>\n" +
18323     "</ul>\n" +
18324     "</div>");
18325 }]);
18326
18327 angular.module("app/scripts/ng_js_att_tpls/tabs/submenuTab.html", []).run(["$templateCache", function($templateCache) {
18328   $templateCache.put("app/scripts/ng_js_att_tpls/tabs/submenuTab.html",
18329     "<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" +
18330     "</li>");
18331 }]);
18332
18333 angular.module("app/scripts/ng_js_att_tpls/tagBadges/tagBadges.html", []).run(["$templateCache", function($templateCache) {
18334   $templateCache.put("app/scripts/ng_js_att_tpls/tagBadges/tagBadges.html",
18335     "<div class=\"tags__item\" \n" +
18336     "     ng-class=\"{'tags__item--small':isSmall, \n" +
18337     "                 'tags__item--color':isColor, \n" +
18338     "                 'tags__item--cloud':!isClosable && !isColor,'active':applyActiveClass}\"\n" +
18339     "     ng-if=\"display\" \n" +
18340     "     ng-style=\"{borderColor: border_type_borderColor, background: isHighlight?'#bbb':undefined, color: isHighlight?'#444':undefined }\"\n" +
18341     "     ng-mousedown=\"activeHighlight(true)\" ng-mouseup=\"activeHighlight(false)\">\n" +
18342     "    <i class=\"icon-filter tags__item--icon\" ng-if=\"isIcon\">&nbsp;</i>\n" +
18343     "    <i class=\"tags__item--color-icon\" ng-if=\"isColor\" ng-style=\"{backgroundColor: background_type_backgroundColor, borderColor: background_type_borderColor}\"></i>\n" +
18344     "    <span class=\"tags__item--title\" tabindex=0 aria-label ng-mousedown=\"activeHighlight(true)\" ng-mouseup=\"activeHighlight(false)\" ng-transclude></span>\n" +
18345     "    <a href=\"javascript:void(0)\" title=\"Dismiss Link\" class=\"tags__item--action\" ng-click=\"closeMe();$event.preventDefault()\" ng-if=\"isClosable\"\n" +
18346     "       ng-style=\"{color: (isHighlight && '#444') || '#888' , borderLeft: (isHighlight && '1px solid #444')|| '1px solid #888' }\">\n" +
18347     "        <i class=\"icon-erase\">&nbsp;</i>\n" +
18348     "    </a>\n" +
18349     "</div>");
18350 }]);
18351
18352 angular.module("app/scripts/ng_js_att_tpls/toggle/demoToggle.html", []).run(["$templateCache", function($templateCache) {
18353   $templateCache.put("app/scripts/ng_js_att_tpls/toggle/demoToggle.html",
18354     "<span ng-transclude></span>\n" +
18355     "<!--<div class=\"att-switch-content\" hm-drag-left = \"dragleft($event)\" hm-drag-right = \"dragright($event)\" hm-dragstart = \"drag($event)\" 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" +
18356     "<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" +
18357     "    <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" +
18358     "    <div class=\"att-switch-thumb\" tabindex=\"0\" ng-class=\"{'large' : directiveValue == 'large'}\"></div>\n" +
18359     "    <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" +
18360     "</div>\n" +
18361     "");
18362 }]);
18363
18364 angular.module("app/scripts/ng_js_att_tpls/tooltip/tooltip-popup.html", []).run(["$templateCache", function($templateCache) {
18365   $templateCache.put("app/scripts/ng_js_att_tpls/tooltip/tooltip-popup.html",
18366     "<div class=\"att-tooltip \" \n" +
18367     "     ng-class=\"{ 'att-tooltip--on': isOpen, \n" +
18368     "                'att-tooltip--dark att-tooltip--dark--hover':stylett=='dark', \n" +
18369     "                'att-tooltip--light att-tooltip--light--hover':stylett=='light',\n" +
18370     "                'att-tooltip--left':placement=='left', \n" +
18371     "                'att-tooltip--above':placement=='above', \n" +
18372     "                'att-tooltip--right':placement=='right', \n" +
18373     "                'att-tooltip--below':placement=='below'}\" \n" +
18374     "    ng-bind-html=\"content\" ></div>");
18375 }]);
18376
18377 angular.module("app/scripts/ng_js_att_tpls/typeAhead/typeAhead.html", []).run(["$templateCache", function($templateCache) {
18378   $templateCache.put("app/scripts/ng_js_att_tpls/typeAhead/typeAhead.html",
18379     "<div class=\"typeahead mainContainerOuter\">\n" +
18380     "    <span class=\"message\">To</span> \n" +
18381     "    <div class='maincontainer' ng-click=\"setFocus()\" ng-class =\"{'typeahed_active':inputActive}\">\n" +
18382     "        <span tag-badges closable ng-repeat =\"lineItem in lineItems track by $index\" on-close=\"theMethodToBeCalled($index)\" >{{lineItem}}</span>\n" +
18383     "        <input type=\"text\"  focus-me=\"clickFocus\" id=\"inpute\" aria-label=\"model\" role=\"textfiled\" ng-model=\"model\" ng-keydown=\"selected = false; selectionIndex($event)\"/><br/> \n" +
18384     "    </div>\n" +
18385     "    <div ng-hide=\"!model.length || selected\">\n" +
18386     "        <div class=\"filtercontainer list-scrollable\" ng-show=\"( items | filter:model).length\">\n" +
18387     "            <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" +
18388     "                <span class=\"title\" >{{item[title]}}</span>\n" +
18389     "                <span class=\"subtitle\">{{item[subtitle]}}</span>\n" +
18390     "            </div>  \n" +
18391     "        </div>\n" +
18392     "    </div>\n" +
18393     "   \n" +
18394     "    <div class=\"textAreaEmailContentDiv\">\n" +
18395     "        <span class=\"message\">Message</span>\n" +
18396     "        <textarea rows=\"4\" cols=\"50\" role=\"textarea\" class=\"textAreaEmailContent\" ng-model=\"emailMessage\">To send \n" +
18397     " a text, picture, or video message1 to an AT&T wireless device from your email:my message.</textarea>\n" +
18398     "        \n" +
18399     "    </div>\n" +
18400     "</div>\n" +
18401     "");
18402 }]);
18403
18404 angular.module("app/scripts/ng_js_att_tpls/userMessages/attTableMessage.html", []).run(["$templateCache", function($templateCache) {
18405   $templateCache.put("app/scripts/ng_js_att_tpls/userMessages/attTableMessage.html",
18406     "<div class=\"att-table-message\">\n" +
18407     "   <div class=\"message\" ng-if=\"msgType==messageConstants.TABLE_MESSAGE_TYPES.noMatching\">\n" +
18408     "      <div class=\"img-magnify-glass\"></div> \n" +
18409     "      <div>\n" +
18410     "         <div ng-transclude></div>\n" +
18411     "      </div>\n" +
18412     "   </div>\n" +
18413     "   <div class=\"message\" ng-if=\"msgType==messageConstants.TABLE_MESSAGE_TYPES.errorLoading\">\n" +
18414     "      <div class=\"img-oops-exclamation\"></div> \n" +
18415     "      <div>Oops!</div>\n" +
18416     "      <div>The information could not load at this time.</div>\n" +
18417     "      <div>Please <a href=\"javascript:void(0)\" ng-click=\"refreshAction($event)\">refresh the page</a>\n" +
18418     "      </div>\n" +
18419     "   </div>\n" +
18420     "   <div class=\"message\" ng-if=\"msgType==messageConstants.TABLE_MESSAGE_TYPES.magnifySearch\">\n" +
18421     "      <div class=\"img-magnify-glass\"></div>\n" +
18422     "      <div>\n" +
18423     "         <p class=\"title\">Please input values to <br/> begin your search.</p>\n" +
18424     "      </div>\n" +
18425     "   </div>\n" +
18426     "   <div class=\"message loading-message\" ng-if=\"msgType==messageConstants.TABLE_MESSAGE_TYPES.isLoading\">\n" +
18427     "      <div class=\"img-loading-dots\"></div>\n" +
18428     "      <div ng-transclude></div>\n" +
18429     "   </div>\n" +
18430     "</div>");
18431 }]);
18432
18433 angular.module("app/scripts/ng_js_att_tpls/userMessages/attUserMessage.html", []).run(["$templateCache", function($templateCache) {
18434   $templateCache.put("app/scripts/ng_js_att_tpls/userMessages/attUserMessage.html",
18435     "<div class=\"att-user-message\">\n" +
18436     "  <div ng-class=\"type==messageConstants.USER_MESSAGE_TYPES.error && trigger ? 'message-wrapper-error' : 'hidden'\">\n" +
18437     "      <div class=\"message-icon-error\"> <i class=\"icon-info-alert\"></i> </div>\n" +
18438     "\n" +
18439     "      <div class=\"message-body-wrapper\">\n" +
18440     "        <div class=\"message-title-error\" ng-if=\"thetitle && thetitle.length > 0\"> <span ng-bind=\"thetitle\"></span> </div>\n" +
18441     "        <div class=\"message-msg\" ng-bind=\"message\" ng-if=\"message && message.length > 0\"> </div>\n" +
18442     "        <div class=\"message-bottom\">\n" +
18443     "           <div ng-transclude></div>\n" +
18444     "        </div>\n" +
18445     "      </div>\n" +
18446     "\n" +
18447     "   </div>\n" +
18448     "  <div ng-class=\"type==messageConstants.USER_MESSAGE_TYPES.success && trigger ? 'message-wrapper-success' : 'hidden'\">\n" +
18449     "      <div class=\"message-icon-success\"> <i class=\"icon-included-checkmark\"></i> </div>\n" +
18450     "\n" +
18451     "      <div class=\"message-body-wrapper\">\n" +
18452     "        <div class=\"message-title-success\" ng-if=\"thetitle && thetitle.length > 0\"> <span ng-bind=\"thetitle\"></span> </div>\n" +
18453     "        <div class=\"message-msg\" ng-bind=\"message\" ng-if=\"message && message.length > 0\"> </div>\n" +
18454     "        <div class=\"message-bottom\">\n" +
18455     "           <div ng-transclude></div>\n" +
18456     "        </div>\n" +
18457     "      </div>\n" +
18458     "\n" +
18459     "   </div>\n" +
18460     "</div>\n" +
18461     "");
18462 }]);
18463
18464 angular.module("app/scripts/ng_js_att_tpls/verticalSteptracker/vertical-step-tracker.html", []).run(["$templateCache", function($templateCache) {
18465   $templateCache.put("app/scripts/ng_js_att_tpls/verticalSteptracker/vertical-step-tracker.html",
18466     "<li>\n" +
18467     "    <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" +
18468     "    <span ng-transclude></span>\n" +
18469     "</li>\n" +
18470     "        \n" +
18471     "");
18472 }]);
18473
18474 angular.module("app/scripts/ng_js_att_tpls/videoControls/photoControls.html", []).run(["$templateCache", function($templateCache) {
18475   $templateCache.put("app/scripts/ng_js_att_tpls/videoControls/photoControls.html",
18476     "<div>\n" +
18477     "    <a title=\"Previous Link\" ng-href=\"{{links.prevLink}}\"><i class=\"icon-arrow-left\">&nbsp;</i></a>\n" +
18478     "    <span ng-transclude></span>\n" +
18479     "    <a title=\"Next Link\" ng-href=\"{{links.nextLink}}\"><i class=\"icon-arrow-right\">&nbsp;</i></a>\n" +
18480     "</div>");
18481 }]);
18482
18483 angular.module("app/scripts/ng_js_att_tpls/videoControls/videoControls.html", []).run(["$templateCache", function($templateCache) {
18484   $templateCache.put("app/scripts/ng_js_att_tpls/videoControls/videoControls.html",
18485     "<div class=\"video-player\">\n" +
18486     "    <div class=\"video-player__control video-player__play-button\">\n" +
18487     "        <a class=\"video-player__button gigant-play\" data-toggle-buttons=\"icon-play, icon-pause\" data-target=\"i\"><i class=\"icon-play\"></i></a>\n" +
18488     "    </div>\n" +
18489     "    <div class=\"video-player__control video-player__track\">\n" +
18490     "\n" +
18491     "        <div class=\"video-player__track--inner\">\n" +
18492     "            <div class=\"video-player__track--loaded\" style=\"width: 75%\"></div>\n" +
18493     "            <div class=\"video-player__track--played\" style=\"width: 40%\">\n" +
18494     "                <div class=\"att-tooltip att-tooltip--on att-tooltip--dark att-tooltip--above video-player__track-tooltip\" ng-transclude></div>\n" +
18495     "                <div class=\"video-player__track-handle\"></div>\n" +
18496     "            </div>\n" +
18497     "        </div>\n" +
18498     "    </div>\n" +
18499     "    <a class=\"video-player__time\" ng-transclude></a>\n" +
18500     "    <div class=\"video-player__control video-player__volume_icon\">\n" +
18501     "        <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" +
18502     "    </div>\n" +
18503     "    <ul class=\"video-player__control video-player__volume\">\n" +
18504     "        <li class=\"video-player__volume-bar video-player__volume-bar--full\">&nbsp;</li>\n" +
18505     "        <li class=\"video-player__volume-bar video-player__volume-bar--full\">&nbsp;</li>\n" +
18506     "        <li class=\"video-player__volume-bar\">&nbsp;</li>\n" +
18507     "        <li class=\"video-player__volume-bar\">&nbsp;</li>\n" +
18508     "        <li class=\"video-player__volume-bar\">&nbsp;</li>\n" +
18509     "    </ul>\n" +
18510     "    <div class=\"video-player__control video-player__toggle-fullscreen-button\">\n" +
18511     "        <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" +
18512     "    </div>\n" +
18513     "</div>");
18514 }]);