| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672 |
- 'use strict';
- function isNumber(subject) {
- return typeof subject === 'number';
- }
- function isString(subject) {
- return typeof subject === 'string';
- }
- function isBoolean(subject) {
- return typeof subject === 'boolean';
- }
- function isObject(subject) {
- return Object.prototype.toString.call(subject) === '[object Object]';
- }
- function mathAbs(n) {
- return Math.abs(n);
- }
- function mathSign(n) {
- return Math.sign(n);
- }
- function deltaAbs(valueB, valueA) {
- return mathAbs(valueB - valueA);
- }
- function factorAbs(valueB, valueA) {
- if (valueB === 0 || valueA === 0) return 0;
- if (mathAbs(valueB) <= mathAbs(valueA)) return 0;
- const diff = deltaAbs(mathAbs(valueB), mathAbs(valueA));
- return mathAbs(diff / valueB);
- }
- function roundToTwoDecimals(num) {
- return Math.round(num * 100) / 100;
- }
- function arrayKeys(array) {
- return objectKeys(array).map(Number);
- }
- function arrayLast(array) {
- return array[arrayLastIndex(array)];
- }
- function arrayLastIndex(array) {
- return Math.max(0, array.length - 1);
- }
- function arrayIsLastIndex(array, index) {
- return index === arrayLastIndex(array);
- }
- function arrayFromNumber(n, startAt = 0) {
- return Array.from(Array(n), (_, i) => startAt + i);
- }
- function objectKeys(object) {
- return Object.keys(object);
- }
- function objectsMergeDeep(objectA, objectB) {
- return [objectA, objectB].reduce((mergedObjects, currentObject) => {
- objectKeys(currentObject).forEach(key => {
- const valueA = mergedObjects[key];
- const valueB = currentObject[key];
- const areObjects = isObject(valueA) && isObject(valueB);
- mergedObjects[key] = areObjects ? objectsMergeDeep(valueA, valueB) : valueB;
- });
- return mergedObjects;
- }, {});
- }
- function isMouseEvent(evt, ownerWindow) {
- return typeof ownerWindow.MouseEvent !== 'undefined' && evt instanceof ownerWindow.MouseEvent;
- }
- function Alignment(align, viewSize) {
- const predefined = {
- start,
- center,
- end
- };
- function start() {
- return 0;
- }
- function center(n) {
- return end(n) / 2;
- }
- function end(n) {
- return viewSize - n;
- }
- function measure(n, index) {
- if (isString(align)) return predefined[align](n);
- return align(viewSize, n, index);
- }
- const self = {
- measure
- };
- return self;
- }
- function EventStore() {
- let listeners = [];
- function add(node, type, handler, options = {
- passive: true
- }) {
- let removeListener;
- if ('addEventListener' in node) {
- node.addEventListener(type, handler, options);
- removeListener = () => node.removeEventListener(type, handler, options);
- } else {
- const legacyMediaQueryList = node;
- legacyMediaQueryList.addListener(handler);
- removeListener = () => legacyMediaQueryList.removeListener(handler);
- }
- listeners.push(removeListener);
- return self;
- }
- function clear() {
- listeners = listeners.filter(remove => remove());
- }
- const self = {
- add,
- clear
- };
- return self;
- }
- function Animations(ownerDocument, ownerWindow, update, render) {
- const documentVisibleHandler = EventStore();
- const fixedTimeStep = 1000 / 60;
- let lastTimeStamp = null;
- let accumulatedTime = 0;
- let animationId = 0;
- function init() {
- documentVisibleHandler.add(ownerDocument, 'visibilitychange', () => {
- if (ownerDocument.hidden) reset();
- });
- }
- function destroy() {
- stop();
- documentVisibleHandler.clear();
- }
- function animate(timeStamp) {
- if (!animationId) return;
- if (!lastTimeStamp) {
- lastTimeStamp = timeStamp;
- update();
- update();
- }
- const timeElapsed = timeStamp - lastTimeStamp;
- lastTimeStamp = timeStamp;
- accumulatedTime += timeElapsed;
- while (accumulatedTime >= fixedTimeStep) {
- update();
- accumulatedTime -= fixedTimeStep;
- }
- const alpha = accumulatedTime / fixedTimeStep;
- render(alpha);
- if (animationId) {
- animationId = ownerWindow.requestAnimationFrame(animate);
- }
- }
- function start() {
- if (animationId) return;
- animationId = ownerWindow.requestAnimationFrame(animate);
- }
- function stop() {
- ownerWindow.cancelAnimationFrame(animationId);
- lastTimeStamp = null;
- accumulatedTime = 0;
- animationId = 0;
- }
- function reset() {
- lastTimeStamp = null;
- accumulatedTime = 0;
- }
- const self = {
- init,
- destroy,
- start,
- stop,
- update,
- render
- };
- return self;
- }
- function Axis(axis, contentDirection) {
- const isRightToLeft = contentDirection === 'rtl';
- const isVertical = axis === 'y';
- const scroll = isVertical ? 'y' : 'x';
- const cross = isVertical ? 'x' : 'y';
- const sign = !isVertical && isRightToLeft ? -1 : 1;
- const startEdge = getStartEdge();
- const endEdge = getEndEdge();
- function measureSize(nodeRect) {
- const {
- height,
- width
- } = nodeRect;
- return isVertical ? height : width;
- }
- function getStartEdge() {
- if (isVertical) return 'top';
- return isRightToLeft ? 'right' : 'left';
- }
- function getEndEdge() {
- if (isVertical) return 'bottom';
- return isRightToLeft ? 'left' : 'right';
- }
- function direction(n) {
- return n * sign;
- }
- const self = {
- scroll,
- cross,
- startEdge,
- endEdge,
- measureSize,
- direction
- };
- return self;
- }
- function Limit(min = 0, max = 0) {
- const length = mathAbs(min - max);
- function reachedMin(n) {
- return n < min;
- }
- function reachedMax(n) {
- return n > max;
- }
- function reachedAny(n) {
- return reachedMin(n) || reachedMax(n);
- }
- function constrain(n) {
- if (!reachedAny(n)) return n;
- return reachedMin(n) ? min : max;
- }
- function removeOffset(n) {
- if (!length) return n;
- return n - length * Math.ceil((n - max) / length);
- }
- const self = {
- length,
- max,
- min,
- constrain,
- reachedAny,
- reachedMax,
- reachedMin,
- removeOffset
- };
- return self;
- }
- function Counter(max, start, loop) {
- const {
- constrain
- } = Limit(0, max);
- const loopEnd = max + 1;
- let counter = withinLimit(start);
- function withinLimit(n) {
- return !loop ? constrain(n) : mathAbs((loopEnd + n) % loopEnd);
- }
- function get() {
- return counter;
- }
- function set(n) {
- counter = withinLimit(n);
- return self;
- }
- function add(n) {
- return clone().set(get() + n);
- }
- function clone() {
- return Counter(max, get(), loop);
- }
- const self = {
- get,
- set,
- add,
- clone
- };
- return self;
- }
- function DragHandler(axis, rootNode, ownerDocument, ownerWindow, target, dragTracker, location, animation, scrollTo, scrollBody, scrollTarget, index, eventHandler, percentOfView, dragFree, dragThreshold, skipSnaps, baseFriction, watchDrag) {
- const {
- cross: crossAxis,
- direction
- } = axis;
- const focusNodes = ['INPUT', 'SELECT', 'TEXTAREA'];
- const nonPassiveEvent = {
- passive: false
- };
- const initEvents = EventStore();
- const dragEvents = EventStore();
- const goToNextThreshold = Limit(50, 225).constrain(percentOfView.measure(20));
- const snapForceBoost = {
- mouse: 300,
- touch: 400
- };
- const freeForceBoost = {
- mouse: 500,
- touch: 600
- };
- const baseSpeed = dragFree ? 43 : 25;
- let isMoving = false;
- let startScroll = 0;
- let startCross = 0;
- let pointerIsDown = false;
- let preventScroll = false;
- let preventClick = false;
- let isMouse = false;
- function init(emblaApi) {
- if (!watchDrag) return;
- function downIfAllowed(evt) {
- if (isBoolean(watchDrag) || watchDrag(emblaApi, evt)) down(evt);
- }
- const node = rootNode;
- initEvents.add(node, 'dragstart', evt => evt.preventDefault(), nonPassiveEvent).add(node, 'touchmove', () => undefined, nonPassiveEvent).add(node, 'touchend', () => undefined).add(node, 'touchstart', downIfAllowed).add(node, 'mousedown', downIfAllowed).add(node, 'touchcancel', up).add(node, 'contextmenu', up).add(node, 'click', click, true);
- }
- function destroy() {
- initEvents.clear();
- dragEvents.clear();
- }
- function addDragEvents() {
- const node = isMouse ? ownerDocument : rootNode;
- dragEvents.add(node, 'touchmove', move, nonPassiveEvent).add(node, 'touchend', up).add(node, 'mousemove', move, nonPassiveEvent).add(node, 'mouseup', up);
- }
- function isFocusNode(node) {
- const nodeName = node.nodeName || '';
- return focusNodes.includes(nodeName);
- }
- function forceBoost() {
- const boost = dragFree ? freeForceBoost : snapForceBoost;
- const type = isMouse ? 'mouse' : 'touch';
- return boost[type];
- }
- function allowedForce(force, targetChanged) {
- const next = index.add(mathSign(force) * -1);
- const baseForce = scrollTarget.byDistance(force, !dragFree).distance;
- if (dragFree || mathAbs(force) < goToNextThreshold) return baseForce;
- if (skipSnaps && targetChanged) return baseForce * 0.5;
- return scrollTarget.byIndex(next.get(), 0).distance;
- }
- function down(evt) {
- const isMouseEvt = isMouseEvent(evt, ownerWindow);
- isMouse = isMouseEvt;
- preventClick = dragFree && isMouseEvt && !evt.buttons && isMoving;
- isMoving = deltaAbs(target.get(), location.get()) >= 2;
- if (isMouseEvt && evt.button !== 0) return;
- if (isFocusNode(evt.target)) return;
- pointerIsDown = true;
- dragTracker.pointerDown(evt);
- scrollBody.useFriction(0).useDuration(0);
- target.set(location);
- addDragEvents();
- startScroll = dragTracker.readPoint(evt);
- startCross = dragTracker.readPoint(evt, crossAxis);
- eventHandler.emit('pointerDown');
- }
- function move(evt) {
- const isTouchEvt = !isMouseEvent(evt, ownerWindow);
- if (isTouchEvt && evt.touches.length >= 2) return up(evt);
- const lastScroll = dragTracker.readPoint(evt);
- const lastCross = dragTracker.readPoint(evt, crossAxis);
- const diffScroll = deltaAbs(lastScroll, startScroll);
- const diffCross = deltaAbs(lastCross, startCross);
- if (!preventScroll && !isMouse) {
- if (!evt.cancelable) return up(evt);
- preventScroll = diffScroll > diffCross;
- if (!preventScroll) return up(evt);
- }
- const diff = dragTracker.pointerMove(evt);
- if (diffScroll > dragThreshold) preventClick = true;
- scrollBody.useFriction(0.3).useDuration(0.75);
- animation.start();
- target.add(direction(diff));
- evt.preventDefault();
- }
- function up(evt) {
- const currentLocation = scrollTarget.byDistance(0, false);
- const targetChanged = currentLocation.index !== index.get();
- const rawForce = dragTracker.pointerUp(evt) * forceBoost();
- const force = allowedForce(direction(rawForce), targetChanged);
- const forceFactor = factorAbs(rawForce, force);
- const speed = baseSpeed - 10 * forceFactor;
- const friction = baseFriction + forceFactor / 50;
- preventScroll = false;
- pointerIsDown = false;
- dragEvents.clear();
- scrollBody.useDuration(speed).useFriction(friction);
- scrollTo.distance(force, !dragFree);
- isMouse = false;
- eventHandler.emit('pointerUp');
- }
- function click(evt) {
- if (preventClick) {
- evt.stopPropagation();
- evt.preventDefault();
- preventClick = false;
- }
- }
- function pointerDown() {
- return pointerIsDown;
- }
- const self = {
- init,
- destroy,
- pointerDown
- };
- return self;
- }
- function DragTracker(axis, ownerWindow) {
- const logInterval = 170;
- let startEvent;
- let lastEvent;
- function readTime(evt) {
- return evt.timeStamp;
- }
- function readPoint(evt, evtAxis) {
- const property = evtAxis || axis.scroll;
- const coord = `client${property === 'x' ? 'X' : 'Y'}`;
- return (isMouseEvent(evt, ownerWindow) ? evt : evt.touches[0])[coord];
- }
- function pointerDown(evt) {
- startEvent = evt;
- lastEvent = evt;
- return readPoint(evt);
- }
- function pointerMove(evt) {
- const diff = readPoint(evt) - readPoint(lastEvent);
- const expired = readTime(evt) - readTime(startEvent) > logInterval;
- lastEvent = evt;
- if (expired) startEvent = evt;
- return diff;
- }
- function pointerUp(evt) {
- if (!startEvent || !lastEvent) return 0;
- const diffDrag = readPoint(lastEvent) - readPoint(startEvent);
- const diffTime = readTime(evt) - readTime(startEvent);
- const expired = readTime(evt) - readTime(lastEvent) > logInterval;
- const force = diffDrag / diffTime;
- const isFlick = diffTime && !expired && mathAbs(force) > 0.1;
- return isFlick ? force : 0;
- }
- const self = {
- pointerDown,
- pointerMove,
- pointerUp,
- readPoint
- };
- return self;
- }
- function NodeRects() {
- function measure(node) {
- const {
- offsetTop,
- offsetLeft,
- offsetWidth,
- offsetHeight
- } = node;
- const offset = {
- top: offsetTop,
- right: offsetLeft + offsetWidth,
- bottom: offsetTop + offsetHeight,
- left: offsetLeft,
- width: offsetWidth,
- height: offsetHeight
- };
- return offset;
- }
- const self = {
- measure
- };
- return self;
- }
- function PercentOfView(viewSize) {
- function measure(n) {
- return viewSize * (n / 100);
- }
- const self = {
- measure
- };
- return self;
- }
- function ResizeHandler(container, eventHandler, ownerWindow, slides, axis, watchResize, nodeRects) {
- const observeNodes = [container].concat(slides);
- let resizeObserver;
- let containerSize;
- let slideSizes = [];
- let destroyed = false;
- function readSize(node) {
- return axis.measureSize(nodeRects.measure(node));
- }
- function init(emblaApi) {
- if (!watchResize) return;
- containerSize = readSize(container);
- slideSizes = slides.map(readSize);
- function defaultCallback(entries) {
- for (const entry of entries) {
- if (destroyed) return;
- const isContainer = entry.target === container;
- const slideIndex = slides.indexOf(entry.target);
- const lastSize = isContainer ? containerSize : slideSizes[slideIndex];
- const newSize = readSize(isContainer ? container : slides[slideIndex]);
- const diffSize = mathAbs(newSize - lastSize);
- if (diffSize >= 0.5) {
- emblaApi.reInit();
- eventHandler.emit('resize');
- break;
- }
- }
- }
- resizeObserver = new ResizeObserver(entries => {
- if (isBoolean(watchResize) || watchResize(emblaApi, entries)) {
- defaultCallback(entries);
- }
- });
- ownerWindow.requestAnimationFrame(() => {
- observeNodes.forEach(node => resizeObserver.observe(node));
- });
- }
- function destroy() {
- destroyed = true;
- if (resizeObserver) resizeObserver.disconnect();
- }
- const self = {
- init,
- destroy
- };
- return self;
- }
- function ScrollBody(location, offsetLocation, previousLocation, target, baseDuration, baseFriction) {
- let scrollVelocity = 0;
- let scrollDirection = 0;
- let scrollDuration = baseDuration;
- let scrollFriction = baseFriction;
- let rawLocation = location.get();
- let rawLocationPrevious = 0;
- function seek() {
- const displacement = target.get() - location.get();
- const isInstant = !scrollDuration;
- let scrollDistance = 0;
- if (isInstant) {
- scrollVelocity = 0;
- previousLocation.set(target);
- location.set(target);
- scrollDistance = displacement;
- } else {
- previousLocation.set(location);
- scrollVelocity += displacement / scrollDuration;
- scrollVelocity *= scrollFriction;
- rawLocation += scrollVelocity;
- location.add(scrollVelocity);
- scrollDistance = rawLocation - rawLocationPrevious;
- }
- scrollDirection = mathSign(scrollDistance);
- rawLocationPrevious = rawLocation;
- return self;
- }
- function settled() {
- const diff = target.get() - offsetLocation.get();
- return mathAbs(diff) < 0.001;
- }
- function duration() {
- return scrollDuration;
- }
- function direction() {
- return scrollDirection;
- }
- function velocity() {
- return scrollVelocity;
- }
- function useBaseDuration() {
- return useDuration(baseDuration);
- }
- function useBaseFriction() {
- return useFriction(baseFriction);
- }
- function useDuration(n) {
- scrollDuration = n;
- return self;
- }
- function useFriction(n) {
- scrollFriction = n;
- return self;
- }
- const self = {
- direction,
- duration,
- velocity,
- seek,
- settled,
- useBaseFriction,
- useBaseDuration,
- useFriction,
- useDuration
- };
- return self;
- }
- function ScrollBounds(limit, location, target, scrollBody, percentOfView) {
- const pullBackThreshold = percentOfView.measure(10);
- const edgeOffsetTolerance = percentOfView.measure(50);
- const frictionLimit = Limit(0.1, 0.99);
- let disabled = false;
- function shouldConstrain() {
- if (disabled) return false;
- if (!limit.reachedAny(target.get())) return false;
- if (!limit.reachedAny(location.get())) return false;
- return true;
- }
- function constrain(pointerDown) {
- if (!shouldConstrain()) return;
- const edge = limit.reachedMin(location.get()) ? 'min' : 'max';
- const diffToEdge = mathAbs(limit[edge] - location.get());
- const diffToTarget = target.get() - location.get();
- const friction = frictionLimit.constrain(diffToEdge / edgeOffsetTolerance);
- target.subtract(diffToTarget * friction);
- if (!pointerDown && mathAbs(diffToTarget) < pullBackThreshold) {
- target.set(limit.constrain(target.get()));
- scrollBody.useDuration(25).useBaseFriction();
- }
- }
- function toggleActive(active) {
- disabled = !active;
- }
- const self = {
- shouldConstrain,
- constrain,
- toggleActive
- };
- return self;
- }
- function ScrollContain(viewSize, contentSize, snapsAligned, containScroll, pixelTolerance) {
- const scrollBounds = Limit(-contentSize + viewSize, 0);
- const snapsBounded = measureBounded();
- const scrollContainLimit = findScrollContainLimit();
- const snapsContained = measureContained();
- function usePixelTolerance(bound, snap) {
- return deltaAbs(bound, snap) <= 1;
- }
- function findScrollContainLimit() {
- const startSnap = snapsBounded[0];
- const endSnap = arrayLast(snapsBounded);
- const min = snapsBounded.lastIndexOf(startSnap);
- const max = snapsBounded.indexOf(endSnap) + 1;
- return Limit(min, max);
- }
- function measureBounded() {
- return snapsAligned.map((snapAligned, index) => {
- const {
- min,
- max
- } = scrollBounds;
- const snap = scrollBounds.constrain(snapAligned);
- const isFirst = !index;
- const isLast = arrayIsLastIndex(snapsAligned, index);
- if (isFirst) return max;
- if (isLast) return min;
- if (usePixelTolerance(min, snap)) return min;
- if (usePixelTolerance(max, snap)) return max;
- return snap;
- }).map(scrollBound => parseFloat(scrollBound.toFixed(3)));
- }
- function measureContained() {
- if (contentSize <= viewSize + pixelTolerance) return [scrollBounds.max];
- if (containScroll === 'keepSnaps') return snapsBounded;
- const {
- min,
- max
- } = scrollContainLimit;
- return snapsBounded.slice(min, max);
- }
- const self = {
- snapsContained,
- scrollContainLimit
- };
- return self;
- }
- function ScrollLimit(contentSize, scrollSnaps, loop) {
- const max = scrollSnaps[0];
- const min = loop ? max - contentSize : arrayLast(scrollSnaps);
- const limit = Limit(min, max);
- const self = {
- limit
- };
- return self;
- }
- function ScrollLooper(contentSize, limit, location, vectors) {
- const jointSafety = 0.1;
- const min = limit.min + jointSafety;
- const max = limit.max + jointSafety;
- const {
- reachedMin,
- reachedMax
- } = Limit(min, max);
- function shouldLoop(direction) {
- if (direction === 1) return reachedMax(location.get());
- if (direction === -1) return reachedMin(location.get());
- return false;
- }
- function loop(direction) {
- if (!shouldLoop(direction)) return;
- const loopDistance = contentSize * (direction * -1);
- vectors.forEach(v => v.add(loopDistance));
- }
- const self = {
- loop
- };
- return self;
- }
- function ScrollProgress(limit) {
- const {
- max,
- length
- } = limit;
- function get(n) {
- const currentLocation = n - max;
- return length ? currentLocation / -length : 0;
- }
- const self = {
- get
- };
- return self;
- }
- function ScrollSnaps(axis, alignment, containerRect, slideRects, slidesToScroll) {
- const {
- startEdge,
- endEdge
- } = axis;
- const {
- groupSlides
- } = slidesToScroll;
- const alignments = measureSizes().map(alignment.measure);
- const snaps = measureUnaligned();
- const snapsAligned = measureAligned();
- function measureSizes() {
- return groupSlides(slideRects).map(rects => arrayLast(rects)[endEdge] - rects[0][startEdge]).map(mathAbs);
- }
- function measureUnaligned() {
- return slideRects.map(rect => containerRect[startEdge] - rect[startEdge]).map(snap => -mathAbs(snap));
- }
- function measureAligned() {
- return groupSlides(snaps).map(g => g[0]).map((snap, index) => snap + alignments[index]);
- }
- const self = {
- snaps,
- snapsAligned
- };
- return self;
- }
- function SlideRegistry(containSnaps, containScroll, scrollSnaps, scrollContainLimit, slidesToScroll, slideIndexes) {
- const {
- groupSlides
- } = slidesToScroll;
- const {
- min,
- max
- } = scrollContainLimit;
- const slideRegistry = createSlideRegistry();
- function createSlideRegistry() {
- const groupedSlideIndexes = groupSlides(slideIndexes);
- const doNotContain = !containSnaps || containScroll === 'keepSnaps';
- if (scrollSnaps.length === 1) return [slideIndexes];
- if (doNotContain) return groupedSlideIndexes;
- return groupedSlideIndexes.slice(min, max).map((group, index, groups) => {
- const isFirst = !index;
- const isLast = arrayIsLastIndex(groups, index);
- if (isFirst) {
- const range = arrayLast(groups[0]) + 1;
- return arrayFromNumber(range);
- }
- if (isLast) {
- const range = arrayLastIndex(slideIndexes) - arrayLast(groups)[0] + 1;
- return arrayFromNumber(range, arrayLast(groups)[0]);
- }
- return group;
- });
- }
- const self = {
- slideRegistry
- };
- return self;
- }
- function ScrollTarget(loop, scrollSnaps, contentSize, limit, targetVector) {
- const {
- reachedAny,
- removeOffset,
- constrain
- } = limit;
- function minDistance(distances) {
- return distances.concat().sort((a, b) => mathAbs(a) - mathAbs(b))[0];
- }
- function findTargetSnap(target) {
- const distance = loop ? removeOffset(target) : constrain(target);
- const ascDiffsToSnaps = scrollSnaps.map((snap, index) => ({
- diff: shortcut(snap - distance, 0),
- index
- })).sort((d1, d2) => mathAbs(d1.diff) - mathAbs(d2.diff));
- const {
- index
- } = ascDiffsToSnaps[0];
- return {
- index,
- distance
- };
- }
- function shortcut(target, direction) {
- const targets = [target, target + contentSize, target - contentSize];
- if (!loop) return target;
- if (!direction) return minDistance(targets);
- const matchingTargets = targets.filter(t => mathSign(t) === direction);
- if (matchingTargets.length) return minDistance(matchingTargets);
- return arrayLast(targets) - contentSize;
- }
- function byIndex(index, direction) {
- const diffToSnap = scrollSnaps[index] - targetVector.get();
- const distance = shortcut(diffToSnap, direction);
- return {
- index,
- distance
- };
- }
- function byDistance(distance, snap) {
- const target = targetVector.get() + distance;
- const {
- index,
- distance: targetSnapDistance
- } = findTargetSnap(target);
- const reachedBound = !loop && reachedAny(target);
- if (!snap || reachedBound) return {
- index,
- distance
- };
- const diffToSnap = scrollSnaps[index] - targetSnapDistance;
- const snapDistance = distance + shortcut(diffToSnap, 0);
- return {
- index,
- distance: snapDistance
- };
- }
- const self = {
- byDistance,
- byIndex,
- shortcut
- };
- return self;
- }
- function ScrollTo(animation, indexCurrent, indexPrevious, scrollBody, scrollTarget, targetVector, eventHandler) {
- function scrollTo(target) {
- const distanceDiff = target.distance;
- const indexDiff = target.index !== indexCurrent.get();
- targetVector.add(distanceDiff);
- if (distanceDiff) {
- if (scrollBody.duration()) {
- animation.start();
- } else {
- animation.update();
- animation.render(1);
- animation.update();
- }
- }
- if (indexDiff) {
- indexPrevious.set(indexCurrent.get());
- indexCurrent.set(target.index);
- eventHandler.emit('select');
- }
- }
- function distance(n, snap) {
- const target = scrollTarget.byDistance(n, snap);
- scrollTo(target);
- }
- function index(n, direction) {
- const targetIndex = indexCurrent.clone().set(n);
- const target = scrollTarget.byIndex(targetIndex.get(), direction);
- scrollTo(target);
- }
- const self = {
- distance,
- index
- };
- return self;
- }
- function SlideFocus(root, slides, slideRegistry, scrollTo, scrollBody, eventStore, eventHandler, watchFocus) {
- const focusListenerOptions = {
- passive: true,
- capture: true
- };
- let lastTabPressTime = 0;
- function init(emblaApi) {
- if (!watchFocus) return;
- function defaultCallback(index) {
- const nowTime = new Date().getTime();
- const diffTime = nowTime - lastTabPressTime;
- if (diffTime > 10) return;
- eventHandler.emit('slideFocusStart');
- root.scrollLeft = 0;
- const group = slideRegistry.findIndex(group => group.includes(index));
- if (!isNumber(group)) return;
- scrollBody.useDuration(0);
- scrollTo.index(group, 0);
- eventHandler.emit('slideFocus');
- }
- eventStore.add(document, 'keydown', registerTabPress, false);
- slides.forEach((slide, slideIndex) => {
- eventStore.add(slide, 'focus', evt => {
- if (isBoolean(watchFocus) || watchFocus(emblaApi, evt)) {
- defaultCallback(slideIndex);
- }
- }, focusListenerOptions);
- });
- }
- function registerTabPress(event) {
- if (event.code === 'Tab') lastTabPressTime = new Date().getTime();
- }
- const self = {
- init
- };
- return self;
- }
- function Vector1D(initialValue) {
- let value = initialValue;
- function get() {
- return value;
- }
- function set(n) {
- value = normalizeInput(n);
- }
- function add(n) {
- value += normalizeInput(n);
- }
- function subtract(n) {
- value -= normalizeInput(n);
- }
- function normalizeInput(n) {
- return isNumber(n) ? n : n.get();
- }
- const self = {
- get,
- set,
- add,
- subtract
- };
- return self;
- }
- function Translate(axis, container) {
- const translate = axis.scroll === 'x' ? x : y;
- const containerStyle = container.style;
- let previousTarget = null;
- let disabled = false;
- function x(n) {
- return `translate3d(${n}px,0px,0px)`;
- }
- function y(n) {
- return `translate3d(0px,${n}px,0px)`;
- }
- function to(target) {
- if (disabled) return;
- const newTarget = roundToTwoDecimals(axis.direction(target));
- if (newTarget === previousTarget) return;
- containerStyle.transform = translate(newTarget);
- previousTarget = newTarget;
- }
- function toggleActive(active) {
- disabled = !active;
- }
- function clear() {
- if (disabled) return;
- containerStyle.transform = '';
- if (!container.getAttribute('style')) container.removeAttribute('style');
- }
- const self = {
- clear,
- to,
- toggleActive
- };
- return self;
- }
- function SlideLooper(axis, viewSize, contentSize, slideSizes, slideSizesWithGaps, snaps, scrollSnaps, location, slides) {
- const roundingSafety = 0.5;
- const ascItems = arrayKeys(slideSizesWithGaps);
- const descItems = arrayKeys(slideSizesWithGaps).reverse();
- const loopPoints = startPoints().concat(endPoints());
- function removeSlideSizes(indexes, from) {
- return indexes.reduce((a, i) => {
- return a - slideSizesWithGaps[i];
- }, from);
- }
- function slidesInGap(indexes, gap) {
- return indexes.reduce((a, i) => {
- const remainingGap = removeSlideSizes(a, gap);
- return remainingGap > 0 ? a.concat([i]) : a;
- }, []);
- }
- function findSlideBounds(offset) {
- return snaps.map((snap, index) => ({
- start: snap - slideSizes[index] + roundingSafety + offset,
- end: snap + viewSize - roundingSafety + offset
- }));
- }
- function findLoopPoints(indexes, offset, isEndEdge) {
- const slideBounds = findSlideBounds(offset);
- return indexes.map(index => {
- const initial = isEndEdge ? 0 : -contentSize;
- const altered = isEndEdge ? contentSize : 0;
- const boundEdge = isEndEdge ? 'end' : 'start';
- const loopPoint = slideBounds[index][boundEdge];
- return {
- index,
- loopPoint,
- slideLocation: Vector1D(-1),
- translate: Translate(axis, slides[index]),
- target: () => location.get() > loopPoint ? initial : altered
- };
- });
- }
- function startPoints() {
- const gap = scrollSnaps[0];
- const indexes = slidesInGap(descItems, gap);
- return findLoopPoints(indexes, contentSize, false);
- }
- function endPoints() {
- const gap = viewSize - scrollSnaps[0] - 1;
- const indexes = slidesInGap(ascItems, gap);
- return findLoopPoints(indexes, -contentSize, true);
- }
- function canLoop() {
- return loopPoints.every(({
- index
- }) => {
- const otherIndexes = ascItems.filter(i => i !== index);
- return removeSlideSizes(otherIndexes, viewSize) <= 0.1;
- });
- }
- function loop() {
- loopPoints.forEach(loopPoint => {
- const {
- target,
- translate,
- slideLocation
- } = loopPoint;
- const shiftLocation = target();
- if (shiftLocation === slideLocation.get()) return;
- translate.to(shiftLocation);
- slideLocation.set(shiftLocation);
- });
- }
- function clear() {
- loopPoints.forEach(loopPoint => loopPoint.translate.clear());
- }
- const self = {
- canLoop,
- clear,
- loop,
- loopPoints
- };
- return self;
- }
- function SlidesHandler(container, eventHandler, watchSlides) {
- let mutationObserver;
- let destroyed = false;
- function init(emblaApi) {
- if (!watchSlides) return;
- function defaultCallback(mutations) {
- for (const mutation of mutations) {
- if (mutation.type === 'childList') {
- emblaApi.reInit();
- eventHandler.emit('slidesChanged');
- break;
- }
- }
- }
- mutationObserver = new MutationObserver(mutations => {
- if (destroyed) return;
- if (isBoolean(watchSlides) || watchSlides(emblaApi, mutations)) {
- defaultCallback(mutations);
- }
- });
- mutationObserver.observe(container, {
- childList: true
- });
- }
- function destroy() {
- if (mutationObserver) mutationObserver.disconnect();
- destroyed = true;
- }
- const self = {
- init,
- destroy
- };
- return self;
- }
- function SlidesInView(container, slides, eventHandler, threshold) {
- const intersectionEntryMap = {};
- let inViewCache = null;
- let notInViewCache = null;
- let intersectionObserver;
- let destroyed = false;
- function init() {
- intersectionObserver = new IntersectionObserver(entries => {
- if (destroyed) return;
- entries.forEach(entry => {
- const index = slides.indexOf(entry.target);
- intersectionEntryMap[index] = entry;
- });
- inViewCache = null;
- notInViewCache = null;
- eventHandler.emit('slidesInView');
- }, {
- root: container.parentElement,
- threshold
- });
- slides.forEach(slide => intersectionObserver.observe(slide));
- }
- function destroy() {
- if (intersectionObserver) intersectionObserver.disconnect();
- destroyed = true;
- }
- function createInViewList(inView) {
- return objectKeys(intersectionEntryMap).reduce((list, slideIndex) => {
- const index = parseInt(slideIndex);
- const {
- isIntersecting
- } = intersectionEntryMap[index];
- const inViewMatch = inView && isIntersecting;
- const notInViewMatch = !inView && !isIntersecting;
- if (inViewMatch || notInViewMatch) list.push(index);
- return list;
- }, []);
- }
- function get(inView = true) {
- if (inView && inViewCache) return inViewCache;
- if (!inView && notInViewCache) return notInViewCache;
- const slideIndexes = createInViewList(inView);
- if (inView) inViewCache = slideIndexes;
- if (!inView) notInViewCache = slideIndexes;
- return slideIndexes;
- }
- const self = {
- init,
- destroy,
- get
- };
- return self;
- }
- function SlideSizes(axis, containerRect, slideRects, slides, readEdgeGap, ownerWindow) {
- const {
- measureSize,
- startEdge,
- endEdge
- } = axis;
- const withEdgeGap = slideRects[0] && readEdgeGap;
- const startGap = measureStartGap();
- const endGap = measureEndGap();
- const slideSizes = slideRects.map(measureSize);
- const slideSizesWithGaps = measureWithGaps();
- function measureStartGap() {
- if (!withEdgeGap) return 0;
- const slideRect = slideRects[0];
- return mathAbs(containerRect[startEdge] - slideRect[startEdge]);
- }
- function measureEndGap() {
- if (!withEdgeGap) return 0;
- const style = ownerWindow.getComputedStyle(arrayLast(slides));
- return parseFloat(style.getPropertyValue(`margin-${endEdge}`));
- }
- function measureWithGaps() {
- return slideRects.map((rect, index, rects) => {
- const isFirst = !index;
- const isLast = arrayIsLastIndex(rects, index);
- if (isFirst) return slideSizes[index] + startGap;
- if (isLast) return slideSizes[index] + endGap;
- return rects[index + 1][startEdge] - rect[startEdge];
- }).map(mathAbs);
- }
- const self = {
- slideSizes,
- slideSizesWithGaps,
- startGap,
- endGap
- };
- return self;
- }
- function SlidesToScroll(axis, viewSize, slidesToScroll, loop, containerRect, slideRects, startGap, endGap, pixelTolerance) {
- const {
- startEdge,
- endEdge,
- direction
- } = axis;
- const groupByNumber = isNumber(slidesToScroll);
- function byNumber(array, groupSize) {
- return arrayKeys(array).filter(i => i % groupSize === 0).map(i => array.slice(i, i + groupSize));
- }
- function bySize(array) {
- if (!array.length) return [];
- return arrayKeys(array).reduce((groups, rectB, index) => {
- const rectA = arrayLast(groups) || 0;
- const isFirst = rectA === 0;
- const isLast = rectB === arrayLastIndex(array);
- const edgeA = containerRect[startEdge] - slideRects[rectA][startEdge];
- const edgeB = containerRect[startEdge] - slideRects[rectB][endEdge];
- const gapA = !loop && isFirst ? direction(startGap) : 0;
- const gapB = !loop && isLast ? direction(endGap) : 0;
- const chunkSize = mathAbs(edgeB - gapB - (edgeA + gapA));
- if (index && chunkSize > viewSize + pixelTolerance) groups.push(rectB);
- if (isLast) groups.push(array.length);
- return groups;
- }, []).map((currentSize, index, groups) => {
- const previousSize = Math.max(groups[index - 1] || 0);
- return array.slice(previousSize, currentSize);
- });
- }
- function groupSlides(array) {
- return groupByNumber ? byNumber(array, slidesToScroll) : bySize(array);
- }
- const self = {
- groupSlides
- };
- return self;
- }
- function Engine(root, container, slides, ownerDocument, ownerWindow, options, eventHandler) {
- // Options
- const {
- align,
- axis: scrollAxis,
- direction,
- startIndex,
- loop,
- duration,
- dragFree,
- dragThreshold,
- inViewThreshold,
- slidesToScroll: groupSlides,
- skipSnaps,
- containScroll,
- watchResize,
- watchSlides,
- watchDrag,
- watchFocus
- } = options;
- // Measurements
- const pixelTolerance = 2;
- const nodeRects = NodeRects();
- const containerRect = nodeRects.measure(container);
- const slideRects = slides.map(nodeRects.measure);
- const axis = Axis(scrollAxis, direction);
- const viewSize = axis.measureSize(containerRect);
- const percentOfView = PercentOfView(viewSize);
- const alignment = Alignment(align, viewSize);
- const containSnaps = !loop && !!containScroll;
- const readEdgeGap = loop || !!containScroll;
- const {
- slideSizes,
- slideSizesWithGaps,
- startGap,
- endGap
- } = SlideSizes(axis, containerRect, slideRects, slides, readEdgeGap, ownerWindow);
- const slidesToScroll = SlidesToScroll(axis, viewSize, groupSlides, loop, containerRect, slideRects, startGap, endGap, pixelTolerance);
- const {
- snaps,
- snapsAligned
- } = ScrollSnaps(axis, alignment, containerRect, slideRects, slidesToScroll);
- const contentSize = -arrayLast(snaps) + arrayLast(slideSizesWithGaps);
- const {
- snapsContained,
- scrollContainLimit
- } = ScrollContain(viewSize, contentSize, snapsAligned, containScroll, pixelTolerance);
- const scrollSnaps = containSnaps ? snapsContained : snapsAligned;
- const {
- limit
- } = ScrollLimit(contentSize, scrollSnaps, loop);
- // Indexes
- const index = Counter(arrayLastIndex(scrollSnaps), startIndex, loop);
- const indexPrevious = index.clone();
- const slideIndexes = arrayKeys(slides);
- // Animation
- const update = ({
- dragHandler,
- scrollBody,
- scrollBounds,
- options: {
- loop
- }
- }) => {
- if (!loop) scrollBounds.constrain(dragHandler.pointerDown());
- scrollBody.seek();
- };
- const render = ({
- scrollBody,
- translate,
- location,
- offsetLocation,
- previousLocation,
- scrollLooper,
- slideLooper,
- dragHandler,
- animation,
- eventHandler,
- scrollBounds,
- options: {
- loop
- }
- }, alpha) => {
- const shouldSettle = scrollBody.settled();
- const withinBounds = !scrollBounds.shouldConstrain();
- const hasSettled = loop ? shouldSettle : shouldSettle && withinBounds;
- const hasSettledAndIdle = hasSettled && !dragHandler.pointerDown();
- if (hasSettledAndIdle) animation.stop();
- const interpolatedLocation = location.get() * alpha + previousLocation.get() * (1 - alpha);
- offsetLocation.set(interpolatedLocation);
- if (loop) {
- scrollLooper.loop(scrollBody.direction());
- slideLooper.loop();
- }
- translate.to(offsetLocation.get());
- if (hasSettledAndIdle) eventHandler.emit('settle');
- if (!hasSettled) eventHandler.emit('scroll');
- };
- const animation = Animations(ownerDocument, ownerWindow, () => update(engine), alpha => render(engine, alpha));
- // Shared
- const friction = 0.68;
- const startLocation = scrollSnaps[index.get()];
- const location = Vector1D(startLocation);
- const previousLocation = Vector1D(startLocation);
- const offsetLocation = Vector1D(startLocation);
- const target = Vector1D(startLocation);
- const scrollBody = ScrollBody(location, offsetLocation, previousLocation, target, duration, friction);
- const scrollTarget = ScrollTarget(loop, scrollSnaps, contentSize, limit, target);
- const scrollTo = ScrollTo(animation, index, indexPrevious, scrollBody, scrollTarget, target, eventHandler);
- const scrollProgress = ScrollProgress(limit);
- const eventStore = EventStore();
- const slidesInView = SlidesInView(container, slides, eventHandler, inViewThreshold);
- const {
- slideRegistry
- } = SlideRegistry(containSnaps, containScroll, scrollSnaps, scrollContainLimit, slidesToScroll, slideIndexes);
- const slideFocus = SlideFocus(root, slides, slideRegistry, scrollTo, scrollBody, eventStore, eventHandler, watchFocus);
- // Engine
- const engine = {
- ownerDocument,
- ownerWindow,
- eventHandler,
- containerRect,
- slideRects,
- animation,
- axis,
- dragHandler: DragHandler(axis, root, ownerDocument, ownerWindow, target, DragTracker(axis, ownerWindow), location, animation, scrollTo, scrollBody, scrollTarget, index, eventHandler, percentOfView, dragFree, dragThreshold, skipSnaps, friction, watchDrag),
- eventStore,
- percentOfView,
- index,
- indexPrevious,
- limit,
- location,
- offsetLocation,
- previousLocation,
- options,
- resizeHandler: ResizeHandler(container, eventHandler, ownerWindow, slides, axis, watchResize, nodeRects),
- scrollBody,
- scrollBounds: ScrollBounds(limit, offsetLocation, target, scrollBody, percentOfView),
- scrollLooper: ScrollLooper(contentSize, limit, offsetLocation, [location, offsetLocation, previousLocation, target]),
- scrollProgress,
- scrollSnapList: scrollSnaps.map(scrollProgress.get),
- scrollSnaps,
- scrollTarget,
- scrollTo,
- slideLooper: SlideLooper(axis, viewSize, contentSize, slideSizes, slideSizesWithGaps, snaps, scrollSnaps, offsetLocation, slides),
- slideFocus,
- slidesHandler: SlidesHandler(container, eventHandler, watchSlides),
- slidesInView,
- slideIndexes,
- slideRegistry,
- slidesToScroll,
- target,
- translate: Translate(axis, container)
- };
- return engine;
- }
- function EventHandler() {
- let listeners = {};
- let api;
- function init(emblaApi) {
- api = emblaApi;
- }
- function getListeners(evt) {
- return listeners[evt] || [];
- }
- function emit(evt) {
- getListeners(evt).forEach(e => e(api, evt));
- return self;
- }
- function on(evt, cb) {
- listeners[evt] = getListeners(evt).concat([cb]);
- return self;
- }
- function off(evt, cb) {
- listeners[evt] = getListeners(evt).filter(e => e !== cb);
- return self;
- }
- function clear() {
- listeners = {};
- }
- const self = {
- init,
- emit,
- off,
- on,
- clear
- };
- return self;
- }
- const defaultOptions = {
- align: 'center',
- axis: 'x',
- container: null,
- slides: null,
- containScroll: 'trimSnaps',
- direction: 'ltr',
- slidesToScroll: 1,
- inViewThreshold: 0,
- breakpoints: {},
- dragFree: false,
- dragThreshold: 10,
- loop: false,
- skipSnaps: false,
- duration: 25,
- startIndex: 0,
- active: true,
- watchDrag: true,
- watchResize: true,
- watchSlides: true,
- watchFocus: true
- };
- function OptionsHandler(ownerWindow) {
- function mergeOptions(optionsA, optionsB) {
- return objectsMergeDeep(optionsA, optionsB || {});
- }
- function optionsAtMedia(options) {
- const optionsAtMedia = options.breakpoints || {};
- const matchedMediaOptions = objectKeys(optionsAtMedia).filter(media => ownerWindow.matchMedia(media).matches).map(media => optionsAtMedia[media]).reduce((a, mediaOption) => mergeOptions(a, mediaOption), {});
- return mergeOptions(options, matchedMediaOptions);
- }
- function optionsMediaQueries(optionsList) {
- return optionsList.map(options => objectKeys(options.breakpoints || {})).reduce((acc, mediaQueries) => acc.concat(mediaQueries), []).map(ownerWindow.matchMedia);
- }
- const self = {
- mergeOptions,
- optionsAtMedia,
- optionsMediaQueries
- };
- return self;
- }
- function PluginsHandler(optionsHandler) {
- let activePlugins = [];
- function init(emblaApi, plugins) {
- activePlugins = plugins.filter(({
- options
- }) => optionsHandler.optionsAtMedia(options).active !== false);
- activePlugins.forEach(plugin => plugin.init(emblaApi, optionsHandler));
- return plugins.reduce((map, plugin) => Object.assign(map, {
- [plugin.name]: plugin
- }), {});
- }
- function destroy() {
- activePlugins = activePlugins.filter(plugin => plugin.destroy());
- }
- const self = {
- init,
- destroy
- };
- return self;
- }
- function EmblaCarousel(root, userOptions, userPlugins) {
- const ownerDocument = root.ownerDocument;
- const ownerWindow = ownerDocument.defaultView;
- const optionsHandler = OptionsHandler(ownerWindow);
- const pluginsHandler = PluginsHandler(optionsHandler);
- const mediaHandlers = EventStore();
- const eventHandler = EventHandler();
- const {
- mergeOptions,
- optionsAtMedia,
- optionsMediaQueries
- } = optionsHandler;
- const {
- on,
- off,
- emit
- } = eventHandler;
- const reInit = reActivate;
- let destroyed = false;
- let engine;
- let optionsBase = mergeOptions(defaultOptions, EmblaCarousel.globalOptions);
- let options = mergeOptions(optionsBase);
- let pluginList = [];
- let pluginApis;
- let container;
- let slides;
- function storeElements() {
- const {
- container: userContainer,
- slides: userSlides
- } = options;
- const customContainer = isString(userContainer) ? root.querySelector(userContainer) : userContainer;
- container = customContainer || root.children[0];
- const customSlides = isString(userSlides) ? container.querySelectorAll(userSlides) : userSlides;
- slides = [].slice.call(customSlides || container.children);
- }
- function createEngine(options) {
- const engine = Engine(root, container, slides, ownerDocument, ownerWindow, options, eventHandler);
- if (options.loop && !engine.slideLooper.canLoop()) {
- const optionsWithoutLoop = Object.assign({}, options, {
- loop: false
- });
- return createEngine(optionsWithoutLoop);
- }
- return engine;
- }
- function activate(withOptions, withPlugins) {
- if (destroyed) return;
- optionsBase = mergeOptions(optionsBase, withOptions);
- options = optionsAtMedia(optionsBase);
- pluginList = withPlugins || pluginList;
- storeElements();
- engine = createEngine(options);
- optionsMediaQueries([optionsBase, ...pluginList.map(({
- options
- }) => options)]).forEach(query => mediaHandlers.add(query, 'change', reActivate));
- if (!options.active) return;
- engine.translate.to(engine.location.get());
- engine.animation.init();
- engine.slidesInView.init();
- engine.slideFocus.init(self);
- engine.eventHandler.init(self);
- engine.resizeHandler.init(self);
- engine.slidesHandler.init(self);
- if (engine.options.loop) engine.slideLooper.loop();
- if (container.offsetParent && slides.length) engine.dragHandler.init(self);
- pluginApis = pluginsHandler.init(self, pluginList);
- }
- function reActivate(withOptions, withPlugins) {
- const startIndex = selectedScrollSnap();
- deActivate();
- activate(mergeOptions({
- startIndex
- }, withOptions), withPlugins);
- eventHandler.emit('reInit');
- }
- function deActivate() {
- engine.dragHandler.destroy();
- engine.eventStore.clear();
- engine.translate.clear();
- engine.slideLooper.clear();
- engine.resizeHandler.destroy();
- engine.slidesHandler.destroy();
- engine.slidesInView.destroy();
- engine.animation.destroy();
- pluginsHandler.destroy();
- mediaHandlers.clear();
- }
- function destroy() {
- if (destroyed) return;
- destroyed = true;
- mediaHandlers.clear();
- deActivate();
- eventHandler.emit('destroy');
- eventHandler.clear();
- }
- function scrollTo(index, jump, direction) {
- if (!options.active || destroyed) return;
- engine.scrollBody.useBaseFriction().useDuration(jump === true ? 0 : options.duration);
- engine.scrollTo.index(index, direction || 0);
- }
- function scrollNext(jump) {
- const next = engine.index.add(1).get();
- scrollTo(next, jump, -1);
- }
- function scrollPrev(jump) {
- const prev = engine.index.add(-1).get();
- scrollTo(prev, jump, 1);
- }
- function canScrollNext() {
- const next = engine.index.add(1).get();
- return next !== selectedScrollSnap();
- }
- function canScrollPrev() {
- const prev = engine.index.add(-1).get();
- return prev !== selectedScrollSnap();
- }
- function scrollSnapList() {
- return engine.scrollSnapList;
- }
- function scrollProgress() {
- return engine.scrollProgress.get(engine.offsetLocation.get());
- }
- function selectedScrollSnap() {
- return engine.index.get();
- }
- function previousScrollSnap() {
- return engine.indexPrevious.get();
- }
- function slidesInView() {
- return engine.slidesInView.get();
- }
- function slidesNotInView() {
- return engine.slidesInView.get(false);
- }
- function plugins() {
- return pluginApis;
- }
- function internalEngine() {
- return engine;
- }
- function rootNode() {
- return root;
- }
- function containerNode() {
- return container;
- }
- function slideNodes() {
- return slides;
- }
- const self = {
- canScrollNext,
- canScrollPrev,
- containerNode,
- internalEngine,
- destroy,
- off,
- on,
- emit,
- plugins,
- previousScrollSnap,
- reInit,
- rootNode,
- scrollNext,
- scrollPrev,
- scrollProgress,
- scrollSnapList,
- scrollTo,
- selectedScrollSnap,
- slideNodes,
- slidesInView,
- slidesNotInView
- };
- activate(userOptions, userPlugins);
- setTimeout(() => eventHandler.emit('init'), 0);
- return self;
- }
- EmblaCarousel.globalOptions = undefined;
- module.exports = EmblaCarousel;
- //# sourceMappingURL=embla-carousel.cjs.js.map
|