Sequence.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. define("dojox/timing/Sequence", [
  2. "dojo/_base/kernel",
  3. "dojo/_base/array",
  4. "dojo/_base/declare",
  5. "dojo/_base/lang",
  6. "./_base"
  7. ], function(dojo){
  8. dojo.experimental("dojox.timing.Sequence");
  9. dojo.declare("dojox.timing.Sequence", null, {
  10. // summary:
  11. // This class provides functionality to really sequentialize
  12. // function calls. You need to provide a list of functions and
  13. // some parameters for each (like: pauseBefore) and they will
  14. // be run one after another. This can be very useful for slideshows
  15. // or alike things.
  16. //
  17. // description:
  18. // This array will contain the sequence defines resolved, so that
  19. // ie. repeat:10 will result in 10 elements in the sequence, so
  20. // the repeat handling is easier and we don't need to handle that
  21. // many extra cases. Also the doneFunction, if given is added at the
  22. // end of the resolved-sequences.
  23. /*=====
  24. // _defsResolved: Array
  25. // The resolved sequence, for easier handling.
  26. _defsResolved: [],
  27. =====*/
  28. // This is the time to wait before goOn() calls _go(), which
  29. // mostly results from a pauseAfter for a function that returned
  30. // false and is later continued by the external goOn() call.
  31. // The time to wait needs to be waited in goOn() where the
  32. // sequence is continued.
  33. // _goOnPause: Integer
  34. // The pause to wait before really going on.
  35. _goOnPause: 0,
  36. _running: false,
  37. constructor: function(){
  38. this._defsResolved = [];
  39. },
  40. go: function(/* Array */defs, /* Function|Array? */doneFunction){
  41. // summary: Run the passed sequence definition
  42. //
  43. // defs: Array
  44. // The sequence of actions
  45. // doneFunction: Function|Array?
  46. // The function to call when done
  47. this._running = true;
  48. dojo.forEach(defs, function(cur){
  49. if(cur.repeat > 1){
  50. var repeat = cur.repeat;
  51. for(var j = 0; j < repeat; j++){
  52. cur.repeat = 1;
  53. this._defsResolved.push(cur);
  54. }
  55. }else{
  56. this._defsResolved.push(cur);
  57. }
  58. }, this);
  59. var last = defs[defs.length - 1];
  60. if(doneFunction){
  61. this._defsResolved.push({ func: doneFunction });
  62. }
  63. // stop the sequence, this actually just sets this._running to false
  64. this._defsResolved.push({ func: [this.stop, this] });
  65. this._curId = 0;
  66. this._go();
  67. },
  68. _go: function(){
  69. // summary: Execute one task of this._defsResolved.
  70. // if _running was set to false stop the sequence, this is the
  71. // case when i.e. stop() was called.
  72. if(!this._running){
  73. return;
  74. }
  75. var cur = this._defsResolved[this._curId];
  76. this._curId += 1;
  77. // create the function to call, the func property might be an array, which means
  78. // [function, context, parameter1, parameter2, ...]
  79. function resolveAndCallFunc(func) {
  80. var ret = null;
  81. if(dojo.isArray(func)){
  82. // Two elements might only be given when the function+context
  83. // is given, this is nice for using this, ie: [this.func, this]
  84. if(func.length>2){
  85. ret = func[0].apply(func[1], func.slice(2));
  86. }else{
  87. ret = func[0].apply(func[1]);
  88. }
  89. }else{
  90. ret = func();
  91. }
  92. return ret;
  93. }
  94. if(this._curId >= this._defsResolved.length){
  95. resolveAndCallFunc(cur.func); // call the last function, since it is the doneFunction we dont need to handle pause stuff
  96. // don't go on and call this._go() again, we are done
  97. return;
  98. }
  99. if(cur.pauseAfter){
  100. if(resolveAndCallFunc(cur.func) !== false){
  101. setTimeout(dojo.hitch(this, "_go"), cur.pauseAfter);
  102. }else{
  103. this._goOnPause = cur.pauseAfter;
  104. }
  105. }else if(cur.pauseBefore){
  106. var x = dojo.hitch(this,function(){
  107. if(resolveAndCallFunc(cur.func) !== false){
  108. this._go()
  109. }
  110. });
  111. setTimeout(x, cur.pauseBefore);
  112. }else{
  113. if(resolveAndCallFunc(cur.func) !== false){
  114. this._go();
  115. }
  116. }
  117. },
  118. goOn: function(){
  119. // summary: This method just provides a hook from the outside, so that
  120. // an interrupted sequence can be continued.
  121. if(this._goOnPause){
  122. setTimeout(dojo.hitch(this, "_go"), this._goOnPause);
  123. this._goOnPause = 0; // reset it, so if the next one doesnt set it we dont use the old pause
  124. }else{ this._go(); }
  125. },
  126. stop: function(){
  127. // summary: Stop the currently running sequence.
  128. //
  129. // description:
  130. // This can only interrupt the sequence not the last function that
  131. // had been started. If the last function was i.e. a slideshow
  132. // that is handled inside a function that you have given as
  133. // one sequence item it cant be stopped, since it is not controlled
  134. // by this object here. In this case it would be smarter to
  135. // run the slideshow using a sequence object so you can also stop
  136. // it using this method.
  137. this._running = false;
  138. }
  139. });
  140. return dojox.timing.Sequence;
  141. });