greensock-rails 1.11.8.0 → 1.12.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * VERSION: 1.11.8
3
- * DATE: 2014-05-13
2
+ * VERSION: 1.12.1
3
+ * DATE: 2014-06-26
4
4
  * UPDATES AND DOCS AT: http://www.greensock.com
5
5
  *
6
6
  * Includes all of the following: TweenLite, TweenMax, TimelineLite, TimelineMax, EasePack, CSSPlugin, RoundPropsPlugin, BezierPlugin, AttrPlugin, DirectionalRotationPlugin
@@ -17,7 +17,7 @@
17
17
  "use strict";
18
18
 
19
19
  window._gsDefine("TweenMax", ["core.Animation","core.SimpleTimeline","TweenLite"], function(Animation, SimpleTimeline, TweenLite) {
20
-
20
+
21
21
  var _slice = [].slice,
22
22
  TweenMax = function(target, duration, vars) {
23
23
  TweenLite.call(this, target, duration, vars);
@@ -29,18 +29,21 @@
29
29
  this.render = TweenMax.prototype.render; //speed optimization (avoid prototype lookup on this "hot" method)
30
30
  },
31
31
  _tinyNum = 0.0000000001,
32
- _isSelector = TweenLite._internals.isSelector,
33
- _isArray = TweenLite._internals.isArray,
32
+ TweenLiteInternals = TweenLite._internals,
33
+ _isSelector = TweenLiteInternals.isSelector,
34
+ _isArray = TweenLiteInternals.isArray,
34
35
  p = TweenMax.prototype = TweenLite.to({}, 0.1, {}),
35
36
  _blankArray = [];
36
37
 
37
- TweenMax.version = "1.11.8";
38
+ TweenMax.version = "1.12.1";
38
39
  p.constructor = TweenMax;
39
40
  p.kill()._gc = false;
40
41
  TweenMax.killTweensOf = TweenMax.killDelayedCallsTo = TweenLite.killTweensOf;
41
42
  TweenMax.getTweensOf = TweenLite.getTweensOf;
43
+ TweenMax.lagSmoothing = TweenLite.lagSmoothing;
42
44
  TweenMax.ticker = TweenLite.ticker;
43
-
45
+ TweenMax.render = TweenLite.render;
46
+
44
47
  p.invalidate = function() {
45
48
  this._yoyo = (this.vars.yoyo === true);
46
49
  this._repeat = this.vars.repeat || 0;
@@ -104,7 +107,8 @@
104
107
  prevTotalTime = this._totalTime,
105
108
  prevCycle = this._cycle,
106
109
  duration = this._duration,
107
- isComplete, callback, pt, cycleDuration, r, type, pow, rawPrevTime;
110
+ prevRawPrevTime = this._rawPrevTime,
111
+ isComplete, callback, pt, cycleDuration, r, type, pow, rawPrevTime, i;
108
112
  if (time >= totalDur) {
109
113
  this._totalTime = totalDur;
110
114
  this._cycle = this._repeat;
@@ -119,34 +123,33 @@
119
123
  isComplete = true;
120
124
  callback = "onComplete";
121
125
  }
122
- if (duration === 0) { //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.
123
- rawPrevTime = this._rawPrevTime;
126
+ 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.
124
127
  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.
125
128
  time = 0;
126
129
  }
127
- if (time === 0 || rawPrevTime < 0 || rawPrevTime === _tinyNum) if (rawPrevTime !== time) {
130
+ if (time === 0 || prevRawPrevTime < 0 || prevRawPrevTime === _tinyNum) if (prevRawPrevTime !== time) {
128
131
  force = true;
129
- if (rawPrevTime > _tinyNum) {
132
+ if (prevRawPrevTime > _tinyNum) {
130
133
  callback = "onReverseComplete";
131
134
  }
132
135
  }
133
- this._rawPrevTime = rawPrevTime = (!suppressEvents || time || this._rawPrevTime === 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.
136
+ 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.
134
137
  }
135
138
 
136
139
  } else if (time < 0.0000001) { //to work around occasional floating point math artifacts, round super small values to 0.
137
140
  this._totalTime = this._time = this._cycle = 0;
138
141
  this.ratio = this._ease._calcEnd ? this._ease.getRatio(0) : 0;
139
- if (prevTotalTime !== 0 || (duration === 0 && this._rawPrevTime > 0 && this._rawPrevTime !== _tinyNum)) {
142
+ if (prevTotalTime !== 0 || (duration === 0 && prevRawPrevTime > 0 && prevRawPrevTime !== _tinyNum)) {
140
143
  callback = "onReverseComplete";
141
144
  isComplete = this._reversed;
142
145
  }
143
146
  if (time < 0) {
144
147
  this._active = false;
145
- if (duration === 0) { //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.
146
- if (this._rawPrevTime >= 0) {
148
+ 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.
149
+ if (prevRawPrevTime >= 0) {
147
150
  force = true;
148
151
  }
149
- this._rawPrevTime = rawPrevTime = (!suppressEvents || time || this._rawPrevTime === 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.
152
+ 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.
150
153
  }
151
154
  } 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.
152
155
  force = true;
@@ -170,7 +173,7 @@
170
173
  this._time = 0;
171
174
  }
172
175
  }
173
-
176
+
174
177
  if (this._easeType) {
175
178
  r = this._time / duration;
176
179
  type = this._easeType;
@@ -190,7 +193,7 @@
190
193
  } else if (pow === 4) {
191
194
  r *= r * r * r * r;
192
195
  }
193
-
196
+
194
197
  if (type === 1) {
195
198
  this.ratio = 1 - r;
196
199
  } else if (type === 2) {
@@ -200,7 +203,7 @@
200
203
  } else {
201
204
  this.ratio = 1 - (r / 2);
202
205
  }
203
-
206
+
204
207
  } else {
205
208
  this.ratio = this._ease.getRatio(this._time / duration);
206
209
  }
@@ -216,6 +219,14 @@
216
219
  this._init();
217
220
  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.
218
221
  return;
222
+ } 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.
223
+ this._time = prevTime;
224
+ this._totalTime = prevTotalTime;
225
+ this._rawPrevTime = prevRawPrevTime;
226
+ this._cycle = prevCycle;
227
+ TweenLiteInternals.lazyTweens.push(this);
228
+ this._lazy = time;
229
+ return;
219
230
  }
220
231
  //_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.
221
232
  if (this._time && !isComplete) {
@@ -224,11 +235,18 @@
224
235
  this.ratio = this._ease.getRatio((this._time === 0) ? 0 : 1);
225
236
  }
226
237
  }
227
-
238
+ if (this._lazy !== false) {
239
+ this._lazy = false;
240
+ }
241
+
228
242
  if (!this._active) if (!this._paused && this._time !== prevTime && time >= 0) {
229
243
  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.
230
244
  }
231
245
  if (prevTotalTime === 0) {
246
+ if (this._initted === 2 && time > 0) {
247
+ //this.invalidate();
248
+ this._init(); //will just apply overwriting since _initted of (2) means it was a from() tween that had immediateRender:true
249
+ }
232
250
  if (this._startAt) {
233
251
  if (time >= 0) {
234
252
  this._startAt.render(time, suppressEvents, force);
@@ -395,7 +413,7 @@
395
413
  tween = a[i];
396
414
  if (allTrue || (tween instanceof SimpleTimeline) || ((isDC = (tween.target === tween.vars.onComplete)) && delayedCalls) || (tweens && !isDC)) {
397
415
  if (complete) {
398
- tween.totalTime(tween.totalDuration());
416
+ tween.totalTime(tween._reversed ? 0 : tween.totalDuration());
399
417
  } else {
400
418
  tween._enabled(false, false);
401
419
  }
@@ -407,7 +425,7 @@
407
425
  if (parent == null) {
408
426
  return;
409
427
  }
410
- var tl = TweenLite._tweenLookup,
428
+ var tl = TweenLiteInternals.tweenLookup,
411
429
  a, curParent, p, i, l;
412
430
  if (typeof(parent) === "string") {
413
431
  parent = TweenLite.selector(parent) || parent;
@@ -611,7 +629,7 @@
611
629
  _slice = _blankArray.slice,
612
630
  p = TimelineLite.prototype = new SimpleTimeline();
613
631
 
614
- TimelineLite.version = "1.11.8";
632
+ TimelineLite.version = "1.12.1";
615
633
  p.constructor = TimelineLite;
616
634
  p.kill()._gc = false;
617
635
 
@@ -929,13 +947,11 @@
929
947
  if (this._paused && !prevPaused) { //in case a tween pauses the timeline when rendering
930
948
  break;
931
949
  } else if (tween._active || (tween._startTime <= this._time && !tween._paused && !tween._gc)) {
932
-
933
950
  if (!tween._reversed) {
934
951
  tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force);
935
952
  } else {
936
953
  tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force);
937
954
  }
938
-
939
955
  }
940
956
  tween = next;
941
957
  }
@@ -946,13 +962,11 @@
946
962
  if (this._paused && !prevPaused) { //in case a tween pauses the timeline when rendering
947
963
  break;
948
964
  } else if (tween._active || (tween._startTime <= prevTime && !tween._paused && !tween._gc)) {
949
-
950
965
  if (!tween._reversed) {
951
966
  tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force);
952
967
  } else {
953
968
  tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force);
954
969
  }
955
-
956
970
  }
957
971
  tween = next;
958
972
  }
@@ -1013,15 +1027,23 @@
1013
1027
  };
1014
1028
 
1015
1029
  p.getTweensOf = function(target, nested) {
1016
- var tweens = TweenLite.getTweensOf(target),
1017
- i = tweens.length,
1030
+ var disabled = this._gc,
1018
1031
  a = [],
1019
- cnt = 0;
1032
+ cnt = 0,
1033
+ tweens, i;
1034
+ if (disabled) {
1035
+ 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.
1036
+ }
1037
+ tweens = TweenLite.getTweensOf(target);
1038
+ i = tweens.length;
1020
1039
  while (--i > -1) {
1021
1040
  if (tweens[i].timeline === this || (nested && this._contains(tweens[i]))) {
1022
1041
  a[cnt++] = tweens[i];
1023
1042
  }
1024
1043
  }
1044
+ if (disabled) {
1045
+ this._enabled(false, true);
1046
+ }
1025
1047
  return a;
1026
1048
  };
1027
1049
 
@@ -1210,7 +1232,7 @@
1210
1232
 
1211
1233
  p.constructor = TimelineMax;
1212
1234
  p.kill()._gc = false;
1213
- TimelineMax.version = "1.11.8";
1235
+ TimelineMax.version = "1.12.1";
1214
1236
 
1215
1237
  p.invalidate = function() {
1216
1238
  this._yoyo = (this.vars.yoyo === true);
@@ -1455,7 +1477,6 @@
1455
1477
  } else {
1456
1478
  tween.render(((!tween._dirty) ? tween._totalDuration : tween.totalDuration()) - ((time - tween._startTime) * tween._timeScale), suppressEvents, force);
1457
1479
  }
1458
-
1459
1480
  }
1460
1481
  tween = next;
1461
1482
  }
@@ -2238,7 +2259,7 @@
2238
2259
  p = CSSPlugin.prototype = new TweenPlugin("css");
2239
2260
 
2240
2261
  p.constructor = CSSPlugin;
2241
- CSSPlugin.version = "1.11.8";
2262
+ CSSPlugin.version = "1.12.1";
2242
2263
  CSSPlugin.API = 2;
2243
2264
  CSSPlugin.defaultTransformPerspective = 0;
2244
2265
  CSSPlugin.defaultSkewType = "compensated";
@@ -2251,8 +2272,8 @@
2251
2272
  _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)"
2252
2273
  _NaNExp = /[^\d\-\.]/g,
2253
2274
  _suffixExp = /(?:\d|\-|\+|=|#|\.)*/g,
2254
- _opacityExp = /opacity *= *([^)]*)/,
2255
- _opacityValExp = /opacity:([^;]*)/,
2275
+ _opacityExp = /opacity *= *([^)]*)/i,
2276
+ _opacityValExp = /opacity:([^;]*)/i,
2256
2277
  _alphaFilterExp = /alpha\(opacity *=.+?\)/i,
2257
2278
  _rgbhslExp = /^(rgb|hsl)/,
2258
2279
  _capsExp = /([A-Z])/g,
@@ -2345,7 +2366,7 @@
2345
2366
  }
2346
2367
  if (!calc && t.style[p]) {
2347
2368
  rv = t.style[p];
2348
- } else if ((cs = cs || _getComputedStyle(t, null))) {
2369
+ } else if ((cs = cs || _getComputedStyle(t))) {
2349
2370
  rv = cs[p] || cs.getPropertyValue(p) || cs.getPropertyValue(p.replace(_capsExp, "-$1").toLowerCase());
2350
2371
  } else if (t.currentStyle) {
2351
2372
  rv = t.currentStyle[p];
@@ -3529,6 +3550,10 @@
3529
3550
  perspective = t.perspective,
3530
3551
  a11, a12, a13, a14, a21, a22, a23, a24, a31, a32, a33, a34, a41, a42, a43,
3531
3552
  zOrigin, rnd, cos, sin, t1, t2, t3, t4;
3553
+ 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
3554
+ _set2DTransformRatio.call(this, v);
3555
+ return;
3556
+ }
3532
3557
  if (_isFirefox) {
3533
3558
  var n = 0.0001;
3534
3559
  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.
@@ -3638,7 +3663,7 @@
3638
3663
  targ = this.t,
3639
3664
  style = targ.style,
3640
3665
  ang, skew, rnd, sx, sy;
3641
- if (t.rotationX || t.rotationY || t.z || t.force3D) { //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.
3666
+ 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.
3642
3667
  this.setRatio = _set3DTransformRatio;
3643
3668
  _set3DTransformRatio.call(this, v);
3644
3669
  return;
@@ -3666,11 +3691,13 @@
3666
3691
  endRotations = {},
3667
3692
  m2, skewY, copy, orig, has3D, hasChange, dr;
3668
3693
  if (typeof(v.transform) === "string" && _transformProp) { //for values like transform:"rotate(60deg) scale(0.5, 0.8)"
3669
- copy = style.cssText;
3670
- style[_transformProp] = v.transform;
3671
- style.display = "block"; //if display is "none", the browser often refuses to report the transform properties correctly.
3672
- m2 = _getTransform(t, null, false);
3673
- style.cssText = copy;
3694
+ 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.
3695
+ copy[_transformProp] = v.transform;
3696
+ copy.display = "block"; //if display is "none", the browser often refuses to report the transform properties correctly.
3697
+ copy.position = "absolute";
3698
+ _doc.body.appendChild(_tempDiv);
3699
+ m2 = _getTransform(_tempDiv, null, false);
3700
+ _doc.body.removeChild(_tempDiv);
3674
3701
  } else if (typeof(v) === "object") { //for values like scaleX, scaleY, rotation, x, y, skewX, and skewY or transform:{...} (object)
3675
3702
  m2 = {scaleX:_parseVal((v.scaleX != null) ? v.scaleX : v.scale, m1.scaleX),
3676
3703
  scaleY:_parseVal((v.scaleY != null) ? v.scaleY : v.scale, m1.scaleY),
@@ -3744,12 +3771,12 @@
3744
3771
  copy = m1.zOrigin;
3745
3772
  orig = orig.split(" ");
3746
3773
  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.
3747
- pt.xs0 = pt.e = style[p] = 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)!
3774
+ 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)!
3748
3775
  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)
3749
3776
  pt.b = copy;
3750
3777
  pt.xs0 = pt.e = m1.zOrigin;
3751
3778
  } else {
3752
- pt.xs0 = pt.e = style[p] = orig;
3779
+ pt.xs0 = pt.e = orig;
3753
3780
  }
3754
3781
 
3755
3782
  //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).
@@ -3904,7 +3931,7 @@
3904
3931
  if (this.xn1) {
3905
3932
  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.
3906
3933
  }
3907
- if (filters.indexOf("opacity") === -1) { //only used if browser doesn't support the standard opacity style property (IE 7 and 8)
3934
+ 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
3908
3935
  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)
3909
3936
  t.filter = filters + " alpha(opacity=" + val + ")"; //we round the value because otherwise, bugs in IE7/8 can prevent "visibility" changes from being applied properly.
3910
3937
  }
@@ -3961,7 +3988,7 @@
3961
3988
  _setClassNameRatio = function(v) {
3962
3989
  this.t._gsClassPT = this;
3963
3990
  if (v === 1 || v === 0) {
3964
- this.t.className = (v === 0) ? this.b : this.e;
3991
+ this.t.setAttribute("class", (v === 0) ? this.b : this.e);
3965
3992
  var mpt = this.data, //first MiniPropTween
3966
3993
  s = this.t.style;
3967
3994
  while (mpt) {
@@ -3975,12 +4002,12 @@
3975
4002
  if (v === 1 && this.t._gsClassPT === this) {
3976
4003
  this.t._gsClassPT = null;
3977
4004
  }
3978
- } else if (this.t.className !== this.e) {
3979
- this.t.className = this.e;
4005
+ } else if (this.t.getAttribute("class") !== this.e) {
4006
+ this.t.setAttribute("class", this.e);
3980
4007
  }
3981
4008
  };
3982
4009
  _registerComplexSpecialProp("className", {parser:function(t, e, p, cssp, pt, plugin, vars) {
3983
- var b = t.className,
4010
+ 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.
3984
4011
  cssText = t.style.cssText,
3985
4012
  difData, bs, cnpt, cnptLookup, mpt;
3986
4013
  pt = cssp._classNamePT = new CSSPropTween(t, p, 0, 0, pt, 2);
@@ -4003,9 +4030,9 @@
4003
4030
  t._gsClassPT = pt;
4004
4031
  pt.e = (e.charAt(1) !== "=") ? e : b.replace(new RegExp("\\s*\\b" + e.substr(2) + "\\b"), "") + ((e.charAt(0) === "+") ? " " + e.substr(2) : "");
4005
4032
  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.
4006
- t.className = pt.e;
4033
+ t.setAttribute("class", pt.e);
4007
4034
  difData = _cssDif(t, bs, _getAllStyles(t), vars, cnptLookup);
4008
- t.className = b;
4035
+ t.setAttribute("class", b);
4009
4036
  pt.data = difData.firstMPT;
4010
4037
  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).
4011
4038
  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)
@@ -4091,7 +4118,7 @@
4091
4118
  v = _getStyle(target, "zIndex", _cs);
4092
4119
  if (v === "auto" || v === "") {
4093
4120
  //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.
4094
- style.zIndex = 0;
4121
+ this._addLazySet(style, "zIndex", 0);
4095
4122
  }
4096
4123
  }
4097
4124
 
@@ -4118,7 +4145,7 @@
4118
4145
  if (style.zIndex === "") {
4119
4146
  zIndex = _getStyle(target, "zIndex", _cs);
4120
4147
  if (zIndex === "auto" || zIndex === "") {
4121
- style.zIndex = 0;
4148
+ this._addLazySet(style, "zIndex", 0);
4122
4149
  }
4123
4150
  }
4124
4151
  //Setting WebkitBackfaceVisibility corrects 3 bugs:
@@ -4127,7 +4154,7 @@
4127
4154
  // 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.
4128
4155
  //Note: we allow the user to override the auto-setting by defining WebkitBackfaceVisibility in the vars of the tween.
4129
4156
  if (_isSafariLT6) {
4130
- style.WebkitBackfaceVisibility = this._vars.WebkitBackfaceVisibility || (threeD ? "visible" : "hidden");
4157
+ this._addLazySet(style, "WebkitBackfaceVisibility", this._vars.WebkitBackfaceVisibility || (threeD ? "visible" : "hidden"));
4131
4158
  }
4132
4159
  }
4133
4160
  pt2 = pt;
@@ -4353,6 +4380,18 @@
4353
4380
  this._transform = this._transform || _getTransform(this._target, _cs, true); //ensures that the element has a _gsTransform property with the appropriate values.
4354
4381
  };
4355
4382
 
4383
+ var lazySet = function(v) {
4384
+ this.t[this.p] = this.e;
4385
+ 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.
4386
+ };
4387
+ /** @private Gives us a way to set a value on the first render (and only the first render). **/
4388
+ p._addLazySet = function(t, p, v) {
4389
+ var pt = this._firstPT = new CSSPropTween(t, p, 0, 0, this._firstPT, 2);
4390
+ pt.e = v;
4391
+ pt.setRatio = lazySet;
4392
+ pt.data = this;
4393
+ };
4394
+
4356
4395
  /** @private **/
4357
4396
  p._linkCSSP = function(pt, next, prev, remove) {
4358
4397
  if (pt) {
@@ -4583,7 +4622,7 @@
4583
4622
  window._gsDefine.plugin({
4584
4623
  propName: "attr",
4585
4624
  API: 2,
4586
- version: "0.3.0",
4625
+ version: "0.3.2",
4587
4626
 
4588
4627
  //called when the tween renders for the first time. This is where initial values should be recorded and any setup routines should run.
4589
4628
  init: function(target, value, tween) {
@@ -4595,11 +4634,10 @@
4595
4634
  this._proxy = {};
4596
4635
  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.
4597
4636
  this._end = {};
4598
- this._endRatio = tween.vars.runBackwards ? 0 : 1;
4599
4637
  for (p in value) {
4600
4638
  this._start[p] = this._proxy[p] = start = target.getAttribute(p);
4601
- this._end[p] = end = value[p];
4602
- this._addTween(this._proxy, p, parseFloat(start), end, p);
4639
+ end = this._addTween(this._proxy, p, parseFloat(start), value[p], p);
4640
+ this._end[p] = end ? end.s + end.c : value[p];
4603
4641
  this._overwriteProps.push(p);
4604
4642
  }
4605
4643
  return true;
@@ -4610,7 +4648,7 @@
4610
4648
  this._super.setRatio.call(this, ratio);
4611
4649
  var props = this._overwriteProps,
4612
4650
  i = props.length,
4613
- lookup = (ratio !== 0 && ratio !== 1) ? this._proxy : (ratio === this._endRatio) ? this._end : this._start,
4651
+ lookup = (ratio === 1) ? this._end : ratio ? this._proxy : this._start,
4614
4652
  p;
4615
4653
  while (--i > -1) {
4616
4654
  p = props[i];
@@ -4618,7 +4656,7 @@
4618
4656
  }
4619
4657
  }
4620
4658
 
4621
- })
4659
+ });
4622
4660
 
4623
4661
 
4624
4662
 
@@ -5328,12 +5366,18 @@
5328
5366
  var _self = this,
5329
5367
  _startTime = _getTime(),
5330
5368
  _useRAF = (useRAF !== false && _reqAnimFrame),
5369
+ _lagThreshold = 500,
5370
+ _adjustedLag = 33,
5331
5371
  _fps, _req, _id, _gap, _nextTime,
5332
5372
  _tick = function(manual) {
5333
- _lastUpdate = _getTime();
5373
+ var elapsed = _getTime() - _lastUpdate,
5374
+ overlap, dispatch;
5375
+ if (elapsed > _lagThreshold) {
5376
+ _startTime += elapsed - _adjustedLag;
5377
+ }
5378
+ _lastUpdate += elapsed;
5334
5379
  _self.time = (_lastUpdate - _startTime) / 1000;
5335
- var overlap = _self.time - _nextTime,
5336
- dispatch;
5380
+ overlap = _self.time - _nextTime;
5337
5381
  if (!_fps || overlap > 0 || manual === true) {
5338
5382
  _self.frame++;
5339
5383
  _nextTime += overlap + (overlap >= _gap ? 0.004 : _gap - overlap);
@@ -5353,6 +5397,11 @@
5353
5397
  _tick(true);
5354
5398
  };
5355
5399
 
5400
+ _self.lagSmoothing = function(threshold, adjustedLag) {
5401
+ _lagThreshold = threshold || (1 / _tinyNum); //zero should be interpreted as basically unlimited
5402
+ _adjustedLag = Math.min(adjustedLag, _lagThreshold, 0);
5403
+ };
5404
+
5356
5405
  _self.sleep = function() {
5357
5406
  if (_id == null) {
5358
5407
  return;
@@ -5372,6 +5421,8 @@
5372
5421
  _self.wake = function() {
5373
5422
  if (_id !== null) {
5374
5423
  _self.sleep();
5424
+ } 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().
5425
+ _lastUpdate = _getTime() - _lagThreshold + 5;
5375
5426
  }
5376
5427
  _req = (_fps === 0) ? _emptyFunc : (!_useRAF || !_reqAnimFrame) ? function(f) { return setTimeout(f, ((_nextTime - _self.time) * 1000 + 1) | 0); } : _reqAnimFrame;
5377
5428
  if (_self === _ticker) {
@@ -5657,6 +5708,9 @@
5657
5708
  }
5658
5709
  if (this._totalTime !== time || this._duration === 0) {
5659
5710
  this.render(time, suppressEvents, false);
5711
+ 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.
5712
+ _lazyRender();
5713
+ }
5660
5714
  }
5661
5715
  }
5662
5716
  return this;
@@ -5837,7 +5891,6 @@
5837
5891
  return this._totalTime;
5838
5892
  };
5839
5893
 
5840
-
5841
5894
  /*
5842
5895
  * ----------------------------------------------------------------
5843
5896
  * TweenLite
@@ -5893,7 +5946,8 @@
5893
5946
  }
5894
5947
  }
5895
5948
  if (this.vars.immediateRender || (duration === 0 && this._delay === 0 && this.vars.immediateRender !== false)) {
5896
- this.render(-this._delay, false, true);
5949
+ 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)
5950
+ this.render(-this._delay);
5897
5951
  }
5898
5952
  }, true),
5899
5953
  _isSelector = function(v) {
@@ -5903,7 +5957,7 @@
5903
5957
  var css = {},
5904
5958
  p;
5905
5959
  for (p in vars) {
5906
- if (!_reservedProps[p] && (!(p in target) || 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.
5960
+ 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.
5907
5961
  css[p] = vars[p];
5908
5962
  delete vars[p];
5909
5963
  }
@@ -5919,33 +5973,57 @@
5919
5973
 
5920
5974
  p.ratio = 0;
5921
5975
  p._firstPT = p._targets = p._overwrittenProps = p._startAt = null;
5922
- p._notifyPluginsOfEnabled = false;
5976
+ p._notifyPluginsOfEnabled = p._lazy = false;
5923
5977
 
5924
- TweenLite.version = "1.11.8";
5978
+ TweenLite.version = "1.12.1";
5925
5979
  TweenLite.defaultEase = p._ease = new Ease(null, null, 1, 1);
5926
5980
  TweenLite.defaultOverwrite = "auto";
5927
5981
  TweenLite.ticker = _ticker;
5928
5982
  TweenLite.autoSleep = true;
5983
+ TweenLite.lagSmoothing = function(threshold, adjustedLag) {
5984
+ _ticker.lagSmoothing(threshold, adjustedLag);
5985
+ };
5929
5986
  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; };
5930
5987
 
5931
- var _internals = TweenLite._internals = {isArray:_isArray, isSelector:_isSelector}, //gives us a way to expose certain private values to other GreenSock classes without contaminating tha main TweenLite object.
5988
+ var _lazyTweens = [],
5989
+ _lazyLookup = {},
5990
+ _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.
5932
5991
  _plugins = TweenLite._plugins = {},
5933
- _tweenLookup = TweenLite._tweenLookup = {},
5992
+ _tweenLookup = _internals.tweenLookup = {},
5934
5993
  _tweenLookupNum = 0,
5935
- _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},
5994
+ _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},
5936
5995
  _overwriteLookup = {none:0, all:1, auto:2, concurrent:3, allOnStart:4, preexisting:5, "true":1, "false":0},
5937
5996
  _rootFramesTimeline = Animation._rootFramesTimeline = new SimpleTimeline(),
5938
- _rootTimeline = Animation._rootTimeline = new SimpleTimeline();
5997
+ _rootTimeline = Animation._rootTimeline = new SimpleTimeline(),
5998
+ _lazyRender = function() {
5999
+ var i = _lazyTweens.length;
6000
+ _lazyLookup = {};
6001
+ while (--i > -1) {
6002
+ a = _lazyTweens[i];
6003
+ if (a && a._lazy !== false) {
6004
+ a.render(a._lazy, false, true);
6005
+ a._lazy = false;
6006
+ }
6007
+ }
6008
+ _lazyTweens.length = 0;
6009
+ };
5939
6010
 
5940
6011
  _rootTimeline._startTime = _ticker.time;
5941
6012
  _rootFramesTimeline._startTime = _ticker.frame;
5942
6013
  _rootTimeline._active = _rootFramesTimeline._active = true;
6014
+ 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".
5943
6015
 
5944
- Animation._updateRoot = function() {
6016
+ Animation._updateRoot = TweenLite.render = function() {
6017
+ var i, a, p;
6018
+ 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.
6019
+ _lazyRender();
6020
+ }
5945
6021
  _rootTimeline.render((_ticker.time - _rootTimeline._startTime) * _rootTimeline._timeScale, false, false);
5946
6022
  _rootFramesTimeline.render((_ticker.frame - _rootFramesTimeline._startTime) * _rootFramesTimeline._timeScale, false, false);
6023
+ if (_lazyTweens.length) {
6024
+ _lazyRender();
6025
+ }
5947
6026
  if (!(_ticker.frame % 120)) { //dump garbage every 120 frames...
5948
- var i, a, p;
5949
6027
  for (p in _tweenLookup) {
5950
6028
  a = _tweenLookup[p].tweens;
5951
6029
  i = a.length;
@@ -6065,16 +6143,23 @@
6065
6143
  var v = this.vars,
6066
6144
  op = this._overwrittenProps,
6067
6145
  dur = this._duration,
6068
- immediate = v.immediateRender,
6146
+ immediate = !!v.immediateRender,
6069
6147
  ease = v.ease,
6070
- i, initPlugins, pt, p;
6148
+ i, initPlugins, pt, p, startVars;
6071
6149
  if (v.startAt) {
6072
6150
  if (this._startAt) {
6073
6151
  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.
6152
+ this._startAt.kill();
6074
6153
  }
6075
- v.startAt.overwrite = 0;
6076
- v.startAt.immediateRender = true;
6077
- this._startAt = TweenLite.to(this.target, 0, v.startAt);
6154
+ startVars = {};
6155
+ 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);
6156
+ startVars[p] = v.startAt[p];
6157
+ }
6158
+ startVars.overwrite = false;
6159
+ startVars.immediateRender = true;
6160
+ startVars.lazy = (immediate && v.lazy !== false);
6161
+ startVars.startAt = startVars.delay = null; //no nesting of startAt objects allowed (otherwise it could cause an infinite loop).
6162
+ this._startAt = TweenLite.to(this.target, 0, startVars);
6078
6163
  if (immediate) {
6079
6164
  if (this._time > 0) {
6080
6165
  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()).
@@ -6086,6 +6171,7 @@
6086
6171
  //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)
6087
6172
  if (this._startAt) {
6088
6173
  this._startAt.render(-1, true);
6174
+ this._startAt.kill();
6089
6175
  this._startAt = null;
6090
6176
  } else {
6091
6177
  pt = {};
@@ -6096,9 +6182,12 @@
6096
6182
  }
6097
6183
  pt.overwrite = 0;
6098
6184
  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.
6185
+ pt.lazy = (immediate && v.lazy !== false);
6186
+ 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)
6099
6187
  this._startAt = TweenLite.to(this.target, 0, pt);
6100
- if (!v.immediateRender) {
6101
- this._startAt.render(-1, true); //for tweens that aren't rendered immediately, we still need to use the _startAt to record the starting values so that we can revert to them if the parent timeline's playhead goes backward beyond the beginning, but we immediately revert the tween back otherwise the parent tween that's currently instantiating wouldn't see the wrong starting values (since they were changed by the _startAt tween)
6188
+ if (!immediate) {
6189
+ this._startAt._init(); //ensures that the initial values are recorded
6190
+ 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.
6102
6191
  } else if (this._time === 0) {
6103
6192
  return;
6104
6193
  }
@@ -6149,6 +6238,11 @@
6149
6238
  if (target == null) {
6150
6239
  return false;
6151
6240
  }
6241
+
6242
+ if (_lazyLookup[target._gsTweenID]) {
6243
+ _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)
6244
+ }
6245
+
6152
6246
  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.
6153
6247
  _autoCSS(this.vars, target);
6154
6248
  }
@@ -6198,48 +6292,51 @@
6198
6292
  this._kill(propLookup, target);
6199
6293
  return this._initProps(target, propLookup, siblings, overwrittenProps);
6200
6294
  }
6295
+ 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.
6296
+ _lazyLookup[target._gsTweenID] = true;
6297
+ }
6201
6298
  return initPlugins;
6202
6299
  };
6203
6300
 
6204
6301
  p.render = function(time, suppressEvents, force) {
6205
6302
  var prevTime = this._time,
6206
6303
  duration = this._duration,
6304
+ prevRawPrevTime = this._rawPrevTime,
6207
6305
  isComplete, callback, pt, rawPrevTime;
6208
6306
  if (time >= duration) {
6209
6307
  this._totalTime = this._time = duration;
6210
6308
  this.ratio = this._ease._calcEnd ? this._ease.getRatio(1) : 1;
6211
- if (!this._reversed) {
6309
+ if (!this._reversed ) {
6212
6310
  isComplete = true;
6213
6311
  callback = "onComplete";
6214
6312
  }
6215
- if (duration === 0) { //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.
6216
- rawPrevTime = this._rawPrevTime;
6313
+ 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.
6217
6314
  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.
6218
6315
  time = 0;
6219
6316
  }
6220
- if (time === 0 || rawPrevTime < 0 || rawPrevTime === _tinyNum) if (rawPrevTime !== time) {
6317
+ if (time === 0 || prevRawPrevTime < 0 || prevRawPrevTime === _tinyNum) if (prevRawPrevTime !== time) {
6221
6318
  force = true;
6222
- if (rawPrevTime > _tinyNum) {
6319
+ if (prevRawPrevTime > _tinyNum) {
6223
6320
  callback = "onReverseComplete";
6224
6321
  }
6225
6322
  }
6226
- this._rawPrevTime = rawPrevTime = (!suppressEvents || time || this._rawPrevTime === 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.
6323
+ 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.
6227
6324
  }
6228
6325
 
6229
6326
  } else if (time < 0.0000001) { //to work around occasional floating point math artifacts, round super small values to 0.
6230
6327
  this._totalTime = this._time = 0;
6231
6328
  this.ratio = this._ease._calcEnd ? this._ease.getRatio(0) : 0;
6232
- if (prevTime !== 0 || (duration === 0 && this._rawPrevTime > 0 && this._rawPrevTime !== _tinyNum)) {
6329
+ if (prevTime !== 0 || (duration === 0 && prevRawPrevTime > 0 && prevRawPrevTime !== _tinyNum)) {
6233
6330
  callback = "onReverseComplete";
6234
6331
  isComplete = this._reversed;
6235
6332
  }
6236
6333
  if (time < 0) {
6237
6334
  this._active = false;
6238
- if (duration === 0) { //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.
6239
- if (this._rawPrevTime >= 0) {
6335
+ 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.
6336
+ if (prevRawPrevTime >= 0) {
6240
6337
  force = true;
6241
6338
  }
6242
- this._rawPrevTime = rawPrevTime = (!suppressEvents || time || this._rawPrevTime === 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.
6339
+ 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.
6243
6340
  }
6244
6341
  } 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.
6245
6342
  force = true;
@@ -6278,7 +6375,6 @@
6278
6375
  } else {
6279
6376
  this.ratio = this._ease.getRatio(time / duration);
6280
6377
  }
6281
-
6282
6378
  }
6283
6379
 
6284
6380
  if (this._time === prevTime && !force) {
@@ -6287,6 +6383,12 @@
6287
6383
  this._init();
6288
6384
  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.
6289
6385
  return;
6386
+ } else if (!force && this._firstPT && ((this.vars.lazy !== false && this._duration) || (this.vars.lazy && !this._duration))) {
6387
+ this._time = this._totalTime = prevTime;
6388
+ this._rawPrevTime = prevRawPrevTime;
6389
+ _lazyTweens.push(this);
6390
+ this._lazy = time;
6391
+ return;
6290
6392
  }
6291
6393
  //_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.
6292
6394
  if (this._time && !isComplete) {
@@ -6295,7 +6397,9 @@
6295
6397
  this.ratio = this._ease.getRatio((this._time === 0) ? 0 : 1);
6296
6398
  }
6297
6399
  }
6298
-
6400
+ 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.
6401
+ this._lazy = false;
6402
+ }
6299
6403
  if (!this._active) if (!this._paused && this._time !== prevTime && time >= 0) {
6300
6404
  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.
6301
6405
  }
@@ -6356,6 +6460,7 @@
6356
6460
  vars = null;
6357
6461
  }
6358
6462
  if (vars == null) if (target == null || target === this.target) {
6463
+ this._lazy = false;
6359
6464
  return this._enabled(false, false);
6360
6465
  }
6361
6466
  target = (typeof(target) !== "string") ? (target || this._targets || this.target) : TweenLite.selector(target) || target;
@@ -6426,7 +6531,7 @@
6426
6531
  this._overwrittenProps = null;
6427
6532
  this._onUpdate = null;
6428
6533
  this._startAt = null;
6429
- this._initted = this._active = this._notifyPluginsOfEnabled = false;
6534
+ this._initted = this._active = this._notifyPluginsOfEnabled = this._lazy = false;
6430
6535
  this._propLookup = (this._targets) ? {} : [];
6431
6536
  return this;
6432
6537
  };