148 lines
4.4 KiB
JavaScript
148 lines
4.4 KiB
JavaScript
|
dojo.provide("dojox.timing.Sequence");
|
||
|
dojo.experimental("dojox.timing.Sequence");
|
||
|
|
||
|
dojo.declare("dojox.timing.Sequence", null, {
|
||
|
// summary:
|
||
|
// This class provides functionality to really sequentialize
|
||
|
// function calls. You need to provide a list of functions and
|
||
|
// some parameters for each (like: pauseBefore) and they will
|
||
|
// be run one after another. This can be very useful for slideshows
|
||
|
// or alike things.
|
||
|
//
|
||
|
// description:
|
||
|
// This array will contain the sequence defines resolved, so that
|
||
|
// ie. repeat:10 will result in 10 elements in the sequence, so
|
||
|
// the repeat handling is easier and we don't need to handle that
|
||
|
// many extra cases. Also the doneFunction, if given is added at the
|
||
|
// end of the resolved-sequences.
|
||
|
|
||
|
/*=====
|
||
|
// _defsResolved: Array
|
||
|
// The resolved sequence, for easier handling.
|
||
|
_defsResolved: [],
|
||
|
=====*/
|
||
|
|
||
|
// This is the time to wait before goOn() calls _go(), which
|
||
|
// mostly results from a pauseAfter for a function that returned
|
||
|
// false and is later continued by the external goOn() call.
|
||
|
// The time to wait needs to be waited in goOn() where the
|
||
|
// sequence is continued.
|
||
|
|
||
|
// _goOnPause: Integer
|
||
|
// The pause to wait before really going on.
|
||
|
_goOnPause: 0,
|
||
|
|
||
|
_running: false,
|
||
|
|
||
|
constructor: function(){
|
||
|
this._defsResolved = [];
|
||
|
},
|
||
|
|
||
|
go: function(/* Array */defs, /* Function|Array? */doneFunction){
|
||
|
// summary: Run the passed sequence definition
|
||
|
//
|
||
|
// defs: Array
|
||
|
// The sequence of actions
|
||
|
// doneFunction: Function|Array?
|
||
|
// The function to call when done
|
||
|
this._running = true;
|
||
|
dojo.forEach(defs, function(cur){
|
||
|
if(cur.repeat > 1){
|
||
|
var repeat = cur.repeat;
|
||
|
for(var j = 0; j < repeat; j++){
|
||
|
cur.repeat = 1;
|
||
|
this._defsResolved.push(cur);
|
||
|
}
|
||
|
}else{
|
||
|
this._defsResolved.push(cur);
|
||
|
}
|
||
|
}, this);
|
||
|
var last = defs[defs.length - 1];
|
||
|
if(doneFunction){
|
||
|
this._defsResolved.push({ func: doneFunction });
|
||
|
}
|
||
|
// stop the sequence, this actually just sets this._running to false
|
||
|
this._defsResolved.push({ func: [this.stop, this] });
|
||
|
this._curId = 0;
|
||
|
this._go();
|
||
|
},
|
||
|
|
||
|
_go: function(){
|
||
|
// summary: Execute one task of this._defsResolved.
|
||
|
|
||
|
// if _running was set to false stop the sequence, this is the
|
||
|
// case when i.e. stop() was called.
|
||
|
if(!this._running){
|
||
|
return;
|
||
|
}
|
||
|
var cur = this._defsResolved[this._curId];
|
||
|
this._curId += 1;
|
||
|
// create the function to call, the func property might be an array, which means
|
||
|
// [function, context, parameter1, parameter2, ...]
|
||
|
function resolveAndCallFunc(func) {
|
||
|
var ret = null;
|
||
|
if(dojo.isArray(func)){
|
||
|
// Two elements might only be given when the function+context
|
||
|
// is given, this is nice for using this, ie: [this.func, this]
|
||
|
if(func.length>2){
|
||
|
ret = func[0].apply(func[1], func.slice(2));
|
||
|
}else{
|
||
|
ret = func[0].apply(func[1]);
|
||
|
}
|
||
|
}else{
|
||
|
ret = func();
|
||
|
}
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
if(this._curId >= this._defsResolved.length){
|
||
|
resolveAndCallFunc(cur.func); // call the last function, since it is the doneFunction we dont need to handle pause stuff
|
||
|
// don't go on and call this._go() again, we are done
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if(cur.pauseAfter){
|
||
|
if(resolveAndCallFunc(cur.func) !== false){
|
||
|
setTimeout(dojo.hitch(this, "_go"), cur.pauseAfter);
|
||
|
}else{
|
||
|
this._goOnPause = cur.pauseAfter;
|
||
|
}
|
||
|
}else if(cur.pauseBefore){
|
||
|
var x = dojo.hitch(this,function(){
|
||
|
if(resolveAndCallFunc(cur.func) !== false){
|
||
|
this._go()
|
||
|
}
|
||
|
});
|
||
|
setTimeout(x, cur.pauseBefore);
|
||
|
}else{
|
||
|
if(resolveAndCallFunc(cur.func) !== false){
|
||
|
this._go();
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
|
||
|
goOn: function(){
|
||
|
// summary: This method just provides a hook from the outside, so that
|
||
|
// an interrupted sequence can be continued.
|
||
|
if(this._goOnPause){
|
||
|
setTimeout(dojo.hitch(this, "_go"), this._goOnPause);
|
||
|
this._goOnPause = 0; // reset it, so if the next one doesnt set it we dont use the old pause
|
||
|
}else{ this._go(); }
|
||
|
},
|
||
|
|
||
|
stop: function(){
|
||
|
// summary: Stop the currently running sequence.
|
||
|
//
|
||
|
// description:
|
||
|
// This can only interrupt the sequence not the last function that
|
||
|
// had been started. If the last function was i.e. a slideshow
|
||
|
// that is handled inside a function that you have given as
|
||
|
// one sequence item it cant be stopped, since it is not controlled
|
||
|
// by this object here. In this case it would be smarter to
|
||
|
// run the slideshow using a sequence object so you can also stop
|
||
|
// it using this method.
|
||
|
this._running = false;
|
||
|
}
|
||
|
|
||
|
});
|