AutoRotator.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /*
  2. Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
  3. Available via Academic Free License >= 2.1 OR the modified BSD license.
  4. see: http://dojotoolkit.org/license for details
  5. */
  6. if(!dojo._hasResource["dojox.widget.AutoRotator"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dojox.widget.AutoRotator"] = true;
  8. dojo.provide("dojox.widget.AutoRotator");
  9. dojo.require("dojox.widget.Rotator");
  10. (function(d){
  11. d.declare("dojox.widget.AutoRotator", dojox.widget.Rotator, {
  12. // summary:
  13. // A rotator that automatically transitions between child nodes.
  14. //
  15. // description:
  16. // Adds automatic rotating to the dojox.widget.Rotator. The
  17. // AutoRotator has parameters that control how user input can
  18. // affect the rotator including a suspend when hovering over the
  19. // rotator and pausing when the user manually advances to another
  20. // pane.
  21. //
  22. // example:
  23. // | <div dojoType="dojox.widget.AutoRotator" duration="3000">
  24. // | <div>
  25. // | Pane 1!
  26. // | </div>
  27. // | <div duration="5000">
  28. // | Pane 2 with an overrided duration!
  29. // | </div>
  30. // | </div>
  31. // suspendOnHover: boolean
  32. // Pause the rotator when the mouse hovers over it.
  33. suspendOnHover: false,
  34. // duration: int
  35. // The time in milliseconds before transitioning to the next pane. The
  36. // default value is 4000 (4 seconds).
  37. duration: 4000,
  38. // autoStart: boolean
  39. // Starts the timer to transition children upon creation.
  40. autoStart: true,
  41. // pauseOnManualChange: boolean
  42. // Pause the rotator when the pane is changed or a controller's next or
  43. // previous buttons are clicked.
  44. pauseOnManualChange: false,
  45. // cycles: int
  46. // Number of cycles before pausing.
  47. cycles: -1,
  48. // random: boolean
  49. // Determines if the panes should cycle randomly.
  50. random: false,
  51. // reverse: boolean
  52. // Causes the rotator to rotate in reverse order.
  53. reverse: false,
  54. constructor: function(){
  55. // summary:
  56. // Initializes the timer and connect to the rotator.
  57. var _t = this;
  58. // validate the cycles counter
  59. if(_t.cycles-0 == _t.cycles && _t.cycles > 0){
  60. // we need to add 1 because we decrement cycles before the animation starts
  61. _t.cycles++;
  62. }else{
  63. _t.cycles = _t.cycles ? -1 : 0;
  64. }
  65. // wire up the mouse hover events
  66. _t._connects = [
  67. d.connect(_t._domNode, "onmouseover", function(){
  68. // temporarily suspend the cycling, but don't officially pause
  69. // it and don't allow suspending if we're transitioning
  70. if(_t.suspendOnHover && !_t.anim && !_t.wfe){
  71. var t = _t._endTime,
  72. n = _t._now();
  73. _t._suspended = true;
  74. _t._resetTimer();
  75. _t._resumeDuration = t > n ? t - n : 0.01;
  76. }
  77. }),
  78. d.connect(_t._domNode, "onmouseout", function(){
  79. // if we were playing, resume playback unless were in the
  80. // middle of a transition
  81. if(_t.suspendOnHover && !_t.anim){
  82. _t._suspended = false;
  83. if(_t.playing && !_t.wfe){
  84. _t.play(true);
  85. }
  86. }
  87. })
  88. ];
  89. // everything is ready, so start
  90. if(_t.autoStart && _t.panes.length > 1){
  91. // start playing
  92. _t.play();
  93. }else{
  94. // since we're not playing, lets pause
  95. _t.pause();
  96. }
  97. },
  98. destroy: function(){
  99. // summary:
  100. // Disconnect the AutoRotator's events.
  101. d.forEach(this._connects, d.disconnect);
  102. this.inherited(arguments);
  103. },
  104. play: function(/*boolean?*/skipCycleDecrement, /*boolean?*/skipDuration){
  105. // summary:
  106. // Sets the state to "playing" and schedules the next cycle to run.
  107. this.playing = true;
  108. this._resetTimer();
  109. // don't decrement the count if we're resuming play
  110. if(skipCycleDecrement !== true && this.cycles > 0){
  111. this.cycles--;
  112. }
  113. if(this.cycles == 0){
  114. // we have reached the number of cycles, so pause
  115. this.pause();
  116. }else if(!this._suspended){
  117. this.onUpdate("play");
  118. // if we haven't been suspended, then grab the duration for this pane and
  119. // schedule a cycle to be run
  120. if(skipDuration){
  121. this._cycle();
  122. }else{
  123. var r = (this._resumeDuration || 0)-0,
  124. u = (r > 0 ? r : (this.panes[this.idx].duration || this.duration))-0;
  125. // call _cycle() after a duration and pass in false so it isn't manual
  126. this._resumeDuration = 0;
  127. this._endTime = this._now() + u;
  128. this._timer = setTimeout(d.hitch(this, "_cycle", false), u);
  129. }
  130. }
  131. },
  132. pause: function(){
  133. // summary:
  134. // Sets the state to "not playing" and clears the cycle timer.
  135. this.playing = this._suspended = false;
  136. this.cycles = -1;
  137. this._resetTimer();
  138. // notify the controllers we're paused
  139. this.onUpdate("pause");
  140. },
  141. _now: function(){
  142. // summary:
  143. // Helper function to return the current system time in milliseconds.
  144. return (new Date()).getTime(); /*int*/
  145. },
  146. _resetTimer: function(){
  147. // summary:
  148. // Resets the timer used to schedule the next transition.
  149. clearTimeout(this._timer);
  150. },
  151. _cycle: function(/*boolean|int?*/manual){
  152. // summary:
  153. // Cycles the rotator to the next/previous pane.
  154. var _t = this,
  155. i = _t.idx,
  156. j;
  157. if(_t.random){
  158. // make sure we don't randomly pick the pane we're already on
  159. do{
  160. j = Math.floor(Math.random() * _t.panes.length + 1);
  161. }while(j == i);
  162. }else{
  163. j = i + (_t.reverse ? -1 : 1)
  164. }
  165. // rotate!
  166. var def = _t.go(j);
  167. if(def){
  168. def.addCallback(function(/*boolean?*/skipDuration){
  169. _t.onUpdate("cycle");
  170. if(_t.playing){
  171. _t.play(false, skipDuration);
  172. }
  173. });
  174. }
  175. },
  176. onManualChange: function(/*string*/action){
  177. // summary:
  178. // Override the Rotator's onManualChange so we can pause.
  179. this.cycles = -1;
  180. // obviously we don't want to pause if play was just clicked
  181. if(action != "play"){
  182. this._resetTimer();
  183. if(this.pauseOnManualChange){
  184. this.pause();
  185. }
  186. }
  187. if(this.playing){
  188. this.play();
  189. }
  190. }
  191. });
  192. })(dojo);
  193. }