ant-design-vue/components/vc-slick/utils/innerSliderUtils.js

791 lines
23 KiB
JavaScript
Raw Normal View History

// import supportsPassive from '../../../_util/supportsPassive';
export function clamp(number, lowerBound, upperBound) {
return Math.max(lowerBound, Math.min(number, upperBound));
}
export const safePreventDefault = event => {
const passiveEvents = ['touchstart', 'touchmove', 'wheel'];
if (!passiveEvents.includes(event.type)) {
event.preventDefault();
}
};
2018-07-20 08:13:21 +00:00
export const getOnDemandLazySlides = spec => {
2019-01-12 03:33:27 +00:00
const onDemandSlides = [];
const startIndex = lazyStartIndex(spec);
const endIndex = lazyEndIndex(spec);
2018-07-20 08:13:21 +00:00
for (let slideIndex = startIndex; slideIndex < endIndex; slideIndex++) {
if (spec.lazyLoadedList.indexOf(slideIndex) < 0) {
2019-01-12 03:33:27 +00:00
onDemandSlides.push(slideIndex);
2018-07-20 08:13:21 +00:00
}
}
2019-01-12 03:33:27 +00:00
return onDemandSlides;
};
2018-07-20 08:13:21 +00:00
// return list of slides that need to be present
export const getRequiredLazySlides = spec => {
2019-01-12 03:33:27 +00:00
const requiredSlides = [];
const startIndex = lazyStartIndex(spec);
const endIndex = lazyEndIndex(spec);
2018-07-20 08:13:21 +00:00
for (let slideIndex = startIndex; slideIndex < endIndex; slideIndex++) {
2019-01-12 03:33:27 +00:00
requiredSlides.push(slideIndex);
2018-07-20 08:13:21 +00:00
}
2019-01-12 03:33:27 +00:00
return requiredSlides;
};
2018-07-20 08:13:21 +00:00
// startIndex that needs to be present
2019-01-12 03:33:27 +00:00
export const lazyStartIndex = spec => spec.currentSlide - lazySlidesOnLeft(spec);
export const lazyEndIndex = spec => spec.currentSlide + lazySlidesOnRight(spec);
2018-07-20 08:13:21 +00:00
export const lazySlidesOnLeft = spec =>
spec.centerMode
2019-01-12 03:33:27 +00:00
? Math.floor(spec.slidesToShow / 2) + (parseInt(spec.centerPadding) > 0 ? 1 : 0)
: 0;
2018-07-20 08:13:21 +00:00
export const lazySlidesOnRight = spec =>
spec.centerMode
2019-01-12 03:33:27 +00:00
? Math.floor((spec.slidesToShow - 1) / 2) + 1 + (parseInt(spec.centerPadding) > 0 ? 1 : 0)
: spec.slidesToShow;
2018-07-20 08:13:21 +00:00
// get width of an element
2019-01-12 03:33:27 +00:00
export const getWidth = elem => (elem && elem.offsetWidth) || 0;
export const getHeight = elem => (elem && elem.offsetHeight) || 0;
2018-07-20 08:13:21 +00:00
export const getSwipeDirection = (touchObject, verticalSwiping = false) => {
2019-01-12 03:33:27 +00:00
let swipeAngle;
const xDist = touchObject.startX - touchObject.curX;
const yDist = touchObject.startY - touchObject.curY;
const r = Math.atan2(yDist, xDist);
swipeAngle = Math.round((r * 180) / Math.PI);
2018-07-20 08:13:21 +00:00
if (swipeAngle < 0) {
2019-01-12 03:33:27 +00:00
swipeAngle = 360 - Math.abs(swipeAngle);
2018-07-20 08:13:21 +00:00
}
2019-01-12 03:33:27 +00:00
if ((swipeAngle <= 45 && swipeAngle >= 0) || (swipeAngle <= 360 && swipeAngle >= 315)) {
return 'left';
2018-07-20 08:13:21 +00:00
}
if (swipeAngle >= 135 && swipeAngle <= 225) {
2019-01-12 03:33:27 +00:00
return 'right';
2018-07-20 08:13:21 +00:00
}
if (verticalSwiping === true) {
if (swipeAngle >= 35 && swipeAngle <= 135) {
2019-01-12 03:33:27 +00:00
return 'up';
2018-07-20 08:13:21 +00:00
} else {
2019-01-12 03:33:27 +00:00
return 'down';
2018-07-20 08:13:21 +00:00
}
}
2019-01-12 03:33:27 +00:00
return 'vertical';
};
2018-07-20 08:13:21 +00:00
// whether or not we can go next
export const canGoNext = spec => {
2019-01-12 03:33:27 +00:00
let canGo = true;
2018-07-20 08:13:21 +00:00
if (!spec.infinite) {
if (spec.centerMode && spec.currentSlide >= spec.slideCount - 1) {
2019-01-12 03:33:27 +00:00
canGo = false;
2018-07-20 08:13:21 +00:00
} else if (
spec.slideCount <= spec.slidesToShow ||
spec.currentSlide >= spec.slideCount - spec.slidesToShow
) {
2019-01-12 03:33:27 +00:00
canGo = false;
2018-07-20 08:13:21 +00:00
}
}
2019-01-12 03:33:27 +00:00
return canGo;
};
2018-07-20 08:13:21 +00:00
// given an object and a list of keys, return new object with given keys
export const extractObject = (spec, keys) => {
2019-01-12 03:33:27 +00:00
const newObject = {};
keys.forEach(key => (newObject[key] = spec[key]));
return newObject;
};
2018-07-20 08:13:21 +00:00
// get initialized state
export const initializedState = spec => {
// spec also contains listRef, trackRef
2019-01-12 03:33:27 +00:00
const slideCount = spec.children.length;
const listNode = spec.listRef;
const listWidth = Math.ceil(getWidth(listNode));
const trackNode = spec.trackRef;
const trackWidth = Math.ceil(getWidth(trackNode));
2019-01-12 03:33:27 +00:00
let slideWidth;
2018-07-20 08:13:21 +00:00
if (!spec.vertical) {
2019-01-12 03:33:27 +00:00
let centerPaddingAdj = spec.centerMode && parseInt(spec.centerPadding) * 2;
if (typeof spec.centerPadding === 'string' && spec.centerPadding.slice(-1) === '%') {
centerPaddingAdj *= listWidth / 100;
2018-07-20 08:13:21 +00:00
}
2019-01-12 03:33:27 +00:00
slideWidth = Math.ceil((listWidth - centerPaddingAdj) / spec.slidesToShow);
2018-07-20 08:13:21 +00:00
} else {
2019-01-12 03:33:27 +00:00
slideWidth = listWidth;
}
const slideHeight = listNode && getHeight(listNode.querySelector('[data-index="0"]'));
2019-01-12 03:33:27 +00:00
const listHeight = slideHeight * spec.slidesToShow;
let currentSlide = spec.currentSlide === undefined ? spec.initialSlide : spec.currentSlide;
2018-07-20 08:13:21 +00:00
if (spec.rtl && spec.currentSlide === undefined) {
2019-01-12 03:33:27 +00:00
currentSlide = slideCount - 1 - spec.initialSlide;
2018-07-20 08:13:21 +00:00
}
let lazyLoadedList = spec.lazyLoadedList || [];
const slidesToLoad = getOnDemandLazySlides({ ...spec, currentSlide, lazyLoadedList }, spec);
lazyLoadedList = lazyLoadedList.concat(slidesToLoad);
2018-07-20 08:13:21 +00:00
const state = {
slideCount,
slideWidth,
listWidth,
trackWidth,
currentSlide,
slideHeight,
listHeight,
lazyLoadedList,
2019-01-12 03:33:27 +00:00
};
2018-07-20 08:13:21 +00:00
if (spec.autoplaying === null && spec.autoplay) {
2019-01-12 03:33:27 +00:00
state['autoplaying'] = 'playing';
2018-07-20 08:13:21 +00:00
}
2019-01-12 03:33:27 +00:00
return state;
};
2018-07-20 08:13:21 +00:00
export const slideHandler = spec => {
const {
waitForAnimate,
animating,
fade,
infinite,
index,
slideCount,
lazyLoad,
currentSlide,
centerMode,
slidesToScroll,
slidesToShow,
useCSS,
2019-01-12 03:33:27 +00:00
} = spec;
let { lazyLoadedList } = spec;
2019-01-12 03:33:27 +00:00
if (waitForAnimate && animating) return {};
let animationSlide = index;
let finalSlide;
let animationLeft;
let finalLeft;
let state = {};
let nextState = {};
const targetSlide = infinite ? index : clamp(index, 0, slideCount - 1);
2018-07-20 08:13:21 +00:00
if (fade) {
2019-01-12 03:33:27 +00:00
if (!infinite && (index < 0 || index >= slideCount)) return {};
2018-07-20 08:13:21 +00:00
if (index < 0) {
2019-01-12 03:33:27 +00:00
animationSlide = index + slideCount;
2018-07-20 08:13:21 +00:00
} else if (index >= slideCount) {
2019-01-12 03:33:27 +00:00
animationSlide = index - slideCount;
2018-07-20 08:13:21 +00:00
}
if (lazyLoad && lazyLoadedList.indexOf(animationSlide) < 0) {
lazyLoadedList = lazyLoadedList.concat(animationSlide);
2018-07-20 08:13:21 +00:00
}
state = {
animating: true,
currentSlide: animationSlide,
lazyLoadedList,
targetSlide: animationSlide,
2019-01-12 03:33:27 +00:00
};
nextState = { animating: false, targetSlide: animationSlide };
2018-07-20 08:13:21 +00:00
} else {
2019-01-12 03:33:27 +00:00
finalSlide = animationSlide;
2018-07-20 08:13:21 +00:00
if (animationSlide < 0) {
2019-01-12 03:33:27 +00:00
finalSlide = animationSlide + slideCount;
if (!infinite) finalSlide = 0;
else if (slideCount % slidesToScroll !== 0) {
finalSlide = slideCount - (slideCount % slidesToScroll);
}
2018-07-20 08:13:21 +00:00
} else if (!canGoNext(spec) && animationSlide > currentSlide) {
2019-01-12 03:33:27 +00:00
animationSlide = finalSlide = currentSlide;
2018-07-20 08:13:21 +00:00
} else if (centerMode && animationSlide >= slideCount) {
2019-01-12 03:33:27 +00:00
animationSlide = infinite ? slideCount : slideCount - 1;
finalSlide = infinite ? 0 : slideCount - 1;
2018-07-20 08:13:21 +00:00
} else if (animationSlide >= slideCount) {
2019-01-12 03:33:27 +00:00
finalSlide = animationSlide - slideCount;
if (!infinite) finalSlide = slideCount - slidesToShow;
else if (slideCount % slidesToScroll !== 0) finalSlide = 0;
2018-07-20 08:13:21 +00:00
}
if (!infinite && animationSlide + slidesToShow >= slideCount) {
finalSlide = slideCount - slidesToShow;
}
2019-01-12 03:33:27 +00:00
animationLeft = getTrackLeft({ ...spec, slideIndex: animationSlide });
finalLeft = getTrackLeft({ ...spec, slideIndex: finalSlide });
2018-07-20 08:13:21 +00:00
if (!infinite) {
2019-01-12 03:33:27 +00:00
if (animationLeft === finalLeft) animationSlide = finalSlide;
animationLeft = finalLeft;
2018-07-20 08:13:21 +00:00
}
if (lazyLoad) {
lazyLoadedList = lazyLoadedList.concat(
getOnDemandLazySlides({ ...spec, currentSlide: animationSlide }),
);
}
2018-07-20 08:13:21 +00:00
if (!useCSS) {
state = {
currentSlide: finalSlide,
trackStyle: getTrackCSS({ ...spec, left: finalLeft }),
lazyLoadedList,
targetSlide,
2019-01-12 03:33:27 +00:00
};
2018-07-20 08:13:21 +00:00
} else {
state = {
animating: true,
currentSlide: finalSlide,
trackStyle: getTrackAnimateCSS({ ...spec, left: animationLeft }),
lazyLoadedList,
targetSlide,
2019-01-12 03:33:27 +00:00
};
2018-07-20 08:13:21 +00:00
nextState = {
animating: false,
currentSlide: finalSlide,
trackStyle: getTrackCSS({ ...spec, left: finalLeft }),
swipeLeft: null,
targetSlide,
2019-01-12 03:33:27 +00:00
};
2018-07-20 08:13:21 +00:00
}
}
2019-01-12 03:33:27 +00:00
return { state, nextState };
};
2018-07-20 08:13:21 +00:00
export const changeSlide = (spec, options) => {
2019-01-12 03:33:27 +00:00
let previousInt, slideOffset, targetSlide;
const {
slidesToScroll,
slidesToShow,
slideCount,
currentSlide,
targetSlide: previousTargetSlide,
lazyLoad,
infinite,
} = spec;
2019-01-12 03:33:27 +00:00
const unevenOffset = slideCount % slidesToScroll !== 0;
const indexOffset = unevenOffset ? 0 : (slideCount - currentSlide) % slidesToScroll;
2018-07-20 08:13:21 +00:00
if (options.message === 'previous') {
2019-01-12 03:33:27 +00:00
slideOffset = indexOffset === 0 ? slidesToScroll : slidesToShow - indexOffset;
targetSlide = currentSlide - slideOffset;
2018-07-20 08:13:21 +00:00
if (lazyLoad && !infinite) {
2019-01-12 03:33:27 +00:00
previousInt = currentSlide - slideOffset;
targetSlide = previousInt === -1 ? slideCount - 1 : previousInt;
2018-07-20 08:13:21 +00:00
}
if (!infinite) {
targetSlide = previousTargetSlide - slidesToScroll;
}
2018-07-20 08:13:21 +00:00
} else if (options.message === 'next') {
2019-01-12 03:33:27 +00:00
slideOffset = indexOffset === 0 ? slidesToScroll : indexOffset;
targetSlide = currentSlide + slideOffset;
2018-07-20 08:13:21 +00:00
if (lazyLoad && !infinite) {
2019-01-12 03:33:27 +00:00
targetSlide = ((currentSlide + slidesToScroll) % slideCount) + indexOffset;
2018-07-20 08:13:21 +00:00
}
if (!infinite) {
targetSlide = previousTargetSlide + slidesToScroll;
}
2018-07-20 08:13:21 +00:00
} else if (options.message === 'dots') {
// Click on dots
2019-01-12 03:33:27 +00:00
targetSlide = options.index * options.slidesToScroll;
2018-07-20 08:13:21 +00:00
} else if (options.message === 'children') {
// Click on the slides
2019-01-12 03:33:27 +00:00
targetSlide = options.index;
2018-07-20 08:13:21 +00:00
if (infinite) {
2019-01-12 03:33:27 +00:00
const direction = siblingDirection({ ...spec, targetSlide });
2018-07-20 08:13:21 +00:00
if (targetSlide > options.currentSlide && direction === 'left') {
2019-01-12 03:33:27 +00:00
targetSlide = targetSlide - slideCount;
2018-07-20 08:13:21 +00:00
} else if (targetSlide < options.currentSlide && direction === 'right') {
2019-01-12 03:33:27 +00:00
targetSlide = targetSlide + slideCount;
2018-07-20 08:13:21 +00:00
}
}
} else if (options.message === 'index') {
2019-01-12 03:33:27 +00:00
targetSlide = Number(options.index);
2018-07-20 08:13:21 +00:00
}
2019-01-12 03:33:27 +00:00
return targetSlide;
};
2018-07-20 08:13:21 +00:00
export const keyHandler = (e, accessibility, rtl) => {
2019-01-12 03:33:27 +00:00
if (e.target.tagName.match('TEXTAREA|INPUT|SELECT') || !accessibility) {
return '';
}
if (e.keyCode === 37) return rtl ? 'next' : 'previous';
if (e.keyCode === 39) return rtl ? 'previous' : 'next';
return '';
};
2018-07-20 08:13:21 +00:00
export const swipeStart = (e, swipe, draggable) => {
2022-03-04 03:31:22 +00:00
e.target.tagName === 'IMG' && safePreventDefault(e);
2019-01-12 03:33:27 +00:00
if (!swipe || (!draggable && e.type.indexOf('mouse') !== -1)) return '';
2018-07-20 08:13:21 +00:00
return {
dragging: true,
touchObject: {
startX: e.touches ? e.touches[0].pageX : e.clientX,
startY: e.touches ? e.touches[0].pageY : e.clientY,
curX: e.touches ? e.touches[0].pageX : e.clientX,
curY: e.touches ? e.touches[0].pageY : e.clientY,
},
2019-01-12 03:33:27 +00:00
};
};
2018-07-20 08:13:21 +00:00
export const swipeMove = (e, spec) => {
// spec also contains, trackRef and slideIndex
const {
scrolling,
animating,
vertical,
swipeToSlide,
verticalSwiping,
rtl,
currentSlide,
edgeFriction,
edgeDragged,
onEdge,
swiped,
swiping,
slideCount,
slidesToScroll,
infinite,
touchObject,
swipeEvent,
listHeight,
listWidth,
2019-01-12 03:33:27 +00:00
} = spec;
if (scrolling) return;
if (animating) return safePreventDefault(e);
if (vertical && swipeToSlide && verticalSwiping) safePreventDefault(e);
2019-01-12 03:33:27 +00:00
let swipeLeft;
let state = {};
const curLeft = getTrackLeft(spec);
touchObject.curX = e.touches ? e.touches[0].pageX : e.clientX;
touchObject.curY = e.touches ? e.touches[0].pageY : e.clientY;
2018-07-20 08:13:21 +00:00
touchObject.swipeLength = Math.round(
2019-01-12 03:33:27 +00:00
Math.sqrt(Math.pow(touchObject.curX - touchObject.startX, 2)),
);
2018-07-20 08:13:21 +00:00
const verticalSwipeLength = Math.round(
2019-01-12 03:33:27 +00:00
Math.sqrt(Math.pow(touchObject.curY - touchObject.startY, 2)),
);
2018-07-20 08:13:21 +00:00
if (!verticalSwiping && !swiping && verticalSwipeLength > 10) {
2019-01-12 03:33:27 +00:00
return { scrolling: true };
}
if (verticalSwiping) touchObject.swipeLength = verticalSwipeLength;
let positionOffset = (!rtl ? 1 : -1) * (touchObject.curX > touchObject.startX ? 1 : -1);
if (verticalSwiping) {
positionOffset = touchObject.curY > touchObject.startY ? 1 : -1;
2018-07-20 08:13:21 +00:00
}
2019-01-12 03:33:27 +00:00
const dotCount = Math.ceil(slideCount / slidesToScroll);
const swipeDirection = getSwipeDirection(spec.touchObject, verticalSwiping);
let touchSwipeLength = touchObject.swipeLength;
2018-07-20 08:13:21 +00:00
if (!infinite) {
if (
(currentSlide === 0 && (swipeDirection === 'right' || swipeDirection === 'down')) ||
(currentSlide + 1 >= dotCount && (swipeDirection === 'left' || swipeDirection === 'up')) ||
(!canGoNext(spec) && (swipeDirection === 'left' || swipeDirection === 'up'))
2018-07-20 08:13:21 +00:00
) {
2019-01-12 03:33:27 +00:00
touchSwipeLength = touchObject.swipeLength * edgeFriction;
2018-07-20 08:13:21 +00:00
if (edgeDragged === false && onEdge) {
2019-01-12 03:33:27 +00:00
onEdge(swipeDirection);
state['edgeDragged'] = true;
2018-07-20 08:13:21 +00:00
}
}
}
if (!swiped && swipeEvent) {
2019-01-12 03:33:27 +00:00
swipeEvent(swipeDirection);
state['swiped'] = true;
2018-07-20 08:13:21 +00:00
}
if (!vertical) {
if (!rtl) {
2019-01-12 03:33:27 +00:00
swipeLeft = curLeft + touchSwipeLength * positionOffset;
2018-07-20 08:13:21 +00:00
} else {
2019-01-12 03:33:27 +00:00
swipeLeft = curLeft - touchSwipeLength * positionOffset;
2018-07-20 08:13:21 +00:00
}
} else {
2019-01-12 03:33:27 +00:00
swipeLeft = curLeft + touchSwipeLength * (listHeight / listWidth) * positionOffset;
2018-07-20 08:13:21 +00:00
}
if (verticalSwiping) {
2019-01-12 03:33:27 +00:00
swipeLeft = curLeft + touchSwipeLength * positionOffset;
2018-07-20 08:13:21 +00:00
}
state = {
...state,
touchObject,
swipeLeft,
trackStyle: getTrackCSS({ ...spec, left: swipeLeft }),
2019-01-12 03:33:27 +00:00
};
2018-07-20 08:13:21 +00:00
if (
Math.abs(touchObject.curX - touchObject.startX) <
Math.abs(touchObject.curY - touchObject.startY) * 0.8
) {
2019-01-12 03:33:27 +00:00
return state;
2018-07-20 08:13:21 +00:00
}
if (touchObject.swipeLength > 10) {
2019-01-12 03:33:27 +00:00
state['swiping'] = true;
safePreventDefault(e);
2018-07-20 08:13:21 +00:00
}
2019-01-12 03:33:27 +00:00
return state;
};
2018-07-20 08:13:21 +00:00
export const swipeEnd = (e, spec) => {
const {
dragging,
swipe,
touchObject,
listWidth,
touchThreshold,
verticalSwiping,
listHeight,
swipeToSlide,
scrolling,
onSwipe,
targetSlide,
currentSlide,
infinite,
2019-01-12 03:33:27 +00:00
} = spec;
2018-07-20 08:13:21 +00:00
if (!dragging) {
if (swipe) safePreventDefault(e);
2019-01-12 03:33:27 +00:00
return {};
2018-07-20 08:13:21 +00:00
}
2019-01-12 03:33:27 +00:00
const minSwipe = verticalSwiping ? listHeight / touchThreshold : listWidth / touchThreshold;
const swipeDirection = getSwipeDirection(touchObject, verticalSwiping);
2018-07-20 08:13:21 +00:00
// reset the state of touch related state variables.
const state = {
dragging: false,
edgeDragged: false,
scrolling: false,
swiping: false,
swiped: false,
swipeLeft: null,
touchObject: {},
2019-01-12 03:33:27 +00:00
};
2018-07-20 08:13:21 +00:00
if (scrolling) {
2019-01-12 03:33:27 +00:00
return state;
2018-07-20 08:13:21 +00:00
}
if (!touchObject.swipeLength) {
2019-01-12 03:33:27 +00:00
return state;
2018-07-20 08:13:21 +00:00
}
if (touchObject.swipeLength > minSwipe) {
safePreventDefault(e);
2018-07-20 08:13:21 +00:00
if (onSwipe) {
2019-01-12 03:33:27 +00:00
onSwipe(swipeDirection);
2018-07-20 08:13:21 +00:00
}
2019-01-12 03:33:27 +00:00
let slideCount, newSlide;
let activeSlide = infinite ? currentSlide : targetSlide;
2018-07-20 08:13:21 +00:00
switch (swipeDirection) {
case 'left':
case 'up':
newSlide = activeSlide + getSlideCount(spec);
2019-01-12 03:33:27 +00:00
slideCount = swipeToSlide ? checkNavigable(spec, newSlide) : newSlide;
state['currentDirection'] = 0;
break;
2018-07-20 08:13:21 +00:00
case 'right':
case 'down':
newSlide = activeSlide - getSlideCount(spec);
2019-01-12 03:33:27 +00:00
slideCount = swipeToSlide ? checkNavigable(spec, newSlide) : newSlide;
state['currentDirection'] = 1;
break;
2018-07-20 08:13:21 +00:00
default:
slideCount = activeSlide;
2018-07-20 08:13:21 +00:00
}
2019-01-12 03:33:27 +00:00
state['triggerSlideHandler'] = slideCount;
2018-07-20 08:13:21 +00:00
} else {
// Adjust the track back to it's original position.
2019-01-12 03:33:27 +00:00
const currentLeft = getTrackLeft(spec);
state['trackStyle'] = getTrackAnimateCSS({ ...spec, left: currentLeft });
2018-07-20 08:13:21 +00:00
}
2019-01-12 03:33:27 +00:00
return state;
};
2018-07-20 08:13:21 +00:00
export const getNavigableIndexes = spec => {
2019-01-12 03:33:27 +00:00
const max = spec.infinite ? spec.slideCount * 2 : spec.slideCount;
let breakpoint = spec.infinite ? spec.slidesToShow * -1 : 0;
let counter = spec.infinite ? spec.slidesToShow * -1 : 0;
const indexes = [];
2018-07-20 08:13:21 +00:00
while (breakpoint < max) {
2019-01-12 03:33:27 +00:00
indexes.push(breakpoint);
breakpoint = counter + spec.slidesToScroll;
counter += Math.min(spec.slidesToScroll, spec.slidesToShow);
2018-07-20 08:13:21 +00:00
}
2019-01-12 03:33:27 +00:00
return indexes;
};
2018-07-20 08:13:21 +00:00
export const checkNavigable = (spec, index) => {
2019-01-12 03:33:27 +00:00
const navigables = getNavigableIndexes(spec);
let prevNavigable = 0;
2018-07-20 08:13:21 +00:00
if (index > navigables[navigables.length - 1]) {
2019-01-12 03:33:27 +00:00
index = navigables[navigables.length - 1];
2018-07-20 08:13:21 +00:00
} else {
for (const n in navigables) {
if (index < navigables[n]) {
2019-01-12 03:33:27 +00:00
index = prevNavigable;
break;
2018-07-20 08:13:21 +00:00
}
2019-01-12 03:33:27 +00:00
prevNavigable = navigables[n];
2018-07-20 08:13:21 +00:00
}
}
2019-01-12 03:33:27 +00:00
return index;
};
2018-07-20 08:13:21 +00:00
export const getSlideCount = spec => {
2019-01-12 03:33:27 +00:00
const centerOffset = spec.centerMode ? spec.slideWidth * Math.floor(spec.slidesToShow / 2) : 0;
2018-07-20 08:13:21 +00:00
if (spec.swipeToSlide) {
2019-01-12 03:33:27 +00:00
let swipedSlide;
const slickList = spec.listRef;
const slides = (slickList.querySelectorAll && slickList.querySelectorAll('.slick-slide')) || [];
2018-07-20 08:13:21 +00:00
Array.from(slides).every(slide => {
if (!spec.vertical) {
2019-01-12 03:33:27 +00:00
if (slide.offsetLeft - centerOffset + getWidth(slide) / 2 > spec.swipeLeft * -1) {
swipedSlide = slide;
return false;
2018-07-20 08:13:21 +00:00
}
} else {
if (slide.offsetTop + getHeight(slide) / 2 > spec.swipeLeft * -1) {
2019-01-12 03:33:27 +00:00
swipedSlide = slide;
return false;
2018-07-20 08:13:21 +00:00
}
}
2019-01-12 03:33:27 +00:00
return true;
});
2018-07-20 08:13:21 +00:00
if (!swipedSlide) {
2019-01-12 03:33:27 +00:00
return 0;
2018-07-20 08:13:21 +00:00
}
const currentIndex =
2019-01-12 03:33:27 +00:00
spec.rtl === true ? spec.slideCount - spec.currentSlide : spec.currentSlide;
const slidesTraversed = Math.abs(swipedSlide.dataset.index - currentIndex) || 1;
return slidesTraversed;
2018-07-20 08:13:21 +00:00
} else {
2019-01-12 03:33:27 +00:00
return spec.slidesToScroll;
2018-07-20 08:13:21 +00:00
}
2019-01-12 03:33:27 +00:00
};
2018-07-20 08:13:21 +00:00
export const checkSpecKeys = (spec, keysArray) =>
keysArray.reduce((value, key) => value && spec.hasOwnProperty(key), true)
? null
2019-01-12 03:33:27 +00:00
: console.error('Keys Missing:', spec);
2018-07-20 08:13:21 +00:00
export const getTrackCSS = spec => {
2019-01-12 03:33:27 +00:00
checkSpecKeys(spec, ['left', 'variableWidth', 'slideCount', 'slidesToShow', 'slideWidth']);
let trackWidth, trackHeight;
const trackChildren = spec.slideCount + 2 * spec.slidesToShow;
2018-07-20 08:13:21 +00:00
if (!spec.vertical) {
2019-01-12 03:33:27 +00:00
trackWidth = getTotalSlides(spec) * spec.slideWidth;
2018-07-20 08:13:21 +00:00
} else {
2019-01-12 03:33:27 +00:00
trackHeight = trackChildren * spec.slideHeight;
2018-07-20 08:13:21 +00:00
}
let style = {
opacity: 1,
transition: '',
WebkitTransition: '',
2019-01-12 03:33:27 +00:00
};
2018-07-20 08:13:21 +00:00
if (spec.useTransform) {
const WebkitTransform = !spec.vertical
? 'translate3d(' + spec.left + 'px, 0px, 0px)'
2019-01-12 03:33:27 +00:00
: 'translate3d(0px, ' + spec.left + 'px, 0px)';
2018-07-20 08:13:21 +00:00
const transform = !spec.vertical
? 'translate3d(' + spec.left + 'px, 0px, 0px)'
2019-01-12 03:33:27 +00:00
: 'translate3d(0px, ' + spec.left + 'px, 0px)';
2018-07-20 08:13:21 +00:00
const msTransform = !spec.vertical
? 'translateX(' + spec.left + 'px)'
2019-01-12 03:33:27 +00:00
: 'translateY(' + spec.left + 'px)';
2018-07-20 08:13:21 +00:00
style = {
...style,
WebkitTransform,
transform,
msTransform,
2019-01-12 03:33:27 +00:00
};
2018-07-20 08:13:21 +00:00
} else {
if (spec.vertical) {
2019-01-12 03:33:27 +00:00
style['top'] = spec.left;
2018-07-20 08:13:21 +00:00
} else {
2019-01-12 03:33:27 +00:00
style['left'] = spec.left;
2018-07-20 08:13:21 +00:00
}
}
2019-01-12 03:33:27 +00:00
if (spec.fade) style = { opacity: 1 };
if (trackWidth) style.width = trackWidth + 'px';
if (trackHeight) style.height = trackHeight + 'px';
2018-07-20 08:13:21 +00:00
// Fallback for IE8
if (window && !window.addEventListener && window.attachEvent) {
if (!spec.vertical) {
2019-01-12 03:33:27 +00:00
style.marginLeft = spec.left + 'px';
2018-07-20 08:13:21 +00:00
} else {
2019-01-12 03:33:27 +00:00
style.marginTop = spec.left + 'px';
2018-07-20 08:13:21 +00:00
}
}
2019-01-12 03:33:27 +00:00
return style;
};
2018-07-20 08:13:21 +00:00
export const getTrackAnimateCSS = spec => {
checkSpecKeys(spec, [
'left',
'variableWidth',
'slideCount',
'slidesToShow',
'slideWidth',
'speed',
'cssEase',
2019-01-12 03:33:27 +00:00
]);
const style = getTrackCSS(spec);
2018-07-20 08:13:21 +00:00
// useCSS is true by default so it can be undefined
if (spec.useTransform) {
2019-01-12 03:33:27 +00:00
style.WebkitTransition = '-webkit-transform ' + spec.speed + 'ms ' + spec.cssEase;
style.transition = 'transform ' + spec.speed + 'ms ' + spec.cssEase;
2018-07-20 08:13:21 +00:00
} else {
if (spec.vertical) {
2019-01-12 03:33:27 +00:00
style.transition = 'top ' + spec.speed + 'ms ' + spec.cssEase;
2018-07-20 08:13:21 +00:00
} else {
2019-01-12 03:33:27 +00:00
style.transition = 'left ' + spec.speed + 'ms ' + spec.cssEase;
2018-07-20 08:13:21 +00:00
}
}
2019-01-12 03:33:27 +00:00
return style;
};
2018-07-20 08:13:21 +00:00
export const getTrackLeft = spec => {
if (spec.unslick) {
2019-01-12 03:33:27 +00:00
return 0;
2018-07-20 08:13:21 +00:00
}
checkSpecKeys(spec, [
'slideIndex',
'trackRef',
'infinite',
'centerMode',
'slideCount',
'slidesToShow',
'slidesToScroll',
'slideWidth',
'listWidth',
'variableWidth',
'slideHeight',
2019-01-12 03:33:27 +00:00
]);
2018-07-20 08:13:21 +00:00
const {
slideIndex,
trackRef,
infinite,
centerMode,
slideCount,
slidesToShow,
slidesToScroll,
slideWidth,
listWidth,
variableWidth,
slideHeight,
fade,
vertical,
2019-01-12 03:33:27 +00:00
} = spec;
2018-07-20 08:13:21 +00:00
2019-01-12 03:33:27 +00:00
let slideOffset = 0;
let targetLeft;
let targetSlide;
let verticalOffset = 0;
2018-07-20 08:13:21 +00:00
if (fade || spec.slideCount === 1) {
2019-01-12 03:33:27 +00:00
return 0;
2018-07-20 08:13:21 +00:00
}
2019-01-12 03:33:27 +00:00
let slidesToOffset = 0;
2018-07-20 08:13:21 +00:00
if (infinite) {
2019-01-12 03:33:27 +00:00
slidesToOffset = -getPreClones(spec); // bring active slide to the beginning of visual area
2018-07-20 08:13:21 +00:00
// if next scroll doesn't have enough children, just reach till the end of original slides instead of shifting slidesToScroll children
2019-01-12 03:33:27 +00:00
if (slideCount % slidesToScroll !== 0 && slideIndex + slidesToScroll > slideCount) {
2018-07-20 08:13:21 +00:00
slidesToOffset = -(slideIndex > slideCount
? slidesToShow - (slideIndex - slideCount)
2019-01-12 03:33:27 +00:00
: slideCount % slidesToScroll);
2018-07-20 08:13:21 +00:00
}
// shift current slide to center of the frame
if (centerMode) {
2019-01-12 03:33:27 +00:00
slidesToOffset += parseInt(slidesToShow / 2);
2018-07-20 08:13:21 +00:00
}
} else {
2019-01-12 03:33:27 +00:00
if (slideCount % slidesToScroll !== 0 && slideIndex + slidesToScroll > slideCount) {
slidesToOffset = slidesToShow - (slideCount % slidesToScroll);
2018-07-20 08:13:21 +00:00
}
if (centerMode) {
2019-01-12 03:33:27 +00:00
slidesToOffset = parseInt(slidesToShow / 2);
2018-07-20 08:13:21 +00:00
}
}
2019-01-12 03:33:27 +00:00
slideOffset = slidesToOffset * slideWidth;
verticalOffset = slidesToOffset * slideHeight;
2018-07-20 08:13:21 +00:00
if (!vertical) {
2019-01-12 03:33:27 +00:00
targetLeft = slideIndex * slideWidth * -1 + slideOffset;
2018-07-20 08:13:21 +00:00
} else {
2019-01-12 03:33:27 +00:00
targetLeft = slideIndex * slideHeight * -1 + verticalOffset;
2018-07-20 08:13:21 +00:00
}
if (variableWidth === true) {
2019-01-12 03:33:27 +00:00
let targetSlideIndex;
const trackElem = trackRef;
targetSlideIndex = slideIndex + getPreClones(spec);
targetSlide = trackElem && trackElem.childNodes[targetSlideIndex];
targetLeft = targetSlide ? targetSlide.offsetLeft * -1 : 0;
2018-07-20 08:13:21 +00:00
if (centerMode === true) {
2019-01-12 03:33:27 +00:00
targetSlideIndex = infinite ? slideIndex + getPreClones(spec) : slideIndex;
targetSlide = trackElem && trackElem.children[targetSlideIndex];
targetLeft = 0;
2018-07-20 08:13:21 +00:00
for (let slide = 0; slide < targetSlideIndex; slide++) {
targetLeft -=
2019-01-12 03:33:27 +00:00
trackElem && trackElem.children[slide] && trackElem.children[slide].offsetWidth;
2018-07-20 08:13:21 +00:00
}
2019-01-12 03:33:27 +00:00
targetLeft -= parseInt(spec.centerPadding);
targetLeft += targetSlide && (listWidth - targetSlide.offsetWidth) / 2;
2018-07-20 08:13:21 +00:00
}
}
2019-01-12 03:33:27 +00:00
return targetLeft;
};
2018-07-20 08:13:21 +00:00
export const getPreClones = spec => {
if (spec.unslick || !spec.infinite) {
2019-01-12 03:33:27 +00:00
return 0;
2018-07-20 08:13:21 +00:00
}
if (spec.variableWidth) {
2019-01-12 03:33:27 +00:00
return spec.slideCount;
2018-07-20 08:13:21 +00:00
}
2019-01-12 03:33:27 +00:00
return spec.slidesToShow + (spec.centerMode ? 1 : 0);
};
2018-07-20 08:13:21 +00:00
export const getPostClones = spec => {
if (spec.unslick || !spec.infinite) {
2019-01-12 03:33:27 +00:00
return 0;
2018-07-20 08:13:21 +00:00
}
2019-01-12 03:33:27 +00:00
return spec.slideCount;
};
2018-07-20 08:13:21 +00:00
export const getTotalSlides = spec =>
2019-01-12 03:33:27 +00:00
spec.slideCount === 1 ? 1 : getPreClones(spec) + spec.slideCount + getPostClones(spec);
2018-07-20 08:13:21 +00:00
export const siblingDirection = spec => {
if (spec.targetSlide > spec.currentSlide) {
if (spec.targetSlide > spec.currentSlide + slidesOnRight(spec)) {
2019-01-12 03:33:27 +00:00
return 'left';
2018-07-20 08:13:21 +00:00
}
2019-01-12 03:33:27 +00:00
return 'right';
2018-07-20 08:13:21 +00:00
} else {
if (spec.targetSlide < spec.currentSlide - slidesOnLeft(spec)) {
2019-01-12 03:33:27 +00:00
return 'right';
2018-07-20 08:13:21 +00:00
}
2019-01-12 03:33:27 +00:00
return 'left';
2018-07-20 08:13:21 +00:00
}
2019-01-12 03:33:27 +00:00
};
2018-07-20 08:13:21 +00:00
2019-01-12 03:33:27 +00:00
export const slidesOnRight = ({ slidesToShow, centerMode, rtl, centerPadding }) => {
2018-07-20 08:13:21 +00:00
// returns no of slides on the right of active slide
if (centerMode) {
2019-01-12 03:33:27 +00:00
let right = (slidesToShow - 1) / 2 + 1;
if (parseInt(centerPadding) > 0) right += 1;
if (rtl && slidesToShow % 2 === 0) right += 1;
return right;
2018-07-20 08:13:21 +00:00
}
if (rtl) {
2019-01-12 03:33:27 +00:00
return 0;
2018-07-20 08:13:21 +00:00
}
2019-01-12 03:33:27 +00:00
return slidesToShow - 1;
};
2018-07-20 08:13:21 +00:00
2019-01-12 03:33:27 +00:00
export const slidesOnLeft = ({ slidesToShow, centerMode, rtl, centerPadding }) => {
2018-07-20 08:13:21 +00:00
// returns no of slides on the left of active slide
if (centerMode) {
2019-01-12 03:33:27 +00:00
let left = (slidesToShow - 1) / 2 + 1;
if (parseInt(centerPadding) > 0) left += 1;
if (!rtl && slidesToShow % 2 === 0) left += 1;
return left;
2018-07-20 08:13:21 +00:00
}
if (rtl) {
2019-01-12 03:33:27 +00:00
return slidesToShow - 1;
2018-07-20 08:13:21 +00:00
}
2019-01-12 03:33:27 +00:00
return 0;
};
2018-07-20 08:13:21 +00:00
export const canUseDOM = () =>
2019-01-12 03:33:27 +00:00
!!(typeof window !== 'undefined' && window.document && window.document.createElement);