Sync.ts 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. import { ALL_ATTRIBUTES, ARIA_ORIENTATION, ROLE } from '../../constants/attributes';
  2. import { TTB } from '../../constants/directions';
  3. import { EVENT_CLICK, EVENT_MOVE, EVENT_NAVIGATION_MOUNTED, EVENT_SLIDE_KEYDOWN } from '../../constants/events';
  4. import { LOOP } from '../../constants/types';
  5. import { EventInterface } from '../../constructors';
  6. import { Splide } from '../../core/Splide/Splide';
  7. import { BaseComponent, Components, Options } from '../../types';
  8. import { empty, includes, prevent, removeAttribute, setAttribute } from '../../utils';
  9. import { SlideComponent } from '../Slides/Slide';
  10. /**
  11. * The interface for the Sync component.
  12. *
  13. * @since 3.0.0
  14. */
  15. export interface SyncComponent extends BaseComponent {
  16. }
  17. /**
  18. * The keys for triggering the navigation slide.
  19. *
  20. * @since 3.0.0
  21. */
  22. const TRIGGER_KEYS = [ ' ', 'Enter', 'Spacebar' ];
  23. /**
  24. * The component for syncing multiple sliders.
  25. *
  26. * @since 3.0.0
  27. *
  28. * @param Splide - A Splide instance.
  29. * @param Components - A collection of components.
  30. * @param options - Options.
  31. *
  32. * @return A Sync component object.
  33. */
  34. export function Sync( Splide: Splide, Components: Components, options: Options ): SyncComponent {
  35. const { splides } = Splide;
  36. const { list } = Components.Elements;
  37. /**
  38. * Called when the component is mounted.
  39. */
  40. function mount(): void {
  41. if ( options.isNavigation ) {
  42. navigate();
  43. } else {
  44. sync();
  45. }
  46. }
  47. /**
  48. * Destroys the component.
  49. */
  50. function destroy(): void {
  51. removeAttribute( list, ALL_ATTRIBUTES )
  52. }
  53. /**
  54. * Syncs the current index among all slides.
  55. * The `processed` array prevents recursive call of handlers.
  56. */
  57. function sync(): void {
  58. const processed: Splide[] = [];
  59. splides.concat( Splide ).forEach( ( splide, index, instances ) => {
  60. EventInterface( splide ).on( EVENT_MOVE, ( index, prev, dest ) => {
  61. instances.forEach( instance => {
  62. if ( instance !== splide && ! includes( processed, splide ) ) {
  63. processed.push( instance );
  64. instance.go( instance.is( LOOP ) ? dest : index );
  65. }
  66. } );
  67. empty( processed );
  68. } );
  69. } );
  70. }
  71. /**
  72. * Makes slides clickable and moves the slider to the index of clicked slide.
  73. * Note that the direction of `menu` is implicitly `vertical` as default.
  74. */
  75. function navigate(): void {
  76. const { on, emit } = EventInterface( Splide );
  77. on( EVENT_CLICK, onClick );
  78. on( EVENT_SLIDE_KEYDOWN, onKeydown );
  79. emit( EVENT_NAVIGATION_MOUNTED, Splide.splides );
  80. setAttribute( list, ROLE, 'menu' );
  81. setAttribute( list, ARIA_ORIENTATION, options.direction !== TTB ? 'horizontal' : null );
  82. }
  83. /**
  84. * Called when the navigation slide is clicked.
  85. *
  86. * @param Slide - A clicked Slide component.
  87. */
  88. function onClick( Slide: SlideComponent ): void {
  89. Splide.go( Slide.index );
  90. }
  91. /**
  92. * Called when any key is pressed on the navigation slide.
  93. *
  94. * @param Slide - A Slide component.
  95. * @param e - A KeyboardEvent object.
  96. */
  97. function onKeydown( Slide: SlideComponent, e: KeyboardEvent ): void {
  98. if ( includes( TRIGGER_KEYS, e.key ) ) {
  99. onClick( Slide );
  100. prevent( e );
  101. }
  102. }
  103. return {
  104. mount,
  105. destroy,
  106. };
  107. }