onTouchStart.js 4.2 KB

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