webui-aria2/js/libs/dojox/app/animation.js.uncompressed.js

348 lines
11 KiB
JavaScript
Raw Normal View History

//>>built
define("dojox/app/animation", ["dojo/_base/kernel",
"dojo/_base/lang",
"dojo/_base/declare",
"dojo/_base/array",
"dojo/_base/Deferred",
"dojo/DeferredList",
"dojo/on",
"dojo/_base/sniff"],
function(dojo, lang, declare, array, deferred, deferredList, on, has){
//TODO create cross platform animation/transition effects
var transitionEndEventName = "transitionend";
var transitionPrefix = "t"; //by default use "t" prefix and "ransition" to make word "transition"
var translateMethodStart = "translate3d(";//Android 2.x does not support translateX in CSS Transition, we need to use translate3d in webkit browsers
var translateMethodEnd = ",0,0)";
if(has("webkit")){
transitionPrefix = "WebkitT";
transitionEndEventName = "webkitTransitionEnd";
}else if(has("mozilla")){
transitionPrefix = "MozT";
translateMethodStart = "translateX(";
translateMethodEnd = ")";
}
//TODO find a way to lock the animation and prevent animation conflict
declare("dojox.app.animation", null, {
constructor: function(args){
//default config should be in animation object itself instead of its prototype
//otherwise, it might be easy for making mistake of modifying prototype
var defaultConfig = {
startState: {},
endState: {},
node: null,
duration: 250,
"in": true,
direction: 1,
autoClear: true
};
lang.mixin(this, defaultConfig);
lang.mixin(this, args);
//create the deferred object which will resolve after the animation is finished.
//We can rely on "onAfterEnd" function to notify the end of a single animation,
//but using a deferred object is easier to wait for multiple animations end.
if(!this.deferred){
this.deferred = new deferred();
}
},
play: function(){
//play the animation using CSS3 Transition
dojox.app.animation.groupedPlay([this]);
},
//method to apply the state of the transition
_applyState: function(state){
var style = this.node.style;
for(var property in state){
if(state.hasOwnProperty(property)){
style[property] = state[property];
}
}
},
//method to initialize state for transition
initState: function(){
//apply the immediate style change for initial state.
this.node.style[transitionPrefix + "ransitionProperty"] = "none";
this.node.style[transitionPrefix + "ransitionDuration"] = "0ms";
this._applyState(this.startState);
},
_beforeStart: function(){
if (this.node.style.display === "none"){
this.node.style.display = "";
}
this.beforeStart();
},
_beforeClear: function(){
this.node.style[transitionPrefix + "ransitionProperty"] = null;
this.node.style[transitionPrefix + "ransitionDuration"] = null;
if(this["in"] !== true){
this.node.style.display = "none";
}
this.beforeClear();
},
_onAfterEnd: function(){
this.deferred.resolve(this.node);
if(this.node.id && dojox.app.animation.playing[this.node.id]===this.deferred){
delete dojox.app.animation.playing[this.node.id];
}
this.onAfterEnd();
},
beforeStart: function(){
},
beforeClear: function(){
},
onAfterEnd: function(){
},
//method to start the transition
start: function(){
this._beforeStart();
var self = this;
//change the transition duration
self.node.style[transitionPrefix + "ransitionProperty"] = "all";
self.node.style[transitionPrefix + "ransitionDuration"] = self.duration + "ms";
//connect to clear the transition state after the transition end.
//Since the transition is conducted asynchronously, we need to
//connect to transition end event to clear the state
on.once(self.node, transitionEndEventName, function(){
self.clear();
});
this._applyState(this.endState);
},
//method to clear state after transition
clear: function(){
this._beforeClear();
this._removeState(this.endState);
console.log(this.node.id + " clear.");
this._onAfterEnd();
},
//create removeState method
_removeState: function(state){
var style = this.node.style;
for(var property in state){
if(state.hasOwnProperty(property)){
style[property] = null;
}
}
}
});
//TODO add the lock mechanism for all of the transition effects
// consider using only one object for one type of transition.
//TODO create the first animation, slide.
dojox.app.animation.slide = function(node, config){
//TODO create the return and set the startState, endState of the return
var ret = new dojox.app.animation(config);
ret.node = node;
var startX = "0";
var endX = "0";
if(ret["in"]){
if(ret.direction === 1){
startX = "100%";
}else{
startX = "-100%";
}
}else{
if(ret.direction === 1){
endX = "-100%";
}else{
endX = "100%";
}
}
ret.startState[transitionPrefix + "ransform"]=translateMethodStart+startX+translateMethodEnd;
ret.endState[transitionPrefix + "ransform"]=translateMethodStart+endX+translateMethodEnd;
return ret;
};
//fade in/out animation effects
dojox.app.animation.fade = function(node, config){
var ret = new dojox.app.animation(config);
ret.node = node;
var startOpacity = "0";
var endOpacity = "0";
if(ret["in"]){
endOpacity = "1";
}else{
startOpacity = "1";
}
lang.mixin(ret, {
startState:{
"opacity": startOpacity
},
endState:{
"opacity": endOpacity
}
});
return ret;
};
//fade in/out animation effects
dojox.app.animation.flip = function(node, config){
var ret = new dojox.app.animation(config);
ret.node = node;
if(ret["in"]){
//Need to set opacity here because Android 2.2 has bug that
//scale(...) in transform does not persist status
lang.mixin(ret,{
startState:{
"opacity": "0"
},
endState:{
"opacity": "1"
}
});
ret.startState[transitionPrefix + "ransform"]="scale(0,0.8) skew(0,-30deg)";
ret.endState[transitionPrefix + "ransform"]="scale(1,1) skew(0,0)";
}else{
lang.mixin(ret,{
startState:{
"opacity": "1"
},
endState:{
"opacity": "0"
}
});
ret.startState[transitionPrefix + "ransform"]="scale(1,1) skew(0,0)";
ret.endState[transitionPrefix + "ransform"]="scale(0,0.8) skew(0,30deg)";
}
return ret;
};
var getWaitingList = function(/*Array*/ nodes){
var defs = [];
array.forEach(nodes, function(node){
//check whether the node is under other animation
if(node.id && dojox.app.animation.playing[node.id]){
//TODO hook on deferred object in dojox.app.animation.playing
defs.push(dojox.app.animation.playing[node.id]);
}
});
return new deferredList(defs);
};
dojox.app.animation.getWaitingList = getWaitingList;
//TODO groupedPlay should ensure the UI update happens when
//all animations end.
//the group player to start multiple animations together
dojox.app.animation.groupedPlay = function(/*Array*/args){
//args should be array of dojox.app.animation
var animNodes = array.filter(args, function(item){
return item.node;
});
var waitingList = getWaitingList(animNodes);
//update registry with deferred objects in animations of args.
array.forEach(args, function(item){
if(item.node.id){
dojox.app.animation.playing[item.node.id] = item.deferred;
}
});
//TODO wait for all deferred object in deferred list to resolve
dojo.when(waitingList, function(){
array.forEach(args, function(item){
//set the start state
item.initState();
});
//Assume the fps of the animation should be higher than 30 fps and
//allow the browser to use one frame's time to redraw so that
//the transition can be started
setTimeout(function(){
array.forEach(args, function(item){
item.start();
});
}, 33);
});
};
//the chain player to start multiple animations one by one
dojox.app.animation.chainedPlay = function(/*Array*/args){
//args should be array of dojox.app.animation
var animNodes = array.filter(args, function(item){
return item.node;
});
var waitingList = getWaitingList(animNodes);
//update registry with deferred objects in animations of args.
array.forEach(args, function(item){
if(item.node.id){
dojox.app.animation.playing[item.node.id] = item.deferred;
}
});
dojo.when(waitingList, function(){
array.forEach(args, function(item){
//set the start state
item.initState();
});
//chain animations together
for (var i=1, len=args.length; i < len; i++){
args[i-1].deferred.then(lang.hitch(args[i], function(){
this.start();
}));
}
//Assume the fps of the animation should be higher than 30 fps and
//allow the browser to use one frame's time to redraw so that
//the transition can be started
setTimeout(function(){
args[0].start();
}, 33);
});
};
//TODO complete the registry mechanism for animation handling and prevent animation conflicts
dojox.app.animation.playing = {};
return dojox.app.animation;
});