/// /// export const addClass = (className: string, element: Element): Element => (element.classList.add(className), element); export const removeClass = (className: string, element: Element): Element => (element.classList.remove(className), element); export const containsClass = (className: string, element: Element): boolean => element.classList.contains(className); export const toggleClass = (className: string, element: Element, flag: boolean): boolean => flag ? (addClass(className, element), true) : (removeClass(className, element), false); export const forEach = (fn: (x: T, i: number) => void, collection: Iterable) => Array.prototype.forEach.call(collection, fn); export const mutate = (dst, src): void => { for (let id in src) { dst[id] = src[id]; } }; export const getInitialItemsOrder = (items: ArrayLike): SlidesOrder => Array.from(items).map((x, i) => i); export const getNextOffset = (index: number, itemWidth: number, maxOffset: number): number => { let offset = index * itemWidth; return offset > maxOffset ? maxOffset : offset; }; export const getNextIndex = (mode: CarouselMode, dir: MoveDirection, maximalIndex: number, oldIndex: CarouselIndex, itemsVisible: number): number => { let newIndex = oldIndex + dir; if (mode === 'infinite') { return newIndex < 0 ? (maximalIndex - itemsVisible) : newIndex > (maximalIndex - itemsVisible) ? 0 : newIndex; } if (mode === 'finite') { newIndex = oldIndex + dir; return newIndex < 0 ? 0 : newIndex > (maximalIndex - itemsVisible) ? maximalIndex - itemsVisible : newIndex; } }; export const calcStepIndex = (dir: MoveDirection, state: ICarousel): number => { let {element, container, itemsOrder, mode, offset, index, pagination} = state; const { itemsVisible } = getVars(element, container); return getNextIndex(mode, dir, container.children.length, index, itemsVisible); }; export const navButtonIsHidden = (theButton: NavigationButton): Boolean => { let theStyle = theButton !== null ? getComputedStyle(theButton) : null; return theStyle !== null && theStyle.display !== 'none'; }; export const navAvailable = (buttons: NavigationButton[]): Boolean => { // I could use `every` here. But browser support is... return buttons.map(navButtonIsHidden).reduce((res, x) => res && x, true); }; export const getElementWidth = (element: Element, inclMargins: boolean): number => { let computed = getComputedStyle(element); let { width, marginLeft, marginRight, paddingLeft, paddingRight, boxSizing } = computed; let totalMargin = inclMargins ? parseFloat(marginLeft) + parseFloat(marginRight) : 0; let totalPadding = boxSizing === 'border-box' ? 0 : parseFloat(paddingLeft) + parseFloat(paddingRight); let resultingWidth = parseFloat(width) + totalPadding + totalMargin; return resultingWidth; }; export const getVars = (element: CarouselElement, container: HTMLDivElement) => { const rootElemWidth: number = getElementWidth(element, false); const stepWidth: number = element.getAttribute('loop') === 'infinite' ? element.getBoundingClientRect().width : getElementWidth(container.children.item(0), true); const totalWidth: number = Math.floor(Array.from(container.children).reduce((acc, item) => acc += getElementWidth(item, true), 0)); const maxOffset: number = Math.floor(totalWidth - rootElemWidth); const itemsVisible: number = Math.floor((rootElemWidth | 0) / (stepWidth | 0)); return { maxOffset, stepWidth, itemsVisible, rootElemWidth, totalWidth }; }; export const zipWith = (fn: (a: T, b: U) => U, arr1: T[], arr2: U[]): U[] => { return arr2.map((val: U, idx) => fn(arr1[idx], val)); }; export const isSwiping = (touchStartCoords: PosCoordinates): boolean => Object.keys(touchStartCoords).length > 0; export const throttle = (fn: () => any, delay: number) => { let timer = null; return () => { if (!timer) { fn(); timer = setTimeout(() => { clearTimeout(timer); timer = null; }, delay); } }; }; export const getTouchCoords = (event: any): PosCoordinates => { let touch = event.touches && event.touches[0]; return new PosCoordinates( event.clientX || (touch && touch.clientX), event.clientY || (touch && touch.clientY) ); }; export class PosCoordinates { x: number; y: number; constructor(x: number, y: number) { this.x = x; this.y = y; } };