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; } });