onTouchStart.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import { getWindow, getDocument } from 'ssr-window';
  2. import $ from '../../shared/dom.js';
  3. import { now } from '../../shared/utils.js'; // Modified from https://stackoverflow.com/questions/54520554/custom-element-getrootnode-closest-function-crossing-multiple-parent-shadowd
  4. function closestElement(selector, base = this) {
  5. function __closestFrom(el) {
  6. if (!el || el === getDocument() || el === getWindow()) return null;
  7. if (el.assignedSlot) el = el.assignedSlot;
  8. const found = el.closest(selector);
  9. return found || __closestFrom(el.getRootNode().host);
  10. }
  11. return __closestFrom(base);
  12. }
  13. export default function onTouchStart(event) {
  14. const swiper = this;
  15. const document = getDocument();
  16. const window = getWindow();
  17. const data = swiper.touchEventsData;
  18. const {
  19. params,
  20. touches,
  21. enabled
  22. } = swiper;
  23. if (!enabled) return;
  24. if (swiper.animating && params.preventInteractionOnTransition) {
  25. return;
  26. }
  27. if (!swiper.animating && params.cssMode && params.loop) {
  28. swiper.loopFix();
  29. }
  30. let e = event;
  31. if (e.originalEvent) e = e.originalEvent;
  32. let $targetEl = $(e.target);
  33. if (params.touchEventsTarget === 'wrapper') {
  34. if (!$targetEl.closest(swiper.wrapperEl).length) return;
  35. }
  36. data.isTouchEvent = e.type === 'touchstart';
  37. if (!data.isTouchEvent && 'which' in e && e.which === 3) return;
  38. if (!data.isTouchEvent && 'button' in e && e.button > 0) return;
  39. if (data.isTouched && data.isMoved) return; // change target el for shadow root component
  40. const swipingClassHasValue = !!params.noSwipingClass && params.noSwipingClass !== '';
  41. if (swipingClassHasValue && e.target && e.target.shadowRoot && event.path && event.path[0]) {
  42. $targetEl = $(event.path[0]);
  43. }
  44. const noSwipingSelector = params.noSwipingSelector ? params.noSwipingSelector : `.${params.noSwipingClass}`;
  45. const isTargetShadow = !!(e.target && e.target.shadowRoot); // use closestElement for shadow root element to get the actual closest for nested shadow root element
  46. if (params.noSwiping && (isTargetShadow ? closestElement(noSwipingSelector, e.target) : $targetEl.closest(noSwipingSelector)[0])) {
  47. swiper.allowClick = true;
  48. return;
  49. }
  50. if (params.swipeHandler) {
  51. if (!$targetEl.closest(params.swipeHandler)[0]) return;
  52. }
  53. touches.currentX = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;
  54. touches.currentY = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
  55. const startX = touches.currentX;
  56. const startY = touches.currentY; // Do NOT start if iOS edge swipe is detected. Otherwise iOS app cannot swipe-to-go-back anymore
  57. const edgeSwipeDetection = params.edgeSwipeDetection || params.iOSEdgeSwipeDetection;
  58. const edgeSwipeThreshold = params.edgeSwipeThreshold || params.iOSEdgeSwipeThreshold;
  59. if (edgeSwipeDetection && (startX <= edgeSwipeThreshold || startX >= window.innerWidth - edgeSwipeThreshold)) {
  60. if (edgeSwipeDetection === 'prevent') {
  61. event.preventDefault();
  62. } else {
  63. return;
  64. }
  65. }
  66. Object.assign(data, {
  67. isTouched: true,
  68. isMoved: false,
  69. allowTouchCallbacks: true,
  70. isScrolling: undefined,
  71. startMoving: undefined
  72. });
  73. touches.startX = startX;
  74. touches.startY = startY;
  75. data.touchStartTime = now();
  76. swiper.allowClick = true;
  77. swiper.updateSize();
  78. swiper.swipeDirection = undefined;
  79. if (params.threshold > 0) data.allowThresholdMove = false;
  80. if (e.type !== 'touchstart') {
  81. let preventDefault = true;
  82. if ($targetEl.is(data.focusableElements)) preventDefault = false;
  83. if (document.activeElement && $(document.activeElement).is(data.focusableElements) && document.activeElement !== $targetEl[0]) {
  84. document.activeElement.blur();
  85. }
  86. const shouldPreventDefault = preventDefault && swiper.allowTouchMove && params.touchStartPreventDefault;
  87. if ((params.touchStartForcePreventDefault || shouldPreventDefault) && !$targetEl[0].isContentEditable) {
  88. e.preventDefault();
  89. }
  90. }
  91. swiper.emit('touchStart', e);
  92. }