navigation.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. import createElementIfNotDefined from '../../shared/create-element-if-not-defined.js';
  2. export default function Navigation({
  3. swiper,
  4. extendParams,
  5. on,
  6. emit
  7. }) {
  8. extendParams({
  9. navigation: {
  10. nextEl: null,
  11. prevEl: null,
  12. hideOnClick: false,
  13. disabledClass: 'swiper-button-disabled',
  14. hiddenClass: 'swiper-button-hidden',
  15. lockClass: 'swiper-button-lock',
  16. navigationDisabledClass: 'swiper-navigation-disabled'
  17. }
  18. });
  19. swiper.navigation = {
  20. nextEl: null,
  21. prevEl: null
  22. };
  23. const makeElementsArray = el => {
  24. if (!Array.isArray(el)) el = [el].filter(e => !!e);
  25. return el;
  26. };
  27. function getEl(el) {
  28. let res;
  29. if (el && typeof el === 'string' && swiper.isElement) {
  30. res = swiper.el.shadowRoot.querySelector(el);
  31. if (res) return res;
  32. }
  33. if (el) {
  34. if (typeof el === 'string') res = [...document.querySelectorAll(el)];
  35. if (swiper.params.uniqueNavElements && typeof el === 'string' && res.length > 1 && swiper.el.querySelectorAll(el).length === 1) {
  36. res = swiper.el.querySelector(el);
  37. }
  38. }
  39. if (el && !res) return el;
  40. // if (Array.isArray(res) && res.length === 1) res = res[0];
  41. return res;
  42. }
  43. function toggleEl(el, disabled) {
  44. const params = swiper.params.navigation;
  45. el = makeElementsArray(el);
  46. el.forEach(subEl => {
  47. if (subEl) {
  48. subEl.classList[disabled ? 'add' : 'remove'](...params.disabledClass.split(' '));
  49. if (subEl.tagName === 'BUTTON') subEl.disabled = disabled;
  50. if (swiper.params.watchOverflow && swiper.enabled) {
  51. subEl.classList[swiper.isLocked ? 'add' : 'remove'](params.lockClass);
  52. }
  53. }
  54. });
  55. }
  56. function update() {
  57. // Update Navigation Buttons
  58. const {
  59. nextEl,
  60. prevEl
  61. } = swiper.navigation;
  62. if (swiper.params.loop) {
  63. toggleEl(prevEl, false);
  64. toggleEl(nextEl, false);
  65. return;
  66. }
  67. toggleEl(prevEl, swiper.isBeginning && !swiper.params.rewind);
  68. toggleEl(nextEl, swiper.isEnd && !swiper.params.rewind);
  69. }
  70. function onPrevClick(e) {
  71. e.preventDefault();
  72. if (swiper.isBeginning && !swiper.params.loop && !swiper.params.rewind) return;
  73. swiper.slidePrev();
  74. emit('navigationPrev');
  75. }
  76. function onNextClick(e) {
  77. e.preventDefault();
  78. if (swiper.isEnd && !swiper.params.loop && !swiper.params.rewind) return;
  79. swiper.slideNext();
  80. emit('navigationNext');
  81. }
  82. function init() {
  83. const params = swiper.params.navigation;
  84. swiper.params.navigation = createElementIfNotDefined(swiper, swiper.originalParams.navigation, swiper.params.navigation, {
  85. nextEl: 'swiper-button-next',
  86. prevEl: 'swiper-button-prev'
  87. });
  88. if (!(params.nextEl || params.prevEl)) return;
  89. let nextEl = getEl(params.nextEl);
  90. let prevEl = getEl(params.prevEl);
  91. Object.assign(swiper.navigation, {
  92. nextEl,
  93. prevEl
  94. });
  95. nextEl = makeElementsArray(nextEl);
  96. prevEl = makeElementsArray(prevEl);
  97. const initButton = (el, dir) => {
  98. if (el) {
  99. el.addEventListener('click', dir === 'next' ? onNextClick : onPrevClick);
  100. }
  101. if (!swiper.enabled && el) {
  102. el.classList.add(...params.lockClass.split(' '));
  103. }
  104. };
  105. nextEl.forEach(el => initButton(el, 'next'));
  106. prevEl.forEach(el => initButton(el, 'prev'));
  107. }
  108. function destroy() {
  109. let {
  110. nextEl,
  111. prevEl
  112. } = swiper.navigation;
  113. nextEl = makeElementsArray(nextEl);
  114. prevEl = makeElementsArray(prevEl);
  115. const destroyButton = (el, dir) => {
  116. el.removeEventListener('click', dir === 'next' ? onNextClick : onPrevClick);
  117. el.classList.remove(...swiper.params.navigation.disabledClass.split(' '));
  118. };
  119. nextEl.forEach(el => destroyButton(el, 'next'));
  120. prevEl.forEach(el => destroyButton(el, 'prev'));
  121. }
  122. on('init', () => {
  123. if (swiper.params.navigation.enabled === false) {
  124. // eslint-disable-next-line
  125. disable();
  126. } else {
  127. init();
  128. update();
  129. }
  130. });
  131. on('toEdge fromEdge lock unlock', () => {
  132. update();
  133. });
  134. on('destroy', () => {
  135. destroy();
  136. });
  137. on('enable disable', () => {
  138. let {
  139. nextEl,
  140. prevEl
  141. } = swiper.navigation;
  142. nextEl = makeElementsArray(nextEl);
  143. prevEl = makeElementsArray(prevEl);
  144. [...nextEl, ...prevEl].filter(el => !!el).forEach(el => el.classList[swiper.enabled ? 'remove' : 'add'](swiper.params.navigation.lockClass));
  145. });
  146. on('click', (_s, e) => {
  147. let {
  148. nextEl,
  149. prevEl
  150. } = swiper.navigation;
  151. nextEl = makeElementsArray(nextEl);
  152. prevEl = makeElementsArray(prevEl);
  153. const targetEl = e.target;
  154. if (swiper.params.navigation.hideOnClick && !prevEl.includes(targetEl) && !nextEl.includes(targetEl)) {
  155. if (swiper.pagination && swiper.params.pagination && swiper.params.pagination.clickable && (swiper.pagination.el === targetEl || swiper.pagination.el.contains(targetEl))) return;
  156. let isHidden;
  157. if (nextEl.length) {
  158. isHidden = nextEl[0].classList.contains(swiper.params.navigation.hiddenClass);
  159. } else if (prevEl.length) {
  160. isHidden = prevEl[0].classList.contains(swiper.params.navigation.hiddenClass);
  161. }
  162. if (isHidden === true) {
  163. emit('navigationShow');
  164. } else {
  165. emit('navigationHide');
  166. }
  167. [...nextEl, ...prevEl].filter(el => !!el).forEach(el => el.classList.toggle(swiper.params.navigation.hiddenClass));
  168. }
  169. });
  170. const enable = () => {
  171. swiper.el.classList.remove(...swiper.params.navigation.navigationDisabledClass.split(' '));
  172. init();
  173. update();
  174. };
  175. const disable = () => {
  176. swiper.el.classList.add(...swiper.params.navigation.navigationDisabledClass.split(' '));
  177. destroy();
  178. };
  179. Object.assign(swiper.navigation, {
  180. enable,
  181. disable,
  182. update,
  183. init,
  184. destroy
  185. });
  186. }