Skip to content

Commit 95cdfc2

Browse files
committed
v0.10.6
1 parent 707d7b3 commit 95cdfc2

File tree

6 files changed

+1521
-26
lines changed

6 files changed

+1521
-26
lines changed

lib/VueFinalModal.esm.js

Lines changed: 107 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,96 +3,143 @@ function _toConsumableArray(arr) {
33
for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) {
44
arr2[i] = arr[i];
55
}
6+
67
return arr2;
78
} else {
89
return Array.from(arr);
910
}
10-
}
11+
} // Older browsers don't support event options, feature detect it.
12+
// Adopted and modified solution from Bohdan Didukh (2017)
13+
// https://stackoverflow.com/questions/41594997/ios-10-safari-prevent-scrolling-behind-a-fixed-overlay-and-maintain-scroll-posi
14+
15+
1116
var hasPassiveEvents = false;
17+
1218
if (typeof window !== 'undefined') {
1319
var passiveTestOptions = {
1420
get passive() {
1521
hasPassiveEvents = true;
1622
return undefined;
1723
}
24+
1825
};
1926
window.addEventListener('testPassive', null, passiveTestOptions);
2027
window.removeEventListener('testPassive', null, passiveTestOptions);
2128
}
29+
2230
var isIosDevice = typeof window !== 'undefined' && window.navigator && window.navigator.platform && (/iP(ad|hone|od)/.test(window.navigator.platform) || window.navigator.platform === 'MacIntel' && window.navigator.maxTouchPoints > 1);
2331
var locks = [];
2432
var documentListenerAdded = false;
2533
var initialClientY = -1;
2634
var previousBodyOverflowSetting = void 0;
27-
var previousBodyPaddingRight = void 0;
35+
var previousBodyPaddingRight = void 0; // returns true if `el` should be allowed to receive touchmove events.
36+
2837
var allowTouchMove = function allowTouchMove(el) {
2938
return locks.some(function (lock) {
3039
if (lock.options.allowTouchMove && lock.options.allowTouchMove(el)) {
3140
return true;
3241
}
42+
3343
return false;
3444
});
3545
};
46+
3647
var preventDefault = function preventDefault(rawEvent) {
37-
var e = rawEvent || window.event;
48+
var e = rawEvent || window.event; // For the case whereby consumers adds a touchmove event listener to document.
49+
// Recall that we do document.addEventListener('touchmove', preventDefault, { passive: false })
50+
// in disableBodyScroll - so if we provide this opportunity to allowTouchMove, then
51+
// the touchmove event on document will break.
52+
3853
if (allowTouchMove(e.target)) {
3954
return true;
40-
}
55+
} // Do not prevent if the event has more than one touch (usually meaning this is a multi touch gesture like pinch to zoom).
56+
57+
4158
if (e.touches.length > 1) return true;
4259
if (e.preventDefault) e.preventDefault();
4360
return false;
4461
};
62+
4563
var setOverflowHidden = function setOverflowHidden(options) {
64+
// Setting overflow on body/documentElement synchronously in Desktop Safari slows down
65+
// the responsiveness for some reason. Setting within a setTimeout fixes this.
4666
setTimeout(function () {
67+
// If previousBodyPaddingRight is already set, don't set it again.
4768
if (previousBodyPaddingRight === undefined) {
4869
var _reserveScrollBarGap = !!options && options.reserveScrollBarGap === true;
70+
4971
var scrollBarGap = window.innerWidth - document.documentElement.clientWidth;
72+
5073
if (_reserveScrollBarGap && scrollBarGap > 0) {
5174
previousBodyPaddingRight = document.body.style.paddingRight;
5275
document.body.style.paddingRight = scrollBarGap + 'px';
5376
}
54-
}
77+
} // If previousBodyOverflowSetting is already set, don't set it again.
78+
79+
5580
if (previousBodyOverflowSetting === undefined) {
5681
previousBodyOverflowSetting = document.body.style.overflow;
5782
document.body.style.overflow = 'hidden';
5883
}
5984
});
6085
};
86+
6187
var restoreOverflowSetting = function restoreOverflowSetting() {
88+
// Setting overflow on body/documentElement synchronously in Desktop Safari slows down
89+
// the responsiveness for some reason. Setting within a setTimeout fixes this.
6290
setTimeout(function () {
6391
if (previousBodyPaddingRight !== undefined) {
64-
document.body.style.paddingRight = previousBodyPaddingRight;
92+
document.body.style.paddingRight = previousBodyPaddingRight; // Restore previousBodyPaddingRight to undefined so setOverflowHidden knows it
93+
// can be set again.
94+
6595
previousBodyPaddingRight = undefined;
6696
}
97+
6798
if (previousBodyOverflowSetting !== undefined) {
68-
document.body.style.overflow = previousBodyOverflowSetting;
99+
document.body.style.overflow = previousBodyOverflowSetting; // Restore previousBodyOverflowSetting to undefined
100+
// so setOverflowHidden knows it can be set again.
101+
69102
previousBodyOverflowSetting = undefined;
70103
}
71104
});
72-
};
105+
}; // https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#Problems_and_solutions
106+
107+
73108
var isTargetElementTotallyScrolled = function isTargetElementTotallyScrolled(targetElement) {
74109
return targetElement ? targetElement.scrollHeight - targetElement.scrollTop <= targetElement.clientHeight : false;
75110
};
111+
76112
var handleScroll = function handleScroll(event, targetElement) {
77113
var clientY = event.targetTouches[0].clientY - initialClientY;
114+
78115
if (allowTouchMove(event.target)) {
79116
return false;
80117
}
118+
81119
if (targetElement && targetElement.scrollTop === 0 && clientY > 0) {
120+
// element is at the top of its scroll.
82121
return preventDefault(event);
83122
}
123+
84124
if (isTargetElementTotallyScrolled(targetElement) && clientY < 0) {
125+
// element is at the bottom of its scroll.
85126
return preventDefault(event);
86127
}
128+
87129
event.stopPropagation();
88130
return true;
89131
};
132+
90133
var disableBodyScroll = function disableBodyScroll(targetElement, options) {
91134
if (isIosDevice) {
135+
// targetElement must be provided, and disableBodyScroll must not have been
136+
// called on this targetElement before.
92137
if (!targetElement) {
138+
// eslint-disable-next-line no-console
93139
console.error('disableBodyScroll unsuccessful - targetElement must be provided when calling disableBodyScroll on IOS devices.');
94140
return;
95141
}
142+
96143
if (targetElement && !locks.some(function (lock) {
97144
return lock.targetElement === targetElement;
98145
})) {
@@ -101,16 +148,21 @@ var disableBodyScroll = function disableBodyScroll(targetElement, options) {
101148
options: options || {}
102149
};
103150
locks = [].concat(_toConsumableArray(locks), [lock]);
151+
104152
targetElement.ontouchstart = function (event) {
105153
if (event.targetTouches.length === 1) {
154+
// detect single touch.
106155
initialClientY = event.targetTouches[0].clientY;
107156
}
108157
};
158+
109159
targetElement.ontouchmove = function (event) {
110160
if (event.targetTouches.length === 1) {
161+
// detect single touch.
111162
handleScroll(event, targetElement);
112163
}
113164
};
165+
114166
if (!documentListenerAdded) {
115167
document.addEventListener('touchmove', preventDefault, hasPassiveEvents ? {
116168
passive: false
@@ -129,24 +181,29 @@ var disableBodyScroll = function disableBodyScroll(targetElement, options) {
129181
};
130182
var clearAllBodyScrollLocks = function clearAllBodyScrollLocks() {
131183
if (isIosDevice) {
184+
// Clear all locks ontouchstart/ontouchmove handlers, and the references.
132185
locks.forEach(function (lock) {
133186
lock.targetElement.ontouchstart = null;
134187
lock.targetElement.ontouchmove = null;
135188
});
189+
136190
if (documentListenerAdded) {
137191
document.removeEventListener('touchmove', preventDefault, hasPassiveEvents ? {
138192
passive: false
139193
} : undefined);
140194
documentListenerAdded = false;
141195
}
142-
locks = [];
196+
197+
locks = []; // Reset initial clientY.
198+
143199
initialClientY = -1;
144200
} else {
145201
restoreOverflowSetting();
146202
locks = [];
147203
}
148204
};
149205

206+
//
150207
let modalStack = [];
151208
const TransitionState = {
152209
Enter: 'enter',
@@ -223,56 +280,72 @@ var script = {
223280
isComponentReadyToBeDestroyed() {
224281
return this.overlayTransitionState === TransitionState.Leave && this.modalTransitionState === TransitionState.Leave;
225282
}
283+
226284
},
227285
watch: {
228286
value(value) {
229287
this.mounted(value);
288+
230289
if (value === false) {
231290
this.close();
232291
}
233292
},
293+
234294
lockScroll: 'handleLockScroll',
295+
235296
hideOverlay(value) {
236297
if (this.value) {
237298
!value && this.appendOverlay();
238299
}
239300
},
301+
240302
attach() {
241303
this.mounted(this.value);
242304
},
305+
243306
isComponentReadyToBeDestroyed(isReady) {
244307
if (isReady) {
245308
this.visible = false;
246309
}
247310
}
311+
248312
},
313+
249314
mounted() {
250315
this.mounted(this.value);
251316
},
317+
252318
beforeDestroy() {
253319
this.close();
254320
},
321+
255322
methods: {
256323
mounted(value) {
257324
if (value) {
258325
let target = this.getAttachElement();
326+
259327
if (target) {
260328
target.appendChild(this.$el);
261329
let index = modalStack.findIndex(vm => vm === this);
330+
262331
if (index !== -1) {
332+
// if this is already exist in modalStack, delete it
263333
modalStack.splice(index, 1);
264334
}
335+
265336
modalStack.push(this);
266337
this.handleLockScroll();
267338
modalStack.filter(vm => vm !== this).forEach(vm => {
268339
if (vm.getAttachElement() === target) {
340+
// if vm and this have the same attach element
269341
vm.visibility.overlay = false;
270342
}
271343
});
272344
} else if (target !== false) {
273345
console.warn('Unable to locate target '.concat(this.attach || 'body'));
274346
return;
275347
}
348+
276349
this.visible = true;
277350
this.$nextTick(() => {
278351
this.startTransitionEnter();
@@ -281,77 +354,102 @@ var script = {
281354
this.lockScroll && clearAllBodyScrollLocks();
282355
}
283356
},
357+
284358
close() {
285359
let index = modalStack.findIndex(vm => vm === this);
360+
286361
if (index !== -1) {
362+
// remove this in modalStack
287363
modalStack.splice(index, 1);
288364
}
365+
289366
if (modalStack.length > 0) {
367+
// If there are still nested modals opened
290368
const $_vm = modalStack[modalStack.length - 1];
291369
$_vm.handleLockScroll();
292370
!$_vm.hideOverlay && $_vm.appendOverlay();
293371
} else {
372+
// If the closed modal is the last one
294373
this.lockScroll && clearAllBodyScrollLocks();
295374
}
375+
296376
this.startTransitionLeave();
297377
},
378+
298379
startTransitionEnter() {
299380
this.visibility.overlay = true;
300381
this.visibility.modal = true;
301382
},
383+
302384
startTransitionLeave() {
303385
this.visibility.overlay = false;
304386
this.visibility.modal = false;
305387
},
388+
306389
appendOverlay() {
307390
this.visibility.overlay = true;
308391
},
392+
309393
handleLockScroll() {
310394
this.lockScroll ? disableBodyScroll(this.$refs.vfmContent) : clearAllBodyScrollLocks();
311395
},
396+
312397
getAttachElement() {
313398
let target;
399+
314400
if (this.attach === false) {
315401
target = false;
316402
} else if (typeof this.attach === 'string') {
403+
// CSS selector
317404
if (window) {
318405
target = window.document.querySelector(this.attach);
319406
} else {
320407
target = false;
321408
}
322409
} else {
410+
// DOM Element
323411
target = this.attach;
324412
}
413+
325414
return target;
326415
},
416+
327417
beforeOverlayEnter() {
328418
this.overlayTransitionState = TransitionState.Entering;
329419
},
420+
330421
afterOverlayEnter() {
331422
this.overlayTransitionState = TransitionState.Enter;
332423
},
424+
333425
beforeOverlayLeave() {
334426
this.overlayTransitionState = TransitionState.Leaving;
335427
},
428+
336429
afterOverlayLeave() {
337430
this.overlayTransitionState = TransitionState.Leave;
338431
},
432+
339433
beforeModalEnter() {
340434
this.$emit('before-open');
341435
this.modalTransitionState = TransitionState.Entering;
342436
},
437+
343438
afterModalEnter() {
344439
this.modalTransitionState = TransitionState.Enter;
345440
this.$emit('opened');
346441
},
442+
347443
beforeModalLeave() {
348444
this.$emit('before-close');
349445
this.modalTransitionState = TransitionState.Leaving;
350446
},
447+
351448
afterModalLeave() {
352449
this.modalTransitionState = TransitionState.Leave;
353450
this.$emit('closed');
354451
}
452+
355453
}
356454
};
357455

0 commit comments

Comments
 (0)