index.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /**
  2. * The component for playing slides automatically.
  3. *
  4. * @author Naotoshi Fujita
  5. * @copyright Naotoshi Fujita. All rights reserved.
  6. */
  7. import { applyStyle, subscribe } from '../../utils/dom';
  8. import { createInterval } from '../../utils/time';
  9. /**
  10. * Set of pause flags.
  11. */
  12. const PAUSE_FLAGS = {
  13. HOVER : 1,
  14. FOCUS : 2,
  15. MANUAL: 3,
  16. };
  17. /**
  18. * The component for playing slides automatically.
  19. *
  20. * @param {Splide} Splide - A Splide instance.
  21. * @param {Object} Components - An object containing components.
  22. * @param {string} name - A component name as a lowercase string.
  23. *
  24. * @return {Object} - The component object.
  25. */
  26. export default ( Splide, Components, name ) => {
  27. /**
  28. * Store pause flags.
  29. *
  30. * @type {Array}
  31. */
  32. let flags = [];
  33. /**
  34. * Store an interval object.
  35. *
  36. * @type {Object};
  37. */
  38. let interval;
  39. /**
  40. * Autoplay component object.
  41. *
  42. * @type {Object}
  43. */
  44. const Autoplay = {
  45. /**
  46. * Required only when the autoplay option is true.
  47. *
  48. * @type {boolean}
  49. */
  50. required: Splide.options.autoplay,
  51. /**
  52. * Called when the component is mounted.
  53. * Note that autoplay starts only if there are slides over perView number.
  54. */
  55. mount() {
  56. const options = Splide.options;
  57. const { slides, bar } = Components.Elements;
  58. if ( slides.length > options.perView ) {
  59. interval = createInterval( () => { Splide.go( '>' ) }, options.interval, rate => {
  60. Splide.emit( `${ name }:playing`, rate );
  61. bar && applyStyle( bar, { width: `${ rate * 100 }%` } );
  62. } );
  63. bind();
  64. this.play();
  65. }
  66. },
  67. /**
  68. * Start autoplay.
  69. *
  70. * @param {number} flag - A pause flag to be removed.
  71. */
  72. play( flag = 0 ) {
  73. flags = flags.filter( f => f !== flag );
  74. if ( ! flags.length ) {
  75. Splide.emit( `${ name }:play` );
  76. interval.play();
  77. }
  78. },
  79. /**
  80. * Pause autoplay.
  81. * Note that Array.includes is not supported by IE.
  82. *
  83. * @param {number} flag - A pause flag to be added.
  84. */
  85. pause( flag = 0 ) {
  86. interval.pause();
  87. if ( flags.indexOf( flag ) === -1 ) {
  88. flags.push( flag );
  89. }
  90. if ( flags.length === 1 ) {
  91. Splide.emit( `${ name }:pause` );
  92. }
  93. },
  94. };
  95. /**
  96. * Listen some events.
  97. */
  98. function bind() {
  99. const options = Splide.options;
  100. const Elements = Components.Elements;
  101. const sub = Splide.sub;
  102. const elms = [ Splide.root, sub ? sub.root : null ];
  103. if ( options.pauseOnHover ) {
  104. switchOn( elms, 'mouseleave', PAUSE_FLAGS.HOVER, true );
  105. switchOn( elms, 'mouseenter', PAUSE_FLAGS.HOVER, false );
  106. }
  107. if ( options.pauseOnFocus ) {
  108. switchOn( elms, 'focusout', PAUSE_FLAGS.FOCUS, true );
  109. switchOn( elms, 'focusin', PAUSE_FLAGS.FOCUS, false );
  110. }
  111. subscribe( Elements.play, 'click', () => {
  112. // Need to be removed a focus flag at first.
  113. Autoplay.play( PAUSE_FLAGS.FOCUS );
  114. Autoplay.play( PAUSE_FLAGS.MANUAL );
  115. } );
  116. switchOn( [ Elements.pause ], 'click', PAUSE_FLAGS.MANUAL, false );
  117. // Rewind the timer when others move the slide.
  118. Splide.on( 'move', () => { Autoplay.play() } );
  119. }
  120. /**
  121. * Play or pause on the given event.
  122. *
  123. * @param {Element[]} elms - Elements.
  124. * @param {string} event - An event name or names.
  125. * @param {number} flag - A pause flag defined on the top.
  126. * @param {boolean} play - Determine whether to play or pause.
  127. */
  128. function switchOn( elms, event, flag, play ) {
  129. for ( let i in elms ) {
  130. subscribe( elms[ i ], event, () => { Autoplay[ play ? 'play' : 'pause' ]( flag ) } );
  131. }
  132. }
  133. return Autoplay;
  134. }