Subversion Repositories Applications.papyrus

Compare Revisions

Ignore whitespace Rev 2149 → Rev 2150

/trunk/api/js/dojo1.0/dojo/_base/fx.js
New file
0,0 → 1,464
if(!dojo._hasResource["dojo._base.fx"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojo._base.fx"] = true;
dojo.provide("dojo._base.fx");
dojo.require("dojo._base.Color");
dojo.require("dojo._base.connect");
dojo.require("dojo._base.declare");
dojo.require("dojo._base.lang");
dojo.require("dojo._base.html");
 
/*
Animation losely package based on Dan Pupius' work, contributed under CLA:
http://pupius.co.uk/js/Toolkit.Drawing.js
*/
 
dojo._Line = function(/*int*/ start, /*int*/ end){
// summary:
// dojo._Line is the object used to generate values from a start value
// to an end value
// start: int
// Beginning value for range
// end: int
// Ending value for range
this.start = start;
this.end = end;
this.getValue = function(/*float*/ n){
// summary: returns the point on the line
// n: a floating point number greater than 0 and less than 1
return ((this.end - this.start) * n) + this.start; // Decimal
}
}
 
dojo.declare("dojo._Animation", null, {
// summary
// A generic animation object that fires callbacks into it's handlers
// object at various states
//
constructor: function(/*Object*/ args){
dojo.mixin(this, args);
if(dojo.isArray(this.curve)){
/* curve: Array
pId: a */
this.curve = new dojo._Line(this.curve[0], this.curve[1]);
}
},
// duration: Integer
// The time in milliseonds the animation will take to run
duration: 1000,
 
/*=====
// curve: dojo._Line||Array
// A two element array of start and end values, or a dojo._Line instance to be
// used in the Animation.
curve: null,
 
// easing: Function
// A Function to adjust the acceleration (or deceleration) of the progress
// across a dojo._Line
easing: null,
=====*/
 
// repeat: Integer
// The number of times to loop the animation
repeat: 0,
 
// rate: Integer
// the time in milliseconds to wait before advancing to next frame
// (used as a fps timer: rate/1000 = fps)
rate: 10 /* 100 fps */,
 
/*=====
// delay: Integer
// The time in milliseconds to wait before starting animation after it has been .play()'ed
delay: null,
 
// events
//
// beforeBegin: Event
// Synthetic event fired before a dojo._Animation begins playing (synhcronous)
beforeBegin: null,
 
// onBegin: Event
// Synthetic event fired as a dojo._Animation begins playing (useful?)
onBegin: null,
 
// onAnimate: Event
// Synthetic event fired at each interval of a dojo._Animation
onAnimate: null,
 
// onEnd: Event
// Synthetic event fired after the final frame of a dojo._Animation
onEnd: null,
 
// ???
onPlay: null,
 
// onPause: Event
// Synthetic event fired when a dojo._Animation is paused
onPause: null,
 
// onStop: Event
// Synthetic event fires when a dojo._Animation is stopped
onStop: null,
 
=====*/
 
_percent: 0,
_startRepeatCount: 0,
 
fire: function(/*Event*/ evt, /*Array?*/ args){
// summary:
// Convenience function. Fire event "evt" and pass it the
// arguments specified in "args".
// evt:
// The event to fire.
// args:
// The arguments to pass to the event.
if(this[evt]){
this[evt].apply(this, args||[]);
}
return this; // dojo._Animation
},
 
play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){
// summary:
// Start the animation.
// delay:
// How many milliseconds to delay before starting.
// gotoStart:
// If true, starts the animation from the beginning; otherwise,
// starts it from its current position.
var _t = this;
if(gotoStart){
_t._stopTimer();
_t._active = _t._paused = false;
_t._percent = 0;
}else if(_t._active && !_t._paused){
return _t; // dojo._Animation
}
 
_t.fire("beforeBegin");
 
var d = delay||_t.delay;
var _p = dojo.hitch(_t, "_play", gotoStart);
if(d > 0){
setTimeout(_p, d);
return _t; // dojo._Animation
}
_p();
return _t;
},
 
_play: function(gotoStart){
var _t = this;
_t._startTime = new Date().valueOf();
if(_t._paused){
_t._startTime -= _t.duration * _t._percent;
}
_t._endTime = _t._startTime + _t.duration;
 
_t._active = true;
_t._paused = false;
 
var value = _t.curve.getValue(_t._percent);
if(!_t._percent){
if(!_t._startRepeatCount){
_t._startRepeatCount = _t.repeat;
}
_t.fire("onBegin", [value]);
}
 
_t.fire("onPlay", [value]);
 
_t._cycle();
return _t; // dojo._Animation
},
 
pause: function(){
// summary: Pauses a running animation.
this._stopTimer();
if(!this._active){ return this; /*dojo._Animation*/}
this._paused = true;
this.fire("onPause", [this.curve.getValue(this._percent)]);
return this; // dojo._Animation
},
 
gotoPercent: function(/*Decimal*/ percent, /*Boolean?*/ andPlay){
// summary:
// Sets the progress of the animation.
// percent:
// A percentage in decimal notation (between and including 0.0 and 1.0).
// andPlay:
// If true, play the animation after setting the progress.
this._stopTimer();
this._active = this._paused = true;
this._percent = percent;
if(andPlay){ this.play(); }
return this; // dojo._Animation
},
 
stop: function(/*boolean?*/ gotoEnd){
// summary: Stops a running animation.
// gotoEnd: If true, the animation will end.
if(!this._timer){ return; }
this._stopTimer();
if(gotoEnd){
this._percent = 1;
}
this.fire("onStop", [this.curve.getValue(this._percent)]);
this._active = this._paused = false;
return this; // dojo._Animation
},
 
status: function(){
// summary: Returns a string token representation of the status of
// the animation, one of: "paused", "playing", "stopped"
if(this._active){
return this._paused ? "paused" : "playing"; // String
}
return "stopped"; // String
},
 
_cycle: function(){
var _t = this;
if(_t._active){
var curr = new Date().valueOf();
var step = (curr - _t._startTime) / (_t._endTime - _t._startTime);
 
if(step >= 1){
step = 1;
}
_t._percent = step;
 
// Perform easing
if(_t.easing){
step = _t.easing(step);
}
 
_t.fire("onAnimate", [_t.curve.getValue(step)]);
 
if(step < 1){
_t._startTimer();
}else{
_t._active = false;
 
if(_t.repeat > 0){
_t.repeat--;
_t.play(null, true);
}else if(_t.repeat == -1){
_t.play(null, true);
}else{
if(_t._startRepeatCount){
_t.repeat = _t._startRepeatCount;
_t._startRepeatCount = 0;
}
}
_t._percent = 0;
_t.fire("onEnd");
}
}
return _t; // dojo._Animation
}
});
 
(function(){
var d = dojo;
var ctr = 0;
var _globalTimerList = [];
var runner = {
run: function(){}
};
var timer = null;
dojo._Animation.prototype._startTimer = function(){
// this._timer = setTimeout(dojo.hitch(this, "_cycle"), this.rate);
if(!this._timer){
this._timer = dojo.connect(runner, "run", this, "_cycle");
ctr++;
}
if(!timer){
timer = setInterval(dojo.hitch(runner, "run"), this.rate);
}
};
 
dojo._Animation.prototype._stopTimer = function(){
dojo.disconnect(this._timer);
this._timer = null;
ctr--;
if(!ctr){
clearInterval(timer);
timer = null;
}
};
 
var _makeFadeable = (d.isIE) ? function(node){
// only set the zoom if the "tickle" value would be the same as the
// default
var ns = node.style;
if(!ns.zoom.length && d.style(node, "zoom") == "normal"){
// make sure the node "hasLayout"
// NOTE: this has been tested with larger and smaller user-set text
// sizes and works fine
ns.zoom = "1";
// node.style.zoom = "normal";
}
// don't set the width to auto if it didn't already cascade that way.
// We don't want to f anyones designs
if(!ns.width.length && d.style(node, "width") == "auto"){
ns.width = "auto";
}
} : function(){};
 
dojo._fade = function(/*Object*/ args){
// summary:
// Returns an animation that will fade the node defined by
// args.node from the start to end values passed (args.start
// args.end) (end is mandatory, start is optional)
 
args.node = d.byId(args.node);
var fArgs = d.mixin({ properties: {} }, args);
var props = (fArgs.properties.opacity = {});
props.start = !("start" in fArgs) ?
function(){ return Number(d.style(fArgs.node, "opacity")); } : fArgs.start;
props.end = fArgs.end;
 
var anim = d.animateProperty(fArgs);
d.connect(anim, "beforeBegin", d.partial(_makeFadeable, fArgs.node));
 
return anim; // dojo._Animation
}
 
/*=====
dojo.__fadeArgs = function(kwArgs){
// duration: Integer?
// Duration of the animation in milliseconds.
// easing: Function?
// An easing function.
}
=====*/
 
dojo.fadeIn = function(/*dojo.__fadeArgs*/ args){
// summary:
// Returns an animation that will fade node defined in 'args' from
// its current opacity to fully opaque.
return d._fade(d.mixin({ end: 1 }, args)); // dojo._Animation
}
 
dojo.fadeOut = function(/*dojo.__fadeArgs*/ args){
// summary:
// Returns an animation that will fade node defined in 'args'
// from its current opacity to fully transparent.
return d._fade(d.mixin({ end: 0 }, args)); // dojo._Animation
}
 
dojo._defaultEasing = function(/*Decimal?*/ n){
// summary: The default easing function for dojo._Animation(s)
return 0.5 + ((Math.sin((n + 1.5) * Math.PI))/2);
}
 
var PropLine = function(properties){
this._properties = properties;
for(var p in properties){
var prop = properties[p];
if(prop.start instanceof d.Color){
// create a reusable temp color object to keep intermediate results
prop.tempColor = new d.Color();
}
}
this.getValue = function(r){
var ret = {};
for(var p in this._properties){
var prop = this._properties[p];
var start = prop.start;
if(start instanceof d.Color){
ret[p] = d.blendColors(start, prop.end, r, prop.tempColor).toCss();
}else if(!d.isArray(start)){
ret[p] = ((prop.end - start) * r) + start + (p != "opacity" ? prop.units||"px" : "");
}
}
return ret;
}
}
 
dojo.animateProperty = function(/*Object*/ args){
// summary:
// Returns an animation that will transition the properties of
// node defined in 'args' depending how they are defined in
// 'args.properties'
//
// description:
// The foundation of most dojo.fx animations, dojo.AnimateProperty
// will take an object of "properties" corresponding to style
// properties, and animate them in parallel over a set duration.
//
// args.node can be a String or a DomNode reference
//
// example:
// | dojo.animateProperty({ node: node, duration:2000,
// | properties: {
// | width: { start: '200', end: '400', unit:"px" },
// | height: { start:'200', end: '400', unit:"px" },
// | paddingTop: { start:'5', end:'50', unit:"px" }
// | }
// | }).play();
//
 
args.node = d.byId(args.node);
if(!args.easing){ args.easing = d._defaultEasing; }
 
var anim = new d._Animation(args);
d.connect(anim, "beforeBegin", anim, function(){
var pm = {};
for(var p in this.properties){
// Make shallow copy of properties into pm because we overwrite some values below.
// In particular if start/end are functions we don't want to overwrite them or
// the functions won't be called if the animation is reused.
var prop = (pm[p] = d.mixin({}, this.properties[p]));
 
if(d.isFunction(prop.start)){
prop.start = prop.start();
}
if(d.isFunction(prop.end)){
prop.end = prop.end();
}
 
var isColor = (p.toLowerCase().indexOf("color") >= 0);
function getStyle(node, p){
// dojo.style(node, "height") can return "auto" or "" on IE; this is more reliable:
var v = ({height: node.offsetHeight, width: node.offsetWidth})[p];
if(v !== undefined){ return v; }
v = d.style(node, p);
return (p=="opacity") ? Number(v) : parseFloat(v);
}
if(!("end" in prop)){
prop.end = getStyle(this.node, p);
}else if(!("start" in prop)){
prop.start = getStyle(this.node, p);
}
 
if(isColor){
// console.debug("it's a color!");
prop.start = new d.Color(prop.start);
prop.end = new d.Color(prop.end);
}else{
prop.start = (p == "opacity") ? Number(prop.start) : parseFloat(prop.start);
}
// console.debug("start:", prop.start);
// console.debug("end:", prop.end);
}
this.curve = new PropLine(pm);
});
d.connect(anim, "onAnimate", anim, function(propValues){
// try{
for(var s in propValues){
// console.debug(s, propValues[s], this.node.style[s]);
d.style(this.node, s, propValues[s]);
// this.node.style[s] = propValues[s];
}
// }catch(e){ console.debug(dojo.toJson(e)); }
});
return anim; // dojo._Animation
}
})();
 
}