Skip to content

Commit 710f742

Browse files
committed
fix: #25
1 parent 7f049c7 commit 710f742

File tree

5 files changed

+130
-7
lines changed

5 files changed

+130
-7
lines changed

dist/VueFinalModal.esm.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/VueFinalModal.esm.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/VueFinalModal.umd.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/VueFinalModal.umd.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/utils/bodyScrollLock.js

Lines changed: 126 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,59 @@
1-
// stolen from body-scroll-lock and removed ios part
1+
// stolen from body-scroll-lock
2+
3+
// Older browsers don't support event options, feature detect it.
4+
let hasPassiveEvents = false
5+
if (typeof window !== 'undefined') {
6+
const passiveTestOptions = {
7+
get passive() {
8+
hasPassiveEvents = true
9+
return undefined
10+
}
11+
}
12+
window.addEventListener('testPassive', null, passiveTestOptions)
13+
window.removeEventListener('testPassive', null, passiveTestOptions)
14+
}
15+
16+
const isIosDevice =
17+
typeof window !== 'undefined' &&
18+
window.navigator &&
19+
window.navigator.platform &&
20+
(/iP(ad|hone|od)/.test(window.navigator.platform) ||
21+
(window.navigator.platform === 'MacIntel' && window.navigator.maxTouchPoints > 1))
222

323
let locks = []
24+
let documentListenerAdded = false
25+
let initialClientY = -1
426
let previousBodyOverflowSetting
527
let previousBodyPaddingRight
628

29+
// returns true if `el` should be allowed to receive touchmove events.
30+
const allowTouchMove = el =>
31+
locks.some(lock => {
32+
if (lock.options.allowTouchMove && lock.options.allowTouchMove(el)) {
33+
return true
34+
}
35+
36+
return false
37+
})
38+
39+
const preventDefault = rawEvent => {
40+
const e = rawEvent || window.event
41+
42+
// For the case whereby consumers adds a touchmove event listener to document.
43+
// Recall that we do document.addEventListener('touchmove', preventDefault, { passive: false })
44+
// in disableBodyScroll - so if we provide this opportunity to allowTouchMove, then
45+
// the touchmove event on document will break.
46+
if (allowTouchMove(e.target)) {
47+
return true
48+
}
49+
// Do not prevent if the event has more than one touch (usually meaning this is a multi touch gesture like pinch to zoom).
50+
if (e.touches.length > 1) return true
51+
52+
if (e.preventDefault) e.preventDefault()
53+
54+
return false
55+
}
56+
757
const setOverflowHidden = options => {
858
// If previousBodyPaddingRight is already set, don't set it again.
959
if (previousBodyPaddingRight === undefined) {
@@ -40,6 +90,30 @@ const restoreOverflowSetting = () => {
4090
previousBodyOverflowSetting = undefined
4191
}
4292
}
93+
// https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#Problems_and_solutions
94+
const isTargetElementTotallyScrolled = targetElement =>
95+
targetElement ? targetElement.scrollHeight - targetElement.scrollTop <= targetElement.clientHeight : false
96+
97+
const handleScroll = (event, targetElement) => {
98+
const clientY = event.targetTouches[0].clientY - initialClientY
99+
100+
if (allowTouchMove(event.target)) {
101+
return false
102+
}
103+
104+
if (targetElement && targetElement.scrollTop === 0 && clientY > 0) {
105+
// element is at the top of its scroll.
106+
return preventDefault(event)
107+
}
108+
109+
if (isTargetElementTotallyScrolled(targetElement) && clientY < 0) {
110+
// element is at the bottom of its scroll.
111+
return preventDefault(event)
112+
}
113+
114+
event.stopPropagation()
115+
return true
116+
}
43117

44118
export const disableBodyScroll = (targetElement, options) => {
45119
// targetElement must be provided
@@ -63,7 +137,48 @@ export const disableBodyScroll = (targetElement, options) => {
63137

64138
locks = [...locks, lock]
65139

66-
setOverflowHidden(options)
140+
if (isIosDevice) {
141+
targetElement.ontouchstart = event => {
142+
if (event.targetTouches.length === 1) {
143+
// detect single touch.
144+
initialClientY = event.targetTouches[0].clientY
145+
}
146+
}
147+
targetElement.ontouchmove = event => {
148+
if (event.targetTouches.length === 1) {
149+
// detect single touch.
150+
handleScroll(event, targetElement)
151+
}
152+
}
153+
154+
if (!documentListenerAdded) {
155+
document.addEventListener('touchmove', preventDefault, hasPassiveEvents ? { passive: false } : undefined)
156+
documentListenerAdded = true
157+
}
158+
} else {
159+
setOverflowHidden(options)
160+
}
161+
}
162+
163+
export const clearAllBodyScrollLocks = () => {
164+
if (isIosDevice) {
165+
// Clear all locks ontouchstart/ontouchmove handlers, and the references.
166+
locks.forEach(lock => {
167+
lock.targetElement.ontouchstart = null
168+
lock.targetElement.ontouchmove = null
169+
})
170+
171+
if (documentListenerAdded) {
172+
document.removeEventListener('touchmove', preventDefault, hasPassiveEvents ? { passive: false } : undefined)
173+
documentListenerAdded = false
174+
}
175+
// Reset initial clientY.
176+
initialClientY = -1
177+
} else {
178+
restoreOverflowSetting()
179+
}
180+
181+
locks = []
67182
}
68183

69184
export const enableBodyScroll = targetElement => {
@@ -77,7 +192,15 @@ export const enableBodyScroll = targetElement => {
77192

78193
locks = locks.filter(lock => lock.targetElement !== targetElement)
79194

80-
if (!locks.length) {
195+
if (isIosDevice) {
196+
targetElement.ontouchstart = null
197+
targetElement.ontouchmove = null
198+
199+
if (documentListenerAdded && locks.length === 0) {
200+
document.removeEventListener('touchmove', preventDefault, hasPassiveEvents ? { passive: false } : undefined)
201+
documentListenerAdded = false
202+
}
203+
} else if (!locks.length) {
81204
restoreOverflowSetting()
82205
}
83206
}

0 commit comments

Comments
 (0)