import { document } from 'ssr-window';
|
import $ from '../../utils/dom';
|
import Utils from '../../utils/utils';
|
import Support from '../../utils/support';
|
|
const Scrollbar = {
|
setTranslate() {
|
const swiper = this;
|
if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) return;
|
const { scrollbar, rtlTranslate: rtl, progress } = swiper;
|
const {
|
dragSize, trackSize, $dragEl, $el,
|
} = scrollbar;
|
const params = swiper.params.scrollbar;
|
|
let newSize = dragSize;
|
let newPos = (trackSize - dragSize) * progress;
|
if (rtl) {
|
newPos = -newPos;
|
if (newPos > 0) {
|
newSize = dragSize - newPos;
|
newPos = 0;
|
} else if (-newPos + dragSize > trackSize) {
|
newSize = trackSize + newPos;
|
}
|
} else if (newPos < 0) {
|
newSize = dragSize + newPos;
|
newPos = 0;
|
} else if (newPos + dragSize > trackSize) {
|
newSize = trackSize - newPos;
|
}
|
if (swiper.isHorizontal()) {
|
$dragEl.transform(`translate3d(${newPos}px, 0, 0)`);
|
$dragEl[0].style.width = `${newSize}px`;
|
} else {
|
$dragEl.transform(`translate3d(0px, ${newPos}px, 0)`);
|
$dragEl[0].style.height = `${newSize}px`;
|
}
|
if (params.hide) {
|
clearTimeout(swiper.scrollbar.timeout);
|
$el[0].style.opacity = 1;
|
swiper.scrollbar.timeout = setTimeout(() => {
|
$el[0].style.opacity = 0;
|
$el.transition(400);
|
}, 1000);
|
}
|
},
|
setTransition(duration) {
|
const swiper = this;
|
if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) return;
|
swiper.scrollbar.$dragEl.transition(duration);
|
},
|
updateSize() {
|
const swiper = this;
|
if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) return;
|
|
const { scrollbar } = swiper;
|
const { $dragEl, $el } = scrollbar;
|
|
$dragEl[0].style.width = '';
|
$dragEl[0].style.height = '';
|
const trackSize = swiper.isHorizontal() ? $el[0].offsetWidth : $el[0].offsetHeight;
|
|
const divider = swiper.size / swiper.virtualSize;
|
const moveDivider = divider * (trackSize / swiper.size);
|
let dragSize;
|
if (swiper.params.scrollbar.dragSize === 'auto') {
|
dragSize = trackSize * divider;
|
} else {
|
dragSize = parseInt(swiper.params.scrollbar.dragSize, 10);
|
}
|
|
if (swiper.isHorizontal()) {
|
$dragEl[0].style.width = `${dragSize}px`;
|
} else {
|
$dragEl[0].style.height = `${dragSize}px`;
|
}
|
|
if (divider >= 1) {
|
$el[0].style.display = 'none';
|
} else {
|
$el[0].style.display = '';
|
}
|
if (swiper.params.scrollbar.hide) {
|
$el[0].style.opacity = 0;
|
}
|
Utils.extend(scrollbar, {
|
trackSize,
|
divider,
|
moveDivider,
|
dragSize,
|
});
|
scrollbar.$el[swiper.params.watchOverflow && swiper.isLocked ? 'addClass' : 'removeClass'](swiper.params.scrollbar.lockClass);
|
},
|
getPointerPosition(e) {
|
const swiper = this;
|
if (swiper.isHorizontal()) {
|
return ((e.type === 'touchstart' || e.type === 'touchmove') ? e.targetTouches[0].clientX : e.clientX);
|
}
|
return ((e.type === 'touchstart' || e.type === 'touchmove') ? e.targetTouches[0].clientY : e.clientY);
|
},
|
setDragPosition(e) {
|
const swiper = this;
|
const { scrollbar, rtlTranslate: rtl } = swiper;
|
const {
|
$el,
|
dragSize,
|
trackSize,
|
dragStartPos,
|
} = scrollbar;
|
|
let positionRatio;
|
positionRatio = ((scrollbar.getPointerPosition(e)) - $el.offset()[swiper.isHorizontal() ? 'left' : 'top']
|
- (dragStartPos !== null ? dragStartPos : dragSize / 2)) / (trackSize - dragSize);
|
positionRatio = Math.max(Math.min(positionRatio, 1), 0);
|
if (rtl) {
|
positionRatio = 1 - positionRatio;
|
}
|
|
const position = swiper.minTranslate() + ((swiper.maxTranslate() - swiper.minTranslate()) * positionRatio);
|
|
swiper.updateProgress(position);
|
swiper.setTranslate(position);
|
swiper.updateActiveIndex();
|
swiper.updateSlidesClasses();
|
},
|
onDragStart(e) {
|
const swiper = this;
|
const params = swiper.params.scrollbar;
|
const { scrollbar, $wrapperEl } = swiper;
|
const { $el, $dragEl } = scrollbar;
|
swiper.scrollbar.isTouched = true;
|
swiper.scrollbar.dragStartPos = (e.target === $dragEl[0] || e.target === $dragEl)
|
? scrollbar.getPointerPosition(e) - e.target.getBoundingClientRect()[swiper.isHorizontal() ? 'left' : 'top'] : null;
|
e.preventDefault();
|
e.stopPropagation();
|
|
$wrapperEl.transition(100);
|
$dragEl.transition(100);
|
scrollbar.setDragPosition(e);
|
|
clearTimeout(swiper.scrollbar.dragTimeout);
|
|
$el.transition(0);
|
if (params.hide) {
|
$el.css('opacity', 1);
|
}
|
if (swiper.params.cssMode) {
|
swiper.$wrapperEl.css('scroll-snap-type', 'none');
|
}
|
swiper.emit('scrollbarDragStart', e);
|
},
|
onDragMove(e) {
|
const swiper = this;
|
const { scrollbar, $wrapperEl } = swiper;
|
const { $el, $dragEl } = scrollbar;
|
|
if (!swiper.scrollbar.isTouched) return;
|
if (e.preventDefault) e.preventDefault();
|
else e.returnValue = false;
|
scrollbar.setDragPosition(e);
|
$wrapperEl.transition(0);
|
$el.transition(0);
|
$dragEl.transition(0);
|
swiper.emit('scrollbarDragMove', e);
|
},
|
onDragEnd(e) {
|
const swiper = this;
|
|
const params = swiper.params.scrollbar;
|
const { scrollbar, $wrapperEl } = swiper;
|
const { $el } = scrollbar;
|
|
if (!swiper.scrollbar.isTouched) return;
|
swiper.scrollbar.isTouched = false;
|
if (swiper.params.cssMode) {
|
swiper.$wrapperEl.css('scroll-snap-type', '');
|
$wrapperEl.transition('');
|
}
|
if (params.hide) {
|
clearTimeout(swiper.scrollbar.dragTimeout);
|
swiper.scrollbar.dragTimeout = Utils.nextTick(() => {
|
$el.css('opacity', 0);
|
$el.transition(400);
|
}, 1000);
|
}
|
swiper.emit('scrollbarDragEnd', e);
|
if (params.snapOnRelease) {
|
swiper.slideToClosest();
|
}
|
},
|
enableDraggable() {
|
const swiper = this;
|
if (!swiper.params.scrollbar.el) return;
|
const {
|
scrollbar, touchEventsTouch, touchEventsDesktop, params,
|
} = swiper;
|
const $el = scrollbar.$el;
|
const target = $el[0];
|
const activeListener = Support.passiveListener && params.passiveListeners ? { passive: false, capture: false } : false;
|
const passiveListener = Support.passiveListener && params.passiveListeners ? { passive: true, capture: false } : false;
|
if (!Support.touch) {
|
target.addEventListener(touchEventsDesktop.start, swiper.scrollbar.onDragStart, activeListener);
|
document.addEventListener(touchEventsDesktop.move, swiper.scrollbar.onDragMove, activeListener);
|
document.addEventListener(touchEventsDesktop.end, swiper.scrollbar.onDragEnd, passiveListener);
|
} else {
|
target.addEventListener(touchEventsTouch.start, swiper.scrollbar.onDragStart, activeListener);
|
target.addEventListener(touchEventsTouch.move, swiper.scrollbar.onDragMove, activeListener);
|
target.addEventListener(touchEventsTouch.end, swiper.scrollbar.onDragEnd, passiveListener);
|
}
|
},
|
disableDraggable() {
|
const swiper = this;
|
if (!swiper.params.scrollbar.el) return;
|
const {
|
scrollbar, touchEventsTouch, touchEventsDesktop, params,
|
} = swiper;
|
const $el = scrollbar.$el;
|
const target = $el[0];
|
const activeListener = Support.passiveListener && params.passiveListeners ? { passive: false, capture: false } : false;
|
const passiveListener = Support.passiveListener && params.passiveListeners ? { passive: true, capture: false } : false;
|
if (!Support.touch) {
|
target.removeEventListener(touchEventsDesktop.start, swiper.scrollbar.onDragStart, activeListener);
|
document.removeEventListener(touchEventsDesktop.move, swiper.scrollbar.onDragMove, activeListener);
|
document.removeEventListener(touchEventsDesktop.end, swiper.scrollbar.onDragEnd, passiveListener);
|
} else {
|
target.removeEventListener(touchEventsTouch.start, swiper.scrollbar.onDragStart, activeListener);
|
target.removeEventListener(touchEventsTouch.move, swiper.scrollbar.onDragMove, activeListener);
|
target.removeEventListener(touchEventsTouch.end, swiper.scrollbar.onDragEnd, passiveListener);
|
}
|
},
|
init() {
|
const swiper = this;
|
if (!swiper.params.scrollbar.el) return;
|
const { scrollbar, $el: $swiperEl } = swiper;
|
const params = swiper.params.scrollbar;
|
|
let $el = $(params.el);
|
if (swiper.params.uniqueNavElements && typeof params.el === 'string' && $el.length > 1 && $swiperEl.find(params.el).length === 1) {
|
$el = $swiperEl.find(params.el);
|
}
|
|
let $dragEl = $el.find(`.${swiper.params.scrollbar.dragClass}`);
|
if ($dragEl.length === 0) {
|
$dragEl = $(`<div class="${swiper.params.scrollbar.dragClass}"></div>`);
|
$el.append($dragEl);
|
}
|
|
Utils.extend(scrollbar, {
|
$el,
|
el: $el[0],
|
$dragEl,
|
dragEl: $dragEl[0],
|
});
|
|
if (params.draggable) {
|
scrollbar.enableDraggable();
|
}
|
},
|
destroy() {
|
const swiper = this;
|
swiper.scrollbar.disableDraggable();
|
},
|
};
|
|
export default {
|
name: 'scrollbar',
|
params: {
|
scrollbar: {
|
el: null,
|
dragSize: 'auto',
|
hide: false,
|
draggable: false,
|
snapOnRelease: true,
|
lockClass: 'swiper-scrollbar-lock',
|
dragClass: 'swiper-scrollbar-drag',
|
},
|
},
|
create() {
|
const swiper = this;
|
Utils.extend(swiper, {
|
scrollbar: {
|
init: Scrollbar.init.bind(swiper),
|
destroy: Scrollbar.destroy.bind(swiper),
|
updateSize: Scrollbar.updateSize.bind(swiper),
|
setTranslate: Scrollbar.setTranslate.bind(swiper),
|
setTransition: Scrollbar.setTransition.bind(swiper),
|
enableDraggable: Scrollbar.enableDraggable.bind(swiper),
|
disableDraggable: Scrollbar.disableDraggable.bind(swiper),
|
setDragPosition: Scrollbar.setDragPosition.bind(swiper),
|
getPointerPosition: Scrollbar.getPointerPosition.bind(swiper),
|
onDragStart: Scrollbar.onDragStart.bind(swiper),
|
onDragMove: Scrollbar.onDragMove.bind(swiper),
|
onDragEnd: Scrollbar.onDragEnd.bind(swiper),
|
isTouched: false,
|
timeout: null,
|
dragTimeout: null,
|
},
|
});
|
},
|
on: {
|
init() {
|
const swiper = this;
|
swiper.scrollbar.init();
|
swiper.scrollbar.updateSize();
|
swiper.scrollbar.setTranslate();
|
},
|
update() {
|
const swiper = this;
|
swiper.scrollbar.updateSize();
|
},
|
resize() {
|
const swiper = this;
|
swiper.scrollbar.updateSize();
|
},
|
observerUpdate() {
|
const swiper = this;
|
swiper.scrollbar.updateSize();
|
},
|
setTranslate() {
|
const swiper = this;
|
swiper.scrollbar.setTranslate();
|
},
|
setTransition(duration) {
|
const swiper = this;
|
swiper.scrollbar.setTransition(duration);
|
},
|
destroy() {
|
const swiper = this;
|
swiper.scrollbar.destroy();
|
},
|
},
|
};
|