UNPKG

17 kBJavaScriptView Raw
1"use strict";
2
3exports.__esModule = true;
4exports.default = void 0;
5
6var _ssrWindow = require("ssr-window");
7
8var _dom = _interopRequireDefault(require("../../utils/dom"));
9
10var _utils = require("../../utils/utils");
11
12function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
14function isEventSupported() {
15 var document = (0, _ssrWindow.getDocument)();
16 var eventName = 'onwheel';
17 var isSupported = (eventName in document);
18
19 if (!isSupported) {
20 var element = document.createElement('div');
21 element.setAttribute(eventName, 'return;');
22 isSupported = typeof element[eventName] === 'function';
23 }
24
25 if (!isSupported && document.implementation && document.implementation.hasFeature && // always returns true in newer browsers as per the standard.
26 // @see http://dom.spec.whatwg.org/#dom-domimplementation-hasfeature
27 document.implementation.hasFeature('', '') !== true) {
28 // This is the only way to test support for the `wheel` event in IE9+.
29 isSupported = document.implementation.hasFeature('Events.wheel', '3.0');
30 }
31
32 return isSupported;
33}
34
35var Mousewheel = {
36 lastScrollTime: (0, _utils.now)(),
37 lastEventBeforeSnap: undefined,
38 recentWheelEvents: [],
39 event: function event() {
40 var window = (0, _ssrWindow.getWindow)();
41 if (window.navigator.userAgent.indexOf('firefox') > -1) return 'DOMMouseScroll';
42 return isEventSupported() ? 'wheel' : 'mousewheel';
43 },
44 normalize: function normalize(e) {
45 // Reasonable defaults
46 var PIXEL_STEP = 10;
47 var LINE_HEIGHT = 40;
48 var PAGE_HEIGHT = 800;
49 var sX = 0;
50 var sY = 0; // spinX, spinY
51
52 var pX = 0;
53 var pY = 0; // pixelX, pixelY
54 // Legacy
55
56 if ('detail' in e) {
57 sY = e.detail;
58 }
59
60 if ('wheelDelta' in e) {
61 sY = -e.wheelDelta / 120;
62 }
63
64 if ('wheelDeltaY' in e) {
65 sY = -e.wheelDeltaY / 120;
66 }
67
68 if ('wheelDeltaX' in e) {
69 sX = -e.wheelDeltaX / 120;
70 } // side scrolling on FF with DOMMouseScroll
71
72
73 if ('axis' in e && e.axis === e.HORIZONTAL_AXIS) {
74 sX = sY;
75 sY = 0;
76 }
77
78 pX = sX * PIXEL_STEP;
79 pY = sY * PIXEL_STEP;
80
81 if ('deltaY' in e) {
82 pY = e.deltaY;
83 }
84
85 if ('deltaX' in e) {
86 pX = e.deltaX;
87 }
88
89 if (e.shiftKey && !pX) {
90 // if user scrolls with shift he wants horizontal scroll
91 pX = pY;
92 pY = 0;
93 }
94
95 if ((pX || pY) && e.deltaMode) {
96 if (e.deltaMode === 1) {
97 // delta in LINE units
98 pX *= LINE_HEIGHT;
99 pY *= LINE_HEIGHT;
100 } else {
101 // delta in PAGE units
102 pX *= PAGE_HEIGHT;
103 pY *= PAGE_HEIGHT;
104 }
105 } // Fall-back if spin cannot be determined
106
107
108 if (pX && !sX) {
109 sX = pX < 1 ? -1 : 1;
110 }
111
112 if (pY && !sY) {
113 sY = pY < 1 ? -1 : 1;
114 }
115
116 return {
117 spinX: sX,
118 spinY: sY,
119 pixelX: pX,
120 pixelY: pY
121 };
122 },
123 handleMouseEnter: function handleMouseEnter() {
124 var swiper = this;
125 swiper.mouseEntered = true;
126 },
127 handleMouseLeave: function handleMouseLeave() {
128 var swiper = this;
129 swiper.mouseEntered = false;
130 },
131 handle: function handle(event) {
132 var e = event;
133 var disableParentSwiper = true;
134 var swiper = this;
135 var params = swiper.params.mousewheel;
136
137 if (swiper.params.cssMode) {
138 e.preventDefault();
139 }
140
141 var target = swiper.$el;
142
143 if (swiper.params.mousewheel.eventsTarget !== 'container') {
144 target = (0, _dom.default)(swiper.params.mousewheel.eventsTarget);
145 }
146
147 if (!swiper.mouseEntered && !target[0].contains(e.target) && !params.releaseOnEdges) return true;
148 if (e.originalEvent) e = e.originalEvent; // jquery fix
149
150 var delta = 0;
151 var rtlFactor = swiper.rtlTranslate ? -1 : 1;
152 var data = Mousewheel.normalize(e);
153
154 if (params.forceToAxis) {
155 if (swiper.isHorizontal()) {
156 if (Math.abs(data.pixelX) > Math.abs(data.pixelY)) delta = -data.pixelX * rtlFactor;else return true;
157 } else if (Math.abs(data.pixelY) > Math.abs(data.pixelX)) delta = -data.pixelY;else return true;
158 } else {
159 delta = Math.abs(data.pixelX) > Math.abs(data.pixelY) ? -data.pixelX * rtlFactor : -data.pixelY;
160 }
161
162 if (delta === 0) return true;
163 if (params.invert) delta = -delta; // Get the scroll positions
164
165 var positions = swiper.getTranslate() + delta * params.sensitivity;
166 if (positions >= swiper.minTranslate()) positions = swiper.minTranslate();
167 if (positions <= swiper.maxTranslate()) positions = swiper.maxTranslate(); // When loop is true:
168 // the disableParentSwiper will be true.
169 // When loop is false:
170 // if the scroll positions is not on edge,
171 // then the disableParentSwiper will be true.
172 // if the scroll on edge positions,
173 // then the disableParentSwiper will be false.
174
175 disableParentSwiper = swiper.params.loop ? true : !(positions === swiper.minTranslate() || positions === swiper.maxTranslate());
176 if (disableParentSwiper && swiper.params.nested) e.stopPropagation();
177
178 if (!swiper.params.freeMode) {
179 // Register the new event in a variable which stores the relevant data
180 var newEvent = {
181 time: (0, _utils.now)(),
182 delta: Math.abs(delta),
183 direction: Math.sign(delta),
184 raw: event
185 }; // Keep the most recent events
186
187 var recentWheelEvents = swiper.mousewheel.recentWheelEvents;
188
189 if (recentWheelEvents.length >= 2) {
190 recentWheelEvents.shift(); // only store the last N events
191 }
192
193 var prevEvent = recentWheelEvents.length ? recentWheelEvents[recentWheelEvents.length - 1] : undefined;
194 recentWheelEvents.push(newEvent); // If there is at least one previous recorded event:
195 // If direction has changed or
196 // if the scroll is quicker than the previous one:
197 // Animate the slider.
198 // Else (this is the first time the wheel is moved):
199 // Animate the slider.
200
201 if (prevEvent) {
202 if (newEvent.direction !== prevEvent.direction || newEvent.delta > prevEvent.delta || newEvent.time > prevEvent.time + 150) {
203 swiper.mousewheel.animateSlider(newEvent);
204 }
205 } else {
206 swiper.mousewheel.animateSlider(newEvent);
207 } // If it's time to release the scroll:
208 // Return now so you don't hit the preventDefault.
209
210
211 if (swiper.mousewheel.releaseScroll(newEvent)) {
212 return true;
213 }
214 } else {
215 // Freemode or scrollContainer:
216 // If we recently snapped after a momentum scroll, then ignore wheel events
217 // to give time for the deceleration to finish. Stop ignoring after 500 msecs
218 // or if it's a new scroll (larger delta or inverse sign as last event before
219 // an end-of-momentum snap).
220 var _newEvent = {
221 time: (0, _utils.now)(),
222 delta: Math.abs(delta),
223 direction: Math.sign(delta)
224 };
225 var lastEventBeforeSnap = swiper.mousewheel.lastEventBeforeSnap;
226 var ignoreWheelEvents = lastEventBeforeSnap && _newEvent.time < lastEventBeforeSnap.time + 500 && _newEvent.delta <= lastEventBeforeSnap.delta && _newEvent.direction === lastEventBeforeSnap.direction;
227
228 if (!ignoreWheelEvents) {
229 swiper.mousewheel.lastEventBeforeSnap = undefined;
230
231 if (swiper.params.loop) {
232 swiper.loopFix();
233 }
234
235 var position = swiper.getTranslate() + delta * params.sensitivity;
236 var wasBeginning = swiper.isBeginning;
237 var wasEnd = swiper.isEnd;
238 if (position >= swiper.minTranslate()) position = swiper.minTranslate();
239 if (position <= swiper.maxTranslate()) position = swiper.maxTranslate();
240 swiper.setTransition(0);
241 swiper.setTranslate(position);
242 swiper.updateProgress();
243 swiper.updateActiveIndex();
244 swiper.updateSlidesClasses();
245
246 if (!wasBeginning && swiper.isBeginning || !wasEnd && swiper.isEnd) {
247 swiper.updateSlidesClasses();
248 }
249
250 if (swiper.params.freeModeSticky) {
251 // When wheel scrolling starts with sticky (aka snap) enabled, then detect
252 // the end of a momentum scroll by storing recent (N=15?) wheel events.
253 // 1. do all N events have decreasing or same (absolute value) delta?
254 // 2. did all N events arrive in the last M (M=500?) msecs?
255 // 3. does the earliest event have an (absolute value) delta that's
256 // at least P (P=1?) larger than the most recent event's delta?
257 // 4. does the latest event have a delta that's smaller than Q (Q=6?) pixels?
258 // If 1-4 are "yes" then we're near the end of a momentum scroll deceleration.
259 // Snap immediately and ignore remaining wheel events in this scroll.
260 // See comment above for "remaining wheel events in this scroll" determination.
261 // If 1-4 aren't satisfied, then wait to snap until 500ms after the last event.
262 clearTimeout(swiper.mousewheel.timeout);
263 swiper.mousewheel.timeout = undefined;
264 var _recentWheelEvents = swiper.mousewheel.recentWheelEvents;
265
266 if (_recentWheelEvents.length >= 15) {
267 _recentWheelEvents.shift(); // only store the last N events
268
269 }
270
271 var _prevEvent = _recentWheelEvents.length ? _recentWheelEvents[_recentWheelEvents.length - 1] : undefined;
272
273 var firstEvent = _recentWheelEvents[0];
274
275 _recentWheelEvents.push(_newEvent);
276
277 if (_prevEvent && (_newEvent.delta > _prevEvent.delta || _newEvent.direction !== _prevEvent.direction)) {
278 // Increasing or reverse-sign delta means the user started scrolling again. Clear the wheel event log.
279 _recentWheelEvents.splice(0);
280 } else if (_recentWheelEvents.length >= 15 && _newEvent.time - firstEvent.time < 500 && firstEvent.delta - _newEvent.delta >= 1 && _newEvent.delta <= 6) {
281 // We're at the end of the deceleration of a momentum scroll, so there's no need
282 // to wait for more events. Snap ASAP on the next tick.
283 // Also, because there's some remaining momentum we'll bias the snap in the
284 // direction of the ongoing scroll because it's better UX for the scroll to snap
285 // in the same direction as the scroll instead of reversing to snap. Therefore,
286 // if it's already scrolled more than 20% in the current direction, keep going.
287 var snapToThreshold = delta > 0 ? 0.8 : 0.2;
288 swiper.mousewheel.lastEventBeforeSnap = _newEvent;
289
290 _recentWheelEvents.splice(0);
291
292 swiper.mousewheel.timeout = (0, _utils.nextTick)(function () {
293 swiper.slideToClosest(swiper.params.speed, true, undefined, snapToThreshold);
294 }, 0); // no delay; move on next tick
295 }
296
297 if (!swiper.mousewheel.timeout) {
298 // if we get here, then we haven't detected the end of a momentum scroll, so
299 // we'll consider a scroll "complete" when there haven't been any wheel events
300 // for 500ms.
301 swiper.mousewheel.timeout = (0, _utils.nextTick)(function () {
302 var snapToThreshold = 0.5;
303 swiper.mousewheel.lastEventBeforeSnap = _newEvent;
304
305 _recentWheelEvents.splice(0);
306
307 swiper.slideToClosest(swiper.params.speed, true, undefined, snapToThreshold);
308 }, 500);
309 }
310 } // Emit event
311
312
313 if (!ignoreWheelEvents) swiper.emit('scroll', e); // Stop autoplay
314
315 if (swiper.params.autoplay && swiper.params.autoplayDisableOnInteraction) swiper.autoplay.stop(); // Return page scroll on edge positions
316
317 if (position === swiper.minTranslate() || position === swiper.maxTranslate()) return true;
318 }
319 }
320
321 if (e.preventDefault) e.preventDefault();else e.returnValue = false;
322 return false;
323 },
324 animateSlider: function animateSlider(newEvent) {
325 var swiper = this;
326 var window = (0, _ssrWindow.getWindow)();
327
328 if (this.params.mousewheel.thresholdDelta && newEvent.delta < this.params.mousewheel.thresholdDelta) {
329 // Prevent if delta of wheel scroll delta is below configured threshold
330 return false;
331 }
332
333 if (this.params.mousewheel.thresholdTime && (0, _utils.now)() - swiper.mousewheel.lastScrollTime < this.params.mousewheel.thresholdTime) {
334 // Prevent if time between scrolls is below configured threshold
335 return false;
336 } // If the movement is NOT big enough and
337 // if the last time the user scrolled was too close to the current one (avoid continuously triggering the slider):
338 // Don't go any further (avoid insignificant scroll movement).
339
340
341 if (newEvent.delta >= 6 && (0, _utils.now)() - swiper.mousewheel.lastScrollTime < 60) {
342 // Return false as a default
343 return true;
344 } // If user is scrolling towards the end:
345 // If the slider hasn't hit the latest slide or
346 // if the slider is a loop and
347 // if the slider isn't moving right now:
348 // Go to next slide and
349 // emit a scroll event.
350 // Else (the user is scrolling towards the beginning) and
351 // if the slider hasn't hit the first slide or
352 // if the slider is a loop and
353 // if the slider isn't moving right now:
354 // Go to prev slide and
355 // emit a scroll event.
356
357
358 if (newEvent.direction < 0) {
359 if ((!swiper.isEnd || swiper.params.loop) && !swiper.animating) {
360 swiper.slideNext();
361 swiper.emit('scroll', newEvent.raw);
362 }
363 } else if ((!swiper.isBeginning || swiper.params.loop) && !swiper.animating) {
364 swiper.slidePrev();
365 swiper.emit('scroll', newEvent.raw);
366 } // If you got here is because an animation has been triggered so store the current time
367
368
369 swiper.mousewheel.lastScrollTime = new window.Date().getTime(); // Return false as a default
370
371 return false;
372 },
373 releaseScroll: function releaseScroll(newEvent) {
374 var swiper = this;
375 var params = swiper.params.mousewheel;
376
377 if (newEvent.direction < 0) {
378 if (swiper.isEnd && !swiper.params.loop && params.releaseOnEdges) {
379 // Return true to animate scroll on edges
380 return true;
381 }
382 } else if (swiper.isBeginning && !swiper.params.loop && params.releaseOnEdges) {
383 // Return true to animate scroll on edges
384 return true;
385 }
386
387 return false;
388 },
389 enable: function enable() {
390 var swiper = this;
391 var event = Mousewheel.event();
392
393 if (swiper.params.cssMode) {
394 swiper.wrapperEl.removeEventListener(event, swiper.mousewheel.handle);
395 return true;
396 }
397
398 if (!event) return false;
399 if (swiper.mousewheel.enabled) return false;
400 var target = swiper.$el;
401
402 if (swiper.params.mousewheel.eventsTarget !== 'container') {
403 target = (0, _dom.default)(swiper.params.mousewheel.eventsTarget);
404 }
405
406 target.on('mouseenter', swiper.mousewheel.handleMouseEnter);
407 target.on('mouseleave', swiper.mousewheel.handleMouseLeave);
408 target.on(event, swiper.mousewheel.handle);
409 swiper.mousewheel.enabled = true;
410 return true;
411 },
412 disable: function disable() {
413 var swiper = this;
414 var event = Mousewheel.event();
415
416 if (swiper.params.cssMode) {
417 swiper.wrapperEl.addEventListener(event, swiper.mousewheel.handle);
418 return true;
419 }
420
421 if (!event) return false;
422 if (!swiper.mousewheel.enabled) return false;
423 var target = swiper.$el;
424
425 if (swiper.params.mousewheel.eventsTarget !== 'container') {
426 target = (0, _dom.default)(swiper.params.mousewheel.eventsTarget);
427 }
428
429 target.off(event, swiper.mousewheel.handle);
430 swiper.mousewheel.enabled = false;
431 return true;
432 }
433};
434var _default = {
435 name: 'mousewheel',
436 params: {
437 mousewheel: {
438 enabled: false,
439 releaseOnEdges: false,
440 invert: false,
441 forceToAxis: false,
442 sensitivity: 1,
443 eventsTarget: 'container',
444 thresholdDelta: null,
445 thresholdTime: null
446 }
447 },
448 create: function create() {
449 var swiper = this;
450 (0, _utils.bindModuleMethods)(swiper, {
451 mousewheel: {
452 enabled: false,
453 lastScrollTime: (0, _utils.now)(),
454 lastEventBeforeSnap: undefined,
455 recentWheelEvents: [],
456 enable: Mousewheel.enable,
457 disable: Mousewheel.disable,
458 handle: Mousewheel.handle,
459 handleMouseEnter: Mousewheel.handleMouseEnter,
460 handleMouseLeave: Mousewheel.handleMouseLeave,
461 animateSlider: Mousewheel.animateSlider,
462 releaseScroll: Mousewheel.releaseScroll
463 }
464 });
465 },
466 on: {
467 init: function init(swiper) {
468 if (!swiper.params.mousewheel.enabled && swiper.params.cssMode) {
469 swiper.mousewheel.disable();
470 }
471
472 if (swiper.params.mousewheel.enabled) swiper.mousewheel.enable();
473 },
474 destroy: function destroy(swiper) {
475 if (swiper.params.cssMode) {
476 swiper.mousewheel.enable();
477 }
478
479 if (swiper.mousewheel.enabled) swiper.mousewheel.disable();
480 }
481 }
482};
483exports.default = _default;
\No newline at end of file