history.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. import { getWindow } from 'ssr-window';
  2. export default function History({
  3. swiper,
  4. extendParams,
  5. on
  6. }) {
  7. extendParams({
  8. history: {
  9. enabled: false,
  10. root: '',
  11. replaceState: false,
  12. key: 'slides',
  13. keepQuery: false
  14. }
  15. });
  16. let initialized = false;
  17. let paths = {};
  18. const slugify = text => {
  19. return text.toString().replace(/\s+/g, '-').replace(/[^\w-]+/g, '').replace(/--+/g, '-').replace(/^-+/, '').replace(/-+$/, '');
  20. };
  21. const getPathValues = urlOverride => {
  22. const window = getWindow();
  23. let location;
  24. if (urlOverride) {
  25. location = new URL(urlOverride);
  26. } else {
  27. location = window.location;
  28. }
  29. const pathArray = location.pathname.slice(1).split('/').filter(part => part !== '');
  30. const total = pathArray.length;
  31. const key = pathArray[total - 2];
  32. const value = pathArray[total - 1];
  33. return {
  34. key,
  35. value
  36. };
  37. };
  38. const setHistory = (key, index) => {
  39. const window = getWindow();
  40. if (!initialized || !swiper.params.history.enabled) return;
  41. let location;
  42. if (swiper.params.url) {
  43. location = new URL(swiper.params.url);
  44. } else {
  45. location = window.location;
  46. }
  47. const slide = swiper.slides[index];
  48. let value = slugify(slide.getAttribute('data-history'));
  49. if (swiper.params.history.root.length > 0) {
  50. let root = swiper.params.history.root;
  51. if (root[root.length - 1] === '/') root = root.slice(0, root.length - 1);
  52. value = `${root}/${key ? `${key}/` : ''}${value}`;
  53. } else if (!location.pathname.includes(key)) {
  54. value = `${key ? `${key}/` : ''}${value}`;
  55. }
  56. if (swiper.params.history.keepQuery) {
  57. value += location.search;
  58. }
  59. const currentState = window.history.state;
  60. if (currentState && currentState.value === value) {
  61. return;
  62. }
  63. if (swiper.params.history.replaceState) {
  64. window.history.replaceState({
  65. value
  66. }, null, value);
  67. } else {
  68. window.history.pushState({
  69. value
  70. }, null, value);
  71. }
  72. };
  73. const scrollToSlide = (speed, value, runCallbacks) => {
  74. if (value) {
  75. for (let i = 0, length = swiper.slides.length; i < length; i += 1) {
  76. const slide = swiper.slides[i];
  77. const slideHistory = slugify(slide.getAttribute('data-history'));
  78. if (slideHistory === value) {
  79. const index = swiper.getSlideIndex(slide);
  80. swiper.slideTo(index, speed, runCallbacks);
  81. }
  82. }
  83. } else {
  84. swiper.slideTo(0, speed, runCallbacks);
  85. }
  86. };
  87. const setHistoryPopState = () => {
  88. paths = getPathValues(swiper.params.url);
  89. scrollToSlide(swiper.params.speed, paths.value, false);
  90. };
  91. const init = () => {
  92. const window = getWindow();
  93. if (!swiper.params.history) return;
  94. if (!window.history || !window.history.pushState) {
  95. swiper.params.history.enabled = false;
  96. swiper.params.hashNavigation.enabled = true;
  97. return;
  98. }
  99. initialized = true;
  100. paths = getPathValues(swiper.params.url);
  101. if (!paths.key && !paths.value) {
  102. if (!swiper.params.history.replaceState) {
  103. window.addEventListener('popstate', setHistoryPopState);
  104. }
  105. return;
  106. }
  107. scrollToSlide(0, paths.value, swiper.params.runCallbacksOnInit);
  108. if (!swiper.params.history.replaceState) {
  109. window.addEventListener('popstate', setHistoryPopState);
  110. }
  111. };
  112. const destroy = () => {
  113. const window = getWindow();
  114. if (!swiper.params.history.replaceState) {
  115. window.removeEventListener('popstate', setHistoryPopState);
  116. }
  117. };
  118. on('init', () => {
  119. if (swiper.params.history.enabled) {
  120. init();
  121. }
  122. });
  123. on('destroy', () => {
  124. if (swiper.params.history.enabled) {
  125. destroy();
  126. }
  127. });
  128. on('transitionEnd _freeModeNoMomentumRelease', () => {
  129. if (initialized) {
  130. setHistory(swiper.params.history.key, swiper.activeIndex);
  131. }
  132. });
  133. on('slideChange', () => {
  134. if (initialized && swiper.params.cssMode) {
  135. setHistory(swiper.params.history.key, swiper.activeIndex);
  136. }
  137. });
  138. }