history.js 3.8 KB

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