Sync.ts 3.4 KB

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