]>
git.wh0rd.org - tt-rss.git/blob - lib/dojo/_base/fx.js.uncompressed.js
1 define("dojo/_base/fx", ["./kernel", "./config", /*===== "./declare", =====*/ "./lang", "../Evented", "./Color", "./connect", "./sniff", "../dom", "../dom-style"],
2 function(dojo, config, /*===== declare, =====*/ lang
, Evented
, Color
, connect
, has
, dom
, style
){
6 // Animation loosely package based on Dan Pupius' work, contributed under CLA; see
7 // http://pupius.co.uk/js/Toolkit.Drawing.js
9 var _mixin
= lang
.mixin
;
14 // This module defines the base dojo/_base/fx implementation.
17 var _Line
= basefx
._Line = function(/*int*/ start
, /*int*/ end
){
19 // Object used to generate values from a start value to an end value
21 // Beginning value for range
23 // Ending value for range
28 _Line
.prototype.getValue = function(/*float*/ n
){
30 // Returns the point on the line
32 // a floating point number greater than 0 and less than 1
33 return ((this.end
- this.start
) * n
) + this.start
; // Decimal
36 var Animation
= basefx
.Animation = function(args
){
38 // A generic animation class that fires callbacks into its handlers
39 // object at various states.
41 // A generic animation class that fires callbacks into its handlers
42 // object at various states. Nearly all dojo animation functions
43 // return an instance of this method, usually without calling the
44 // .play() method beforehand. Therefore, you will likely need to
45 // call .play() on instances of `Animation` when one is
48 // The 'magic argument', mixing all the properties into this
49 // animation instance.
52 if(lang
.isArray(this.curve
)){
53 this.curve
= new _Line(this.curve
[0], this.curve
[1]);
57 Animation
.prototype = new Evented();
59 lang
.extend(Animation
, {
61 // The time in milliseconds the animation will take to run
66 // A two element array of start and end values, or a `_Line` instance to be
67 // used in the Animation.
71 // A Function to adjust the acceleration (or deceleration) of the progress
77 // The number of times to loop the animation
81 // the time in milliseconds to wait before advancing to next frame
82 // (used as a fps timer: 1000/rate = fps)
83 rate
: 20 /* 50 fps */,
87 // The time in milliseconds to wait before starting animation after it
88 // has been .play()'ed
91 // beforeBegin: Event?
92 // Synthetic event fired before a Animation begins playing (synchronous)
96 // Synthetic event fired as a Animation begins playing (useful?)
100 // Synthetic event fired at each interval of the Animation
104 // Synthetic event fired after the final frame of the Animation
108 // Synthetic event fired any time the Animation is play()'ed
112 // Synthetic event fired when the Animation is paused
116 // Synthetic event fires when the Animation is stopped
122 _startRepeatCount
: 0,
124 _getStep: function(){
125 var _p
= this._percent
,
128 return _e
? _e(_p
) : _p
;
130 _fire: function(/*Event*/ evt
, /*Array?*/ args
){
132 // Convenience function. Fire event "evt" and pass it the
133 // arguments specified in "args".
135 // Convenience function. Fire event "evt" and pass it the
136 // arguments specified in "args".
137 // Fires the callback in the scope of this Animation
140 // The event to fire.
142 // The arguments to pass to the event.
145 if(config
.debugAtAllCosts
){
146 this[evt
].apply(this, a
);
149 this[evt
].apply(this, a
);
151 // squelch and log because we shouldn't allow exceptions in
152 // synthetic event handlers to cause the internal timer to run
153 // amuck, potentially pegging the CPU. I'm not a fan of this
154 // squelch, but hopefully logging will make it clear what's
156 console
.error("exception in animation handler for:", evt
);
161 return this; // Animation
164 play: function(/*int?*/ delay
, /*Boolean?*/ gotoStart
){
166 // Start the animation.
168 // How many milliseconds to delay before starting.
170 // If true, starts the animation from the beginning; otherwise,
171 // starts it from its current position.
172 // returns: Animation
173 // The instance to allow chaining.
176 if(_t
._delayTimer
){ _t
._clearTimer(); }
179 _t
._active
= _t
._paused
= false;
181 }else if(_t
._active
&& !_t
._paused
){
185 _t
._fire("beforeBegin", [_t
.node
]);
187 var de
= delay
|| _t
.delay
,
188 _p
= lang
.hitch(_t
, "_play", gotoStart
);
191 _t
._delayTimer
= setTimeout(_p
, de
);
195 return _t
; // Animation
198 _play: function(gotoStart
){
200 if(_t
._delayTimer
){ _t
._clearTimer(); }
201 _t
._startTime
= new Date().valueOf();
203 _t
._startTime
-= _t
.duration
* _t
._percent
;
208 var value
= _t
.curve
.getValue(_t
._getStep());
210 if(!_t
._startRepeatCount
){
211 _t
._startRepeatCount
= _t
.repeat
;
213 _t
._fire("onBegin", [value
]);
216 _t
._fire("onPlay", [value
]);
219 return _t
; // Animation
224 // Pauses a running animation.
226 if(_t
._delayTimer
){ _t
._clearTimer(); }
228 if(!_t
._active
){ return _t
; /*Animation*/ }
230 _t
._fire("onPause", [_t
.curve
.getValue(_t
._getStep())]);
231 return _t
; // Animation
234 gotoPercent: function(/*Decimal*/ percent
, /*Boolean?*/ andPlay
){
236 // Sets the progress of the animation.
238 // A percentage in decimal notation (between and including 0.0 and 1.0).
240 // If true, play the animation after setting the progress.
243 _t
._active
= _t
._paused
= true;
244 _t
._percent
= percent
;
245 if(andPlay
){ _t
.play(); }
246 return _t
; // Animation
249 stop: function(/*boolean?*/ gotoEnd
){
251 // Stops a running animation.
253 // If true, the animation will end.
255 if(_t
._delayTimer
){ _t
._clearTimer(); }
256 if(!_t
._timer
){ return _t
; /* Animation */ }
261 _t
._fire("onStop", [_t
.curve
.getValue(_t
._getStep())]);
262 _t
._active
= _t
._paused
= false;
263 return _t
; // Animation
268 // Returns a string token representation of the status of
269 // the animation, one of: "paused", "playing", "stopped"
271 return this._paused
? "paused" : "playing"; // String
273 return "stopped"; // String
279 var curr
= new Date().valueOf();
280 // Allow durations of 0 (instant) by setting step to 1 - see #13798
281 var step
= _t
.duration
=== 0 ? 1 : (curr
- _t
._startTime
) / (_t
.duration
);
290 step
= _t
.easing(step
);
293 _t
._fire("onAnimate", [_t
.curve
.getValue(step
)]);
303 }else if(_t
.repeat
== -1){
306 if(_t
._startRepeatCount
){
307 _t
.repeat
= _t
._startRepeatCount
;
308 _t
._startRepeatCount
= 0;
312 _t
._fire("onEnd", [_t
.node
]);
313 !_t
.repeat
&& _t
._stopTimer();
316 return _t
; // Animation
319 _clearTimer: function(){
321 // Clear the play delay timer
322 clearTimeout(this._delayTimer
);
323 delete this._delayTimer
;
328 // the local timer, stubbed into all Animation instances
335 lang
.extend(Animation
, {
337 _startTimer: function(){
339 this._timer
= connect
.connect(runner
, "run", this, "_cycle");
343 timer
= setInterval(lang
.hitch(runner
, "run"), this.rate
);
347 _stopTimer: function(){
349 connect
.disconnect(this._timer
);
354 clearInterval(timer
);
363 has("ie") ? function(node
){
364 // only set the zoom if the "tickle" value would be the same as the
367 // don't set the width to auto if it didn't already cascade that way.
368 // We don't want to f anyones designs
369 if(!ns
.width
.length
&& style
.get(node
, "width") == "auto"){
375 basefx
._fade = function(/*Object*/ args
){
377 // Returns an animation that will fade the node defined by
378 // args.node from the start to end values passed (args.start
379 // args.end) (end is mandatory, start is optional)
381 args
.node
= dom
.byId(args
.node
);
382 var fArgs
= _mixin({ properties
: {} }, args
),
383 props
= (fArgs
.properties
.opacity
= {});
385 props
.start
= !("start" in fArgs
) ?
387 return +style
.get(fArgs
.node
, "opacity")||0;
389 props
.end
= fArgs
.end
;
391 var anim
= basefx
.animateProperty(fArgs
);
392 connect
.connect(anim
, "beforeBegin", lang
.partial(_makeFadeable
, fArgs
.node
));
394 return anim
; // Animation
398 var __FadeArgs = declare(null, {
399 // node: DOMNode|String
400 // The node referenced in the animation
401 // duration: Integer?
402 // Duration of the animation in milliseconds.
404 // An easing function.
408 basefx
.fadeIn = function(/*__FadeArgs*/ args
){
410 // Returns an animation that will fade node defined in 'args' from
411 // its current opacity to fully opaque.
412 return basefx
._fade(_mixin({ end
: 1 }, args
)); // Animation
415 basefx
.fadeOut = function(/*__FadeArgs*/ args
){
417 // Returns an animation that will fade node defined in 'args'
418 // from its current opacity to fully transparent.
419 return basefx
._fade(_mixin({ end
: 0 }, args
)); // Animation
422 basefx
._defaultEasing = function(/*Decimal?*/ n
){
424 // The default easing function for Animation(s)
425 return 0.5 + ((Math
.sin((n
+ 1.5) * Math
.PI
)) / 2); // Decimal
428 var PropLine = function(properties
){
429 // PropLine is an internal class which is used to model the values of
430 // an a group of CSS properties across an animation lifecycle. In
431 // particular, the "getValue" function handles getting interpolated
432 // values between start and end for a particular CSS value.
433 this._properties
= properties
;
434 for(var p
in properties
){
435 var prop
= properties
[p
];
436 if(prop
.start
instanceof Color
){
437 // create a reusable temp color object to keep intermediate results
438 prop
.tempColor
= new Color();
443 PropLine
.prototype.getValue = function(r
){
445 for(var p
in this._properties
){
446 var prop
= this._properties
[p
],
448 if(start
instanceof Color
){
449 ret
[p
] = Color
.blendColors(start
, prop
.end
, r
, prop
.tempColor
).toCss();
450 }else if(!lang
.isArray(start
)){
451 ret
[p
] = ((prop
.end
- start
) * r
) + start
+ (p
!= "opacity" ? prop
.units
|| "px" : 0);
458 var __AnimArgs = declare(__FadeArgs, {
459 // properties: Object?
460 // A hash map of style properties to Objects describing the transition,
461 // such as the properties of _Line with an additional 'units' property
464 //TODOC: add event callbacks
468 basefx
.animateProperty = function(/*__AnimArgs*/ args
){
470 // Returns an animation that will transition the properties of
471 // node defined in `args` depending how they are defined in
475 // Foundation of most `dojo/_base/fx`
476 // animations. It takes an object of "properties" corresponding to
477 // style properties, and animates them in parallel over a set
481 // A simple animation that changes the width of the specified node.
482 // | basefx.animateProperty({
484 // | properties: { width: 400 },
486 // Dojo figures out the start value for the width and converts the
487 // integer specified for the width to the more expressive but
488 // verbose form `{ width: { end: '400', units: 'px' } }` which you
489 // can also specify directly. Defaults to 'px' if omitted.
492 // Animate width, height, and padding over 2 seconds... the
494 // | basefx.animateProperty({ node: node, duration:2000,
496 // | width: { start: '200', end: '400', units:"px" },
497 // | height: { start:'200', end: '400', units:"px" },
498 // | paddingTop: { start:'5', end:'50', units:"px" }
501 // Note 'paddingTop' is used over 'padding-top'. Multi-name CSS properties
502 // are written using "mixed case", as the hyphen is illegal as an object key.
505 // Plug in a different easing function and register a callback for
506 // when the animation ends. Easing functions accept values between
507 // zero and one and return a value on that basis. In this case, an
508 // exponential-in curve.
509 // | basefx.animateProperty({
511 // | // dojo figures out the start value
512 // | properties: { width: { end: 400 } },
513 // | easing: function(n){
514 // | return (n==0) ? 0 : Math.pow(2, 10 * (n - 1));
516 // | onEnd: function(node){
517 // | // called when the animation finishes. The animation
518 // | // target is passed to this function
520 // | }).play(500); // delay playing half a second
523 // Like all `Animation`s, animateProperty returns a handle to the
524 // Animation instance, which fires the events common to Dojo FX. Use `aspect.after`
525 // to access these events outside of the Animation definition:
526 // | var anim = basefx.animateProperty({
529 // | width:400, height:500
532 // | aspect.after(anim, "onEnd", function(){
533 // | console.log("animation ended");
535 // | // play the animation now:
539 // Each property can be a function whose return value is substituted along.
540 // Additionally, each measurement (eg: start, end) can be a function. The node
541 // reference is passed directly to callbacks.
542 // | basefx.animateProperty({
545 // | height:function(node){
546 // | // shrink this node by 50%
547 // | return domGeom.position(node).h / 2
550 // | start:function(node){ return 100; },
551 // | end:function(node){ return 200; }
557 var n
= args
.node
= dom
.byId(args
.node
);
558 if(!args
.easing
){ args
.easing
= dojo
._defaultEasing
; }
560 var anim
= new Animation(args
);
561 connect
.connect(anim
, "beforeBegin", anim
, function(){
563 for(var p
in this.properties
){
564 // Make shallow copy of properties into pm because we overwrite
565 // some values below. In particular if start/end are functions
566 // we don't want to overwrite them or the functions won't be
567 // called if the animation is reused.
568 if(p
== "width" || p
== "height"){
569 this.node
.display
= "block";
571 var prop
= this.properties
[p
];
572 if(lang
.isFunction(prop
)){
575 prop
= pm
[p
] = _mixin({}, (lang
.isObject(prop
) ? prop
: { end
: prop
}));
577 if(lang
.isFunction(prop
.start
)){
578 prop
.start
= prop
.start(n
);
580 if(lang
.isFunction(prop
.end
)){
581 prop
.end
= prop
.end(n
);
583 var isColor
= (p
.toLowerCase().indexOf("color") >= 0);
584 function getStyle(node
, p
){
585 // domStyle.get(node, "height") can return "auto" or "" on IE; this is more reliable:
586 var v
= { height
: node
.offsetHeight
, width
: node
.offsetWidth
}[p
];
587 if(v
!== undefined){ return v
; }
588 v
= style
.get(node
, p
);
589 return (p
== "opacity") ? +v
: (isColor
? v
: parseFloat(v
));
591 if(!("end" in prop
)){
592 prop
.end
= getStyle(n
, p
);
593 }else if(!("start" in prop
)){
594 prop
.start
= getStyle(n
, p
);
598 prop
.start
= new Color(prop
.start
);
599 prop
.end
= new Color(prop
.end
);
601 prop
.start
= (p
== "opacity") ? +prop
.start
: parseFloat(prop
.start
);
604 this.curve
= new PropLine(pm
);
606 connect
.connect(anim
, "onAnimate", lang
.hitch(style
, "set", anim
.node
));
607 return anim
; // Animation
610 basefx
.anim = function( /*DOMNode|String*/ node
,
611 /*Object*/ properties
,
612 /*Integer?*/ duration
,
613 /*Function?*/ easing
,
617 // A simpler interface to `animateProperty()`, also returns
618 // an instance of `Animation` but begins the animation
619 // immediately, unlike nearly every other Dojo animation API.
621 // Simpler (but somewhat less powerful) version
622 // of `animateProperty`. It uses defaults for many basic properties
623 // and allows for positional parameters to be used in place of the
624 // packed "property bag" which is used for other Dojo animation
627 // The `Animation` object returned will be already playing, so
628 // calling play() on it again is (usually) a no-op.
630 // a DOM node or the id of a node to animate CSS properties on
632 // The number of milliseconds over which the animation
633 // should run. Defaults to the global animation default duration
636 // An easing function over which to calculate acceleration
637 // and deceleration of the animation through its duration.
638 // A default easing algorithm is provided, but you may
639 // plug in any you wish. A large selection of easing algorithms
640 // are available in `dojo/fx/easing`.
642 // A function to be called when the animation finishes
645 // The number of milliseconds to delay beginning the
646 // animation by. The default is 0.
649 // | basefx.anim("id", { opacity: 0 });
651 // Fade out a node over a full second
652 // | basefx.anim("id", { opacity: 0 }, 1000);
653 return basefx
.animateProperty({ // Animation
655 duration
: duration
|| Animation
.prototype.duration
,
656 properties
: properties
,
664 _mixin(dojo
, basefx
);
665 // Alias to drop come 2.0:
666 dojo
._Animation
= Animation
;