hash-navigation.js 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import { getWindow, getDocument } from 'ssr-window';
  2. import { elementChildren } from '../../shared/utils.js';
  3. export default function HashNavigation({
  4. swiper,
  5. extendParams,
  6. emit,
  7. on
  8. }) {
  9. let initialized = false;
  10. const document = getDocument();
  11. const window = getWindow();
  12. extendParams({
  13. hashNavigation: {
  14. enabled: false,
  15. replaceState: false,
  16. watchState: false,
  17. getSlideIndex(_s, hash) {
  18. if (swiper.virtual && swiper.params.virtual.enabled) {
  19. const slideWithHash = swiper.slides.filter(slideEl => slideEl.getAttribute('data-hash') === hash)[0];
  20. if (!slideWithHash) return 0;
  21. const index = parseInt(slideWithHash.getAttribute('data-swiper-slide-index'), 10);
  22. return index;
  23. }
  24. return swiper.getSlideIndex(elementChildren(swiper.slidesEl, `.${swiper.params.slideClass}[data-hash="${hash}"], swiper-slide[data-hash="${hash}"]`)[0]);
  25. }
  26. }
  27. });
  28. const onHashChange = () => {
  29. emit('hashChange');
  30. const newHash = document.location.hash.replace('#', '');
  31. const activeSlideEl = swiper.virtual && swiper.params.virtual.enabled ? swiper.slidesEl.querySelector(`[data-swiper-slide-index="${swiper.activeIndex}"]`) : swiper.slides[swiper.activeIndex];
  32. const activeSlideHash = activeSlideEl ? activeSlideEl.getAttribute('data-hash') : '';
  33. if (newHash !== activeSlideHash) {
  34. const newIndex = swiper.params.hashNavigation.getSlideIndex(swiper, newHash);
  35. if (typeof newIndex === 'undefined' || Number.isNaN(newIndex)) return;
  36. swiper.slideTo(newIndex);
  37. }
  38. };
  39. const setHash = () => {
  40. if (!initialized || !swiper.params.hashNavigation.enabled) return;
  41. const activeSlideEl = swiper.virtual && swiper.params.virtual.enabled ? swiper.slidesEl.querySelector(`[data-swiper-slide-index="${swiper.activeIndex}"]`) : swiper.slides[swiper.activeIndex];
  42. const activeSlideHash = activeSlideEl ? activeSlideEl.getAttribute('data-hash') || activeSlideEl.getAttribute('data-history') : '';
  43. if (swiper.params.hashNavigation.replaceState && window.history && window.history.replaceState) {
  44. window.history.replaceState(null, null, `#${activeSlideHash}` || '');
  45. emit('hashSet');
  46. } else {
  47. document.location.hash = activeSlideHash || '';
  48. emit('hashSet');
  49. }
  50. };
  51. const init = () => {
  52. if (!swiper.params.hashNavigation.enabled || swiper.params.history && swiper.params.history.enabled) return;
  53. initialized = true;
  54. const hash = document.location.hash.replace('#', '');
  55. if (hash) {
  56. const speed = 0;
  57. const index = swiper.params.hashNavigation.getSlideIndex(swiper, hash);
  58. swiper.slideTo(index || 0, speed, swiper.params.runCallbacksOnInit, true);
  59. }
  60. if (swiper.params.hashNavigation.watchState) {
  61. window.addEventListener('hashchange', onHashChange);
  62. }
  63. };
  64. const destroy = () => {
  65. if (swiper.params.hashNavigation.watchState) {
  66. window.removeEventListener('hashchange', onHashChange);
  67. }
  68. };
  69. on('init', () => {
  70. if (swiper.params.hashNavigation.enabled) {
  71. init();
  72. }
  73. });
  74. on('destroy', () => {
  75. if (swiper.params.hashNavigation.enabled) {
  76. destroy();
  77. }
  78. });
  79. on('transitionEnd _freeModeNoMomentumRelease', () => {
  80. if (initialized) {
  81. setHash();
  82. }
  83. });
  84. on('slideChange', () => {
  85. if (initialized && swiper.params.cssMode) {
  86. setHash();
  87. }
  88. });
  89. }