vendor: 3,739 bytes, lines 1-113
1/** 2 * Swiper 14.0.7 3 * Most modern mobile touch slider and framework with hardware accelerated transitions 4 * https://swiperjs.com 5 * 6 * Copyright 2014-2026 Vladimir Kharlampidi 7 * 8 * Released under the MIT License 9 * 10 * Released on: July 28, 2026 11 */ 12 13var Swiper = (function () { 14 'use strict'; 15 16 function classesToTokens(classes = '') { 17 return classes 18 .trim() 19 .split(' ') 20 .filter((c) => !!c.trim()); 21 } 22 23 function deleteProps(obj) { 24 Object.keys(obj).forEach((key) => { 25 try { 26 obj[key] = null; 27 } 28 catch { 29 // no getter for object 30 } 31 try { 32 delete obj[key]; 33 } 34 catch { 35 // something got wrong 36 } 37 }); 38 } 39 function nextTick(callback, delay = 0) { 40 return setTimeout(callback, delay); 41 } 42 function now() { 43 return Date.now(); 44 } 45 function getComputedStyle$1(el) { 46 return window.getComputedStyle(el, null); 47 } 48 function getTranslate(el, axis = 'x') { 49 const style = getComputedStyle$1(el); 50 const transform = style.transform || style.webkitTransform; 51 if (!transform || transform === 'none') 52 return 0; 53 const matrix = new DOMMatrixReadOnly(transform); 54 return axis === 'x' ? matrix.m41 : matrix.m42; 55 } 56 function isObject(o) { 57 return (typeof o === 'object' && 58 o !== null && 59 o.constructor === Object && 60 Object.prototype.toString.call(o).slice(8, -1) === 'Object'); 61 } 62 function isNode(node) { 63 if (typeof HTMLElement !== 'undefined' && node instanceof HTMLElement) 64 return true; 65 return (!!node && 66 typeof node === 'object' && 67 (node.nodeType === 1 || node.nodeType === 11)); 68 } 69 function extend(target, ...sources) { 70 const to = Object(target); 71 for (let i = 0; i < sources.length; i += 1) { 72 const nextSource = sources[i]; 73 if (nextSource === undefined || nextSource === null || isNode(nextSource)) 74 continue; 75 const sourceObj = nextSource; 76 const keysArray = Object.keys(Object(sourceObj)).filter((key) => key !== '__proto__' && key !== 'constructor' && key !== 'prototype'); 77 for (const nextKey of keysArray) { 78 const desc = Object.getOwnPropertyDescriptor(sourceObj, nextKey); 79 if (!desc || !desc.enumerable) 80 continue; 81 const sourceVal = sourceObj[nextKey]; 82 if (isObject(to[nextKey]) && isObject(sourceVal)) { 83 if (sourceVal.__swiper__) { 84 to[nextKey] = sourceVal; 85 } 86 else { 87 extend(to[nextKey], sourceVal); 88 } 89 } 90 else if (!isObject(to[nextKey]) && isObject(sourceVal)) { 91 to[nextKey] = {}; 92 if (sourceVal.__swiper__) { 93 to[nextKey] = sourceVal; 94 } 95 else { 96 extend(to[nextKey], sourceVal); 97 } 98 } 99 else { 100 to[nextKey] = sourceVal; 101 } 102 } 103 } 104 return to; 105 } 106 function setCSSProperty(el, varName, varValue) { 107 el.style.setProperty(varName, varValue); 108 } 109 function getSlideTransformEl(slideEl) { 110 const direct = slideEl.querySelector('.swiper-slide-transform'); 111 if (direct) 112 return direct; 113 if (slideEl.shadowRoot) {
vendor: 8,514 bytes, lines 114-343
114 const shadowed = slideEl.shadowRoot.querySelector('.swiper-slide-transform'); 115 if (shadowed) 116 return shadowed; 117 } 118 return slideEl; 119 } 120 function elementChildren(element, selector = '') { 121 const children = [...element.children]; 122 if (element instanceof HTMLSlotElement) { 123 children.push(...element.assignedElements()); 124 } 125 return selector ? children.filter((el) => el.matches(selector)) : children; 126 } 127 function elementIsChildOfSlot(el, slot) { 128 const queue = [slot]; 129 while (queue.length > 0) { 130 const cur = queue.shift(); 131 if (el === cur) 132 return true; 133 queue.push(...cur.children, ...(cur.shadowRoot ? cur.shadowRoot.children : []), ...(cur.assignedElements 134 ? cur.assignedElements() 135 : [])); 136 } 137 return false; 138 } 139 function elementIsChildOf(el, parent) { 140 let isChild = parent.contains(el); 141 if (!isChild && parent instanceof HTMLSlotElement) { 142 const children = [...parent.assignedElements()]; 143 isChild = children.includes(el); 144 if (!isChild) 145 isChild = elementIsChildOfSlot(el, parent); 146 } 147 return isChild; 148 } 149 function showWarning(text) { 150 try { 151 console.warn(text); 152 } 153 catch { 154 // err 155 } 156 } 157 function createElement(tag, classes = []) { 158 const el = document.createElement(tag); 159 el.classList.add(...(Array.isArray(classes) ? classes : classesToTokens(classes))); 160 return el; 161 } 162 function elementOffset(el) { 163 const box = el.getBoundingClientRect(); 164 return { 165 top: box.top + window.scrollY - (el.clientTop || 0), 166 left: box.left + window.scrollX - (el.clientLeft || 0), 167 }; 168 } 169 function elementPrevAll(el, selector) { 170 const prevEls = []; 171 let prev = el.previousElementSibling; 172 while (prev) { 173 if (!selector || prev.matches(selector)) 174 prevEls.push(prev); 175 prev = prev.previousElementSibling; 176 } 177 return prevEls; 178 } 179 function elementNextAll(el, selector) { 180 const nextEls = []; 181 let next = el.nextElementSibling; 182 while (next) { 183 if (!selector || next.matches(selector)) 184 nextEls.push(next); 185 next = next.nextElementSibling; 186 } 187 return nextEls; 188 } 189 function elementStyle(el, prop) { 190 return window.getComputedStyle(el, null).getPropertyValue(prop); 191 } 192 function elementIndex(el) { 193 if (!el || !el.parentNode) 194 return undefined; 195 return [...el.parentNode.children].indexOf(el); 196 } 197 function elementParents(el, selector) { 198 const parents = []; 199 let parent = el.parentElement; 200 while (parent) { 201 if (!selector || parent.matches(selector)) 202 parents.push(parent); 203 parent = parent.parentElement; 204 } 205 return parents; 206 } 207 function elementTransitionEnd(el, callback) { 208 if (!callback) 209 return; 210 el.addEventListener('transitionend', function fireCallBack(e) { 211 if (e.target !== el) 212 return; 213 callback.call(el, e); 214 }, { once: true }); 215 } 216 function elementOuterSize(el, size, includeMargins) { 217 { 218 const style = window.getComputedStyle(el, null); 219 return (el[size === 'width' ? 'offsetWidth' : 'offsetHeight'] + 220 parseFloat(style.getPropertyValue(size === 'width' ? 'margin-right' : 'margin-top')) + 221 parseFloat(style.getPropertyValue(size === 'width' ? 'margin-left' : 'margin-bottom'))); 222 } 223 } 224 function makeElementsArray(el) { 225 return (Array.isArray(el) ? el : [el]).filter((e) => !!e); 226 } 227 function getRotateFix(swiper) { 228 return (v) => { 229 if (Math.abs(v) > 0 && swiper.browser && swiper.browser.need3dFix && Math.abs(v) % 90 === 0) { 230 return v + 0.001; 231 } 232 return v; 233 }; 234 } 235 function setInnerHTML(el, html = '') { 236 const tt = globalThis.trustedTypes; 237 if (typeof tt !== 'undefined') { 238 el.innerHTML = tt.createPolicy('html', { createHTML: (s) => s }).createHTML(html); 239 } 240 else { 241 el.innerHTML = html; 242 } 243 } 244 245 let supportCached; 246 function calcSupport() { 247 if (typeof window === 'undefined') 248 return { touch: false }; 249 return { 250 touch: 'ontouchstart' in window || navigator.maxTouchPoints > 0, 251 }; 252 } 253 function getSupport() { 254 if (!supportCached) 255 supportCached = calcSupport(); 256 return supportCached; 257 } 258 259 let deviceCached; 260 function calcDevice({ userAgent } = {}) { 261 if (typeof window === 'undefined') 262 return { ios: false, android: false }; 263 const support = getSupport(); 264 const platform = navigator.platform; 265 const ua = userAgent || navigator.userAgent; 266 const device = { ios: false, android: false }; 267 const isAndroid = /(Android);?[\s/]+([\d.]+)?/.test(ua); 268 const isIPhoneOrIPod = /(iPhone\sOS|iOS|iPod)/.test(ua); 269 const isIPadDirect = /iPad/.test(ua); 270 // iPad on iPadOS 13+ reports as MacIntel; distinguish from a real Mac by touch capability. 271 const isIPadMasquerade = platform === 'MacIntel' && support.touch && navigator.maxTouchPoints > 1; 272 const isIPad = isIPadDirect || isIPadMasquerade; 273 const isWindows = platform === 'Win32'; 274 if (isAndroid && !isWindows) { 275 device.os = 'android'; 276 device.android = true; 277 } 278 if (isIPad || isIPhoneOrIPod) { 279 device.os = 'ios'; 280 device.ios = true; 281 } 282 return device; 283 } 284 function getDevice(overrides = {}) { 285 if (!deviceCached) 286 deviceCached = calcDevice(overrides); 287 return deviceCached; 288 } 289 290 let browserCached; 291 function calcBrowser() { 292 if (typeof window === 'undefined') { 293 return { isSafari: false, isWebView: false, need3dFix: false }; 294 } 295 const device = getDevice(); 296 const ua = navigator.userAgent; 297 const uaLower = ua.toLowerCase(); 298 const isSafari = uaLower.includes('safari') && !uaLower.includes('chrome') && !uaLower.includes('android'); 299 const isWebView = /(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(ua); 300 // 3D transform glitches still affect iOS WebView and Safari at the baseline (16.4+). 301 const need3dFix = isSafari || (isWebView && device.ios); 302 return { isSafari, isWebView, need3dFix }; 303 } 304 function getBrowser() { 305 if (!browserCached) 306 browserCached = calcBrowser(); 307 return browserCached; 308 } 309 310 const processLazyPreloader = (swiper, imageEl) => { 311 if (!swiper || swiper.destroyed || !swiper.params) 312 return; 313 const slideSelector = () => (swiper.isElement ? 'swiper-slide' : `.${swiper.params.slideClass}`); 314 const slideEl = imageEl.closest(slideSelector()); 315 if (slideEl) { 316 let lazyEl = slideEl.querySelector(`.${swiper.params.lazyPreloaderClass}`); 317 if (!lazyEl && swiper.isElement) { 318 if (slideEl.shadowRoot) { 319 lazyEl = slideEl.shadowRoot.querySelector(`.${swiper.params.lazyPreloaderClass}`); 320 } 321 else { 322 requestAnimationFrame(() => { 323 if (slideEl.shadowRoot) { 324 const innerLazy = slideEl.shadowRoot.querySelector(`.${swiper.params.lazyPreloaderClass}`); 325 if (innerLazy && !innerLazy.lazyPreloaderManaged) 326 innerLazy.remove(); 327 } 328 }); 329 } 330 } 331 if (lazyEl && !lazyEl.lazyPreloaderManaged) 332 lazyEl.remove(); 333 } 334 }; 335 const unlazy = (swiper, index) => { 336 if (!swiper.slides[index]) 337 return; 338 const imageEl = swiper.slides[index].querySelector('[loading="lazy"]'); 339 if (imageEl) 340 imageEl.removeAttribute('loading'); 341 }; 342 const preload = (swiper) => { 343 if (!swiper || swiper.destroyed || !swiper.params
vendor: 2,012 bytes, lines 343-385
343) 344 return; 345 let amount = swiper.params.lazyPreloadPrevNext; 346 const len = swiper.slides.length; 347 if (!len || !amount || amount < 0) 348 return; 349 amount = Math.min(amount, len); 350 const slidesPerView = swiper.params.slidesPerView === 'auto' 351 ? swiper.slidesPerViewDynamic() 352 : Math.ceil(swiper.params.slidesPerView); 353 const activeIndex = swiper.activeIndex; 354 if (swiper.params.grid && (swiper.params.grid.rows ?? 1) > 1) { 355 const activeColumn = activeIndex; 356 const preloadColumns = [activeColumn - amount]; 357 preloadColumns.push(...Array.from({ length: amount }).map((_, i) => activeColumn + slidesPerView + i)); 358 swiper.slides.forEach((slideEl, i) => { 359 if (slideEl.column !== undefined && preloadColumns.includes(slideEl.column)) 360 unlazy(swiper, i); 361 }); 362 return; 363 } 364 const slideIndexLastInView = activeIndex + slidesPerView - 1; 365 if (swiper.params.rewind || swiper.params.loop) { 366 for (let i = activeIndex - amount; i <= slideIndexLastInView + amount; i += 1) { 367 const realIndex = ((i % len) + len) % len; 368 if (realIndex < activeIndex || realIndex > slideIndexLastInView) 369 unlazy(swiper, realIndex); 370 } 371 } 372 else { 373 for (let i = Math.max(activeIndex - amount, 0); i <= Math.min(slideIndexLastInView + amount, len - 1); i += 1) { 374 if (i !== activeIndex && (i > slideIndexLastInView || i < activeIndex)) { 375 unlazy(swiper, i); 376 } 377 } 378 } 379 }; 380 381 function getBreakpoint(breakpoints, base = 'window', containerEl) { 382 if (!breakpoints || (base === 'container' && !containerEl)) 383 return undefined; 384 let breakpoint = false; 385 const currentHeight = base === 'window' ? window.innerHeight : containerEl.clientHeight;
vendor: 50,109 bytes, lines 386-1664
386 const points = Object.keys(breakpoints).map((point) => { 387 if (typeof point === 'string' && point.indexOf('@') === 0) { 388 const minRatio = parseFloat(point.substr(1)); 389 const value = currentHeight * minRatio; 390 return { value, point }; 391 } 392 return { value: point, point }; 393 }); 394 points.sort((a, b) => parseInt(String(a.value), 10) - parseInt(String(b.value), 10)); 395 for (let i = 0; i < points.length; i += 1) { 396 const { point, value } = points[i]; 397 if (base === 'window') { 398 if (window.matchMedia(`(min-width: ${value}px)`).matches) { 399 breakpoint = point; 400 } 401 } 402 else if (value <= containerEl.clientWidth) { 403 breakpoint = point; 404 } 405 } 406 return breakpoint || 'max'; 407 } 408 409 const isGridEnabled = (swiper, params) => { 410 return !!(swiper.grid && params.grid && params.grid.rows > 1); 411 }; 412 function setBreakpoint() { 413 const swiper = this; 414 const { realIndex, initialized, params, el } = swiper; 415 const breakpoints = params.breakpoints; 416 if (!breakpoints || (breakpoints && Object.keys(breakpoints).length === 0)) 417 return; 418 // Get breakpoint for window/container width and update parameters 419 const breakpointsBase = params.breakpointsBase === 'window' || !params.breakpointsBase 420 ? params.breakpointsBase 421 : 'container'; 422 const breakpointContainer = ['window', 'container'].includes(params.breakpointsBase) || !params.breakpointsBase 423 ? swiper.el 424 : document.querySelector(params.breakpointsBase); 425 const breakpoint = swiper.getBreakpoint(breakpoints, breakpointsBase, breakpointContainer); 426 if (!breakpoint || swiper.currentBreakpoint === breakpoint) 427 return; 428 const breakpointsRecord = breakpoints; 429 const breakpointOnlyParams = breakpoint in breakpointsRecord ? breakpointsRecord[breakpoint] : undefined; 430 const breakpointParams = breakpointOnlyParams || swiper.originalParams; 431 const wasMultiRow = isGridEnabled(swiper, params); 432 const isMultiRow = isGridEnabled(swiper, breakpointParams); 433 const wasGrabCursor = swiper.params.grabCursor; 434 const isGrabCursor = breakpointParams.grabCursor; 435 const wasEnabled = params.enabled; 436 if (wasMultiRow && !isMultiRow) { 437 el.classList.remove(`${params.containerModifierClass}grid`, `${params.containerModifierClass}grid-column`); 438 swiper.emitContainerClasses(); 439 } 440 else if (!wasMultiRow && isMultiRow) { 441 el.classList.add(`${params.containerModifierClass}grid`); 442 if ((breakpointParams.grid.fill && breakpointParams.grid.fill === 'column') || 443 (!breakpointParams.grid.fill && params.grid.fill === 'column')) { 444 el.classList.add(`${params.containerModifierClass}grid-column`); 445 } 446 swiper.emitContainerClasses(); 447 } 448 if (wasGrabCursor && !isGrabCursor) { 449 swiper.unsetGrabCursor(); 450 } 451 else if (!wasGrabCursor && isGrabCursor) { 452 swiper.setGrabCursor(); 453 } 454 const moduleOpt = (opts, prop) => opts[prop]; 455 ['navigation', 'pagination', 'scrollbar'].forEach((prop) => { 456 const bpOpts = moduleOpt(breakpointParams, prop); 457 if (typeof bpOpts === 'undefined') 458 return; 459 const paramsOpts = moduleOpt(params, prop); 460 const wasModuleEnabled = typeof paramsOpts === 'object' && paramsOpts !== null && paramsOpts.enabled; 461 const isModuleEnabled = typeof bpOpts === 'object' && bpOpts !== null && bpOpts.enabled; 462 const moduleApi = swiper[prop]; 463 if (wasModuleEnabled && !isModuleEnabled) 464 moduleApi?.disable?.(); 465 if (!wasModuleEnabled && isModuleEnabled) 466 moduleApi?.enable?.(); 467 }); 468 const directionChanged = breakpointParams.direction && breakpointParams.direction !== params.direction; 469 const needsReLoop = params.loop && (breakpointParams.slidesPerView !== params.slidesPerView || directionChanged); 470 const wasLoop = params.loop; 471 if (directionChanged && initialized) { 472 swiper.changeDirection(); 473 } 474 extend(swiper.params, breakpointParams); 475 const isEnabled = swiper.params.enabled; 476 const hasLoop = swiper.params.loop; 477 Object.assign(swiper, { 478 allowTouchMove: swiper.params.allowTouchMove, 479 allowSlideNext: swiper.params.allowSlideNext, 480 allowSlidePrev: swiper.params.allowSlidePrev, 481 }); 482 if (wasEnabled && !isEnabled) { 483 swiper.disable(); 484 } 485 else if (!wasEnabled && isEnabled) { 486 swiper.enable(); 487 } 488 swiper.currentBreakpoint = breakpoint; 489 swiper.emit('_beforeBreakpoint', breakpointParams); 490 if (initialized) { 491 if (needsReLoop) { 492 swiper.loopDestroy(); 493 swiper.loopCreate(realIndex); 494 swiper.updateSlides(); 495 } 496 else if (!wasLoop && hasLoop) { 497 swiper.loopCreate(realIndex); 498 swiper.updateSlides(); 499 } 500 else if (wasLoop && !hasLoop) { 501 swiper.loopDestroy(); 502 } 503 } 504 swiper.emit('breakpoint', breakpointParams); 505 } 506 507 var breakpoints = { setBreakpoint, getBreakpoint }; 508 509 function checkOverflow() { 510 const swiper = this; 511 const { isLocked: wasLocked, params } = swiper; 512 const { slidesOffsetBefore } = params; 513 if (slidesOffsetBefore) { 514 const lastSlideIndex = swiper.slides.length - 1; 515 const lastSlideRightEdge = swiper.slidesGrid[lastSlideIndex] + 516 swiper.slidesSizesGrid[lastSlideIndex] + 517 slidesOffsetBefore * 2; 518 swiper.isLocked = swiper.size > lastSlideRightEdge; 519 } 520 else { 521 swiper.isLocked = swiper.snapGrid.length === 1; 522 } 523 if (params.allowSlideNext === true) { 524 swiper.allowSlideNext = !swiper.isLocked; 525 } 526 if (params.allowSlidePrev === true) { 527 swiper.allowSlidePrev = !swiper.isLocked; 528 } 529 if (wasLocked && wasLocked !== swiper.isLocked) { 530 swiper.isEnd = false; 531 } 532 if (wasLocked !== swiper.isLocked) { 533 swiper.emit(swiper.isLocked ? 'lock' : 'unlock'); 534 } 535 } 536 var checkOverflow$1 = { checkOverflow }; 537 538 function prepareClasses(entries, prefix) { 539 const resultClasses = []; 540 entries.forEach((item) => { 541 if (typeof item === 'object') { 542 Object.keys(item).forEach((classNames) => { 543 if (item[classNames]) { 544 resultClasses.push(prefix + classNames); 545 } 546 }); 547 } 548 else if (typeof item === 'string') { 549 resultClasses.push(prefix + item); 550 } 551 }); 552 return resultClasses; 553 } 554 function addClasses() { 555 const swiper = this; 556 const { classNames, params, rtl, el, device } = swiper; 557 // oxfmt-ignore 558 const suffixes = prepareClasses([ 559 'initialized', 560 params.direction, 561 { 'free-mode': swiper.params.freeMode && params.freeMode.enabled }, 562 { 'autoheight': params.autoHeight }, 563 { 'rtl': rtl }, 564 { 'grid': params.grid && params.grid.rows > 1 }, 565 { 'grid-column': params.grid && params.grid.rows > 1 && params.grid.fill === 'column' }, 566 { 'android': device.android }, 567 { 'ios': device.ios }, 568 { 'css-mode': params.cssMode }, 569 { 'centered': params.cssMode && params.centeredSlides }, 570 { 'watch-progress': params.watchSlidesProgress }, 571 ], params.containerModifierClass); 572 classNames.push(...suffixes); 573 el.classList.add(...classNames); 574 swiper.emitContainerClasses(); 575 } 576 577 function removeClasses() { 578 const swiper = this; 579 const { el, classNames } = swiper; 580 if (!el || typeof el === 'string') 581 return; 582 el.classList.remove(...classNames); 583 swiper.emitContainerClasses(); 584 } 585 586 var classes = { addClasses, removeClasses }; 587 588 const defaults = { 589 init: true, 590 direction: 'horizontal', 591 oneWayMovement: false, 592 swiperElementNodeName: 'SWIPER-CONTAINER', 593 touchEventsTarget: 'wrapper', 594 initialSlide: 0, 595 speed: 300, 596 cssMode: false, 597 updateOnWindowResize: true, 598 resizeObserver: true, 599 nested: false, 600 createElements: false, 601 eventsPrefix: 'swiper', 602 enabled: true, 603 focusableElements: 'input, select, option, textarea, button, video, label', 604 // Overrides 605 width: null, 606 height: null, 607 // 608 preventInteractionOnTransition: false, 609 // ssr 610 userAgent: null, 611 url: null, 612 // To support iOS's swipe-to-go-back gesture (when being used in-app). 613 edgeSwipeDetection: false, 614 edgeSwipeThreshold: 20, 615 // Autoheight 616 autoHeight: false, 617 // Set wrapper width 618 setWrapperSize: false, 619 // Virtual Translate 620 virtualTranslate: false, 621 // Effects 622 effect: 'slide', 623 // Breakpoints 624 breakpoints: undefined, 625 breakpointsBase: 'window', 626 // Slides grid 627 spaceBetween: 0, 628 slidesPerView: 1, 629 slidesPerGroup: 1, 630 slidesPerGroupSkip: 0, 631 slidesPerGroupAuto: false, 632 centeredSlides: false, 633 centeredSlidesBounds: false, 634 slidesOffsetBefore: 0, 635 slidesOffsetAfter: 0, 636 normalizeSlideIndex: true, 637 centerInsufficientSlides: false, 638 snapToSlideEdge: false, 639 // Disable swiper and hide navigation when container not overflow 640 watchOverflow: true, 641 // Round length 642 roundLengths: false, 643 // Touches 644 touchRatio: 1, 645 touchAngle: 45, 646 simulateTouch: true, 647 shortSwipes: true, 648 longSwipes: true, 649 longSwipesRatio: 0.5, 650 longSwipesMs: 300, 651 followFinger: true, 652 allowTouchMove: true, 653 threshold: 5, 654 touchMoveStopPropagation: false, 655 touchStartPreventDefault: true, 656 touchStartForcePreventDefault: false, 657 touchReleaseOnEdges: false, 658 // Unique Navigation Elements 659 uniqueNavElements: true, 660 // Resistance 661 resistance: true, 662 resistanceRatio: 0.85, 663 // Progress 664 watchSlidesProgress: false, 665 // Cursor 666 grabCursor: false, 667 // Clicks 668 preventClicks: true, 669 preventClicksPropagation: true, 670 slideToClickedSlide: false, 671 // loop 672 loop: false, 673 loopAddBlankSlides: true, 674 loopAdditionalSlides: 0, 675 loopPreventsSliding: true, 676 // rewind 677 rewind: false, 678 // Swiping/no swiping 679 allowSlidePrev: true, 680 allowSlideNext: true, 681 swipeHandler: null, 682 noSwiping: true, 683 noSwipingClass: 'swiper-no-swiping', 684 noSwipingSelector: null, 685 // Passive Listeners 686 passiveListeners: true, 687 maxBackfaceHiddenSlides: 10, 688 // NS 689 containerModifierClass: 'swiper-', 690 slideClass: 'swiper-slide', 691 slideBlankClass: 'swiper-slide-blank', 692 slideActiveClass: 'swiper-slide-active', 693 slideVisibleClass: 'swiper-slide-visible', 694 slideFullyVisibleClass: 'swiper-slide-fully-visible', 695 slideNextClass: 'swiper-slide-next', 696 slidePrevClass: 'swiper-slide-prev', 697 wrapperClass: 'swiper-wrapper', 698 lazyPreloaderClass: 'swiper-lazy-preloader', 699 lazyPreloadPrevNext: 0, 700 // Callbacks 701 runCallbacksOnInit: true, 702 // Internals 703 _emitClasses: false, 704 }; 705 706 var eventsEmitter = { 707 on(events, handler, priority) { 708 const self = this; 709 if (!self.eventsListeners || self.destroyed) 710 return self; 711 if (typeof handler !== 'function') 712 return self; 713 const method = priority ? 'unshift' : 'push'; 714 events.split(' ').forEach((event) => { 715 if (!self.eventsListeners[event]) 716 self.eventsListeners[event] = []; 717 self.eventsListeners[event][method](handler); 718 }); 719 return self; 720 }, 721 once(events, handler, priority) { 722 const self = this; 723 if (!self.eventsListeners || self.destroyed) 724 return self; 725 if (typeof handler !== 'function') 726 return self; 727 const onceHandler = function onceHandlerFn(...args) { 728 self.off(events, onceHandler); 729 if (onceHandler.__emitterProxy) { 730 delete onceHandler.__emitterProxy; 731 } 732 handler.apply(self, args); 733 }; 734 onceHandler.__emitterProxy = handler; 735 return self.on(events, onceHandler, priority); 736 }, 737 onAny(handler, priority) { 738 const self = this; 739 if (!self.eventsListeners || self.destroyed) 740 return self; 741 if (typeof handler !== 'function') 742 return self; 743 const method = priority ? 'unshift' : 'push'; 744 if (self.eventsAnyListeners.indexOf(handler) < 0) { 745 self.eventsAnyListeners[method](handler); 746 } 747 return self; 748 }, 749 offAny(handler) { 750 const self = this; 751 if (!self.eventsListeners || self.destroyed) 752 return self; 753 if (!self.eventsAnyListeners) 754 return self; 755 const index = self.eventsAnyListeners.indexOf(handler); 756 if (index >= 0) { 757 self.eventsAnyListeners.splice(index, 1); 758 } 759 return self; 760 }, 761 off(events, handler) { 762 const self = this; 763 if (!self.eventsListeners || self.destroyed) 764 return self; 765 if (!self.eventsListeners) 766 return self; 767 events.split(' ').forEach((event) => { 768 if (typeof handler === 'undefined') { 769 self.eventsListeners[event] = []; 770 } 771 else if (self.eventsListeners[event]) { 772 self.eventsListeners[event].forEach((eventHandler, index) => { 773 if (eventHandler === handler || 774 (eventHandler.__emitterProxy && eventHandler.__emitterProxy === handler)) { 775 self.eventsListeners[event].splice(index, 1); 776 } 777 }); 778 } 779 }); 780 return self; 781 }, 782 emit(...args) { 783 const self = this; 784 if (!self.eventsListeners || self.destroyed) 785 return self; 786 if (!self.eventsListeners) 787 return self; 788 let events; 789 let data; 790 let context; 791 if (typeof args[0] === 'string' || Array.isArray(args[0])) { 792 events = args[0]; 793 data = args.slice(1, args.length); 794 context = self; 795 } 796 else { 797 const opts = args[0]; 798 events = opts.events; 799 data = opts.data ?? []; 800 context = opts.context || self; 801 } 802 data.unshift(context); 803 const eventsArray = Array.isArray(events) ? events : events.split(' '); 804 eventsArray.forEach((event) => { 805 if (self.eventsAnyListeners && self.eventsAnyListeners.length) { 806 self.eventsAnyListeners.forEach((eventHandler) => { 807 eventHandler.apply(context, [event, ...data]); 808 }); 809 } 810 if (self.eventsListeners && self.eventsListeners[event]) { 811 self.eventsListeners[event].forEach((eventHandler) => { 812 eventHandler.apply(context, data); 813 }); 814 } 815 }); 816 return self; 817 }, 818 }; 819 820 function onClick(e) { 821 const swiper = this; 822 if (swiper.destroyed) 823 return; 824 if (!swiper.enabled) 825 return; 826 if (!swiper.allowClick) { 827 if (swiper.params.preventClicks) 828 e.preventDefault(); 829 if (swiper.params.preventClicksPropagation && swiper.animating) { 830 e.stopPropagation(); 831 e.stopImmediatePropagation(); 832 } 833 } 834 } 835 836 function onDocumentTouchStart() { 837 const swiper = this; 838 if (swiper.destroyed) 839 return; 840 if (swiper.documentTouchHandlerProceeded) 841 return; 842 swiper.documentTouchHandlerProceeded = true; 843 if (swiper.params.touchReleaseOnEdges) { 844 swiper.el.style.touchAction = 'auto'; 845 } 846 } 847 848 function onLoad(e) { 849 const swiper = this; 850 if (swiper.destroyed) 851 return; 852 processLazyPreloader(swiper, e.target); 853 if (swiper.params.cssMode || 854 (swiper.params.slidesPerView !== 'auto' && !swiper.params.autoHeight)) { 855 return; 856 } 857 swiper.update(); 858 } 859 860 function onResize() { 861 const swiper = this; 862 const { params, el } = swiper; 863 if (el && el.offsetWidth === 0) 864 return; 865 // Breakpoints 866 if (params.breakpoints) { 867 swiper.setBreakpoint(); 868 } 869 // Save locks 870 const { allowSlideNext, allowSlidePrev, snapGrid } = swiper; 871 const isVirtual = swiper.virtual && swiper.params.virtual?.enabled; 872 // Disable locks on resize 873 swiper.allowSlideNext = true; 874 swiper.allowSlidePrev = true; 875 swiper.updateSize(); 876 swiper.updateSlides(); 877 swiper.updateSlidesClasses(); 878 const isVirtualLoop = isVirtual && params.loop; 879 if ((params.slidesPerView === 'auto' || params.slidesPerView > 1) && 880 swiper.isEnd && 881 !swiper.isBeginning && 882 !swiper.params.centeredSlides && 883 !isVirtualLoop) { 884 const slidesLength = isVirtual ? swiper.virtual.slides.length : swiper.slides.length; 885 swiper.slideTo(slidesLength - 1, 0, false, true); 886 } 887 else { 888 if (swiper.params.loop && !isVirtual) { 889 swiper.slideToLoop(swiper.realIndex, 0, false, true); 890 } 891 else { 892 swiper.slideTo(swiper.activeIndex, 0, false, true); 893 } 894 } 895 if (swiper.autoplay && swiper.autoplay.running && swiper.autoplay.paused) { 896 const autoplay = swiper.autoplay; 897 clearTimeout(autoplay.resizeTimeout); 898 autoplay.resizeTimeout = setTimeout(() => { 899 if (swiper.autoplay && swiper.autoplay.running && swiper.autoplay.paused) { 900 swiper.autoplay.resume(); 901 } 902 }, 500); 903 } 904 // Return locks after resize 905 swiper.allowSlidePrev = allowSlidePrev; 906 swiper.allowSlideNext = allowSlideNext; 907 if (swiper.params.watchOverflow && snapGrid !== swiper.snapGrid) { 908 swiper.checkOverflow(); 909 } 910 } 911 912 function onScroll() { 913 const swiper = this; 914 if (swiper.destroyed) 915 return; 916 const { wrapperEl, rtlTranslate, enabled } = swiper; 917 if (!enabled) 918 return; 919 swiper.previousTranslate = swiper.translate; 920 if (swiper.isHorizontal()) { 921 swiper.translate = -wrapperEl.scrollLeft; 922 } 923 else { 924 swiper.translate = -wrapperEl.scrollTop; 925 } 926 if (swiper.translate === 0) 927 swiper.translate = 0; 928 swiper.updateActiveIndex(); 929 swiper.updateSlidesClasses(); 930 let newProgress; 931 const translatesDiff = swiper.maxTranslate() - swiper.minTranslate(); 932 if (translatesDiff === 0) { 933 newProgress = 0; 934 } 935 else { 936 newProgress = (swiper.translate - swiper.minTranslate()) / translatesDiff; 937 } 938 if (newProgress !== swiper.progress) { 939 swiper.updateProgress(rtlTranslate ? -swiper.translate : swiper.translate); 940 } 941 swiper.emit('setTranslate', swiper.translate, false); 942 } 943 944 function onTouchEnd(event) { 945 const swiper = this; 946 if (swiper.destroyed) 947 return; 948 const data = swiper.touchEventsData; 949 let e = event.originalEvent ?? event; 950 const isTouchEvent = e.type === 'touchend' || e.type === 'touchcancel'; 951 if (!isTouchEvent) { 952 if (data.touchId !== null) 953 return; // return from pointer if we use touch 954 const pe = e; 955 if (pe.pointerId !== data.pointerId) 956 return; 957 } 958 else { 959 const te = e; 960 const found = [...te.changedTouches].find((t) => t.identifier === data.touchId); 961 if (!found || found.identifier !== data.touchId) 962 return; 963 } 964 if (['pointercancel', 'pointerout', 'pointerleave', 'contextmenu'].includes(e.type)) { 965 const proceed = ['pointercancel', 'contextmenu'].includes(e.type) && 966 (swiper.browser.isSafari || swiper.browser.isWebView); 967 if (!proceed) { 968 return; 969 } 970 } 971 data.pointerId = null; 972 data.touchId = null; 973 const { params, touches, rtlTranslate: rtl, slidesGrid, enabled } = swiper; 974 if (!enabled) 975 return; 976 if (!params.simulateTouch && e.pointerType === 'mouse') 977 return; 978 if (data.allowTouchCallbacks) { 979 swiper.emit('touchEnd', e); 980 } 981 data.allowTouchCallbacks = false; 982 if (!data.isTouched) { 983 if (data.isMoved && params.grabCursor) { 984 swiper.setGrabCursor(false); 985 } 986 data.isMoved = false; 987 data.startMoving = false; 988 return; 989 } 990 // Return Grab Cursor 991 if (params.grabCursor && 992 data.isMoved && 993 data.isTouched && 994 (swiper.allowSlideNext === true || swiper.allowSlidePrev === true)) { 995 swiper.setGrabCursor(false); 996 } 997 // Time diff 998 const touchEndTime = now(); 999 const timeDiff = touchEndTime - data.touchStartTime; 1000 // Tap, doubleTap, Click 1001 if (swiper.allowClick) { 1002 // Legacy `e.path` was a non-standard Chrome extension; `composedPath()` is the modern API. 1003 const pathTree = e.path ?? (e.composedPath && e.composedPath()); 1004 swiper.updateClickedSlide((pathTree && pathTree[0]), pathTree); 1005 swiper.emit('tap click', e); 1006 if (timeDiff < 300 && touchEndTime - data.lastClickTime < 300) { 1007 swiper.emit('doubleTap doubleClick', e); 1008 } 1009 } 1010 data.lastClickTime = now(); 1011 nextTick(() => { 1012 if (!swiper.destroyed) 1013 swiper.allowClick = true; 1014 }); 1015 if (!data.isTouched || 1016 !data.isMoved || 1017 !swiper.swipeDirection || 1018 (touches.diff === 0 && !data.loopSwapReset) || 1019 (data.currentTranslate === data.startTranslate && !data.loopSwapReset)) { 1020 data.isTouched = false; 1021 data.isMoved = false; 1022 data.startMoving = false; 1023 return; 1024 } 1025 data.isTouched = false; 1026 data.isMoved = false; 1027 data.startMoving = false; 1028 let currentPos; 1029 if (params.followFinger) { 1030 currentPos = rtl ? swiper.translate : -swiper.translate; 1031 } 1032 else { 1033 currentPos = -(data.currentTranslate ?? 0); 1034 } 1035 if (params.cssMode) { 1036 return; 1037 } 1038 if (params.freeMode && params.freeMode.enabled) { 1039 swiper.freeMode.onTouchEnd({ currentPos }); 1040 return; 1041 } 1042 // Find current slide 1043 const swipeToLast = currentPos >= -swiper.maxTranslate() && !swiper.params.loop; 1044 let stopIndex = 0; 1045 let groupSize = swiper.slidesSizesGrid[0]; 1046 for (let i = 0; i < slidesGrid.length; i += i < params.slidesPerGroupSkip ? 1 : params.slidesPerGroup) { 1047 const increment = i < params.slidesPerGroupSkip - 1 ? 1 : params.slidesPerGroup; 1048 if (typeof slidesGrid[i + increment] !== 'undefined') { 1049 if (swipeToLast || 1050 (currentPos >= slidesGrid[i] && currentPos < slidesGrid[i + increment])) { 1051 stopIndex = i; 1052 groupSize = slidesGrid[i + increment] - slidesGrid[i]; 1053 } 1054 } 1055 else if (swipeToLast || currentPos >= slidesGrid[i]) { 1056 stopIndex = i; 1057 groupSize = slidesGrid[slidesGrid.length - 1] - slidesGrid[slidesGrid.length - 2]; 1058 } 1059 } 1060 let rewindFirstIndex = null; 1061 let rewindLastIndex = null; 1062 if (params.rewind) { 1063 if (swiper.isBeginning) { 1064 rewindLastIndex = 1065 params.virtual?.enabled && swiper.virtual 1066 ? swiper.virtual.slides.length - 1 1067 : swiper.slides.length - 1; 1068 } 1069 else if (swiper.isEnd) { 1070 rewindFirstIndex = 0; 1071 } 1072 } 1073 // Find current slide size 1074 const ratio = (currentPos - slidesGrid[stopIndex]) / groupSize; 1075 const increment = stopIndex < params.slidesPerGroupSkip - 1 ? 1 : params.slidesPerGroup; 1076 if (timeDiff > params.longSwipesMs) { 1077 // Long touches 1078 if (!params.longSwipes) { 1079 swiper.slideTo(swiper.activeIndex); 1080 return; 1081 } 1082 if (swiper.swipeDirection === 'next') { 1083 if (ratio >= params.longSwipesRatio) 1084 swiper.slideTo(params.rewind && swiper.isEnd ? rewindFirstIndex : stopIndex + increment); 1085 else 1086 swiper.slideTo(stopIndex); 1087 } 1088 if (swiper.swipeDirection === 'prev') { 1089 if (ratio > 1 - params.longSwipesRatio) { 1090 swiper.slideTo(stopIndex + increment); 1091 } 1092 else if (rewindLastIndex !== null && 1093 ratio < 0 && 1094 Math.abs(ratio) > params.longSwipesRatio) { 1095 swiper.slideTo(rewindLastIndex); 1096 } 1097 else { 1098 swiper.slideTo(stopIndex); 1099 } 1100 } 1101 } 1102 else { 1103 // Short swipes 1104 if (!params.shortSwipes) { 1105 swiper.slideTo(swiper.activeIndex); 1106 return; 1107 } 1108 const isNavButtonTarget = swiper.navigation && 1109 (e.target === swiper.navigation.nextEl || e.target === swiper.navigation.prevEl); 1110 if (!isNavButtonTarget) { 1111 if (swiper.swipeDirection === 'next') { 1112 swiper.slideTo(rewindFirstIndex !== null ? rewindFirstIndex : stopIndex + increment); 1113 } 1114 if (swiper.swipeDirection === 'prev') { 1115 swiper.slideTo(rewindLastIndex !== null ? rewindLastIndex : stopIndex); 1116 } 1117 } 1118 else if (e.target === swiper.navigation.nextEl) { 1119 swiper.slideTo(stopIndex + increment); 1120 } 1121 else { 1122 swiper.slideTo(stopIndex); 1123 } 1124 } 1125 } 1126 1127 function onTouchMove(event) { 1128 const swiper = this; 1129 if (swiper.destroyed) 1130 return; 1131 const data = swiper.touchEventsData; 1132 const { params, touches, rtlTranslate: rtl, enabled } = swiper; 1133 if (!enabled) 1134 return; 1135 if (!params.simulateTouch && event.pointerType === 'mouse') 1136 return; 1137 // Legacy event wrappers nest the native event under .originalEvent. 1138 const wrapped = event; 1139 const e = wrapped.originalEvent ?? wrapped; 1140 if (e.type === 'pointermove') { 1141 if (data.touchId !== null) 1142 return; // return from pointer if we use touch 1143 const pe = e; 1144 if (pe.pointerId !== data.pointerId) 1145 return; 1146 } 1147 let targetTouch; 1148 if (e.type === 'touchmove') { 1149 const te = e; 1150 const found = [...te.changedTouches].find((t) => t.identifier === data.touchId); 1151 if (!found || found.identifier !== data.touchId) 1152 return; 1153 targetTouch = found; 1154 } 1155 else { 1156 targetTouch = e; 1157 } 1158 if (!data.isTouched) { 1159 if (data.startMoving && data.isScrolling) { 1160 swiper.emit('touchMoveOpposite', e); 1161 } 1162 return; 1163 } 1164 const pageX = targetTouch.pageX; 1165 const pageY = targetTouch.pageY; 1166 if (e.preventedByNestedSwiper) { 1167 touches.startX = pageX; 1168 touches.startY = pageY; 1169 return; 1170 } 1171 if (!swiper.allowTouchMove) { 1172 if (!e.target.matches(data.focusableElements)) { 1173 swiper.allowClick = false; 1174 } 1175 if (data.isTouched) { 1176 Object.assign(touches, { 1177 startX: pageX, 1178 startY: pageY, 1179 currentX: pageX, 1180 currentY: pageY, 1181 }); 1182 data.touchStartTime = now(); 1183 } 1184 return; 1185 } 1186 if (params.touchReleaseOnEdges && !params.loop) { 1187 if (swiper.isVertical()) { 1188 // Vertical 1189 if ((pageY < touches.startY && swiper.translate <= swiper.maxTranslate()) || 1190 (pageY > touches.startY && swiper.translate >= swiper.minTranslate())) { 1191 data.isTouched = false; 1192 data.isMoved = false; 1193 return; 1194 } 1195 } 1196 else if (rtl && 1197 ((pageX > touches.startX && -swiper.translate <= swiper.maxTranslate()) || 1198 (pageX < touches.startX && -swiper.translate >= swiper.minTranslate()))) { 1199 return; 1200 } 1201 else if (!rtl && 1202 ((pageX < touches.startX && swiper.translate <= swiper.maxTranslate()) || 1203 (pageX > touches.startX && swiper.translate >= swiper.minTranslate()))) { 1204 return; 1205 } 1206 } 1207 if (document.activeElement && 1208 document.activeElement.matches(data.focusableElements) && 1209 document.activeElement !== e.target && 1210 e.pointerType !== 'mouse') { 1211 document.activeElement.blur(); 1212 } 1213 if (document.activeElement) { 1214 if (e.target === document.activeElement && 1215 e.target.matches(data.focusableElements)) { 1216 data.isMoved = true; 1217 swiper.allowClick = false; 1218 return; 1219 } 1220 } 1221 if (data.allowTouchCallbacks) { 1222 swiper.emit('touchMove', e); 1223 } 1224 touches.previousX = touches.currentX; 1225 touches.previousY = touches.currentY; 1226 touches.currentX = pageX; 1227 touches.currentY = pageY; 1228 const diffX = touches.currentX - touches.startX; 1229 const diffY = touches.currentY - touches.startY; 1230 if (swiper.params.threshold && Math.sqrt(diffX ** 2 + diffY ** 2) < swiper.params.threshold) 1231 return; 1232 if (typeof data.isScrolling === 'undefined') { 1233 let touchAngle; 1234 if ((swiper.isHorizontal() && touches.currentY === touches.startY) || 1235 (swiper.isVertical() && touches.currentX === touches.startX)) { 1236 data.isScrolling = false; 1237 } 1238 else { 1239 if (diffX * diffX + diffY * diffY >= 25) { 1240 touchAngle = (Math.atan2(Math.abs(diffY), Math.abs(diffX)) * 180) / Math.PI; 1241 data.isScrolling = swiper.isHorizontal() 1242 ? touchAngle > params.touchAngle 1243 : 90 - touchAngle > params.touchAngle; 1244 } 1245 } 1246 } 1247 if (data.isScrolling) { 1248 swiper.emit('touchMoveOpposite', e); 1249 } 1250 if (typeof data.startMoving === 'undefined') { 1251 if (touches.currentX !== touches.startX || touches.currentY !== touches.startY) { 1252 data.startMoving = true; 1253 } 1254 } 1255 if (data.isScrolling || (e.type === 'touchmove' && data.preventTouchMoveFromPointerMove)) { 1256 data.isTouched = false; 1257 return; 1258 } 1259 if (!data.startMoving) { 1260 return; 1261 } 1262 swiper.allowClick = false; 1263 if (!params.cssMode && e.cancelable) { 1264 e.preventDefault(); 1265 } 1266 if (params.touchMoveStopPropagation && !params.nested) { 1267 e.stopPropagation(); 1268 } 1269 let diff = swiper.isHorizontal() ? diffX : diffY; 1270 let touchesDiff = swiper.isHorizontal() 1271 ? touches.currentX - touches.previousX 1272 : touches.currentY - touches.previousY; 1273 if (params.oneWayMovement) { 1274 diff = Math.abs(diff) * (rtl ? 1 : -1); 1275 touchesDiff = Math.abs(touchesDiff) * (rtl ? 1 : -1); 1276 } 1277 touches.diff = diff; 1278 diff *= params.touchRatio; 1279 if (rtl) { 1280 diff = -diff; 1281 touchesDiff = -touchesDiff; 1282 } 1283 const prevTouchesDirection = swiper.touchesDirection; 1284 swiper.swipeDirection = diff > 0 ? 'prev' : 'next'; 1285 swiper.touchesDirection = touchesDiff > 0 ? 'prev' : 'next'; 1286 const isLoop = swiper.params.loop && !params.cssMode; 1287 const allowLoopFix = (swiper.touchesDirection === 'next' && swiper.allowSlideNext) || 1288 (swiper.touchesDirection === 'prev' && swiper.allowSlidePrev); 1289 if (!data.isMoved) { 1290 if (isLoop && allowLoopFix) { 1291 swiper.loopFix({ direction: swiper.swipeDirection }); 1292 } 1293 data.startTranslate = swiper.getTranslate(); 1294 swiper.setTransition(0); 1295 if (swiper.animating) { 1296 const evt = new window.CustomEvent('transitionend', { 1297 bubbles: true, 1298 cancelable: true, 1299 detail: { 1300 bySwiperTouchMove: true, 1301 }, 1302 }); 1303 swiper.wrapperEl.dispatchEvent(evt); 1304 } 1305 data.allowMomentumBounce = false; 1306 // Grab Cursor 1307 if (params.grabCursor && (swiper.allowSlideNext === true || swiper.allowSlidePrev === true)) { 1308 swiper.setGrabCursor(true); 1309 } 1310 swiper.emit('sliderFirstMove', e); 1311 } 1312 new Date().getTime(); 1313 if (params._loopSwapReset !== false && 1314 data.isMoved && 1315 data.allowThresholdMove && 1316 prevTouchesDirection !== swiper.touchesDirection && 1317 isLoop && 1318 allowLoopFix && 1319 Math.abs(diff) >= 1) { 1320 Object.assign(touches, { 1321 startX: pageX, 1322 startY: pageY, 1323 currentX: pageX, 1324 currentY: pageY, 1325 startTranslate: data.currentTranslate, 1326 }); 1327 data.loopSwapReset = true; 1328 data.startTranslate = data.currentTranslate; 1329 return; 1330 } 1331 swiper.emit('sliderMove', e); 1332 data.isMoved = true; 1333 // startTranslate is guaranteed to be set by this point (set in onTouchStart-side init). 1334 const startTranslate = data.startTranslate ?? 0; 1335 data.currentTranslate = diff + startTranslate; 1336 let disableParentSwiper = true; 1337 let resistanceRatio = params.resistanceRatio; 1338 if (params.touchReleaseOnEdges) { 1339 resistanceRatio = 0; 1340 } 1341 if (diff > 0) { 1342 if (isLoop && 1343 allowLoopFix && 1344 true && 1345 data.allowThresholdMove && 1346 data.currentTranslate > 1347 (params.centeredSlides 1348 ? swiper.minTranslate() - 1349 swiper.slidesSizesGrid[swiper.activeIndex + 1] - 1350 (params.slidesPerView !== 'auto' && 1351 swiper.slides.length - params.slidesPerView >= 2 1352 ? swiper.slidesSizesGrid[swiper.activeIndex + 1] + 1353 swiper.params.spaceBetween 1354 : 0) - 1355 swiper.params.spaceBetween 1356 : swiper.minTranslate())) { 1357 swiper.loopFix({ direction: 'prev', setTranslate: true, activeSlideIndex: 0 }); 1358 } 1359 if (data.currentTranslate > swiper.minTranslate()) { 1360 disableParentSwiper = false; 1361 if (params.resistance) { 1362 data.currentTranslate = 1363 swiper.minTranslate() - 1364 1 + 1365 (-swiper.minTranslate() + startTranslate + diff) ** resistanceRatio; 1366 } 1367 } 1368 } 1369 else if (diff < 0) { 1370 if (isLoop && 1371 allowLoopFix && 1372 true && 1373 data.allowThresholdMove && 1374 data.currentTranslate < 1375 (params.centeredSlides 1376 ? swiper.maxTranslate() + 1377 swiper.slidesSizesGrid[swiper.slidesSizesGrid.length - 1] + 1378 swiper.params.spaceBetween + 1379 (params.slidesPerView !== 'auto' && 1380 swiper.slides.length - params.slidesPerView >= 2 1381 ? swiper.slidesSizesGrid[swiper.slidesSizesGrid.length - 1] + 1382 swiper.params.spaceBetween 1383 : 0) 1384 : swiper.maxTranslate())) { 1385 swiper.loopFix({ 1386 direction: 'next', 1387 setTranslate: true, 1388 activeSlideIndex: swiper.slides.length - 1389 (params.slidesPerView === 'auto' 1390 ? swiper.slidesPerViewDynamic() 1391 : Math.ceil(parseFloat(String(params.slidesPerView)))), 1392 }); 1393 } 1394 if (data.currentTranslate < swiper.maxTranslate()) { 1395 disableParentSwiper = false; 1396 if (params.resistance) { 1397 data.currentTranslate = 1398 swiper.maxTranslate() + 1399 1 - 1400 (swiper.maxTranslate() - startTranslate - diff) ** resistanceRatio; 1401 } 1402 } 1403 } 1404 if (disableParentSwiper) { 1405 e.preventedByNestedSwiper = true; 1406 } 1407 // Directions locks 1408 if (!swiper.allowSlideNext && 1409 swiper.swipeDirection === 'next' && 1410 (data.currentTranslate ?? 0) < startTranslate) { 1411 data.currentTranslate = startTranslate; 1412 } 1413 if (!swiper.allowSlidePrev && 1414 swiper.swipeDirection === 'prev' && 1415 (data.currentTranslate ?? 0) > startTranslate) { 1416 data.currentTranslate = startTranslate; 1417 } 1418 if (!swiper.allowSlidePrev && !swiper.allowSlideNext) { 1419 data.currentTranslate = startTranslate; 1420 } 1421 // Threshold 1422 if (params.threshold > 0) { 1423 if (Math.abs(diff) > params.threshold || data.allowThresholdMove) { 1424 if (!data.allowThresholdMove) { 1425 data.allowThresholdMove = true; 1426 touches.startX = touches.currentX; 1427 touches.startY = touches.currentY; 1428 data.currentTranslate = data.startTranslate; 1429 touches.diff = swiper.isHorizontal() 1430 ? touches.currentX - touches.startX 1431 : touches.currentY - touches.startY; 1432 return; 1433 } 1434 } 1435 else { 1436 data.currentTranslate = data.startTranslate; 1437 return; 1438 } 1439 } 1440 if (!params.followFinger || params.cssMode) 1441 return; 1442 // Update active index in free mode 1443 if ((params.freeMode && params.freeMode.enabled && swiper.freeMode) || 1444 params.watchSlidesProgress) { 1445 swiper.updateActiveIndex(); 1446 swiper.updateSlidesClasses(); 1447 } 1448 if (params.freeMode && params.freeMode.enabled && swiper.freeMode) { 1449 swiper.freeMode.onTouchMove(); 1450 } 1451 // Update progress 1452 swiper.updateProgress(data.currentTranslate); 1453 // Update translate 1454 swiper.setTranslate(data.currentTranslate ?? 0); 1455 } 1456 1457 // Modified from https://stackoverflow.com/questions/54520554/custom-element-getrootnode-closest-function-crossing-multiple-parent-shadowd 1458 function closestElement(selector, base) { 1459 function __closestFrom(el) { 1460 if (!el || el === document || el === window) 1461 return null; 1462 let cur = el; 1463 if (cur.assignedSlot) 1464 cur = cur.assignedSlot; 1465 const found = cur.closest(selector); 1466 if (!found && !cur.getRootNode) { 1467 return null; 1468 } 1469 const root = cur.getRootNode(); 1470 return found || __closestFrom(root.host); 1471 } 1472 return __closestFrom(base); 1473 } 1474 function preventEdgeSwipe(swiper, event, startX) { 1475 const { params } = swiper; 1476 const edgeSwipeDetection = params.edgeSwipeDetection; 1477 const edgeSwipeThreshold = params.edgeSwipeThreshold; 1478 if (edgeSwipeDetection && 1479 (startX <= edgeSwipeThreshold || startX >= window.innerWidth - edgeSwipeThreshold)) { 1480 if (edgeSwipeDetection === 'prevent') { 1481 event.preventDefault(); 1482 return true; 1483 } 1484 return false; 1485 } 1486 return true; 1487 } 1488 function onTouchStart(event) { 1489 const swiper = this; 1490 if (swiper.destroyed) 1491 return; 1492 const e = event.originalEvent ?? event; 1493 const data = swiper.touchEventsData; 1494 if (e.type === 'pointerdown') { 1495 const pe = e; 1496 if (data.pointerId !== null && data.pointerId !== pe.pointerId) { 1497 return; 1498 } 1499 data.pointerId = pe.pointerId; 1500 } 1501 else if (e.type === 'touchstart' && e.targetTouches.length === 1) { 1502 data.touchId = e.targetTouches[0].identifier; 1503 } 1504 if (e.type === 'touchstart') { 1505 // don't proceed touch event 1506 preventEdgeSwipe(swiper, e, e.targetTouches[0].pageX); 1507 return; 1508 } 1509 const { params, touches, enabled } = swiper; 1510 if (!enabled) 1511 return; 1512 if (!params.simulateTouch && e.pointerType === 'mouse') 1513 return; 1514 if (swiper.animating && params.preventInteractionOnTransition) { 1515 return; 1516 } 1517 if (!swiper.animating && params.cssMode && params.loop) { 1518 swiper.loopFix(); 1519 } 1520 let targetEl = e.target; 1521 if (params.touchEventsTarget === 'wrapper') { 1522 if (!elementIsChildOf(targetEl, swiper.wrapperEl)) 1523 return; 1524 } 1525 // Secondary mouse buttons (right-click / middle-click) shouldn't start a swipe. 1526 const mouseLike = e; 1527 if (typeof mouseLike.which === 'number' && mouseLike.which === 3) 1528 return; 1529 if (typeof mouseLike.button === 'number' && mouseLike.button > 0) 1530 return; 1531 if (data.isTouched && data.isMoved) 1532 return; 1533 // change target el for shadow root component 1534 const swipingClassHasValue = !!params.noSwipingClass && params.noSwipingClass !== ''; 1535 // `path` is a non-standard Chrome extension; `composedPath()` is the modern API. 1536 const eventPath = e.composedPath 1537 ? e.composedPath() 1538 : e.path; 1539 if (swipingClassHasValue && 1540 e.target && 1541 e.target.shadowRoot && 1542 eventPath) { 1543 targetEl = eventPath[0]; 1544 } 1545 const noSwipingSelector = params.noSwipingSelector 1546 ? params.noSwipingSelector 1547 : `.${params.noSwipingClass}`; 1548 const isTargetShadow = !!(e.target && e.target.shadowRoot); 1549 // use closestElement for shadow root element to get the actual closest for nested shadow root element 1550 if (params.noSwiping && 1551 (isTargetShadow 1552 ? closestElement(noSwipingSelector, targetEl) 1553 : targetEl.closest(noSwipingSelector))) { 1554 swiper.allowClick = true; 1555 return; 1556 } 1557 if (params.swipeHandler) { 1558 if (typeof params.swipeHandler === 'string' && !targetEl.closest(params.swipeHandler)) 1559 return; 1560 } 1561 // At this point `e` is a PointerEvent or MouseEvent (touchstart returned earlier). 1562 const pe = e; 1563 touches.currentX = pe.pageX; 1564 touches.currentY = pe.pageY; 1565 const startX = touches.currentX; 1566 const startY = touches.currentY; 1567 // Do NOT start if iOS edge swipe is detected. Otherwise iOS app cannot swipe-to-go-back anymore 1568 if (!preventEdgeSwipe(swiper, e, startX)) { 1569 return; 1570 } 1571 Object.assign(data, { 1572 isTouched: true, 1573 isMoved: false, 1574 allowTouchCallbacks: true, 1575 isScrolling: undefined, 1576 startMoving: undefined, 1577 }); 1578 touches.startX = startX; 1579 touches.startY = startY; 1580 data.touchStartTime = now(); 1581 swiper.allowClick = true; 1582 swiper.updateSize(); 1583 swiper.swipeDirection = undefined; 1584 if (params.threshold > 0) 1585 data.allowThresholdMove = false; 1586 let preventDefault = true; 1587 if (targetEl.matches(data.focusableElements)) { 1588 preventDefault = false; 1589 if (targetEl.nodeName === 'SELECT') { 1590 data.isTouched = false; 1591 } 1592 } 1593 if (document.activeElement && 1594 document.activeElement.matches(data.focusableElements) && 1595 document.activeElement !== targetEl && 1596 (pe.pointerType === 'mouse' || 1597 (pe.pointerType !== 'mouse' && !targetEl.matches(data.focusableElements)))) { 1598 document.activeElement.blur(); 1599 } 1600 const shouldPreventDefault = preventDefault && swiper.allowTouchMove && params.touchStartPreventDefault; 1601 if ((params.touchStartForcePreventDefault || shouldPreventDefault) && 1602 !targetEl.isContentEditable) { 1603 e.preventDefault(); 1604 } 1605 if (params.freeMode && 1606 params.freeMode.enabled && 1607 swiper.freeMode && 1608 swiper.animating && 1609 !params.cssMode) { 1610 swiper.freeMode.onTouchStart(); 1611 } 1612 swiper.emit('touchStart', e); 1613 } 1614 1615 const events = (swiper, method) => { 1616 const { params, el, wrapperEl, device } = swiper; 1617 const capture = !!params.nested; 1618 const domMethod = method === 'on' ? 'addEventListener' : 'removeEventListener'; 1619 const swiperMethod = method; 1620 if (!el || typeof el === 'string') 1621 return; 1622 // Touch Events 1623 document[domMethod]('touchstart', swiper.onDocumentTouchStart, { 1624 passive: false, 1625 capture, 1626 }); 1627 el[domMethod]('touchstart', swiper.onTouchStart, { passive: false }); 1628 el[domMethod]('pointerdown', swiper.onTouchStart, { passive: false }); 1629 document[domMethod]('touchmove', swiper.onTouchMove, { 1630 passive: false, 1631 capture, 1632 }); 1633 document[domMethod]('pointermove', swiper.onTouchMove, { 1634 passive: false, 1635 capture, 1636 }); 1637 document[domMethod]('touchend', swiper.onTouchEnd, { passive: true }); 1638 document[domMethod]('pointerup', swiper.onTouchEnd, { passive: true }); 1639 document[domMethod]('pointercancel', swiper.onTouchEnd, { passive: true }); 1640 document[domMethod]('touchcancel', swiper.onTouchEnd, { passive: true }); 1641 document[domMethod]('pointerout', swiper.onTouchEnd, { passive: true }); 1642 document[domMethod]('pointerleave', swiper.onTouchEnd, { passive: true }); 1643 document[domMethod]('contextmenu', swiper.onTouchEnd, { passive: true }); 1644 // Prevent Links Clicks 1645 if (params.preventClicks || params.preventClicksPropagation) { 1646 el[domMethod]('click', swiper.onClick, true); 1647 } 1648 if (params.cssMode) { 1649 wrapperEl[domMethod]('scroll', swiper.onScroll); 1650 } 1651 // Resize handler 1652 const subscribe = (events) => { 1653 swiper[swiperMethod](events, onResize, true); 1654 }; 1655 if (params.updateOnWindowResize) { 1656 subscribe(device.ios || device.android 1657 ? 'resize orientationchange observerUpdate' 1658 : 'resize observerUpdate'); 1659 } 1660 else { 1661 subscribe('observerUpdate'); 1662 } 1663 // Images loader 1664
1664el[domMethod]('load', swiper.onLoad, { capture: true });
vendor: 6,525 bytes, lines 1664-1831
1664 1665 }; 1666 function attachEvents() { 1667 const swiper = this; 1668 const { params } = swiper; 1669 swiper.onTouchStart = onTouchStart.bind(swiper); 1670 swiper.onTouchMove = onTouchMove.bind(swiper); 1671 swiper.onTouchEnd = onTouchEnd.bind(swiper); 1672 swiper.onDocumentTouchStart = onDocumentTouchStart.bind(swiper); 1673 if (params.cssMode) { 1674 swiper.onScroll = onScroll.bind(swiper); 1675 } 1676 swiper.onClick = onClick.bind(swiper); 1677 swiper.onLoad = onLoad.bind(swiper); 1678 events(swiper, 'on'); 1679 } 1680 function detachEvents() { 1681 const swiper = this; 1682 events(swiper, 'off'); 1683 } 1684 var events$1 = { 1685 attachEvents, 1686 detachEvents, 1687 }; 1688 1689 function setGrabCursor(moving) { 1690 const swiper = this; 1691 if (!swiper.params.simulateTouch || 1692 (swiper.params.watchOverflow && swiper.isLocked) || 1693 swiper.params.cssMode) 1694 return; 1695 const el = swiper.params.touchEventsTarget === 'container' ? swiper.el : swiper.wrapperEl; 1696 if (swiper.isElement) { 1697 swiper.__preventObserver__ = true; 1698 } 1699 el.style.cursor = 'move'; 1700 el.style.cursor = moving ? 'grabbing' : 'grab'; 1701 if (swiper.isElement) { 1702 requestAnimationFrame(() => { 1703 swiper.__preventObserver__ = false; 1704 }); 1705 } 1706 } 1707 1708 function unsetGrabCursor() { 1709 const swiper = this; 1710 if ((swiper.params.watchOverflow && swiper.isLocked) || swiper.params.cssMode) { 1711 return; 1712 } 1713 if (swiper.isElement) { 1714 swiper.__preventObserver__ = true; 1715 } 1716 swiper[swiper.params.touchEventsTarget === 'container' ? 'el' : 'wrapperEl'].style.cursor = ''; 1717 if (swiper.isElement) { 1718 requestAnimationFrame(() => { 1719 swiper.__preventObserver__ = false; 1720 }); 1721 } 1722 } 1723 1724 var grabCursor = { 1725 setGrabCursor, 1726 unsetGrabCursor, 1727 }; 1728 1729 function loopCreate(slideRealIndex, initial) { 1730 const swiper = this; 1731 const { params, slidesEl } = swiper; 1732 if (!params.loop || (swiper.virtual && swiper.params.virtual?.enabled)) 1733 return; 1734 const initSlides = () => { 1735 const slides = elementChildren(slidesEl, `.${params.slideClass}, swiper-slide`); 1736 slides.forEach((el, index) => { 1737 el.setAttribute('data-swiper-slide-index', String(index)); 1738 }); 1739 }; 1740 const clearBlankSlides = () => { 1741 const slides = elementChildren(slidesEl, `.${params.slideBlankClass}`); 1742 slides.forEach((el) => { 1743 el.remove(); 1744 }); 1745 if (slides.length > 0) { 1746 swiper.recalcSlides(); 1747 swiper.updateSlides(); 1748 } 1749 }; 1750 const gridEnabled = swiper.grid && params.grid && params.grid.rows > 1; 1751 if (params.loopAddBlankSlides && (params.slidesPerGroup > 1 || gridEnabled)) { 1752 clearBlankSlides(); 1753 } 1754 const slidesPerGroup = params.slidesPerGroup * (gridEnabled ? params.grid.rows : 1); 1755 const shouldFillGroup = swiper.slides.length % slidesPerGroup !== 0; 1756 const shouldFillGrid = gridEnabled && swiper.slides.length % params.grid.rows !== 0; 1757 const addBlankSlides = (amountOfSlides) => { 1758 for (let i = 0; i < amountOfSlides; i += 1) { 1759 const slideEl = swiper.isElement 1760 ? createElement('swiper-slide', [params.slideBlankClass]) 1761 : createElement('div', [params.slideClass, params.slideBlankClass]); 1762 swiper.slidesEl.append(slideEl); 1763 } 1764 }; 1765 if (shouldFillGroup) { 1766 if (params.loopAddBlankSlides) { 1767 const slidesToAdd = slidesPerGroup - (swiper.slides.length % slidesPerGroup); 1768 addBlankSlides(slidesToAdd); 1769 swiper.recalcSlides(); 1770 swiper.updateSlides(); 1771 } 1772 else { 1773 showWarning('Swiper Loop Warning: The number of slides is not even to slidesPerGroup, loop mode may not function properly. You need to add more slides (or make duplicates, or empty slides)'); 1774 } 1775 initSlides(); 1776 } 1777 else if (shouldFillGrid) { 1778 if (params.loopAddBlankSlides) { 1779 const slidesToAdd = params.grid.rows - (swiper.slides.length % params.grid.rows); 1780 addBlankSlides(slidesToAdd); 1781 swiper.recalcSlides(); 1782 swiper.updateSlides(); 1783 } 1784 else { 1785 showWarning('Swiper Loop Warning: The number of slides is not even to grid.rows, loop mode may not function properly. You need to add more slides (or make duplicates, or empty slides)'); 1786 } 1787 initSlides(); 1788 } 1789 else { 1790 initSlides(); 1791 } 1792 const bothDirections = params.centeredSlides || !!params.slidesOffsetBefore || !!params.slidesOffsetAfter; 1793 swiper.loopFix({ 1794 slideRealIndex, 1795 direction: bothDirections ? undefined : 'next', 1796 initial, 1797 }); 1798 } 1799 1800 function loopDestroy() { 1801 const swiper = this; 1802 const { params, slidesEl } = swiper; 1803 if (!params.loop || !slidesEl || (swiper.virtual && swiper.params.virtual?.enabled)) 1804 return; 1805 swiper.recalcSlides(); 1806 const newSlidesOrder = []; 1807 swiper.slides.forEach((slideEl) => { 1808 const loopSlideEl = slideEl; 1809 const index = typeof loopSlideEl.swiperSlideIndex === 'undefined' 1810 ? Number(slideEl.getAttribute('data-swiper-slide-index')) 1811 : loopSlideEl.swiperSlideIndex; 1812 newSlidesOrder[index] = slideEl; 1813 }); 1814 swiper.slides.forEach((slideEl) => { 1815 slideEl.removeAttribute('data-swiper-slide-index'); 1816 }); 1817 newSlidesOrder.forEach((slideEl) => { 1818 slidesEl.append(slideEl); 1819 }); 1820 swiper.recalcSlides(); 1821 swiper.slideTo(swiper.realIndex, 0); 1822 } 1823 1824 function loopFix(options = {}) { 1825 const { slideRealIndex, slideTo = true, direction, setTranslate, activeSlideIndex: activeSlideIndexParam, initial, byController, byMousewheel, } = options; 1826 let activeSlideIndex = activeSlideIndexParam; 1827 const swiper = this; 1828 if (!swiper.params.loop) 1829 return; 1830 swiper.emit('beforeLoopFix'); 1831
vendor: 11,277 bytes, lines 1831-2062
1831const { slides, allowSlidePrev, allowSlideNext, slidesEl, params } = swiper; 1832 const { centeredSlides, slidesOffsetBefore, slidesOffsetAfter, initialSlide } = params; 1833 const bothDirections = centeredSlides || !!slidesOffsetBefore || !!slidesOffsetAfter; 1834 swiper.allowSlidePrev = true; 1835 swiper.allowSlideNext = true; 1836 if (swiper.virtual && params.virtual?.enabled) { 1837 if (slideTo) { 1838 const virtualSlidesLength = swiper.virtual.slides.length; 1839 const virtualSlidesBefore = swiper.virtual.slidesBefore ?? 0; 1840 if (!bothDirections && swiper.snapIndex === 0) { 1841 swiper.slideTo(virtualSlidesLength, 0, false, true); 1842 } 1843 else if (bothDirections && swiper.snapIndex < params.slidesPerView) { 1844 swiper.slideTo(virtualSlidesLength + swiper.snapIndex, 0, false, true); 1845 } 1846 else if (swiper.snapIndex === swiper.snapGrid.length - 1) { 1847 swiper.slideTo(virtualSlidesBefore, 0, false, true); 1848 } 1849 } 1850 swiper.allowSlidePrev = allowSlidePrev; 1851 swiper.allowSlideNext = allowSlideNext; 1852 swiper.emit('loopFix'); 1853 return; 1854 } 1855 let slidesPerView = params.slidesPerView; 1856 if (slidesPerView === 'auto') { 1857 slidesPerView = swiper.slidesPerViewDynamic(); 1858 } 1859 else { 1860 slidesPerView = Math.ceil(parseFloat(String(params.slidesPerView))); 1861 if (bothDirections && slidesPerView % 2 === 0) { 1862 slidesPerView = slidesPerView + 1; 1863 } 1864 } 1865 const slidesPerGroup = params.slidesPerGroupAuto 1866 ? slidesPerView 1867 : params.slidesPerGroup; 1868 let loopedSlides = bothDirections 1869 ? Math.max(slidesPerGroup, Math.ceil(slidesPerView / 2)) 1870 : slidesPerGroup; 1871 if (loopedSlides % slidesPerGroup !== 0) { 1872 loopedSlides += slidesPerGroup - (loopedSlides % slidesPerGroup); 1873 } 1874 loopedSlides += params.loopAdditionalSlides; 1875 swiper.loopedSlides = loopedSlides; 1876 const gridEnabled = swiper.grid && params.grid && params.grid.rows > 1; 1877 if (slides.length < slidesPerView + loopedSlides || 1878 (swiper.params.effect === 'cards' && slides.length < slidesPerView + loopedSlides * 2)) { 1879 showWarning('Swiper Loop Warning: The number of slides is not enough for loop mode, it will be disabled or not function properly. You need to add more slides (or make duplicates) or lower the values of slidesPerView and slidesPerGroup parameters'); 1880 } 1881 else if (gridEnabled && params.grid.fill === 'row') { 1882 showWarning('Swiper Loop Warning: Loop mode is not compatible with grid.fill = `row`'); 1883 } 1884 const prependSlidesIndexes = []; 1885 const appendSlidesIndexes = []; 1886 const cols = gridEnabled ? Math.ceil(slides.length / params.grid.rows) : slides.length; 1887 const isInitialOverflow = initial && cols - initialSlide < slidesPerView && !bothDirections; 1888 let activeIndex = isInitialOverflow ? initialSlide : swiper.activeIndex; 1889 if (typeof activeSlideIndex === 'undefined') { 1890 activeSlideIndex = swiper.getSlideIndex(slides.find((el) => el.classList.contains(params.slideActiveClass))); 1891 } 1892 else { 1893 activeIndex = activeSlideIndex; 1894 } 1895 const isNext = direction === 'next' || !direction; 1896 const isPrev = direction === 'prev' || !direction; 1897 let slidesPrepended = 0; 1898 let slidesAppended = 0; 1899 const activeColIndex = gridEnabled 1900 ? (slides[activeSlideIndex].column ?? 0) 1901 : activeSlideIndex; 1902 const activeColIndexWithShift = activeColIndex + 1903 (bothDirections && typeof setTranslate === 'undefined' ? -slidesPerView / 2 + 0.5 : 0); 1904 // prepend last slides before start 1905 if (activeColIndexWithShift < loopedSlides) { 1906 slidesPrepended = Math.max(loopedSlides - activeColIndexWithShift, slidesPerGroup); 1907 for (let i = 0; i < loopedSlides - activeColIndexWithShift; i += 1) { 1908 const index = i - Math.floor(i / cols) * cols; 1909 if (gridEnabled) { 1910 const colIndexToPrepend = cols - index - 1; 1911 for (let j = slides.length - 1; j >= 0; j -= 1) { 1912 if (slides[j].column === colIndexToPrepend) 1913 prependSlidesIndexes.push(j); 1914 } 1915 } 1916 else { 1917 prependSlidesIndexes.push(cols - index - 1); 1918 } 1919 } 1920 } 1921 else if (activeColIndexWithShift + slidesPerView > cols - loopedSlides) { 1922 slidesAppended = Math.max(activeColIndexWithShift - (cols - loopedSlides * 2), slidesPerGroup); 1923 if (isInitialOverflow) { 1924 slidesAppended = Math.max(slidesAppended, slidesPerView - cols + initialSlide + 1); 1925 } 1926 for (let i = 0; i < slidesAppended; i += 1) { 1927 const index = i - Math.floor(i / cols) * cols; 1928 if (gridEnabled) { 1929 slides.forEach((slide, slideIndex) => { 1930 if (slide.column === index) 1931 appendSlidesIndexes.push(slideIndex); 1932 }); 1933 } 1934 else { 1935 appendSlidesIndexes.push(index); 1936 } 1937 } 1938 } 1939 swiper.__preventObserver__ = true; 1940 requestAnimationFrame(() => { 1941 swiper.__preventObserver__ = false; 1942 }); 1943 if (swiper.params.effect === 'cards' && slides.length < slidesPerView + loopedSlides * 2) { 1944 if (appendSlidesIndexes.includes(activeSlideIndex)) { 1945 appendSlidesIndexes.splice(appendSlidesIndexes.indexOf(activeSlideIndex), 1); 1946 } 1947 if (prependSlidesIndexes.includes(activeSlideIndex)) { 1948 prependSlidesIndexes.splice(prependSlidesIndexes.indexOf(activeSlideIndex), 1); 1949 } 1950 } 1951 if (isPrev) { 1952 prependSlidesIndexes.forEach((index) => { 1953 const slideEl = slides[index]; 1954 slideEl.swiperLoopMoveDOM = true; 1955 slidesEl.prepend(slideEl); 1956 slideEl.swiperLoopMoveDOM = false; 1957 }); 1958 } 1959 if (isNext) { 1960 appendSlidesIndexes.forEach((index) => { 1961 const slideEl = slides[index]; 1962 slideEl.swiperLoopMoveDOM = true; 1963 slidesEl.append(slideEl); 1964 slideEl.swiperLoopMoveDOM = false; 1965 }); 1966 } 1967 swiper.recalcSlides(); 1968 if (params.slidesPerView === 'auto') { 1969 swiper.updateSlides(); 1970 } 1971 else if (gridEnabled && 1972 ((prependSlidesIndexes.length > 0 && isPrev) || (appendSlidesIndexes.length > 0 && isNext))) { 1973 swiper.slides.forEach((slide, slideIndex) => { 1974 swiper.grid.updateSlide(slideIndex, slide, swiper.slides); 1975 }); 1976 } 1977 if (params.watchSlidesProgress) { 1978 swiper.updateSlidesOffset(); 1979 } 1980 if (slideTo) { 1981 if (prependSlidesIndexes.length > 0 && isPrev) { 1982 if (typeof slideRealIndex === 'undefined') { 1983 const currentSlideTranslate = swiper.slidesGrid[activeIndex]; 1984 const newSlideTranslate = swiper.slidesGrid[activeIndex + slidesPrepended]; 1985 const diff = newSlideTranslate - currentSlideTranslate; 1986 if (byMousewheel) { 1987 swiper.setTranslate(swiper.translate - diff); 1988 } 1989 else { 1990 swiper.slideTo(activeIndex + Math.ceil(slidesPrepended), 0, false, true); 1991 if (setTranslate) { 1992 swiper.touchEventsData.startTranslate = 1993 swiper.touchEventsData.startTranslate - diff; 1994 swiper.touchEventsData.currentTranslate = 1995 swiper.touchEventsData.currentTranslate - diff; 1996 } 1997 } 1998 } 1999 else { 2000 if (setTranslate) { 2001 const shift = gridEnabled 2002 ? prependSlidesIndexes.length / params.grid.rows 2003 : prependSlidesIndexes.length; 2004 swiper.slideTo(swiper.activeIndex + shift, 0, false, true); 2005 swiper.touchEventsData.currentTranslate = swiper.translate; 2006 } 2007 } 2008 } 2009 else if (appendSlidesIndexes.length > 0 && isNext) { 2010 if (typeof slideRealIndex === 'undefined') { 2011 const currentSlideTranslate = swiper.slidesGrid[activeIndex]; 2012 const newSlideTranslate = swiper.slidesGrid[activeIndex - slidesAppended]; 2013 const diff = newSlideTranslate - currentSlideTranslate; 2014 if (byMousewheel) { 2015 swiper.setTranslate(swiper.translate - diff); 2016 } 2017 else { 2018 swiper.slideTo(activeIndex - slidesAppended, 0, false, true); 2019 if (setTranslate) { 2020 swiper.touchEventsData.startTranslate = 2021 swiper.touchEventsData.startTranslate - diff; 2022 swiper.touchEventsData.currentTranslate = 2023 swiper.touchEventsData.currentTranslate - diff; 2024 } 2025 } 2026 } 2027 else { 2028 const shift = gridEnabled 2029 ? appendSlidesIndexes.length / params.grid.rows 2030 : appendSlidesIndexes.length; 2031 swiper.slideTo(swiper.activeIndex - shift, 0, false, true); 2032 } 2033 } 2034 } 2035 swiper.allowSlidePrev = allowSlidePrev; 2036 swiper.allowSlideNext = allowSlideNext; 2037 const controlled = swiper.controller?.control; 2038 if (controlled && !byController) { 2039 const loopParams = { 2040 slideRealIndex, 2041 direction, 2042 setTranslate, 2043 activeSlideIndex, 2044 byController: true, 2045 }; 2046 if (Array.isArray(controlled)) { 2047 controlled.forEach((c) => { 2048 if (!c.destroyed && c.params.loop) 2049 c.loopFix({ 2050 ...loopParams, 2051 slideTo: c.params.slidesPerView === params.slidesPerView ? slideTo : false, 2052 }); 2053 }); 2054 } 2055 else if (controlled instanceof swiper.constructor && 2056 controlled.params.loop) { 2057 controlled.loopFix({ 2058 ...loopParams, 2059 slideTo: controlled.params.slidesPerView === params.slidesPerView ? slideTo : false, 2060 }); 2061 } 2062 }
vendor: 37,413 bytes, lines 2062-2983
2062 2063 swiper.emit('loopFix'); 2064 } 2065 2066 var loop = { 2067 loopCreate, 2068 loopFix, 2069 loopDestroy, 2070 }; 2071 2072 function moduleExtendParams(params, allModulesParams) { 2073 return function extendParams(obj = {}) { 2074 const moduleParamName = Object.keys(obj)[0]; 2075 const moduleParams = obj[moduleParamName]; 2076 if (typeof moduleParams !== 'object' || moduleParams === null) { 2077 extend(allModulesParams, obj); 2078 return; 2079 } 2080 if (params[moduleParamName] === true) { 2081 params[moduleParamName] = { enabled: true }; 2082 } 2083 if (moduleParamName === 'navigation' && 2084 params[moduleParamName] && 2085 params[moduleParamName].enabled && 2086 !params[moduleParamName].prevEl && 2087 !params[moduleParamName].nextEl) { 2088 params[moduleParamName].auto = true; 2089 } 2090 if (['pagination', 'scrollbar'].indexOf(moduleParamName) >= 0 && 2091 params[moduleParamName] && 2092 params[moduleParamName].enabled && 2093 !params[moduleParamName].el) { 2094 params[moduleParamName].auto = true; 2095 } 2096 if (!(moduleParamName in params && 'enabled' in moduleParams)) { 2097 extend(allModulesParams, obj); 2098 return; 2099 } 2100 if (typeof params[moduleParamName] === 'object' && !('enabled' in params[moduleParamName])) { 2101 params[moduleParamName].enabled = true; 2102 } 2103 if (!params[moduleParamName]) 2104 params[moduleParamName] = { enabled: false }; 2105 extend(allModulesParams, obj); 2106 }; 2107 } 2108 2109 const Observer = ({ swiper, extendParams, on }) => { 2110 const observers = []; 2111 const attach = (target, options = {}) => { 2112 const ObserverFunc = window.MutationObserver || 2113 window 2114 .WebkitMutationObserver; 2115 if (!ObserverFunc) 2116 return; 2117 const observer = new ObserverFunc((mutations) => { 2118 // The observerUpdate event should only be triggered 2119 // once despite the number of mutations. Additional 2120 // triggers are redundant and are very costly 2121 if (swiper.__preventObserver__) 2122 return; 2123 if (mutations.length === 1) { 2124 swiper.emit('observerUpdate', mutations[0]); 2125 return; 2126 } 2127 const observerUpdate = function observerUpdate() { 2128 swiper.emit('observerUpdate', mutations[0]); 2129 }; 2130 if (window.requestAnimationFrame) { 2131 window.requestAnimationFrame(observerUpdate); 2132 } 2133 else { 2134 window.setTimeout(observerUpdate, 0); 2135 } 2136 }); 2137 observer.observe(target, { 2138 attributes: typeof options.attributes === 'undefined' ? true : options.attributes, 2139 childList: swiper.isElement || (typeof options.childList === 'undefined' ? true : options.childList), 2140 characterData: typeof options.characterData === 'undefined' ? true : options.characterData, 2141 }); 2142 observers.push(observer); 2143 }; 2144 const init = () => { 2145 if (!swiper.params.observer) 2146 return; 2147 if (swiper.params.observeParents) { 2148 const containerParents = elementParents(swiper.hostEl); 2149 for (let i = 0; i < containerParents.length; i += 1) { 2150 attach(containerParents[i]); 2151 } 2152 } 2153 // Observe container 2154 attach(swiper.hostEl, { 2155 childList: swiper.params.observeSlideChildren, 2156 }); 2157 // Observe wrapper 2158 attach(swiper.wrapperEl, { attributes: false }); 2159 }; 2160 const destroy = () => { 2161 observers.forEach((observer) => { 2162 observer.disconnect(); 2163 }); 2164 observers.splice(0, observers.length); 2165 }; 2166 extendParams({ 2167 observer: false, 2168 observeParents: false, 2169 observeSlideChildren: false, 2170 }); 2171 on('init', init); 2172 on('destroy', destroy); 2173 }; 2174 2175 const Resize = ({ swiper, on, emit }) => { 2176 let observer = null; 2177 let animationFrame = null; 2178 const resizeHandler = () => { 2179 if (!swiper || swiper.destroyed || !swiper.initialized) 2180 return; 2181 emit('beforeResize'); 2182 emit('resize'); 2183 }; 2184 const createObserver = () => { 2185 if (!swiper || swiper.destroyed || !swiper.initialized) 2186 return; 2187 observer = new ResizeObserver((entries) => { 2188 animationFrame = window.requestAnimationFrame(() => { 2189 const { width, height } = swiper; 2190 let newWidth = width; 2191 let newHeight = height; 2192 entries.forEach(({ contentBoxSize, contentRect, target }) => { 2193 if (target && target !== swiper.el) 2194 return; 2195 // Older Safari (≤15) exposed `contentBoxSize` as a single object instead of an array. 2196 const box = Array.isArray(contentBoxSize) 2197 ? contentBoxSize[0] 2198 : contentBoxSize; 2199 newWidth = contentRect ? contentRect.width : box.inlineSize; 2200 newHeight = contentRect ? contentRect.height : box.blockSize; 2201 }); 2202 if (newWidth !== width || newHeight !== height) { 2203 resizeHandler(); 2204 } 2205 }); 2206 }); 2207 observer.observe(swiper.el); 2208 }; 2209 const removeObserver = () => { 2210 if (animationFrame) { 2211 window.cancelAnimationFrame(animationFrame); 2212 } 2213 if (observer && observer.unobserve && swiper.el) { 2214 observer.unobserve(swiper.el); 2215 observer = null; 2216 } 2217 }; 2218 const orientationChangeHandler = () => { 2219 if (!swiper || swiper.destroyed || !swiper.initialized) 2220 return; 2221 emit('orientationchange'); 2222 }; 2223 on('init', () => { 2224 if (swiper.params.resizeObserver && typeof window.ResizeObserver !== 'undefined') { 2225 createObserver(); 2226 return; 2227 } 2228 window.addEventListener('resize', resizeHandler); 2229 window.addEventListener('orientationchange', orientationChangeHandler); 2230 }); 2231 on('destroy', () => { 2232 removeObserver(); 2233 window.removeEventListener('resize', resizeHandler); 2234 window.removeEventListener('orientationchange', orientationChangeHandler); 2235 }); 2236 }; 2237 2238 function slideNext(speed, runCallbacks = true, internal) { 2239 const swiper = this; 2240 const { enabled, params, animating } = swiper; 2241 if (!enabled || swiper.destroyed) 2242 return swiper; 2243 if (typeof speed === 'undefined') { 2244 speed = swiper.params.speed; 2245 } 2246 let perGroup = params.slidesPerGroup; 2247 if (params.slidesPerView === 'auto' && params.slidesPerGroup === 1 && params.slidesPerGroupAuto) { 2248 perGroup = Math.max(swiper.slidesPerViewDynamic('current', true), 1); 2249 } 2250 const increment = swiper.activeIndex < params.slidesPerGroupSkip ? 1 : perGroup; 2251 const isVirtual = swiper.virtual && params.virtual?.enabled; 2252 if (params.loop) { 2253 if (animating && !isVirtual && params.loopPreventsSliding) 2254 return false; 2255 swiper.loopFix({ direction: 'next' }); 2256 swiper._clientLeft = swiper.wrapperEl.clientLeft; 2257 if (swiper.activeIndex === swiper.slides.length - 1 && params.cssMode) { 2258 requestAnimationFrame(() => { 2259 swiper.slideTo(swiper.activeIndex + increment, speed, runCallbacks, internal); 2260 }); 2261 return true; 2262 } 2263 } 2264 if (params.rewind && swiper.isEnd) { 2265 return swiper.slideTo(0, speed, runCallbacks, internal); 2266 } 2267 return swiper.slideTo(swiper.activeIndex + increment, speed, runCallbacks, internal); 2268 } 2269 2270 function slidePrev(speed, runCallbacks = true, internal) { 2271 const swiper = this; 2272 const { params, snapGrid, slidesGrid, rtlTranslate, enabled, animating } = swiper; 2273 if (!enabled || swiper.destroyed) 2274 return swiper; 2275 if (typeof speed === 'undefined') { 2276 speed = swiper.params.speed; 2277 } 2278 const isVirtual = swiper.virtual && params.virtual?.enabled; 2279 if (params.loop) { 2280 if (animating && !isVirtual && params.loopPreventsSliding) 2281 return false; 2282 swiper.loopFix({ direction: 'prev' }); 2283 swiper._clientLeft = swiper.wrapperEl.clientLeft; 2284 } 2285 const translate = rtlTranslate ? swiper.translate : -swiper.translate; 2286 function normalize(val) { 2287 if (val < 0) 2288 return -Math.floor(Math.abs(val)); 2289 return Math.floor(val); 2290 } 2291 const normalizedTranslate = normalize(translate); 2292 const normalizedSnapGrid = snapGrid.map((val) => normalize(val)); 2293 const isFreeMode = params.freeMode && params.freeMode.enabled; 2294 let prevSnap = snapGrid[normalizedSnapGrid.indexOf(normalizedTranslate) - 1]; 2295 if (typeof prevSnap === 'undefined' && (params.cssMode || isFreeMode)) { 2296 let prevSnapIndex; 2297 snapGrid.forEach((snap, snapIndex) => { 2298 if (normalizedTranslate >= snap) { 2299 prevSnapIndex = snapIndex; 2300 } 2301 }); 2302 if (typeof prevSnapIndex !== 'undefined') { 2303 prevSnap = isFreeMode 2304 ? snapGrid[prevSnapIndex] 2305 : snapGrid[prevSnapIndex > 0 ? prevSnapIndex - 1 : prevSnapIndex]; 2306 } 2307 } 2308 let prevIndex = 0; 2309 if (typeof prevSnap !== 'undefined') { 2310 prevIndex = slidesGrid.indexOf(prevSnap); 2311 if (prevIndex < 0) 2312 prevIndex = swiper.activeIndex - 1; 2313 if (params.slidesPerView === 'auto' && 2314 params.slidesPerGroup === 1 && 2315 params.slidesPerGroupAuto) { 2316 prevIndex = prevIndex - swiper.slidesPerViewDynamic('previous', true) + 1; 2317 prevIndex = Math.max(prevIndex, 0); 2318 } 2319 } 2320 if (params.rewind && swiper.isBeginning) { 2321 const lastIndex = swiper.params.virtual?.enabled && swiper.virtual 2322 ? swiper.virtual.slides.length - 1 2323 : swiper.slides.length - 1; 2324 return swiper.slideTo(lastIndex, speed, runCallbacks, internal); 2325 } 2326 else if (params.loop && swiper.activeIndex === 0 && params.cssMode) { 2327 requestAnimationFrame(() => { 2328 swiper.slideTo(prevIndex, speed, runCallbacks, internal); 2329 }); 2330 return true; 2331 } 2332 return swiper.slideTo(prevIndex, speed, runCallbacks, internal); 2333 } 2334 2335 function slideReset(speed, runCallbacks = true, internal) { 2336 const swiper = this; 2337 if (swiper.destroyed) 2338 return; 2339 if (typeof speed === 'undefined') { 2340 speed = swiper.params.speed; 2341 } 2342 return swiper.slideTo(swiper.activeIndex, speed, runCallbacks, internal); 2343 } 2344 2345 function slideTo(index = 0, speed, runCallbacks = true, internal, initial) { 2346 if (typeof index === 'string') { 2347 index = parseInt(index, 10); 2348 } 2349 const swiper = this; 2350 let slideIndex = index; 2351 if (slideIndex < 0) 2352 slideIndex = 0; 2353 const { params, snapGrid, slidesGrid, previousIndex, activeIndex, rtlTranslate: rtl, wrapperEl, enabled, } = swiper; 2354 if ((!enabled && !internal && !initial) || 2355 swiper.destroyed || 2356 (swiper.animating && params.preventInteractionOnTransition)) { 2357 return false; 2358 } 2359 if (typeof speed === 'undefined') { 2360 speed = swiper.params.speed; 2361 } 2362 const skip = Math.min(swiper.params.slidesPerGroupSkip, slideIndex); 2363 let snapIndex = skip + Math.floor((slideIndex - skip) / swiper.params.slidesPerGroup); 2364 if (snapIndex >= snapGrid.length) 2365 snapIndex = snapGrid.length - 1; 2366 const translate = -snapGrid[snapIndex]; 2367 // Normalize slideIndex 2368 if (params.normalizeSlideIndex) { 2369 for (let i = 0; i < slidesGrid.length; i += 1) { 2370 const normalizedTranslate = -Math.floor(translate * 100); 2371 const normalizedGrid = Math.floor(slidesGrid[i] * 100); 2372 const normalizedGridNext = Math.floor(slidesGrid[i + 1] * 100); 2373 if (typeof slidesGrid[i + 1] !== 'undefined') { 2374 if (normalizedTranslate >= normalizedGrid && 2375 normalizedTranslate < normalizedGridNext - (normalizedGridNext - normalizedGrid) / 2) { 2376 slideIndex = i; 2377 } 2378 else if (normalizedTranslate >= normalizedGrid && 2379 normalizedTranslate < normalizedGridNext) { 2380 slideIndex = i + 1; 2381 } 2382 } 2383 else if (normalizedTranslate >= normalizedGrid) { 2384 slideIndex = i; 2385 } 2386 } 2387 } 2388 // Directions locks 2389 if (swiper.initialized && slideIndex !== activeIndex) { 2390 if (!swiper.allowSlideNext && 2391 (rtl 2392 ? translate > swiper.translate && translate > swiper.minTranslate() 2393 : translate < swiper.translate && translate < swiper.minTranslate())) { 2394 return false; 2395 } 2396 if (!swiper.allowSlidePrev && 2397 translate > swiper.translate && 2398 translate > swiper.maxTranslate()) { 2399 if ((activeIndex || 0) !== slideIndex) { 2400 return false; 2401 } 2402 } 2403 } 2404 if (slideIndex !== (previousIndex || 0) && runCallbacks) { 2405 swiper.emit('beforeSlideChangeStart'); 2406 } 2407 // Update progress 2408 swiper.updateProgress(translate); 2409 let direction; 2410 if (slideIndex > activeIndex) 2411 direction = 'next'; 2412 else if (slideIndex < activeIndex) 2413 direction = 'prev'; 2414 else 2415 direction = 'reset'; 2416 // initial virtual 2417 const isVirtual = swiper.virtual && swiper.params.virtual?.enabled; 2418 const isInitialVirtual = isVirtual && initial; 2419 // Update Index 2420 if (!isInitialVirtual && 2421 ((rtl && -translate === swiper.translate) || (!rtl && translate === swiper.translate))) { 2422 swiper.updateActiveIndex(slideIndex); 2423 // Update Height 2424 if (params.autoHeight) { 2425 swiper.updateAutoHeight(); 2426 } 2427 swiper.updateSlidesClasses(); 2428 if (params.effect !== 'slide') { 2429 swiper.setTranslate(translate); 2430 } 2431 if (direction !== 'reset') { 2432 swiper.transitionStart(runCallbacks, direction); 2433 swiper.transitionEnd(runCallbacks, direction); 2434 } 2435 return false; 2436 } 2437 if (params.cssMode) { 2438 const isH = swiper.isHorizontal(); 2439 const t = rtl ? translate : -translate; 2440 if (speed === 0) { 2441 if (isVirtual) { 2442 swiper.wrapperEl.style.scrollSnapType = 'none'; 2443 swiper._immediateVirtual = true; 2444 } 2445 if (isVirtual && !swiper._cssModeVirtualInitialSet && (swiper.params.initialSlide ?? 0) > 0) { 2446 swiper._cssModeVirtualInitialSet = true; 2447 requestAnimationFrame(() => { 2448 wrapperEl[isH ? 'scrollLeft' : 'scrollTop'] = t; 2449 }); 2450 } 2451 else { 2452 wrapperEl[isH ? 'scrollLeft' : 'scrollTop'] = t; 2453 } 2454 if (isVirtual) { 2455 requestAnimationFrame(() => { 2456 swiper.wrapperEl.style.scrollSnapType = ''; 2457 swiper._immediateVirtual = false; 2458 }); 2459 } 2460 } 2461 else { 2462 wrapperEl.scrollTo({ 2463 [isH ? 'left' : 'top']: t, 2464 behavior: 'smooth', 2465 }); 2466 } 2467 return true; 2468 } 2469 const browser = getBrowser(); 2470 const isSafari = browser.isSafari; 2471 if (isVirtual && !initial && isSafari && swiper.isElement) { 2472 swiper.virtual.update(false, false, slideIndex); 2473 } 2474 swiper.setTransition(speed); 2475 swiper.setTranslate(translate); 2476 swiper.updateActiveIndex(slideIndex); 2477 swiper.updateSlidesClasses(); 2478 swiper.emit('beforeTransitionStart', speed, internal); 2479 swiper.transitionStart(runCallbacks, direction); 2480 if (speed === 0) { 2481 swiper.transitionEnd(runCallbacks, direction); 2482 } 2483 else if (!swiper.animating) { 2484 swiper.animating = true; 2485 if (!swiper.onSlideToWrapperTransitionEnd) { 2486 swiper.onSlideToWrapperTransitionEnd = function transitionEnd(e) { 2487 if (!swiper || swiper.destroyed) 2488 return; 2489 if (e.target !== this) 2490 return; 2491 swiper.wrapperEl.removeEventListener('transitionend', swiper.onSlideToWrapperTransitionEnd); 2492 swiper.onSlideToWrapperTransitionEnd = null; 2493 delete swiper.onSlideToWrapperTransitionEnd; 2494 swiper.transitionEnd(runCallbacks, direction); 2495 }; 2496 } 2497 swiper.wrapperEl.addEventListener('transitionend', swiper.onSlideToWrapperTransitionEnd); 2498 } 2499 return true; 2500 } 2501 2502 function slideToClickedSlide() { 2503 const swiper = this; 2504 if (swiper.destroyed) 2505 return; 2506 const { params, slidesEl, clickedSlide, clickedIndex } = swiper; 2507 if (clickedSlide === undefined || clickedIndex === undefined) 2508 return; 2509 const slidesPerView = params.slidesPerView === 'auto' 2510 ? swiper.slidesPerViewDynamic() 2511 : params.slidesPerView; 2512 let slideToIndex = swiper.getSlideIndexWhenGrid(clickedIndex); 2513 let realIndex; 2514 const slideSelector = swiper.isElement ? `swiper-slide` : `.${params.slideClass}`; 2515 const isGrid = swiper.grid && swiper.params.grid && swiper.params.grid.rows > 1; 2516 if (params.loop) { 2517 if (swiper.animating) 2518 return; 2519 realIndex = parseInt(clickedSlide.getAttribute('data-swiper-slide-index'), 10); 2520 if (params.centeredSlides) { 2521 swiper.slideToLoop(realIndex); 2522 } 2523 else if (slideToIndex > 2524 (isGrid 2525 ? (swiper.slides.length - slidesPerView) / 2 - (swiper.params.grid.rows - 1) 2526 : swiper.slides.length - slidesPerView)) { 2527 swiper.loopFix(); 2528 slideToIndex = swiper.getSlideIndex(elementChildren(slidesEl, `${slideSelector}[data-swiper-slide-index="${realIndex}"]`)[0]); 2529 nextTick(() => { 2530 swiper.slideTo(slideToIndex); 2531 }); 2532 } 2533 else { 2534 swiper.slideTo(slideToIndex); 2535 } 2536 } 2537 else { 2538 swiper.slideTo(slideToIndex); 2539 } 2540 } 2541 2542 function slideToClosest(speed, runCallbacks = true, internal, threshold = 0.5) { 2543 const swiper = this; 2544 if (swiper.destroyed) 2545 return; 2546 if (typeof speed === 'undefined') { 2547 speed = swiper.params.speed; 2548 } 2549 let index = swiper.activeIndex; 2550 const skip = Math.min(swiper.params.slidesPerGroupSkip, index); 2551 const snapIndex = skip + Math.floor((index - skip) / swiper.params.slidesPerGroup); 2552 const translate = swiper.rtlTranslate ? swiper.translate : -swiper.translate; 2553 if (translate >= swiper.snapGrid[snapIndex]) { 2554 // The current translate is on or after the current snap index, so the choice 2555 // is between the current index and the one after it. 2556 const currentSnap = swiper.snapGrid[snapIndex]; 2557 const nextSnap = swiper.snapGrid[snapIndex + 1]; 2558 if (translate - currentSnap > (nextSnap - currentSnap) * threshold) { 2559 index += swiper.params.slidesPerGroup; 2560 } 2561 } 2562 else { 2563 // The current translate is before the current snap index, so the choice 2564 // is between the current index and the one before it. 2565 const prevSnap = swiper.snapGrid[snapIndex - 1]; 2566 const currentSnap = swiper.snapGrid[snapIndex]; 2567 if (translate - prevSnap <= (currentSnap - prevSnap) * threshold) { 2568 index -= swiper.params.slidesPerGroup; 2569 } 2570 } 2571 index = Math.max(index, 0); 2572 index = Math.min(index, swiper.slidesGrid.length - 1); 2573 return swiper.slideTo(index, speed, runCallbacks, internal); 2574 } 2575 2576 function slideToLoop(index = 0, speed, runCallbacks = true, internal) { 2577 if (typeof index === 'string') { 2578 const indexAsNumber = parseInt(index, 10); 2579 index = indexAsNumber; 2580 } 2581 const swiper = this; 2582 if (swiper.destroyed) 2583 return; 2584 if (typeof speed === 'undefined') { 2585 speed = swiper.params.speed; 2586 } 2587 const gridEnabled = swiper.grid && swiper.params.grid && swiper.params.grid.rows > 1; 2588 let newIndex = index; 2589 if (swiper.params.loop) { 2590 if (swiper.virtual && swiper.params.virtual?.enabled) { 2591 newIndex = newIndex + (swiper.virtual.slidesBefore ?? 0); 2592 } 2593 else { 2594 let targetSlideIndex; 2595 if (gridEnabled) { 2596 const slideIndex = newIndex * swiper.params.grid.rows; 2597 const targetSlideEl = swiper.slides.find((slideEl) => Number(slideEl.getAttribute('data-swiper-slide-index')) === slideIndex); 2598 targetSlideIndex = targetSlideEl?.column ?? 0; 2599 } 2600 else { 2601 targetSlideIndex = swiper.getSlideIndexByData(newIndex); 2602 } 2603 const cols = gridEnabled 2604 ? Math.ceil(swiper.slides.length / swiper.params.grid.rows) 2605 : swiper.slides.length; 2606 const { centeredSlides, slidesOffsetBefore, slidesOffsetAfter } = swiper.params; 2607 const bothDirections = centeredSlides || !!slidesOffsetBefore || !!slidesOffsetAfter; 2608 let slidesPerView; 2609 if (swiper.params.slidesPerView === 'auto') { 2610 slidesPerView = swiper.slidesPerViewDynamic(); 2611 } 2612 else { 2613 slidesPerView = Math.ceil(parseFloat(String(swiper.params.slidesPerView))); 2614 if (bothDirections && slidesPerView % 2 === 0) { 2615 slidesPerView = slidesPerView + 1; 2616 } 2617 } 2618 let needLoopFix = cols - targetSlideIndex < slidesPerView; 2619 if (bothDirections) { 2620 needLoopFix = needLoopFix || targetSlideIndex < Math.ceil(slidesPerView / 2); 2621 } 2622 if (internal && bothDirections && swiper.params.slidesPerView !== 'auto' && !gridEnabled) { 2623 needLoopFix = false; 2624 } 2625 if (needLoopFix) { 2626 const direction = bothDirections 2627 ? targetSlideIndex < swiper.activeIndex 2628 ? 'prev' 2629 : 'next' 2630 : targetSlideIndex - swiper.activeIndex - 1 < swiper.params.slidesPerView 2631 ? 'next' 2632 : 'prev'; 2633 swiper.loopFix({ 2634 direction, 2635 slideTo: true, 2636 activeSlideIndex: direction === 'next' ? targetSlideIndex + 1 : targetSlideIndex - cols + 1, 2637 slideRealIndex: direction === 'next' ? swiper.realIndex : undefined, 2638 }); 2639 } 2640 if (gridEnabled) { 2641 const slideIndex = newIndex * swiper.params.grid.rows; 2642 const targetSlideEl = swiper.slides.find((slideEl) => Number(slideEl.getAttribute('data-swiper-slide-index')) === slideIndex); 2643 newIndex = targetSlideEl?.column ?? 0; 2644 } 2645 else { 2646 newIndex = swiper.getSlideIndexByData(newIndex); 2647 } 2648 } 2649 } 2650 requestAnimationFrame(() => { 2651 swiper.slideTo(newIndex, speed, runCallbacks, internal); 2652 }); 2653 return swiper; 2654 } 2655 2656 var slide = { 2657 slideTo, 2658 slideToLoop, 2659 slideNext, 2660 slidePrev, 2661 slideReset, 2662 slideToClosest, 2663 slideToClickedSlide, 2664 }; 2665 2666 function setTransition(duration, byController) { 2667 const swiper = this; 2668 if (!swiper.params.cssMode) { 2669 swiper.wrapperEl.style.transitionDuration = `${duration}ms`; 2670 swiper.wrapperEl.style.transitionDelay = duration === 0 ? `0ms` : ''; 2671 } 2672 swiper.emit('setTransition', duration, byController); 2673 } 2674 2675 function transitionEmit({ swiper, runCallbacks, direction, step, }) { 2676 const { activeIndex, previousIndex } = swiper; 2677 let dir = direction; 2678 if (!dir) { 2679 if (activeIndex > previousIndex) 2680 dir = 'next'; 2681 else if (activeIndex < previousIndex) 2682 dir = 'prev'; 2683 else 2684 dir = 'reset'; 2685 } 2686 swiper.emit(`transition${step}`); 2687 if (runCallbacks && dir === 'reset') { 2688 swiper.emit(`slideResetTransition${step}`); 2689 } 2690 else if (runCallbacks && activeIndex !== previousIndex) { 2691 swiper.emit(`slideChangeTransition${step}`); 2692 if (dir === 'next') { 2693 swiper.emit(`slideNextTransition${step}`); 2694 } 2695 else { 2696 swiper.emit(`slidePrevTransition${step}`); 2697 } 2698 } 2699 } 2700 2701 function transitionEnd(runCallbacks = true, direction) { 2702 const swiper = this; 2703 const { params } = swiper; 2704 swiper.animating = false; 2705 if (params.cssMode) 2706 return; 2707 swiper.setTransition(0); 2708 transitionEmit({ swiper, runCallbacks, direction, step: 'End' }); 2709 } 2710 2711 function transitionStart(runCallbacks = true, direction) { 2712 const swiper = this; 2713 const { params } = swiper; 2714 if (params.cssMode) 2715 return; 2716 if (params.autoHeight) { 2717 swiper.updateAutoHeight(); 2718 } 2719 transitionEmit({ swiper, runCallbacks, direction, step: 'Start' }); 2720 } 2721 2722 var transition = { 2723 setTransition, 2724 transitionStart, 2725 transitionEnd, 2726 }; 2727 2728 function getSwiperTranslate(axis = this.isHorizontal() ? 'x' : 'y') { 2729 const swiper = this; 2730 const { params, rtlTranslate: rtl, translate, wrapperEl } = swiper; 2731 if (params.virtualTranslate) { 2732 return rtl ? -translate : translate; 2733 } 2734 if (params.cssMode) { 2735 return translate; 2736 } 2737 let currentTranslate = getTranslate(wrapperEl, axis); 2738 currentTranslate += swiper.cssOverflowAdjustment(); 2739 if (rtl) 2740 currentTranslate = -currentTranslate; 2741 return currentTranslate || 0; 2742 } 2743 2744 function maxTranslate() { 2745 return -this.snapGrid[this.snapGrid.length - 1]; 2746 } 2747 2748 function minTranslate() { 2749 return -this.snapGrid[0]; 2750 } 2751 2752 function setTranslate(translate, byController) { 2753 const swiper = this; 2754 const { rtlTranslate: rtl, params, wrapperEl, progress } = swiper; 2755 let x = 0; 2756 let y = 0; 2757 const z = 0; 2758 if (swiper.isHorizontal()) { 2759 x = rtl ? -translate : translate; 2760 } 2761 else { 2762 y = translate; 2763 } 2764 if (params.roundLengths) { 2765 x = Math.floor(x); 2766 y = Math.floor(y); 2767 } 2768 swiper.previousTranslate = swiper.translate; 2769 swiper.translate = swiper.isHorizontal() ? x : y; 2770 if (params.cssMode) { 2771 wrapperEl[swiper.isHorizontal() ? 'scrollLeft' : 'scrollTop'] = swiper.isHorizontal() ? -x : -y; 2772 } 2773 else if (!params.virtualTranslate) { 2774 if (swiper.isHorizontal()) { 2775 x -= swiper.cssOverflowAdjustment(); 2776 } 2777 else { 2778 y -= swiper.cssOverflowAdjustment(); 2779 } 2780 wrapperEl.style.transform = `translate3d(${x}px, ${y}px, ${z}px)`; 2781 } 2782 // Check if we need to update progress 2783 let newProgress; 2784 const translatesDiff = swiper.maxTranslate() - swiper.minTranslate(); 2785 if (translatesDiff === 0) { 2786 newProgress = 0; 2787 } 2788 else { 2789 newProgress = (translate - swiper.minTranslate()) / translatesDiff; 2790 } 2791 if (newProgress !== progress) { 2792 swiper.updateProgress(translate); 2793 } 2794 swiper.emit('setTranslate', swiper.translate, byController); 2795 } 2796 2797 function translateTo(translate = 0, speed = this.params.speed, runCallbacks = true, translateBounds = true, internal) { 2798 const swiper = this; 2799 const { params, wrapperEl } = swiper; 2800 if (swiper.animating && params.preventInteractionOnTransition) { 2801 return false; 2802 } 2803 const minTranslate = swiper.minTranslate(); 2804 const maxTranslate = swiper.maxTranslate(); 2805 let newTranslate; 2806 if (translateBounds && translate > minTranslate) 2807 newTranslate = minTranslate; 2808 else if (translateBounds && translate < maxTranslate) 2809 newTranslate = maxTranslate; 2810 else 2811 newTranslate = translate; 2812 // Update progress 2813 swiper.updateProgress(newTranslate); 2814 if (params.cssMode) { 2815 const isH = swiper.isHorizontal(); 2816 if (speed === 0) { 2817 wrapperEl[isH ? 'scrollLeft' : 'scrollTop'] = -newTranslate; 2818 } 2819 else { 2820 wrapperEl.scrollTo({ 2821 [isH ? 'left' : 'top']: -newTranslate, 2822 behavior: 'smooth', 2823 }); 2824 } 2825 return true; 2826 } 2827 if (speed === 0) { 2828 swiper.setTransition(0); 2829 swiper.setTranslate(newTranslate); 2830 if (runCallbacks) { 2831 swiper.emit('beforeTransitionStart', speed, internal); 2832 swiper.emit('transitionEnd'); 2833 } 2834 } 2835 else { 2836 swiper.setTransition(speed); 2837 swiper.setTranslate(newTranslate); 2838 if (runCallbacks) { 2839 swiper.emit('beforeTransitionStart', speed, internal); 2840 swiper.emit('transitionStart'); 2841 } 2842 if (!swiper.animating) { 2843 swiper.animating = true; 2844 if (!swiper.onTranslateToWrapperTransitionEnd) { 2845 swiper.onTranslateToWrapperTransitionEnd = function transitionEnd(e) { 2846 if (!swiper || swiper.destroyed) 2847 return; 2848 if (e.target !== this) 2849 return; 2850 swiper.wrapperEl.removeEventListener('transitionend', swiper.onTranslateToWrapperTransitionEnd); 2851 swiper.onTranslateToWrapperTransitionEnd = null; 2852 delete swiper.onTranslateToWrapperTransitionEnd; 2853 swiper.animating = false; 2854 if (runCallbacks) { 2855 swiper.emit('transitionEnd'); 2856 } 2857 }; 2858 } 2859 swiper.wrapperEl.addEventListener('transitionend', swiper.onTranslateToWrapperTransitionEnd); 2860 } 2861 } 2862 return true; 2863 } 2864 2865 var translate = { 2866 getTranslate: getSwiperTranslate, 2867 setTranslate, 2868 minTranslate, 2869 maxTranslate, 2870 translateTo, 2871 }; 2872 2873 function getActiveIndexByTranslate(swiper) { 2874 const { slidesGrid, params } = swiper; 2875 const translate = swiper.rtlTranslate ? swiper.translate : -swiper.translate; 2876 let activeIndex; 2877 for (let i = 0; i < slidesGrid.length; i += 1) { 2878 if (typeof slidesGrid[i + 1] !== 'undefined') { 2879 if (translate >= slidesGrid[i] && 2880 translate < slidesGrid[i + 1] - (slidesGrid[i + 1] - slidesGrid[i]) / 2) { 2881 activeIndex = i; 2882 } 2883 else if (translate >= slidesGrid[i] && translate < slidesGrid[i + 1]) { 2884 activeIndex = i + 1; 2885 } 2886 } 2887 else if (translate >= slidesGrid[i]) { 2888 activeIndex = i; 2889 } 2890 } 2891 // Normalize slideIndex 2892 if (params.normalizeSlideIndex) { 2893 if (activeIndex < 0 || typeof activeIndex === 'undefined') 2894 activeIndex = 0; 2895 } 2896 return activeIndex; 2897 } 2898 function updateActiveIndex(newActiveIndex) { 2899 const swiper = this; 2900 const translate = swiper.rtlTranslate ? swiper.translate : -swiper.translate; 2901 const { snapGrid, params, activeIndex: previousIndex, realIndex: previousRealIndex, snapIndex: previousSnapIndex, } = swiper; 2902 let activeIndex = newActiveIndex; 2903 let snapIndex; 2904 const getVirtualRealIndex = (aIndex) => { 2905 const virtualSlides = swiper.virtual.slides; 2906 let realIndex = aIndex - (swiper.virtual.slidesBefore ?? 0); 2907 if (realIndex < 0) { 2908 realIndex = virtualSlides.length + realIndex; 2909 } 2910 if (realIndex >= virtualSlides.length) { 2911 realIndex -= virtualSlides.length; 2912 } 2913 return realIndex; 2914 }; 2915 if (typeof activeIndex === 'undefined') { 2916 activeIndex = getActiveIndexByTranslate(swiper); 2917 } 2918 if (snapGrid.indexOf(translate) >= 0) { 2919 snapIndex = snapGrid.indexOf(translate); 2920 } 2921 else { 2922 const skip = Math.min(params.slidesPerGroupSkip, activeIndex); 2923 snapIndex = skip + Math.floor((activeIndex - skip) / params.slidesPerGroup); 2924 } 2925 if (snapIndex >= snapGrid.length) 2926 snapIndex = snapGrid.length - 1; 2927 if (activeIndex === previousIndex && !swiper.params.loop) { 2928 if (snapIndex !== previousSnapIndex) { 2929 swiper.snapIndex = snapIndex; 2930 swiper.emit('snapIndexChange'); 2931 } 2932 return; 2933 } 2934 if (activeIndex === previousIndex && 2935 swiper.params.loop && 2936 swiper.virtual && 2937 swiper.params.virtual?.enabled) { 2938 swiper.realIndex = getVirtualRealIndex(activeIndex); 2939 return; 2940 } 2941 const gridEnabled = swiper.grid && params.grid && params.grid.rows > 1; 2942 // Get real index 2943 let realIndex; 2944 if (swiper.virtual && params.virtual?.enabled) { 2945 if (params.loop) { 2946 realIndex = getVirtualRealIndex(activeIndex); 2947 } 2948 else { 2949 realIndex = activeIndex; 2950 } 2951 } 2952 else if (gridEnabled) { 2953 const firstSlideInColumn = swiper.slides.find((slideEl) => slideEl.column === activeIndex); 2954 let activeSlideIndex = parseInt(firstSlideInColumn.getAttribute('data-swiper-slide-index'), 10); 2955 if (Number.isNaN(activeSlideIndex)) { 2956 activeSlideIndex = Math.max(swiper.slides.indexOf(firstSlideInColumn), 0); 2957 } 2958 realIndex = Math.floor(activeSlideIndex / params.grid.rows); 2959 } 2960 else if (swiper.slides[activeIndex]) { 2961 const slideIndex = swiper.slides[activeIndex].getAttribute('data-swiper-slide-index'); 2962 if (slideIndex) { 2963 realIndex = parseInt(slideIndex, 10); 2964 } 2965 else { 2966 realIndex = activeIndex; 2967 } 2968 } 2969 else { 2970 realIndex = activeIndex; 2971 } 2972 Object.assign(swiper, { 2973 previousSnapIndex, 2974 snapIndex, 2975 previousRealIndex, 2976 realIndex, 2977 previousIndex, 2978 activeIndex, 2979 }); 2980 if (swiper.initialized) { 2981 preload(swiper); 2982 } 2983
2983swiper.emit('activeIndexChange'); 2984 swiper.emit('snapIndexChange'); 2985 if (swiper.initialized || swiper.params.runCallbacksOnInit) { 2986 if (previousRealIndex !== realIndex) { 2987 swiper.emit('realIndexChange'); 2988 } 2989 swiper.emit('slideChange'); 2990 }
vendor: 45,653 bytes, lines 2990-4074
2990 2991 } 2992 2993 function updateAutoHeight(speed) { 2994 const swiper = this; 2995 const activeSlides = []; 2996 const isVirtual = swiper.virtual && swiper.params.virtual?.enabled; 2997 let newHeight = 0; 2998 let i; 2999 if (typeof speed === 'number') { 3000 swiper.setTransition(speed); 3001 } 3002 else if (speed === true) { 3003 swiper.setTransition(swiper.params.speed); 3004 } 3005 const getSlideByIndex = (index) => { 3006 if (isVirtual) { 3007 return swiper.slides[swiper.getSlideIndexByData(index)]; 3008 } 3009 return swiper.slides[index]; 3010 }; 3011 // Find slides currently in view 3012 if (swiper.params.slidesPerView !== 'auto' && swiper.params.slidesPerView > 1) { 3013 if (swiper.params.centeredSlides) { 3014 (swiper.visibleSlides || []).forEach((slide) => { 3015 activeSlides.push(slide); 3016 }); 3017 } 3018 else { 3019 for (i = 0; i < Math.ceil(swiper.params.slidesPerView); i += 1) { 3020 const index = swiper.activeIndex + i; 3021 if (index > swiper.slides.length && !isVirtual) 3022 break; 3023 const slide = getSlideByIndex(index); 3024 if (slide) 3025 activeSlides.push(slide); 3026 } 3027 } 3028 } 3029 else { 3030 const slide = getSlideByIndex(swiper.activeIndex); 3031 if (slide) 3032 activeSlides.push(slide); 3033 } 3034 // Find new height from highest slide in view 3035 for (i = 0; i < activeSlides.length; i += 1) { 3036 if (typeof activeSlides[i] !== 'undefined') { 3037 const height = activeSlides[i].offsetHeight; 3038 newHeight = height > newHeight ? height : newHeight; 3039 } 3040 } 3041 // Update Height 3042 if (newHeight || newHeight === 0) 3043 swiper.wrapperEl.style.height = `${newHeight}px`; 3044 } 3045 3046 function updateClickedSlide(el, path) { 3047 const swiper = this; 3048 const params = swiper.params; 3049 let slide = el.closest(`.${params.slideClass}, swiper-slide`); 3050 if (!slide && swiper.isElement && path && path.length > 1 && path.includes(el)) { 3051 [...path.slice(path.indexOf(el) + 1, path.length)].forEach((pathEl) => { 3052 if (!slide && 3053 pathEl.matches && 3054 pathEl.matches(`.${params.slideClass}, swiper-slide`)) { 3055 slide = pathEl; 3056 } 3057 }); 3058 } 3059 let slideFound = false; 3060 let slideIndex; 3061 if (slide) { 3062 for (let i = 0; i < swiper.slides.length; i += 1) { 3063 if (swiper.slides[i] === slide) { 3064 slideFound = true; 3065 slideIndex = i; 3066 break; 3067 } 3068 } 3069 } 3070 if (slide && slideFound) { 3071 swiper.clickedSlide = slide; 3072 if (swiper.virtual && swiper.params.virtual?.enabled) { 3073 swiper.clickedIndex = parseInt(slide.getAttribute('data-swiper-slide-index'), 10); 3074 } 3075 else { 3076 swiper.clickedIndex = slideIndex; 3077 } 3078 } 3079 else { 3080 swiper.clickedSlide = undefined; 3081 swiper.clickedIndex = undefined; 3082 return; 3083 } 3084 if (params.slideToClickedSlide && 3085 swiper.clickedIndex !== undefined && 3086 swiper.clickedIndex !== swiper.activeIndex) { 3087 swiper.slideToClickedSlide(); 3088 } 3089 } 3090 3091 function updateProgress(translate) { 3092 const swiper = this; 3093 if (typeof translate === 'undefined') { 3094 const multiplier = swiper.rtlTranslate ? -1 : 1; 3095 translate = (swiper && swiper.translate && swiper.translate * multiplier) || 0; 3096 } 3097 const params = swiper.params; 3098 const translatesDiff = swiper.maxTranslate() - swiper.minTranslate(); 3099 let { progress, isBeginning, isEnd } = swiper; 3100 let progressLoop = swiper.progressLoop; 3101 const wasBeginning = isBeginning; 3102 const wasEnd = isEnd; 3103 if (translatesDiff === 0) { 3104 progress = 0; 3105 isBeginning = true; 3106 isEnd = true; 3107 } 3108 else { 3109 progress = (translate - swiper.minTranslate()) / translatesDiff; 3110 const isBeginningRounded = Math.abs(translate - swiper.minTranslate()) < 1; 3111 const isEndRounded = Math.abs(translate - swiper.maxTranslate()) < 1; 3112 isBeginning = isBeginningRounded || progress <= 0; 3113 isEnd = isEndRounded || progress >= 1; 3114 if (isBeginningRounded) 3115 progress = 0; 3116 if (isEndRounded) 3117 progress = 1; 3118 } 3119 if (params.loop) { 3120 const firstSlideIndex = swiper.getSlideIndexByData(0); 3121 const lastSlideIndex = swiper.getSlideIndexByData(swiper.slides.length - 1); 3122 const firstSlideTranslate = swiper.slidesGrid[firstSlideIndex]; 3123 const lastSlideTranslate = swiper.slidesGrid[lastSlideIndex]; 3124 const translateMax = swiper.slidesGrid[swiper.slidesGrid.length - 1]; 3125 const translateAbs = Math.abs(translate); 3126 if (translateAbs >= firstSlideTranslate) { 3127 progressLoop = (translateAbs - firstSlideTranslate) / translateMax; 3128 } 3129 else { 3130 progressLoop = (translateAbs + translateMax - lastSlideTranslate) / translateMax; 3131 } 3132 if (progressLoop > 1) 3133 progressLoop -= 1; 3134 } 3135 Object.assign(swiper, { 3136 progress, 3137 progressLoop, 3138 isBeginning, 3139 isEnd, 3140 }); 3141 if (params.watchSlidesProgress || (params.centeredSlides && params.autoHeight)) 3142 swiper.updateSlidesProgress(translate); 3143 if (isBeginning && !wasBeginning) { 3144 swiper.emit('reachBeginning toEdge'); 3145 } 3146 if (isEnd && !wasEnd) { 3147 swiper.emit('reachEnd toEdge'); 3148 } 3149 if ((wasBeginning && !isBeginning) || (wasEnd && !isEnd)) { 3150 swiper.emit('fromEdge'); 3151 } 3152 swiper.emit('progress', progress); 3153 } 3154 3155 function updateSize() { 3156 const swiper = this; 3157 let width; 3158 let height; 3159 const el = swiper.el; 3160 if (typeof swiper.params.width !== 'undefined' && swiper.params.width !== null) { 3161 width = swiper.params.width; 3162 } 3163 else { 3164 width = el.clientWidth; 3165 } 3166 if (typeof swiper.params.height !== 'undefined' && swiper.params.height !== null) { 3167 height = swiper.params.height; 3168 } 3169 else { 3170 height = el.clientHeight; 3171 } 3172 if ((width === 0 && swiper.isHorizontal()) || (height === 0 && swiper.isVertical())) { 3173 return; 3174 } 3175 // Subtract paddings 3176 width = 3177 width - 3178 parseInt(elementStyle(el, 'padding-left') || '0', 10) - 3179 parseInt(elementStyle(el, 'padding-right') || '0', 10); 3180 height = 3181 height - 3182 parseInt(elementStyle(el, 'padding-top') || '0', 10) - 3183 parseInt(elementStyle(el, 'padding-bottom') || '0', 10); 3184 if (Number.isNaN(width)) 3185 width = 0; 3186 if (Number.isNaN(height)) 3187 height = 0; 3188 Object.assign(swiper, { 3189 width, 3190 height, 3191 size: swiper.isHorizontal() ? width : height, 3192 }); 3193 } 3194 3195 function updateSlides() { 3196 const swiper = this; 3197 function getDirectionPropertyValue(node, label) { 3198 return parseFloat(node.getPropertyValue(swiper.getDirectionLabel(label)) || '0'); 3199 } 3200 const params = swiper.params; 3201 const { wrapperEl, slidesEl, rtlTranslate: rtl, wrongRTL } = swiper; 3202 const isVirtual = !!(swiper.virtual && params.virtual?.enabled); 3203 const previousSlidesLength = isVirtual ? swiper.virtual.slides.length : swiper.slides.length; 3204 const slides = elementChildren(slidesEl, `.${swiper.params.slideClass}, swiper-slide`); 3205 const slidesLength = isVirtual ? swiper.virtual.slides.length : slides.length; 3206 let snapGrid = []; 3207 const slidesGrid = []; 3208 const slidesSizesGrid = []; 3209 const resolveOffset = (value) => typeof value === 'function' ? value.call(swiper) : value; 3210 const offsetBefore = resolveOffset(params.slidesOffsetBefore); 3211 const offsetAfter = resolveOffset(params.slidesOffsetAfter); 3212 const previousSnapGridLength = swiper.snapGrid.length; 3213 const previousSlidesGridLength = swiper.slidesGrid.length; 3214 const swiperSize = swiper.size - offsetBefore - offsetAfter; 3215 let spaceBetween = params.spaceBetween; 3216 let slidePosition = -offsetBefore; 3217 let prevSlideSize = 0; 3218 let index = 0; 3219 if (typeof swiperSize === 'undefined') { 3220 return; 3221 } 3222 if (typeof spaceBetween === 'string' && spaceBetween.indexOf('%') >= 0) { 3223 spaceBetween = (parseFloat(spaceBetween.replace('%', '')) / 100) * swiperSize; 3224 } 3225 else if (typeof spaceBetween === 'string') { 3226 spaceBetween = parseFloat(spaceBetween); 3227 } 3228 swiper.virtualSize = 3229 -spaceBetween - offsetBefore - offsetAfter; 3230 // reset margins 3231 slides.forEach((slideEl) => { 3232 if (rtl) { 3233 slideEl.style.marginLeft = ''; 3234 } 3235 else { 3236 slideEl.style.marginRight = ''; 3237 } 3238 slideEl.style.marginBottom = ''; 3239 slideEl.style.marginTop = ''; 3240 }); 3241 // reset cssMode offsets 3242 if (params.centeredSlides && params.cssMode) { 3243 setCSSProperty(wrapperEl, '--swiper-centered-offset-before', ''); 3244 setCSSProperty(wrapperEl, '--swiper-centered-offset-after', ''); 3245 } 3246 // set cssMode offsets 3247 if (params.cssMode) { 3248 setCSSProperty(wrapperEl, '--swiper-slides-offset-before', `${offsetBefore}px`); 3249 setCSSProperty(wrapperEl, '--swiper-slides-offset-after', `${offsetAfter}px`); 3250 } 3251 const gridEnabled = params.grid && params.grid.rows > 1 && swiper.grid; 3252 if (gridEnabled) { 3253 swiper.grid.initSlides(slides); 3254 } 3255 else if (swiper.grid) { 3256 swiper.grid.unsetSlides(); 3257 } 3258 // Calc slides 3259 let slideSize = 0; 3260 const shouldResetSlideSize = params.slidesPerView === 'auto' && 3261 params.breakpoints && 3262 Object.keys(params.breakpoints).filter((key) => { 3263 const bp = params.breakpoints[key]; 3264 return typeof bp?.slidesPerView !== 'undefined'; 3265 }).length > 0; 3266 for (let i = 0; i < slidesLength; i += 1) { 3267 slideSize = 0; 3268 const slide = slides[i]; 3269 if (slide) { 3270 if (gridEnabled) { 3271 swiper.grid.updateSlide(i, slide, slides); 3272 } 3273 if (elementStyle(slide, 'display') === 'none') 3274 continue; 3275 } 3276 if (isVirtual && params.slidesPerView === 'auto') { 3277 if (params.virtual?.slidesPerViewAutoSlideSize) { 3278 slideSize = params.virtual.slidesPerViewAutoSlideSize; 3279 } 3280 if (slideSize && slide) { 3281 if (params.roundLengths) 3282 slideSize = Math.floor(slideSize); 3283 slide.style[swiper.getDirectionLabel('width')] = 3284 `${slideSize}px`; 3285 } 3286 } 3287 else if (params.slidesPerView === 'auto') { 3288 if (shouldResetSlideSize) { 3289 slide.style[swiper.getDirectionLabel('width')] = ``; 3290 } 3291 const slideStyles = getComputedStyle(slide); 3292 const currentTransform = slide.style.transform; 3293 const currentWebKitTransform = slide.style.webkitTransform; 3294 if (currentTransform) { 3295 slide.style.transform = 'none'; 3296 } 3297 if (currentWebKitTransform) { 3298 slide.style.webkitTransform = 3299 'none'; 3300 } 3301 if (params.roundLengths) { 3302 slideSize = swiper.isHorizontal() 3303 ? elementOuterSize(slide, 'width') 3304 : elementOuterSize(slide, 'height'); 3305 } 3306 else { 3307 const width = getDirectionPropertyValue(slideStyles, 'width'); 3308 const paddingLeft = getDirectionPropertyValue(slideStyles, 'padding-left'); 3309 const paddingRight = getDirectionPropertyValue(slideStyles, 'padding-right'); 3310 const marginLeft = getDirectionPropertyValue(slideStyles, 'margin-left'); 3311 const marginRight = getDirectionPropertyValue(slideStyles, 'margin-right'); 3312 const boxSizing = slideStyles.getPropertyValue('box-sizing'); 3313 if (boxSizing && boxSizing === 'border-box') { 3314 slideSize = width + marginLeft + marginRight; 3315 } 3316 else { 3317 const { clientWidth, offsetWidth } = slide; 3318 slideSize = 3319 width + 3320 paddingLeft + 3321 paddingRight + 3322 marginLeft + 3323 marginRight + 3324 (offsetWidth - clientWidth); 3325 } 3326 } 3327 if (currentTransform) { 3328 slide.style.transform = currentTransform; 3329 } 3330 if (currentWebKitTransform) { 3331 slide.style.webkitTransform = 3332 currentWebKitTransform; 3333 } 3334 if (params.roundLengths) 3335 slideSize = Math.floor(slideSize); 3336 } 3337 else { 3338 slideSize = 3339 (swiperSize - (params.slidesPerView - 1) * spaceBetween) / 3340 params.slidesPerView; 3341 if (params.roundLengths) 3342 slideSize = Math.floor(slideSize); 3343 if (slide) { 3344 slide.style[swiper.getDirectionLabel('width')] = 3345 `${slideSize}px`; 3346 } 3347 } 3348 if (slide) { 3349 slide.swiperSlideSize = slideSize; 3350 } 3351 slidesSizesGrid.push(slideSize); 3352 if (params.centeredSlides) { 3353 slidePosition = slidePosition + slideSize / 2 + prevSlideSize / 2 + spaceBetween; 3354 if (prevSlideSize === 0 && i !== 0) 3355 slidePosition = slidePosition - swiperSize / 2 - spaceBetween; 3356 if (i === 0) 3357 slidePosition = slidePosition - swiperSize / 2 - spaceBetween; 3358 if (Math.abs(slidePosition) < 1 / 1000) 3359 slidePosition = 0; 3360 if (params.roundLengths) 3361 slidePosition = Math.floor(slidePosition); 3362 if (index % params.slidesPerGroup === 0) 3363 snapGrid.push(slidePosition); 3364 slidesGrid.push(slidePosition); 3365 } 3366 else { 3367 if (params.roundLengths) 3368 slidePosition = Math.floor(slidePosition); 3369 if ((index - Math.min(swiper.params.slidesPerGroupSkip, index)) % 3370 swiper.params.slidesPerGroup === 3371 0) 3372 snapGrid.push(slidePosition); 3373 slidesGrid.push(slidePosition); 3374 slidePosition = slidePosition + slideSize + spaceBetween; 3375 } 3376 swiper.virtualSize += slideSize + spaceBetween; 3377 prevSlideSize = slideSize; 3378 index += 1; 3379 } 3380 swiper.virtualSize = Math.max(swiper.virtualSize, swiperSize) + offsetAfter; 3381 if (rtl && wrongRTL && (params.effect === 'slide' || params.effect === 'coverflow')) { 3382 wrapperEl.style.width = `${swiper.virtualSize + spaceBetween}px`; 3383 } 3384 if (params.setWrapperSize) { 3385 wrapperEl.style[swiper.getDirectionLabel('width')] = `${swiper.virtualSize + spaceBetween}px`; 3386 } 3387 if (gridEnabled) { 3388 swiper.grid.updateWrapperSize(slideSize, snapGrid); 3389 } 3390 // Remove last grid elements depending on width 3391 if (!params.centeredSlides) { 3392 // Check if snapToSlideEdge should be applied 3393 const isFractionalSlidesPerView = params.slidesPerView !== 'auto' && params.slidesPerView % 1 !== 0; 3394 const shouldSnapToSlideEdge = params.snapToSlideEdge && 3395 !params.loop && 3396 (params.slidesPerView === 'auto' || isFractionalSlidesPerView); 3397 // Calculate the last allowed snap index when snapToSlideEdge is enabled 3398 // This ensures minimum slides are visible at the end 3399 let lastAllowedSnapIndex = snapGrid.length; 3400 if (shouldSnapToSlideEdge) { 3401 let minVisibleSlides; 3402 if (params.slidesPerView === 'auto') { 3403 // For 'auto' mode, calculate how many slides fit based on actual sizes 3404 minVisibleSlides = 1; 3405 let accumulatedSize = 0; 3406 for (let i = slidesSizesGrid.length - 1; i >= 0; i -= 1) { 3407 accumulatedSize += 3408 slidesSizesGrid[i] + (i < slidesSizesGrid.length - 1 ? spaceBetween : 0); 3409 if (accumulatedSize <= swiperSize) { 3410 minVisibleSlides = slidesSizesGrid.length - i; 3411 } 3412 else { 3413 break; 3414 } 3415 } 3416 } 3417 else { 3418 minVisibleSlides = Math.floor(params.slidesPerView); 3419 } 3420 lastAllowedSnapIndex = Math.max(slidesLength - minVisibleSlides, 0); 3421 } 3422 const newSlidesGrid = []; 3423 for (let i = 0; i < snapGrid.length; i += 1) { 3424 let slidesGridItem = snapGrid[i]; 3425 if (params.roundLengths) 3426 slidesGridItem = Math.floor(slidesGridItem); 3427 if (shouldSnapToSlideEdge) { 3428 // When snapToSlideEdge is enabled, only keep snaps up to lastAllowedSnapIndex 3429 if (i <= lastAllowedSnapIndex) { 3430 newSlidesGrid.push(slidesGridItem); 3431 } 3432 } 3433 else if (snapGrid[i] <= swiper.virtualSize - swiperSize) { 3434 // When snapToSlideEdge is disabled, keep snaps that fit within scrollable area 3435 newSlidesGrid.push(slidesGridItem); 3436 } 3437 } 3438 snapGrid = newSlidesGrid; 3439 if (Math.floor(swiper.virtualSize - swiperSize) - Math.floor(snapGrid[snapGrid.length - 1]) > 3440 1) { 3441 // Only add edge-aligned snap if snapToSlideEdge is not enabled 3442 if (!shouldSnapToSlideEdge) { 3443 snapGrid.push(swiper.virtualSize - swiperSize); 3444 } 3445 } 3446 } 3447 if (isVirtual && params.loop) { 3448 const size = slidesSizesGrid[0] + spaceBetween; 3449 const slidesBefore = swiper.virtual.slidesBefore ?? 0; 3450 const slidesAfter = swiper.virtual.slidesAfter ?? 0; 3451 const virtualLoopCount = slidesBefore + slidesAfter; 3452 if (params.slidesPerGroup > 1) { 3453 const groups = Math.ceil(virtualLoopCount / params.slidesPerGroup); 3454 const groupSize = size * params.slidesPerGroup; 3455 for (let i = 0; i < groups; i += 1) { 3456 snapGrid.push(snapGrid[snapGrid.length - 1] + groupSize); 3457 } 3458 } 3459 for (let i = 0; i < virtualLoopCount; i += 1) { 3460 if (params.slidesPerGroup === 1) { 3461 snapGrid.push(snapGrid[snapGrid.length - 1] + size); 3462 } 3463 slidesGrid.push(slidesGrid[slidesGrid.length - 1] + size); 3464 swiper.virtualSize += size; 3465 } 3466 } 3467 if (snapGrid.length === 0) 3468 snapGrid = [0]; 3469 if (spaceBetween !== 0) { 3470 const key = swiper.isHorizontal() && rtl ? 'marginLeft' : swiper.getDirectionLabel('marginRight'); 3471 slides 3472 .filter((_, slideIndex) => { 3473 if (!params.cssMode || params.loop) 3474 return true; 3475 if (slideIndex === slides.length - 1) { 3476 return false; 3477 } 3478 return true; 3479 }) 3480 .forEach((slideEl) => { 3481 slideEl.style[key] = `${spaceBetween}px`; 3482 }); 3483 } 3484 if (params.centeredSlides && params.centeredSlidesBounds) { 3485 let allSlidesSize = 0; 3486 slidesSizesGrid.forEach((slideSizeValue) => { 3487 allSlidesSize += slideSizeValue + (spaceBetween || 0); 3488 }); 3489 allSlidesSize -= spaceBetween; 3490 const maxSnap = allSlidesSize > swiperSize ? allSlidesSize - swiperSize : 0; 3491 snapGrid = snapGrid.map((snap) => { 3492 if (snap <= 0) 3493 return -offsetBefore; 3494 if (snap > maxSnap) 3495 return maxSnap + offsetAfter; 3496 return snap; 3497 }); 3498 } 3499 if (params.centerInsufficientSlides) { 3500 let allSlidesSize = 0; 3501 slidesSizesGrid.forEach((slideSizeValue) => { 3502 allSlidesSize += slideSizeValue + (spaceBetween || 0); 3503 }); 3504 allSlidesSize -= spaceBetween; 3505 if (allSlidesSize < swiperSize) { 3506 const allSlidesOffset = (swiperSize - allSlidesSize) / 2; 3507 snapGrid.forEach((snap, snapIndex) => { 3508 snapGrid[snapIndex] = snap - allSlidesOffset; 3509 }); 3510 slidesGrid.forEach((snap, snapIndex) => { 3511 slidesGrid[snapIndex] = snap + allSlidesOffset; 3512 }); 3513 } 3514 } 3515 Object.assign(swiper, { 3516 slides, 3517 snapGrid, 3518 slidesGrid, 3519 slidesSizesGrid, 3520 }); 3521 if (params.centeredSlides && params.cssMode && !params.centeredSlidesBounds) { 3522 setCSSProperty(wrapperEl, '--swiper-centered-offset-before', `${-snapGrid[0]}px`); 3523 setCSSProperty(wrapperEl, '--swiper-centered-offset-after', `${swiper.size / 2 - slidesSizesGrid[slidesSizesGrid.length - 1] / 2}px`); 3524 const addToSnapGrid = -swiper.snapGrid[0]; 3525 const addToSlidesGrid = -swiper.slidesGrid[0]; 3526 swiper.snapGrid = swiper.snapGrid.map((v) => v + addToSnapGrid); 3527 swiper.slidesGrid = swiper.slidesGrid.map((v) => v + addToSlidesGrid); 3528 } 3529 if (slidesLength !== previousSlidesLength) { 3530 swiper.emit('slidesLengthChange'); 3531 } 3532 if (snapGrid.length !== previousSnapGridLength) { 3533 if (swiper.params.watchOverflow) 3534 swiper.checkOverflow(); 3535 swiper.emit('snapGridLengthChange'); 3536 } 3537 if (slidesGrid.length !== previousSlidesGridLength) { 3538 swiper.emit('slidesGridLengthChange'); 3539 } 3540 if (params.watchSlidesProgress) { 3541 swiper.updateSlidesOffset(); 3542 } 3543 swiper.emit('slidesUpdated'); 3544 if (!isVirtual && !params.cssMode && (params.effect === 'slide' || params.effect === 'fade')) { 3545 const backFaceHiddenClass = `${params.containerModifierClass}backface-hidden`; 3546 const hasClassBackfaceClassAdded = swiper.el.classList.contains(backFaceHiddenClass); 3547 if (slidesLength <= params.maxBackfaceHiddenSlides) { 3548 if (!hasClassBackfaceClassAdded) 3549 swiper.el.classList.add(backFaceHiddenClass); 3550 } 3551 else if (hasClassBackfaceClassAdded) { 3552 swiper.el.classList.remove(backFaceHiddenClass); 3553 } 3554 } 3555 } 3556 3557 const toggleSlideClasses$1 = (slideEl, condition, className) => { 3558 if (condition && !slideEl.classList.contains(className)) { 3559 slideEl.classList.add(className); 3560 } 3561 else if (!condition && slideEl.classList.contains(className)) { 3562 slideEl.classList.remove(className); 3563 } 3564 }; 3565 function updateSlidesClasses() { 3566 const swiper = this; 3567 const { slides, params, slidesEl, activeIndex } = swiper; 3568 const isVirtual = !!(swiper.virtual && params.virtual?.enabled); 3569 const gridEnabled = swiper.grid && params.grid && params.grid.rows > 1; 3570 const getFilteredSlide = (selector) => { 3571 return elementChildren(slidesEl, `.${params.slideClass}${selector}, swiper-slide${selector}`)[0]; 3572 }; 3573 let activeSlide; 3574 let prevSlide; 3575 let nextSlide; 3576 if (isVirtual) { 3577 if (params.loop) { 3578 const virtualSlides = swiper.virtual.slides; 3579 let slideIndex = activeIndex - (swiper.virtual.slidesBefore ?? 0); 3580 if (slideIndex < 0) 3581 slideIndex = virtualSlides.length + slideIndex; 3582 if (slideIndex >= virtualSlides.length) 3583 slideIndex -= virtualSlides.length; 3584 activeSlide = getFilteredSlide(`[data-swiper-slide-index="${slideIndex}"]`); 3585 } 3586 else { 3587 activeSlide = getFilteredSlide(`[data-swiper-slide-index="${activeIndex}"]`); 3588 } 3589 } 3590 else if (gridEnabled) { 3591 activeSlide = slides.find((slideEl) => slideEl.column === activeIndex); 3592 nextSlide = slides.find((slideEl) => slideEl.column === activeIndex + 1); 3593 prevSlide = slides.find((slideEl) => slideEl.column === activeIndex - 1); 3594 } 3595 else { 3596 activeSlide = slides[activeIndex]; 3597 } 3598 if (activeSlide) { 3599 if (!gridEnabled) { 3600 // Next Slide 3601 nextSlide = elementNextAll(activeSlide, `.${params.slideClass}, swiper-slide`)[0]; 3602 if (params.loop && !nextSlide) { 3603 nextSlide = slides[0]; 3604 } 3605 // Prev Slide 3606 prevSlide = elementPrevAll(activeSlide, `.${params.slideClass}, swiper-slide`)[0]; 3607 // NOTE: legacy guard from v9; `(!prevSlide) === 0` is always false, but we preserve 3608 // the original behaviour (no-op) to avoid runtime changes in v14. Audit candidate. 3609 if (params.loop && !prevSlide === 0) { 3610 prevSlide = slides[slides.length - 1]; 3611 } 3612 } 3613 } 3614 slides.forEach((slideEl) => { 3615 toggleSlideClasses$1(slideEl, slideEl === activeSlide, params.slideActiveClass); 3616 toggleSlideClasses$1(slideEl, slideEl === nextSlide, params.slideNextClass); 3617 toggleSlideClasses$1(slideEl, slideEl === prevSlide, params.slidePrevClass); 3618 }); 3619 swiper.emitSlidesClasses(); 3620 } 3621 3622 function updateSlidesOffset() { 3623 const swiper = this; 3624 const slides = swiper.slides; 3625 const minusOffset = swiper.isElement 3626 ? swiper.isHorizontal() 3627 ? swiper.wrapperEl.offsetLeft 3628 : swiper.wrapperEl.offsetTop 3629 : 0; 3630 for (let i = 0; i < slides.length; i += 1) { 3631 slides[i].swiperSlideOffset = 3632 (swiper.isHorizontal() ? slides[i].offsetLeft : slides[i].offsetTop) - 3633 minusOffset - 3634 swiper.cssOverflowAdjustment(); 3635 } 3636 } 3637 3638 const toggleSlideClasses = (slideEl, condition, className) => { 3639 if (condition && !slideEl.classList.contains(className)) { 3640 slideEl.classList.add(className); 3641 } 3642 else if (!condition && slideEl.classList.contains(className)) { 3643 slideEl.classList.remove(className); 3644 } 3645 }; 3646 function updateSlidesProgress(translate = (this && this.translate) || 0) { 3647 const swiper = this; 3648 const params = swiper.params; 3649 const { slides, rtlTranslate: rtl, snapGrid } = swiper; 3650 if (slides.length === 0) 3651 return; 3652 if (typeof slides[0].swiperSlideOffset === 'undefined') 3653 swiper.updateSlidesOffset(); 3654 let offsetCenter = -translate; 3655 if (rtl) 3656 offsetCenter = translate; 3657 swiper.visibleSlidesIndexes = []; 3658 swiper.visibleSlides = []; 3659 let spaceBetween = params.spaceBetween; 3660 if (typeof spaceBetween === 'string' && spaceBetween.indexOf('%') >= 0) { 3661 spaceBetween = (parseFloat(spaceBetween.replace('%', '')) / 100) * swiper.size; 3662 } 3663 else if (typeof spaceBetween === 'string') { 3664 spaceBetween = parseFloat(spaceBetween); 3665 } 3666 for (let i = 0; i < slides.length; i += 1) { 3667 const slide = slides[i]; 3668 let slideOffset = slide.swiperSlideOffset ?? 0; 3669 if (params.cssMode && params.centeredSlides) { 3670 slideOffset -= slides[0].swiperSlideOffset ?? 0; 3671 } 3672 const slideSize = slide.swiperSlideSize ?? 0; 3673 const slideProgress = (offsetCenter + (params.centeredSlides ? swiper.minTranslate() : 0) - slideOffset) / 3674 (slideSize + spaceBetween); 3675 const originalSlideProgress = (offsetCenter - 3676 snapGrid[0] + 3677 (params.centeredSlides ? swiper.minTranslate() : 0) - 3678 slideOffset) / 3679 (slideSize + spaceBetween); 3680 const slideBefore = -(offsetCenter - slideOffset); 3681 const slideAfter = slideBefore + swiper.slidesSizesGrid[i]; 3682 const isFullyVisible = slideBefore >= 0 && slideBefore <= swiper.size - swiper.slidesSizesGrid[i]; 3683 const isVisible = (slideBefore >= 0 && slideBefore < swiper.size - 1) || 3684 (slideAfter > 1 && slideAfter <= swiper.size) || 3685 (slideBefore <= 0 && slideAfter >= swiper.size); 3686 if (isVisible) { 3687 swiper.visibleSlides.push(slide); 3688 swiper.visibleSlidesIndexes.push(i); 3689 } 3690 toggleSlideClasses(slide, isVisible, params.slideVisibleClass); 3691 toggleSlideClasses(slide, isFullyVisible, params.slideFullyVisibleClass); 3692 slide.progress = rtl ? -slideProgress : slideProgress; 3693 slide.originalProgress = rtl ? -originalSlideProgress : originalSlideProgress; 3694 } 3695 } 3696 3697 var update = { 3698 updateSize, 3699 updateSlides, 3700 updateAutoHeight, 3701 updateSlidesOffset, 3702 updateSlidesProgress, 3703 updateProgress, 3704 updateSlidesClasses, 3705 updateActiveIndex, 3706 updateClickedSlide, 3707 }; 3708 3709 const prototypes = { 3710 eventsEmitter, 3711 update, 3712 translate, 3713 transition, 3714 slide, 3715 loop, 3716 grabCursor, 3717 events: events$1, 3718 breakpoints, 3719 checkOverflow: checkOverflow$1, 3720 classes, 3721 }; 3722 const extendedDefaults = {}; 3723 class Swiper { 3724 static extendedDefaults; 3725 static defaults; 3726 constructor(...args) { 3727 let el; 3728 let params; 3729 if (args.length === 1 && 3730 args[0] !== null && 3731 typeof args[0] === 'object' && 3732 Object.prototype.toString.call(args[0]).slice(8, -1) === 'Object') { 3733 params = args[0]; 3734 } 3735 else { 3736 [el, params] = args; 3737 } 3738 if (!params) 3739 params = {}; 3740 params = extend({}, params); 3741 if (el && !params.el) 3742 params.el = el; 3743 if (params.el && 3744 typeof params.el === 'string' && 3745 typeof document !== 'undefined' && 3746 document.querySelectorAll(params.el).length > 1) { 3747 const swipers = []; 3748 document.querySelectorAll(params.el).forEach((containerEl) => { 3749 const newParams = extend({}, params, { el: containerEl }); 3750 swipers.push(new Swiper(newParams)); 3751 }); 3752 return swipers; 3753 } 3754 // Swiper Instance 3755 const swiper = this; 3756 swiper.__swiper__ = true; 3757 swiper.support = getSupport(); 3758 swiper.device = getDevice({ userAgent: params.userAgent ?? undefined }); 3759 swiper.browser = getBrowser(); 3760 swiper.eventsListeners = {}; 3761 swiper.eventsAnyListeners = []; 3762 swiper.modules = [...(swiper.__modules__ || [])]; 3763 if (params.modules && Array.isArray(params.modules)) { 3764 params.modules.forEach((mod) => { 3765 const fn = mod; 3766 if (typeof fn === 'function' && swiper.modules.indexOf(fn) < 0) { 3767 swiper.modules.push(fn); 3768 } 3769 }); 3770 } 3771 const allModulesParams = {}; 3772 swiper.modules.forEach((mod) => { 3773 mod({ 3774 params: params, 3775 swiper, 3776 extendParams: moduleExtendParams(params, allModulesParams), 3777 on: swiper.on.bind(swiper), 3778 once: swiper.once.bind(swiper), 3779 off: swiper.off.bind(swiper), 3780 emit: swiper.emit.bind(swiper), 3781 }); 3782 }); 3783 // Extend defaults with modules params 3784 const swiperParams = extend({}, defaults, allModulesParams); 3785 // Extend defaults with passed params 3786 swiper.params = extend({}, swiperParams, extendedDefaults, params); 3787 swiper.originalParams = extend({}, swiper.params); 3788 swiper.passedParams = extend({}, params); 3789 // add event listeners 3790 if (swiper.params && swiper.params.on) { 3791 const onHandlers = swiper.params.on; 3792 Object.keys(onHandlers).forEach((eventName) => { 3793 const handler = onHandlers[eventName]; 3794 if (handler) 3795 swiper.on(eventName, handler); 3796 }); 3797 } 3798 if (swiper.params && swiper.params.onAny) { 3799 swiper.onAny(swiper.params.onAny); 3800 } 3801 // Extend Swiper 3802 Object.assign(swiper, { 3803 enabled: swiper.params.enabled, 3804 el, 3805 // Classes 3806 classNames: [], 3807 // Slides 3808 slides: [], 3809 slidesGrid: [], 3810 snapGrid: [], 3811 slidesSizesGrid: [], 3812 // isDirection 3813 isHorizontal() { 3814 return swiper.params.direction === 'horizontal'; 3815 }, 3816 isVertical() { 3817 return swiper.params.direction === 'vertical'; 3818 }, 3819 // Indexes 3820 activeIndex: 0, 3821 realIndex: 0, 3822 // 3823 isBeginning: true, 3824 isEnd: false, 3825 // Props 3826 translate: 0, 3827 previousTranslate: 0, 3828 progress: 0, 3829 velocity: 0, 3830 animating: false, 3831 cssOverflowAdjustment() { 3832 // Returns 0 unless `translate` is > 2**23 3833 // Should be subtracted from css values to prevent overflow 3834 return Math.trunc(this.translate / 2 ** 23) * 2 ** 23; 3835 }, 3836 // Locks 3837 allowSlideNext: swiper.params.allowSlideNext, 3838 allowSlidePrev: swiper.params.allowSlidePrev, 3839 // Touch Events 3840 touchEventsData: { 3841 isTouched: undefined, 3842 isMoved: undefined, 3843 allowTouchCallbacks: undefined, 3844 touchStartTime: undefined, 3845 isScrolling: undefined, 3846 currentTranslate: undefined, 3847 startTranslate: undefined, 3848 allowThresholdMove: undefined, 3849 // Form elements to match 3850 focusableElements: swiper.params.focusableElements, 3851 // Last click time 3852 lastClickTime: 0, 3853 clickTimeout: undefined, 3854 // Velocities 3855 velocities: [], 3856 allowMomentumBounce: undefined, 3857 startMoving: undefined, 3858 pointerId: null, 3859 touchId: null, 3860 }, 3861 // Clicks 3862 allowClick: true, 3863 // Touches 3864 allowTouchMove: swiper.params.allowTouchMove, 3865 touches: { 3866 startX: 0, 3867 startY: 0, 3868 currentX: 0, 3869 currentY: 0, 3870 diff: 0, 3871 }, 3872 // Images 3873 imagesToLoad: [], 3874 imagesLoaded: 0, 3875 }); 3876 swiper.emit('_swiper'); 3877 // Init 3878 if (swiper.params.init) { 3879 swiper.init(); 3880 } 3881 // Return app instance 3882 return swiper; 3883 } 3884 getDirectionLabel(property) { 3885 if (this.isHorizontal()) { 3886 return property; 3887 } 3888 // oxfmt-ignore 3889 return { 3890 'width': 'height', 3891 'margin-top': 'margin-left', 3892 'margin-bottom ': 'margin-right', 3893 'margin-left': 'margin-top', 3894 'margin-right': 'margin-bottom', 3895 'padding-left': 'padding-top', 3896 'padding-right': 'padding-bottom', 3897 'marginRight': 'marginBottom', 3898 }[property]; 3899 } 3900 /** 3901 * !INTERNAL 3902 */ 3903 isHorizontal() { 3904 return this.params.direction === 'horizontal'; 3905 } 3906 isVertical() { 3907 return this.params.direction === 'vertical'; 3908 } 3909 cssOverflowAdjustment() { 3910 return Math.trunc(this.translate / 2 ** 23) * 2 ** 23; 3911 } 3912 getSlideIndex(slideEl) { 3913 const { slidesEl, params } = this; 3914 const slides = elementChildren(slidesEl, `.${params.slideClass}, swiper-slide`); 3915 const firstSlideIndex = elementIndex(slides[0]); 3916 return elementIndex(slideEl) - (firstSlideIndex ?? 0); 3917 } 3918 getSlideIndexByData(index) { 3919 return this.getSlideIndex(this.slides.find((slideEl) => Number(slideEl.getAttribute('data-swiper-slide-index')) === index)); 3920 } 3921 getSlideIndexWhenGrid(index) { 3922 if (this.grid && this.params.grid && this.params.grid.rows > 1) { 3923 if (this.params.grid.fill === 'column') { 3924 index = Math.floor(index / this.params.grid.rows); 3925 } 3926 else if (this.params.grid.fill === 'row') { 3927 index = index % Math.ceil(this.slides.length / this.params.grid.rows); 3928 } 3929 } 3930 return index; 3931 } 3932 recalcSlides() { 3933 const { slidesEl, params } = this; 3934 this.slides = elementChildren(slidesEl, `.${params.slideClass}, swiper-slide`); 3935 } 3936 /** 3937 * Enable Swiper (if it was disabled) 3938 */ 3939 enable() { 3940 if (this.enabled) 3941 return; 3942 this.enabled = true; 3943 if (this.params.grabCursor) { 3944 this.setGrabCursor(); 3945 } 3946 this.emit('enable'); 3947 } 3948 /** 3949 * Disable Swiper (if it was enabled). When Swiper is disabled, it will hide all navigation elements and won't respond to any events and interactions 3950 */ 3951 disable() { 3952 if (!this.enabled) 3953 return; 3954 this.enabled = false; 3955 if (this.params.grabCursor) { 3956 this.unsetGrabCursor(); 3957 } 3958 this.emit('disable'); 3959 } 3960 /** 3961 * Set Swiper translate progress (from 0 to 1). Where 0 - its initial position (offset) on first slide, and 1 - its maximum position (offset) on last slide 3962 * 3963 * @param progress Swiper translate progress (from 0 to 1). 3964 * @param speed Transition duration (in ms). 3965 */ 3966 setProgress(progress, speed) { 3967 progress = Math.min(Math.max(progress, 0), 1); 3968 const min = this.minTranslate(); 3969 const max = this.maxTranslate(); 3970 const current = (max - min) * progress + min; 3971 this.translateTo(current, typeof speed === 'undefined' ? 0 : speed); 3972 this.updateActiveIndex(); 3973 this.updateSlidesClasses(); 3974 } 3975 emitContainerClasses() { 3976 if (!this.params._emitClasses || !this.el) 3977 return; 3978 const cls = this.el.className.split(' ').filter((className) => { 3979 return (className.indexOf('swiper') === 0 || 3980 className.indexOf(this.params.containerModifierClass) === 0); 3981 }); 3982 this.emit('_containerClasses', cls.join(' ')); 3983 } 3984 getSlideClasses(slideEl) { 3985 if (this.destroyed) 3986 return ''; 3987 return slideEl.className 3988 .split(' ') 3989 .filter((className) => { 3990 return (className.indexOf('swiper-slide') === 0 || 3991 className.indexOf(this.params.slideClass) === 0); 3992 }) 3993 .join(' '); 3994 } 3995 emitSlidesClasses() { 3996 if (!this.params._emitClasses || !this.el) 3997 return; 3998 const updates = []; 3999 this.slides.forEach((slideEl) => { 4000 const classNames = this.getSlideClasses(slideEl); 4001 updates.push({ slideEl, classNames }); 4002 this.emit('_slideClass', slideEl, classNames); 4003 }); 4004 this.emit('_slideClasses', updates); 4005 } 4006 /** 4007 * Get dynamically calculated amount of slides per view, useful only when slidesPerView set to `auto` 4008 */ 4009 slidesPerViewDynamic(view = 'current', exact = false) { 4010 const { params, slides, slidesGrid, slidesSizesGrid, size: swiperSize, activeIndex } = this; 4011 let spv = 1; 4012 if (typeof params.slidesPerView === 'number') 4013 return params.slidesPerView; 4014 // container not measured yet — centered branch below would never break and return ~slides.length (#7586) 4015 if (!swiperSize) 4016 return spv; 4017 if (params.centeredSlides) { 4018 let slideSize = slides[activeIndex] ? Math.ceil(slides[activeIndex].swiperSlideSize ?? 0) : 0; 4019 let breakLoop = false; 4020 for (let i = activeIndex + 1; i < slides.length; i += 1) { 4021 if (slides[i] && !breakLoop) { 4022 slideSize += Math.ceil(slides[i].swiperSlideSize ?? 0); 4023 spv += 1; 4024 if (slideSize > swiperSize) 4025 breakLoop = true; 4026 } 4027 } 4028 for (let i = activeIndex - 1; i >= 0; i -= 1) { 4029 if (slides[i] && !breakLoop) { 4030 slideSize += slides[i].swiperSlideSize ?? 0; 4031 spv += 1; 4032 if (slideSize > swiperSize) 4033 breakLoop = true; 4034 } 4035 } 4036 } 4037 else if (view === 'current') { 4038 for (let i = activeIndex + 1; i < slides.length; i += 1) { 4039 const slideInView = exact 4040 ? slidesGrid[i] + slidesSizesGrid[i] - slidesGrid[activeIndex] < swiperSize 4041 : slidesGrid[i] - slidesGrid[activeIndex] < swiperSize; 4042 if (slideInView) { 4043 spv += 1; 4044 } 4045 } 4046 } 4047 else { 4048 // previous 4049 for (let i = activeIndex - 1; i >= 0; i -= 1) { 4050 const slideInView = slidesGrid[activeIndex] - slidesGrid[i] < swiperSize; 4051 if (slideInView) { 4052 spv += 1; 4053 } 4054 } 4055 } 4056 return spv; 4057 } 4058 /** 4059 * You should call it after you add/remove slides 4060 * manually, or after you hide/show it, or do any 4061 * custom DOM modifications with Swiper 4062 * This method also includes subcall of the following 4063 * methods which you can use separately: 4064 */ 4065 update() { 4066 const swiper = this; 4067 if (!swiper || swiper.destroyed) 4068 return; 4069 const { snapGrid, params } = swiper; 4070 // Breakpoints 4071 if (params.breakpoints) { 4072 swiper.setBreakpoint(); 4073 } 4074
vendor: 8,612 bytes, lines 4074-4277
4074[...swiper.el.querySelectorAll('[loading="lazy"]')].forEach((imageEl) => { 4075 if (imageEl.complete) { 4076 processLazyPreloader(swiper, imageEl); 4077 } 4078 }); 4079 swiper.updateSize(); 4080 swiper.updateSlides(); 4081 swiper.updateProgress(); 4082 swiper.updateSlidesClasses(); 4083 function setTranslate() { 4084 const translateValue = swiper.rtlTranslate ? swiper.translate * -1 : swiper.translate; 4085 const newTranslate = Math.min(Math.max(translateValue, swiper.maxTranslate()), swiper.minTranslate()); 4086 swiper.setTranslate(newTranslate); 4087 swiper.updateActiveIndex(); 4088 swiper.updateSlidesClasses(); 4089 } 4090 let translated; 4091 if (params.freeMode?.enabled && !params.cssMode) { 4092 setTranslate(); 4093 if (params.autoHeight) { 4094 swiper.updateAutoHeight(); 4095 } 4096 } 4097 else { 4098 if ((params.slidesPerView === 'auto' || params.slidesPerView > 1) && 4099 swiper.isEnd && 4100 !params.centeredSlides) { 4101 const slidesLength = swiper.virtual && params.virtual?.enabled 4102 ? swiper.virtual.slides.length 4103 : swiper.slides.length; 4104 translated = swiper.slideTo(slidesLength - 1, 0, false, true); 4105 } 4106 else { 4107 translated = swiper.slideTo(swiper.activeIndex, 0, false, true); 4108 } 4109 if (!translated) { 4110 setTranslate(); 4111 } 4112 } 4113 if (params.watchOverflow && snapGrid !== swiper.snapGrid) { 4114 swiper.checkOverflow(); 4115 } 4116 swiper.emit('update'); 4117 } 4118 /** 4119 * Changes slider direction from horizontal to vertical and back. 4120 * 4121 * @param direction New direction. If not specified, then will automatically changed to opposite direction 4122 * @param needUpdate Will call swiper.update(). Default true 4123 */ 4124 changeDirection(newDirection, needUpdate = true) { 4125 const swiper = this; 4126 const currentDirection = swiper.params.direction; 4127 if (!newDirection) { 4128 newDirection = currentDirection === 'horizontal' ? 'vertical' : 'horizontal'; 4129 } 4130 if (newDirection === currentDirection || 4131 (newDirection !== 'horizontal' && newDirection !== 'vertical')) { 4132 return swiper; 4133 } 4134 swiper.el.classList.remove(`${swiper.params.containerModifierClass}${currentDirection}`); 4135 swiper.el.classList.add(`${swiper.params.containerModifierClass}${newDirection}`); 4136 swiper.emitContainerClasses(); 4137 swiper.params.direction = newDirection; 4138 swiper.slides.forEach((slideEl) => { 4139 if (newDirection === 'vertical') { 4140 slideEl.style.width = ''; 4141 } 4142 else { 4143 slideEl.style.height = ''; 4144 } 4145 }); 4146 swiper.emit('changeDirection'); 4147 if (needUpdate) 4148 swiper.update(); 4149 return swiper; 4150 } 4151 /** 4152 * Changes slider language 4153 * 4154 * @param direction New direction. Should be `rtl` or `ltr` 4155 */ 4156 changeLanguageDirection(direction) { 4157 const swiper = this; 4158 if ((swiper.rtl && direction === 'rtl') || (!swiper.rtl && direction === 'ltr')) 4159 return; 4160 swiper.rtl = direction === 'rtl'; 4161 swiper.rtlTranslate = swiper.params.direction === 'horizontal' && swiper.rtl; 4162 if (swiper.rtl) { 4163 swiper.el.classList.add(`${swiper.params.containerModifierClass}rtl`); 4164 swiper.el.dir = 'rtl'; 4165 } 4166 else { 4167 swiper.el.classList.remove(`${swiper.params.containerModifierClass}rtl`); 4168 swiper.el.dir = 'ltr'; 4169 } 4170 swiper.update(); 4171 } 4172 mount(element) { 4173 const swiper = this; 4174 if (swiper.mounted) 4175 return true; 4176 // No DOM (SSR / Node) — nothing to mount to. 4177 if (typeof document === 'undefined') 4178 return false; 4179 // Find el (params.el can be a CSSSelector, HTMLElement, or undefined) 4180 const initialEl = element ?? swiper.params.el; 4181 let el = null; 4182 if (typeof initialEl === 'string') { 4183 el = document.querySelector(initialEl); 4184 } 4185 else if (initialEl instanceof HTMLElement) { 4186 el = initialEl; 4187 } 4188 if (!el) { 4189 return false; 4190 } 4191 el.swiper = swiper; 4192 const parent = el.parentNode; 4193 if (parent && 4194 parent.host && 4195 parent.host.nodeName === swiper.params.swiperElementNodeName.toUpperCase()) { 4196 swiper.isElement = true; 4197 } 4198 const getWrapperSelector = () => { 4199 return `.${(swiper.params.wrapperClass || '').trim().split(' ').join('.')}`; 4200 }; 4201 const getWrapper = () => { 4202 if (el && el.shadowRoot) { 4203 const res = el.shadowRoot.querySelector(getWrapperSelector()); 4204 // Children needs to return slot items 4205 return res; 4206 } 4207 return elementChildren(el, getWrapperSelector())[0]; 4208 }; 4209 // Find Wrapper 4210 let wrapperEl = getWrapper(); 4211 if (!wrapperEl && swiper.params.createElements) { 4212 wrapperEl = createElement('div', swiper.params.wrapperClass); 4213 el.append(wrapperEl); 4214 elementChildren(el, `.${swiper.params.slideClass}`).forEach((slideEl) => { 4215 wrapperEl.append(slideEl); 4216 }); 4217 } 4218 const host = swiper.isElement ? el.parentNode.host : null; 4219 Object.assign(swiper, { 4220 el, 4221 wrapperEl, 4222 slidesEl: swiper.isElement && !host.slideSlots ? host : wrapperEl, 4223 hostEl: swiper.isElement ? host : el, 4224 mounted: true, 4225 // RTL 4226 rtl: el.dir.toLowerCase() === 'rtl' || elementStyle(el, 'direction') === 'rtl', 4227 rtlTranslate: swiper.params.direction === 'horizontal' && 4228 (el.dir.toLowerCase() === 'rtl' || elementStyle(el, 'direction') === 'rtl'), 4229 wrongRTL: elementStyle(wrapperEl, 'display') === '-webkit-box', 4230 }); 4231 return true; 4232 } 4233 /** 4234 * Initialize slider 4235 */ 4236 init(el) { 4237 const swiper = this; 4238 if (swiper.initialized) 4239 return swiper; 4240 const mounted = swiper.mount(el); 4241 if (mounted === false) 4242 return swiper; 4243 swiper.emit('beforeInit'); 4244 // Set breakpoint 4245 if (swiper.params.breakpoints) { 4246 swiper.setBreakpoint(); 4247 } 4248 // Add Classes 4249 swiper.addClasses(); 4250 // Update size 4251 swiper.updateSize(); 4252 // Update slides 4253 swiper.updateSlides(); 4254 if (swiper.params.watchOverflow) { 4255 swiper.checkOverflow(); 4256 } 4257 // Set Grab Cursor 4258 if (swiper.params.grabCursor && swiper.enabled) { 4259 swiper.setGrabCursor(); 4260 } 4261 // Slide To Initial Slide 4262 if (swiper.params.loop && swiper.virtual && swiper.params.virtual?.enabled) { 4263 swiper.slideTo((swiper.params.initialSlide ?? 0) + (swiper.virtual.slidesBefore ?? 0), 0, swiper.params.runCallbacksOnInit, false, true); 4264 } 4265 else { 4266 swiper.slideTo(swiper.params.initialSlide, 0, swiper.params.runCallbacksOnInit, false, true); 4267 } 4268 // Create loop 4269 if (swiper.params.loop) { 4270 swiper.loopCreate(undefined, true); 4271 } 4272 // Attach events 4273 swiper.attachEvents(); 4274 const lazyElements = [...swiper.el.querySelectorAll('[loading="lazy"]')]; 4275 if (swiper.isElement) { 4276 lazyElements.push(...swiper.hostEl.querySelectorAll('[loading="lazy"]')); 4277 }
4278 lazyElements.forEach((imageEl) => { 4279 if (imageEl.complete) { 4280 processLazyPreloader(swiper, imageEl); 4281 } 4282 else { 4283 imageEl.addEventListener('load', (e) => { 4284 processLazyPreloader(swiper, e.target); 4285 }); 4286 } 4287 }); 4288 preload(swiper);
vendor: 10,242 bytes, lines 4288-4537
4288 4289 // Init Flag 4290 swiper.initialized = true; 4291 preload(swiper); 4292 // Emit 4293 swiper.emit('init'); 4294 swiper.emit('afterInit'); 4295 return swiper; 4296 } 4297 /** 4298 * Destroy slider instance and detach all events listeners 4299 * 4300 * @param deleteInstance Set it to false (by default it is true) to not to delete Swiper instance 4301 * @param cleanStyles Set it to true (by default it is true) and all custom styles will be removed from slides, wrapper and container. 4302 * Useful if you need to destroy Swiper and to init again with new options or in different direction 4303 */ 4304 destroy(deleteInstance = true, cleanStyles = true) { 4305 const swiper = this; 4306 const { params, el, wrapperEl, slides } = swiper; 4307 if (typeof swiper.params === 'undefined' || swiper.destroyed) { 4308 return null; 4309 } 4310 swiper.emit('beforeDestroy'); 4311 // Init Flag 4312 swiper.initialized = false; 4313 // Detach events 4314 swiper.detachEvents(); 4315 // Destroy loop 4316 if (params.loop) { 4317 swiper.loopDestroy(); 4318 } 4319 // Cleanup styles 4320 if (cleanStyles) { 4321 swiper.removeClasses(); 4322 if (el && typeof el !== 'string') { 4323 el.removeAttribute('style'); 4324 } 4325 if (wrapperEl) { 4326 wrapperEl.removeAttribute('style'); 4327 } 4328 if (slides && slides.length) { 4329 slides.forEach((slideEl) => { 4330 slideEl.classList.remove(params.slideVisibleClass, params.slideFullyVisibleClass, params.slideActiveClass, params.slideNextClass, params.slidePrevClass); 4331 slideEl.removeAttribute('style'); 4332 slideEl.removeAttribute('data-swiper-slide-index'); 4333 }); 4334 } 4335 } 4336 swiper.emit('destroy'); 4337 // Detach emitter events 4338 Object.keys(swiper.eventsListeners).forEach((eventName) => { 4339 swiper.off(eventName); 4340 }); 4341 if (deleteInstance !== false) { 4342 if (swiper.el && typeof swiper.el !== 'string') { 4343 swiper.el.swiper = null; 4344 } 4345 deleteProps(swiper); 4346 } 4347 swiper.destroyed = true; 4348 return null; 4349 } 4350 static extendDefaults(newDefaults) { 4351 extend(extendedDefaults, newDefaults); 4352 } 4353 static installModule(mod) { 4354 if (!Swiper.prototype.__modules__) 4355 Swiper.prototype.__modules__ = []; 4356 const modules = Swiper.prototype.__modules__; 4357 if (typeof mod === 'function' && modules.indexOf(mod) < 0) { 4358 modules.push(mod); 4359 } 4360 } 4361 static use(module) { 4362 if (Array.isArray(module)) { 4363 module.forEach((m) => Swiper.installModule(m)); 4364 return Swiper; 4365 } 4366 Swiper.installModule(module); 4367 return Swiper; 4368 } 4369 } 4370 Object.defineProperty(Swiper, 'extendedDefaults', { 4371 get() { 4372 return extendedDefaults; 4373 }, 4374 }); 4375 Object.defineProperty(Swiper, 'defaults', { 4376 get() { 4377 return defaults; 4378 }, 4379 }); 4380 // Attach prototype-mixin method groups onto Swiper.prototype. Each group is a 4381 // plain record of method-name → function; we copy them across as-is. 4382 const prototypeRecord = prototypes; 4383 const swiperProto = Swiper.prototype; 4384 Object.keys(prototypeRecord).forEach((prototypeGroup) => { 4385 const group = prototypeRecord[prototypeGroup]; 4386 Object.keys(group).forEach((protoMethod) => { 4387 swiperProto[protoMethod] = group[protoMethod]; 4388 }); 4389 }); 4390 Swiper.use([Resize, Observer]); 4391 4392 const Virtual = ({ swiper, extendParams, on, emit }) => { 4393 extendParams({ 4394 virtual: { 4395 enabled: false, 4396 slides: [], 4397 cache: true, 4398 slidesPerViewAutoSlideSize: 320, 4399 renderSlide: null, 4400 renderExternal: null, 4401 renderExternalUpdate: true, 4402 addSlidesBefore: 0, 4403 addSlidesAfter: 0, 4404 }, 4405 }); 4406 let cssModeTimeout; 4407 // Methods (appendSlide/prependSlide/removeSlide/removeAllSlides/update) are 4408 // attached via Object.assign below once they're defined. Cast through 4409 // Partial<> so the initial state-only literal can be assigned without 4410 // pretending the methods exist yet. 4411 swiper.virtual = { 4412 cache: {}, 4413 from: 0, 4414 // -1 marks "nothing rendered yet": no real update can produce to < from, 4415 // so the first update() never mistakes slide 0 for an already-rendered 4416 // slide and always appends the full [from, to] window (#8202). 4417 to: -1, 4418 slides: [], 4419 offset: 0, 4420 slidesGrid: [], 4421 }; 4422 function getParams() { 4423 return swiper.params.virtual; 4424 } 4425 // Created lazily so module init does not touch the DOM (SSR / Node safe). 4426 let tempDOM; 4427 const getTempDOM = () => (tempDOM ??= document.createElement('div')); 4428 function renderSlide(slide, index) { 4429 const params = getParams(); 4430 if (params.cache && swiper.virtual.cache[index]) { 4431 return swiper.virtual.cache[index]; 4432 } 4433 let slideEl; 4434 if (params.renderSlide) { 4435 const rendered = params.renderSlide.call(swiper, slide, index); 4436 if (typeof rendered === 'string') { 4437 const el = getTempDOM(); 4438 setInnerHTML(el, rendered); 4439 slideEl = el.children[0]; 4440 } 4441 else { 4442 slideEl = rendered; 4443 } 4444 } 4445 else if (swiper.isElement) { 4446 slideEl = createElement('swiper-slide'); 4447 } 4448 else { 4449 slideEl = createElement('div', swiper.params.slideClass); 4450 } 4451 slideEl.setAttribute('data-swiper-slide-index', String(index)); 4452 if (!params.renderSlide) { 4453 setInnerHTML(slideEl, slide); 4454 } 4455 if (params.cache) { 4456 swiper.virtual.cache[index] = slideEl; 4457 } 4458 return slideEl; 4459 } 4460 function update(force, beforeInit, forceActiveIndex) { 4461 const { slidesPerGroup, centeredSlides, slidesPerView, loop: isLoop, initialSlide, } = swiper.params; 4462 if (beforeInit && !isLoop && (initialSlide ?? 0) > 0) { 4463 return; 4464 } 4465 const { addSlidesBefore, addSlidesAfter, slidesPerViewAutoSlideSize } = getParams(); 4466 const { from: previousFrom, to: previousTo, slides, slidesGrid: previousSlidesGrid, offset: previousOffset, } = swiper.virtual; 4467 if (!swiper.params.cssMode) { 4468 swiper.updateActiveIndex(); 4469 } 4470 const activeIndex = typeof forceActiveIndex === 'undefined' ? swiper.activeIndex || 0 : forceActiveIndex; 4471 let offsetProp; 4472 if (swiper.rtlTranslate) 4473 offsetProp = 'right'; 4474 else 4475 offsetProp = swiper.isHorizontal() ? 'left' : 'top'; 4476 let slidesPerViewNumeric; 4477 if (slidesPerView === 'auto') { 4478 if (slidesPerViewAutoSlideSize) { 4479 let swiperSize = swiper.size; 4480 if (!swiperSize) { 4481 swiperSize = swiper.isHorizontal() 4482 ? swiper.el.getBoundingClientRect().width 4483 : swiper.el.getBoundingClientRect().height; 4484 } 4485 slidesPerViewNumeric = Math.max(1, Math.ceil(swiperSize / slidesPerViewAutoSlideSize)); 4486 } 4487 else { 4488 slidesPerViewNumeric = 1; 4489 } 4490 } 4491 else { 4492 slidesPerViewNumeric = slidesPerView ?? 1; 4493 } 4494 const groupSize = slidesPerGroup ?? 1; 4495 let slidesAfter; 4496 let slidesBefore; 4497 if (centeredSlides) { 4498 slidesAfter = Math.floor(slidesPerViewNumeric / 2) + groupSize + addSlidesAfter; 4499 slidesBefore = Math.floor(slidesPerViewNumeric / 2) + groupSize + addSlidesBefore; 4500 } 4501 else { 4502 slidesAfter = slidesPerViewNumeric + (groupSize - 1) + addSlidesAfter; 4503 slidesBefore = (isLoop ? slidesPerViewNumeric : groupSize) + addSlidesBefore; 4504 } 4505 let from = activeIndex - slidesBefore; 4506 let to = activeIndex + slidesAfter; 4507 if (!isLoop) { 4508 from = Math.max(from, 0); 4509 to = Math.min(to, slides.length - 1); 4510 } 4511 let offset = (swiper.slidesGrid[from] || 0) - (swiper.slidesGrid[0] || 0); 4512 if (isLoop && activeIndex >= slidesBefore) { 4513 from -= slidesBefore; 4514 if (!centeredSlides) 4515 offset += swiper.slidesGrid[0]; 4516 } 4517 else if (isLoop && activeIndex < slidesBefore) { 4518 from = -slidesBefore; 4519 if (centeredSlides) 4520 offset += swiper.slidesGrid[0]; 4521 } 4522 Object.assign(swiper.virtual, { 4523 from, 4524 to, 4525 offset, 4526 slidesGrid: swiper.slidesGrid, 4527 slidesBefore, 4528 slidesAfter, 4529 }); 4530 function onRendered() { 4531 swiper.updateSlides(); 4532 swiper.updateProgress(); 4533 swiper.updateSlidesClasses(); 4534 emit('virtualUpdate'); 4535 } 4536 if (previousFrom === from && previousTo === to && !force) { 4537 if (swiper.slidesGrid !== previousSlidesGrid && offset !== previousOffset) {
vendor: 168,981 bytes, lines 4538-8602
4538 swiper.slides.forEach((slideEl) => { 4539 slideEl.style.setProperty(offsetProp, `${offset - Math.abs(swiper.cssOverflowAdjustment())}px`); 4540 }); 4541 } 4542 swiper.updateProgress(); 4543 emit('virtualUpdate'); 4544 return; 4545 } 4546 const virtualParams = getParams(); 4547 if (virtualParams.renderExternal) { 4548 const slidesToRender = []; 4549 for (let i = from; i <= to; i += 1) { 4550 slidesToRender.push(slides[i]); 4551 } 4552 virtualParams.renderExternal.call(swiper, { 4553 offset, 4554 from, 4555 to, 4556 slides: slidesToRender, 4557 }); 4558 if (virtualParams.renderExternalUpdate) { 4559 onRendered(); 4560 } 4561 else { 4562 emit('virtualUpdate'); 4563 } 4564 return; 4565 } 4566 const prependIndexes = []; 4567 const appendIndexes = []; 4568 const getSlideIndex = (index) => { 4569 let slideIndex = index; 4570 if (index < 0) { 4571 slideIndex = slides.length + index; 4572 } 4573 else if (slideIndex >= slides.length) { 4574 slideIndex = slideIndex - slides.length; 4575 } 4576 return slideIndex; 4577 }; 4578 if (force) { 4579 swiper.slides 4580 .filter((el) => el.matches(`.${swiper.params.slideClass}, swiper-slide`)) 4581 .forEach((slideEl) => { 4582 slideEl.remove(); 4583 }); 4584 } 4585 else { 4586 for (let i = previousFrom; i <= previousTo; i += 1) { 4587 if (i < from || i > to) { 4588 const slideIndex = getSlideIndex(i); 4589 swiper.slides 4590 .filter((el) => el.matches(`.${swiper.params.slideClass}[data-swiper-slide-index="${slideIndex}"], swiper-slide[data-swiper-slide-index="${slideIndex}"]`)) 4591 .forEach((slideEl) => { 4592 slideEl.remove(); 4593 }); 4594 } 4595 } 4596 } 4597 const loopFrom = isLoop ? -slides.length : 0; 4598 const loopTo = isLoop ? slides.length * 2 : slides.length; 4599 for (let i = loopFrom; i < loopTo; i += 1) { 4600 if (i >= from && i <= to) { 4601 const slideIndex = getSlideIndex(i); 4602 if (typeof previousTo === 'undefined' || force) { 4603 appendIndexes.push(slideIndex); 4604 } 4605 else { 4606 if (i > previousTo) 4607 appendIndexes.push(slideIndex); 4608 if (i < previousFrom) 4609 prependIndexes.push(slideIndex); 4610 } 4611 } 4612 } 4613 appendIndexes.forEach((index) => { 4614 swiper.slidesEl.append(renderSlide(slides[index], index)); 4615 }); 4616 if (isLoop) { 4617 for (let i = prependIndexes.length - 1; i >= 0; i -= 1) { 4618 const index = prependIndexes[i]; 4619 swiper.slidesEl.prepend(renderSlide(slides[index], index)); 4620 } 4621 } 4622 else { 4623 prependIndexes.sort((a, b) => b - a); 4624 prependIndexes.forEach((index) => { 4625 swiper.slidesEl.prepend(renderSlide(slides[index], index)); 4626 }); 4627 } 4628 elementChildren(swiper.slidesEl, '.swiper-slide, swiper-slide').forEach((slideEl) => { 4629 slideEl.style.setProperty(offsetProp, `${offset - Math.abs(swiper.cssOverflowAdjustment())}px`); 4630 }); 4631 onRendered(); 4632 } 4633 function appendSlide(slides) { 4634 if (slides !== null && 4635 typeof slides === 'object' && 4636 'length' in slides) { 4637 const arr = slides; 4638 for (let i = 0; i < arr.length; i += 1) { 4639 if (arr[i]) 4640 swiper.virtual.slides.push(arr[i]); 4641 } 4642 } 4643 else { 4644 swiper.virtual.slides.push(slides); 4645 } 4646 update(true); 4647 } 4648 function prependSlide(slides) { 4649 const activeIndex = swiper.activeIndex; 4650 let newActiveIndex = activeIndex + 1; 4651 let numberOfNewSlides = 1; 4652 if (Array.isArray(slides)) { 4653 for (let i = 0; i < slides.length; i += 1) { 4654 if (slides[i]) 4655 swiper.virtual.slides.unshift(slides[i]); 4656 } 4657 newActiveIndex = activeIndex + slides.length; 4658 numberOfNewSlides = slides.length; 4659 } 4660 else { 4661 swiper.virtual.slides.unshift(slides); 4662 } 4663 if (getParams().cache) { 4664 const cache = swiper.virtual.cache; 4665 const newCache = {}; 4666 Object.keys(cache).forEach((cachedIndex) => { 4667 const cachedEl = cache[Number(cachedIndex)]; 4668 const cachedElIndex = cachedEl.getAttribute('data-swiper-slide-index'); 4669 if (cachedElIndex) { 4670 cachedEl.setAttribute('data-swiper-slide-index', String(parseInt(cachedElIndex, 10) + numberOfNewSlides)); 4671 } 4672 newCache[parseInt(cachedIndex, 10) + numberOfNewSlides] = cachedEl; 4673 }); 4674 swiper.virtual.cache = newCache; 4675 } 4676 update(true); 4677 swiper.slideTo(newActiveIndex, 0); 4678 } 4679 function removeSlide(slidesIndexes) { 4680 if (typeof slidesIndexes === 'undefined' || slidesIndexes === null) 4681 return; 4682 let activeIndex = swiper.activeIndex; 4683 const shiftCacheDownFrom = (removedIndex) => { 4684 Object.keys(swiper.virtual.cache).forEach((key) => { 4685 const numericKey = Number(key); 4686 if (numericKey > removedIndex) { 4687 const shifted = swiper.virtual.cache[numericKey]; 4688 swiper.virtual.cache[numericKey - 1] = shifted; 4689 shifted.setAttribute('data-swiper-slide-index', String(numericKey - 1)); 4690 delete swiper.virtual.cache[numericKey]; 4691 } 4692 }); 4693 }; 4694 if (Array.isArray(slidesIndexes)) { 4695 for (let i = slidesIndexes.length - 1; i >= 0; i -= 1) { 4696 if (getParams().cache) { 4697 delete swiper.virtual.cache[slidesIndexes[i]]; 4698 shiftCacheDownFrom(slidesIndexes[i]); 4699 } 4700 swiper.virtual.slides.splice(slidesIndexes[i], 1); 4701 if (slidesIndexes[i] < activeIndex) 4702 activeIndex -= 1; 4703 activeIndex = Math.max(activeIndex, 0); 4704 } 4705 } 4706 else { 4707 if (getParams().cache) { 4708 delete swiper.virtual.cache[slidesIndexes]; 4709 shiftCacheDownFrom(slidesIndexes); 4710 } 4711 swiper.virtual.slides.splice(slidesIndexes, 1); 4712 if (slidesIndexes < activeIndex) 4713 activeIndex -= 1; 4714 activeIndex = Math.max(activeIndex, 0); 4715 } 4716 update(true); 4717 swiper.slideTo(activeIndex, 0); 4718 } 4719 function removeAllSlides() { 4720 swiper.virtual.slides = []; 4721 if (getParams().cache) { 4722 swiper.virtual.cache = {}; 4723 } 4724 update(true); 4725 swiper.slideTo(0, 0); 4726 } 4727 on('beforeInit', () => { 4728 if (!getParams().enabled) 4729 return; 4730 let domSlidesAssigned = false; 4731 const passedVirtual = swiper.passedParams.virtual; 4732 const passedSlidesUndefined = !passedVirtual || typeof passedVirtual !== 'object' || passedVirtual.slides === undefined; 4733 if (passedSlidesUndefined) { 4734 const slides = [...swiper.slidesEl.children].filter((el) => el.matches(`.${swiper.params.slideClass}, swiper-slide`)); 4735 if (slides && slides.length) { 4736 swiper.virtual.slides = [...slides]; 4737 domSlidesAssigned = true; 4738 slides.forEach((slideEl, slideIndex) => { 4739 slideEl.setAttribute('data-swiper-slide-index', String(slideIndex)); 4740 swiper.virtual.cache[slideIndex] = slideEl; 4741 slideEl.remove(); 4742 }); 4743 } 4744 } 4745 if (!domSlidesAssigned) { 4746 swiper.virtual.slides = getParams().slides; 4747 } 4748 swiper.classNames.push(`${swiper.params.containerModifierClass}virtual`); 4749 swiper.params.watchSlidesProgress = true; 4750 swiper.originalParams.watchSlidesProgress = true; 4751 update(false, true); 4752 }); 4753 on('setTranslate', () => { 4754 if (!getParams().enabled) 4755 return; 4756 if (swiper.params.cssMode && !swiper._immediateVirtual) { 4757 clearTimeout(cssModeTimeout); 4758 cssModeTimeout = setTimeout(() => { 4759 update(); 4760 }, 100); 4761 } 4762 else { 4763 update(); 4764 } 4765 }); 4766 on('init update resize', () => { 4767 if (!getParams().enabled) 4768 return; 4769 if (swiper.params.cssMode) { 4770 setCSSProperty(swiper.wrapperEl, '--swiper-virtual-size', `${swiper.virtualSize}px`); 4771 } 4772 }); 4773 Object.assign(swiper.virtual, { 4774 appendSlide, 4775 prependSlide, 4776 removeSlide, 4777 removeAllSlides, 4778 update, 4779 }); 4780 }; 4781 4782 const Keyboard = ({ swiper, extendParams, on, emit }) => { 4783 extendParams({ 4784 keyboard: { 4785 enabled: false, 4786 onlyInViewport: true, 4787 pageUpDown: true, 4788 speed: undefined, 4789 }, 4790 }); 4791 function getParams() { 4792 return swiper.params.keyboard; 4793 } 4794 function handle(event) { 4795 if (!swiper.enabled) 4796 return; 4797 const { rtlTranslate: rtl } = swiper; 4798 const e = 'originalEvent' in event && event.originalEvent ? event.originalEvent : event; 4799 const kc = e.keyCode || e.charCode; 4800 const params = getParams(); 4801 const pageUpDown = !!params.pageUpDown; 4802 const isPageUp = pageUpDown && kc === 33; 4803 const isPageDown = pageUpDown && kc === 34; 4804 const isArrowLeft = kc === 37; 4805 const isArrowRight = kc === 39; 4806 const isArrowUp = kc === 38; 4807 const isArrowDown = kc === 40; 4808 // Directions locks 4809 if (!swiper.allowSlideNext && 4810 ((swiper.isHorizontal() && isArrowRight) || 4811 (swiper.isVertical() && isArrowDown) || 4812 isPageDown)) { 4813 return false; 4814 } 4815 if (!swiper.allowSlidePrev && 4816 ((swiper.isHorizontal() && isArrowLeft) || (swiper.isVertical() && isArrowUp) || isPageUp)) { 4817 return false; 4818 } 4819 if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) { 4820 return undefined; 4821 } 4822 const activeElement = document.activeElement; 4823 if (activeElement && 4824 (activeElement.isContentEditable || 4825 (activeElement.nodeName && 4826 (activeElement.nodeName.toLowerCase() === 'input' || 4827 activeElement.nodeName.toLowerCase() === 'textarea')))) { 4828 return undefined; 4829 } 4830 if (params.onlyInViewport && 4831 (isPageUp || isPageDown || isArrowLeft || isArrowRight || isArrowUp || isArrowDown)) { 4832 let inView = false; 4833 // Check that swiper should be inside of visible area of window 4834 if (elementParents(swiper.el, `.${swiper.params.slideClass}, swiper-slide`).length > 0 && 4835 elementParents(swiper.el, `.${swiper.params.slideActiveClass}`).length === 0) { 4836 return undefined; 4837 } 4838 const el = swiper.el; 4839 const swiperWidth = el.clientWidth; 4840 const swiperHeight = el.clientHeight; 4841 const windowWidth = window.innerWidth; 4842 const windowHeight = window.innerHeight; 4843 const swiperOffset = elementOffset(el); 4844 if (rtl) 4845 swiperOffset.left -= el.scrollLeft; 4846 const swiperCoord = [ 4847 [swiperOffset.left, swiperOffset.top], 4848 [swiperOffset.left + swiperWidth, swiperOffset.top], 4849 [swiperOffset.left, swiperOffset.top + swiperHeight], 4850 [swiperOffset.left + swiperWidth, swiperOffset.top + swiperHeight], 4851 ]; 4852 for (let i = 0; i < swiperCoord.length; i += 1) { 4853 const point = swiperCoord[i]; 4854 if (point[0] >= 0 && point[0] <= windowWidth && point[1] >= 0 && point[1] <= windowHeight) { 4855 if (point[0] === 0 && point[1] === 0) 4856 continue; 4857 inView = true; 4858 } 4859 } 4860 if (!inView) 4861 return undefined; 4862 } 4863 const speed = params.speed; 4864 if (swiper.isHorizontal()) { 4865 if (isPageUp || isPageDown || isArrowLeft || isArrowRight) { 4866 if (e.cancelable) 4867 e.preventDefault(); 4868 } 4869 if (((isPageDown || isArrowRight) && !rtl) || ((isPageUp || isArrowLeft) && rtl)) 4870 swiper.slideNext(speed); 4871 if (((isPageUp || isArrowLeft) && !rtl) || ((isPageDown || isArrowRight) && rtl)) 4872 swiper.slidePrev(speed); 4873 } 4874 else { 4875 if (isPageUp || isPageDown || isArrowUp || isArrowDown) { 4876 if (e.cancelable) 4877 e.preventDefault(); 4878 } 4879 if (isPageDown || isArrowDown) 4880 swiper.slideNext(speed); 4881 if (isPageUp || isArrowUp) 4882 swiper.slidePrev(speed); 4883 } 4884 emit('keyPress', kc); 4885 return undefined; 4886 } 4887 function enable() { 4888 if (swiper.keyboard.enabled) 4889 return; 4890 document.addEventListener('keydown', handle); 4891 swiper.keyboard.enabled = true; 4892 } 4893 function disable() { 4894 if (!swiper.keyboard.enabled) 4895 return; 4896 document.removeEventListener('keydown', handle); 4897 swiper.keyboard.enabled = false; 4898 } 4899 swiper.keyboard = { 4900 enabled: false, 4901 enable, 4902 disable, 4903 }; 4904 on('init', () => { 4905 if (getParams().enabled) { 4906 enable(); 4907 } 4908 }); 4909 on('destroy', () => { 4910 if (swiper.keyboard.enabled) { 4911 disable(); 4912 } 4913 }); 4914 }; 4915 4916 const Mousewheel = ({ swiper, extendParams, on, emit }) => { 4917 extendParams({ 4918 mousewheel: { 4919 enabled: false, 4920 releaseOnEdges: false, 4921 invert: false, 4922 forceToAxis: false, 4923 sensitivity: 1, 4924 eventsTarget: 'container', 4925 thresholdDelta: null, 4926 thresholdTime: null, 4927 noMousewheelClass: 'swiper-no-mousewheel', 4928 }, 4929 }); 4930 let timeout; 4931 let lastScrollTime = now(); 4932 let lastEventBeforeSnap; 4933 let mouseEntered = false; 4934 const recentWheelEvents = []; 4935 function getParams() { 4936 return swiper.params.mousewheel; 4937 } 4938 function normalize(e) { 4939 // Reasonable defaults 4940 const PIXEL_STEP = 10; 4941 const LINE_HEIGHT = 40; 4942 const PAGE_HEIGHT = 800; 4943 const ev = e; 4944 let sX = 0; 4945 let sY = 0; // spinX, spinY 4946 let pX = 0; 4947 let pY = 0; // pixelX, pixelY 4948 // Legacy 4949 if (ev.detail !== undefined) { 4950 sY = ev.detail; 4951 } 4952 if (ev.wheelDelta !== undefined) { 4953 sY = -ev.wheelDelta / 120; 4954 } 4955 if (ev.wheelDeltaY !== undefined) { 4956 sY = -ev.wheelDeltaY / 120; 4957 } 4958 if (ev.wheelDeltaX !== undefined) { 4959 sX = -ev.wheelDeltaX / 120; 4960 } 4961 // side scrolling on FF with DOMMouseScroll 4962 if (ev.axis !== undefined && 4963 ev.HORIZONTAL_AXIS !== undefined && 4964 ev.axis === ev.HORIZONTAL_AXIS) { 4965 sX = sY; 4966 sY = 0; 4967 } 4968 pX = sX * PIXEL_STEP; 4969 pY = sY * PIXEL_STEP; 4970 if (ev.deltaY !== undefined) { 4971 pY = ev.deltaY; 4972 } 4973 if (ev.deltaX !== undefined) { 4974 pX = ev.deltaX; 4975 } 4976 if (ev.shiftKey && !pX) { 4977 // if user scrolls with shift he wants horizontal scroll 4978 pX = pY; 4979 pY = 0; 4980 } 4981 if ((pX || pY) && ev.deltaMode) { 4982 if (ev.deltaMode === 1) { 4983 // delta in LINE units 4984 pX *= LINE_HEIGHT; 4985 pY *= LINE_HEIGHT; 4986 } 4987 else { 4988 // delta in PAGE units 4989 pX *= PAGE_HEIGHT; 4990 pY *= PAGE_HEIGHT; 4991 } 4992 } 4993 // Fall-back if spin cannot be determined 4994 if (pX && !sX) { 4995 sX = pX < 1 ? -1 : 1; 4996 } 4997 if (pY && !sY) { 4998 sY = pY < 1 ? -1 : 1; 4999 } 5000 return { 5001 spinX: sX, 5002 spinY: sY, 5003 pixelX: pX, 5004 pixelY: pY, 5005 }; 5006 } 5007 function handleMouseEnter() { 5008 if (!swiper.enabled) 5009 return; 5010 mouseEntered = true; 5011 } 5012 function handleMouseLeave() { 5013 if (!swiper.enabled) 5014 return; 5015 mouseEntered = false; 5016 } 5017 function animateSlider(newEvent) { 5018 const params = getParams(); 5019 if (params.thresholdDelta && newEvent.delta < params.thresholdDelta) { 5020 // Prevent if delta of wheel scroll delta is below configured threshold 5021 return false; 5022 } 5023 if (params.thresholdTime && now() - lastScrollTime < params.thresholdTime) { 5024 // Prevent if time between scrolls is below configured threshold 5025 return false; 5026 } 5027 // If the movement is NOT big enough and 5028 // if the last time the user scrolled was too close to the current one (avoid continuously triggering the slider): 5029 // Don't go any further (avoid insignificant scroll movement). 5030 if (newEvent.delta >= 6 && now() - lastScrollTime < 60) { 5031 // Return false as a default 5032 return true; 5033 } 5034 if (newEvent.direction < 0) { 5035 if ((!swiper.isEnd || swiper.params.loop) && !swiper.animating) { 5036 swiper.slideNext(); 5037 emit('scroll', newEvent.raw); 5038 } 5039 } 5040 else if ((!swiper.isBeginning || swiper.params.loop) && !swiper.animating) { 5041 swiper.slidePrev(); 5042 emit('scroll', newEvent.raw); 5043 } 5044 // If you got here is because an animation has been triggered so store the current time 5045 lastScrollTime = new window.Date().getTime(); 5046 // Return false as a default 5047 return false; 5048 } 5049 function releaseScroll(newEvent) { 5050 const params = getParams(); 5051 if (newEvent.direction < 0) { 5052 if (swiper.isEnd && !swiper.params.loop && params.releaseOnEdges) { 5053 // Return true to animate scroll on edges 5054 return true; 5055 } 5056 } 5057 else if (swiper.isBeginning && !swiper.params.loop && params.releaseOnEdges) { 5058 // Return true to animate scroll on edges 5059 return true; 5060 } 5061 return false; 5062 } 5063 function handle(event) { 5064 let e = 'originalEvent' in event && event.originalEvent ? event.originalEvent : event; 5065 let disableParentSwiper = true; 5066 if (!swiper.enabled) 5067 return false; 5068 // Ignore event if the target or its parents have the swiper-no-mousewheel class 5069 const params = getParams(); 5070 if (event.target.closest(`.${params.noMousewheelClass}`)) 5071 return false; 5072 if (swiper.params.cssMode) { 5073 e.preventDefault(); 5074 } 5075 let targetEl = swiper.el; 5076 if (params.eventsTarget !== 'container') { 5077 targetEl = document.querySelector(params.eventsTarget); 5078 } 5079 const targetElContainsTarget = targetEl && targetEl.contains(e.target); 5080 if (!mouseEntered && !targetElContainsTarget && !params.releaseOnEdges) 5081 return true; 5082 let delta = 0; 5083 const rtlFactor = swiper.rtlTranslate ? -1 : 1; 5084 const data = normalize(e); 5085 if (params.forceToAxis) { 5086 if (swiper.isHorizontal()) { 5087 if (Math.abs(data.pixelX) > Math.abs(data.pixelY)) 5088 delta = -data.pixelX * rtlFactor; 5089 else 5090 return true; 5091 } 5092 else if (Math.abs(data.pixelY) > Math.abs(data.pixelX)) 5093 delta = -data.pixelY; 5094 else 5095 return true; 5096 } 5097 else { 5098 delta = 5099 Math.abs(data.pixelX) > Math.abs(data.pixelY) ? -data.pixelX * rtlFactor : -data.pixelY; 5100 } 5101 if (delta === 0) 5102 return true; 5103 if (params.invert) 5104 delta = -delta; 5105 // Get the scroll positions 5106 let positions = swiper.getTranslate() + delta * (params.sensitivity ?? 1); 5107 if (positions >= swiper.minTranslate()) 5108 positions = swiper.minTranslate(); 5109 if (positions <= swiper.maxTranslate()) 5110 positions = swiper.maxTranslate(); 5111 // When loop is true: 5112 // the disableParentSwiper will be true. 5113 // When loop is false: 5114 // if the scroll positions is not on edge, 5115 // then the disableParentSwiper will be true. 5116 // if the scroll on edge positions, 5117 // then the disableParentSwiper will be false. 5118 disableParentSwiper = swiper.params.loop 5119 ? true 5120 : !(positions === swiper.minTranslate() || positions === swiper.maxTranslate()); 5121 if (disableParentSwiper && swiper.params.nested) 5122 e.stopPropagation(); 5123 const freeModeParams = swiper.params.freeMode; 5124 if (!swiper.params.freeMode || !freeModeParams?.enabled) { 5125 // Register the new event in a variable which stores the relevant data 5126 const newEvent = { 5127 time: now(), 5128 delta: Math.abs(delta), 5129 direction: Math.sign(delta), 5130 raw: event, 5131 }; 5132 // Keep the most recent events 5133 if (recentWheelEvents.length >= 2) { 5134 recentWheelEvents.shift(); // only store the last N events 5135 } 5136 const prevEvent = recentWheelEvents.length 5137 ? recentWheelEvents[recentWheelEvents.length - 1] 5138 : undefined; 5139 recentWheelEvents.push(newEvent); 5140 if (prevEvent) { 5141 if (newEvent.direction !== prevEvent.direction || 5142 newEvent.delta > prevEvent.delta || 5143 newEvent.time > prevEvent.time + 150) { 5144 animateSlider(newEvent); 5145 } 5146 } 5147 else { 5148 animateSlider(newEvent); 5149 } 5150 // If it's time to release the scroll: 5151 // Return now so you don't hit the preventDefault. 5152 if (releaseScroll(newEvent)) { 5153 return true; 5154 } 5155 } 5156 else { 5157 // Freemode or scrollContainer: 5158 const newEvent = { 5159 time: now(), 5160 delta: Math.abs(delta), 5161 direction: Math.sign(delta), 5162 }; 5163 const ignoreWheelEvents = lastEventBeforeSnap && 5164 newEvent.time < lastEventBeforeSnap.time + 500 && 5165 newEvent.delta <= lastEventBeforeSnap.delta && 5166 newEvent.direction === lastEventBeforeSnap.direction; 5167 if (!ignoreWheelEvents) { 5168 lastEventBeforeSnap = undefined; 5169 let position = swiper.getTranslate() + delta * (params.sensitivity ?? 1); 5170 const wasBeginning = swiper.isBeginning; 5171 const wasEnd = swiper.isEnd; 5172 if (position >= swiper.minTranslate()) 5173 position = swiper.minTranslate(); 5174 if (position <= swiper.maxTranslate()) 5175 position = swiper.maxTranslate(); 5176 swiper.setTransition(0); 5177 swiper.setTranslate(position); 5178 swiper.updateProgress(); 5179 swiper.updateActiveIndex(); 5180 swiper.updateSlidesClasses(); 5181 if ((!wasBeginning && swiper.isBeginning) || (!wasEnd && swiper.isEnd)) { 5182 swiper.updateSlidesClasses(); 5183 } 5184 if (swiper.params.loop) { 5185 swiper.loopFix({ 5186 direction: newEvent.direction < 0 ? 'next' : 'prev', 5187 byMousewheel: true, 5188 }); 5189 } 5190 if (freeModeParams?.sticky) { 5191 clearTimeout(timeout); 5192 timeout = undefined; 5193 if (recentWheelEvents.length >= 15) { 5194 recentWheelEvents.shift(); // only store the last N events 5195 } 5196 const prevEvent = recentWheelEvents.length 5197 ? recentWheelEvents[recentWheelEvents.length - 1] 5198 : undefined; 5199 const firstEvent = recentWheelEvents[0]; 5200 recentWheelEvents.push(newEvent); 5201 if (prevEvent && 5202 (newEvent.delta > prevEvent.delta || newEvent.direction !== prevEvent.direction)) { 5203 // Increasing or reverse-sign delta means the user started scrolling again. Clear the wheel event log. 5204 recentWheelEvents.splice(0); 5205 } 5206 else if (recentWheelEvents.length >= 15 && 5207 firstEvent && 5208 newEvent.time - firstEvent.time < 500 && 5209 firstEvent.delta - newEvent.delta >= 1 && 5210 newEvent.delta <= 6) { 5211 const snapToThreshold = delta > 0 ? 0.8 : 0.2; 5212 lastEventBeforeSnap = newEvent; 5213 recentWheelEvents.splice(0); 5214 timeout = nextTick(() => { 5215 if (swiper.destroyed || !swiper.params) 5216 return; 5217 swiper.slideToClosest(swiper.params.speed, true, undefined, snapToThreshold); 5218 }, 0); // no delay; move on next tick 5219 } 5220 if (!timeout) { 5221 timeout = nextTick(() => { 5222 if (swiper.destroyed || !swiper.params) 5223 return; 5224 const snapToThreshold = 0.5; 5225 lastEventBeforeSnap = newEvent; 5226 recentWheelEvents.splice(0); 5227 swiper.slideToClosest(swiper.params.speed, true, undefined, snapToThreshold); 5228 }, 500); 5229 } 5230 } 5231 // Emit event 5232 if (!ignoreWheelEvents) 5233 emit('scroll', e); 5234 // Stop autoplay 5235 const autoplayParams = swiper.params.autoplay; 5236 if (swiper.params.autoplay && autoplayParams?.disableOnInteraction) { 5237 swiper.autoplay.stop(); 5238 } 5239 // Return page scroll on edge positions 5240 if (params.releaseOnEdges && 5241 (position === swiper.minTranslate() || position === swiper.maxTranslate())) { 5242 return true; 5243 } 5244 } 5245 } 5246 if (e.cancelable) 5247 e.preventDefault(); 5248 return false; 5249 } 5250 function events(method) { 5251 const params = getParams(); 5252 let targetEl = swiper.el; 5253 if (params.eventsTarget !== 'container') { 5254 targetEl = document.querySelector(params.eventsTarget); 5255 } 5256 targetEl[method]('mouseenter', handleMouseEnter); 5257 targetEl[method]('mouseleave', handleMouseLeave); 5258 targetEl[method]('wheel', handle); 5259 } 5260 function enable() { 5261 if (swiper.params.cssMode) { 5262 swiper.wrapperEl.removeEventListener('wheel', handle); 5263 return true; 5264 } 5265 if (swiper.mousewheel.enabled) 5266 return false; 5267 events('addEventListener'); 5268 swiper.mousewheel.enabled = true; 5269 return true; 5270 } 5271 function disable() { 5272 if (swiper.params.cssMode) { 5273 swiper.wrapperEl.addEventListener('wheel', handle); 5274 return true; 5275 } 5276 if (!swiper.mousewheel.enabled) 5277 return false; 5278 events('removeEventListener'); 5279 swiper.mousewheel.enabled = false; 5280 return true; 5281 } 5282 on('init', () => { 5283 const params = getParams(); 5284 if (!params.enabled && swiper.params.cssMode) { 5285 disable(); 5286 } 5287 if (params.enabled) 5288 enable(); 5289 }); 5290 swiper.mousewheel = { 5291 enabled: false, 5292 enable, 5293 disable, 5294 }; 5295 on('destroy', () => { 5296 if (swiper.params.cssMode) { 5297 enable(); 5298 } 5299 if (swiper.mousewheel.enabled) 5300 disable(); 5301 }); 5302 }; 5303 5304 function createElementIfNotDefined(swiper, originalParams, params, checkProps) { 5305 const target = (params ?? {}); 5306 const original = (originalParams ?? {}); 5307 if (swiper.params.createElements) { 5308 Object.keys(checkProps).forEach((key) => { 5309 if (!target[key] && target.auto === true) { 5310 let element = elementChildren(swiper.el, `.${checkProps[key]}`)[0]; 5311 if (!element) { 5312 element = createElement('div', checkProps[key]); 5313 element.className = checkProps[key]; 5314 swiper.el.append(element); 5315 } 5316 target[key] = element; 5317 original[key] = element; 5318 } 5319 }); 5320 } 5321 return target; 5322 } 5323 5324 const arrowSvg = `<svg class="swiper-navigation-icon" width="11" height="20" viewBox="0 0 11 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0.38296 20.0762C0.111788 19.805 0.111788 19.3654 0.38296 19.0942L9.19758 10.2796L0.38296 1.46497C0.111788 1.19379 0.111788 0.754138 0.38296 0.482966C0.654131 0.211794 1.09379 0.211794 1.36496 0.482966L10.4341 9.55214C10.8359 9.9539 10.8359 10.6053 10.4341 11.007L1.36496 20.0762C1.09379 20.3474 0.654131 20.3474 0.38296 20.0762Z" fill="currentColor"/></svg>`; 5325 const Navigation = ({ swiper, extendParams, on, emit }) => { 5326 extendParams({ 5327 navigation: { 5328 nextEl: null, 5329 prevEl: null, 5330 addIcons: true, 5331 hideOnClick: false, 5332 disabledClass: 'swiper-button-disabled', 5333 hiddenClass: 'swiper-button-hidden', 5334 lockClass: 'swiper-button-lock', 5335 navigationDisabledClass: 'swiper-navigation-disabled', 5336 }, 5337 }); 5338 // Initialized as a partial; remaining methods (update, init, destroy, 5339 // enable, disable) attach after their definitions below. 5340 swiper.navigation = { 5341 nextEl: null, 5342 prevEl: null, 5343 arrowSvg, 5344 }; 5345 function getParams() { 5346 return swiper.params.navigation; 5347 } 5348 function getEl(el) { 5349 let res; 5350 if (el && typeof el === 'string' && swiper.isElement) { 5351 res = (swiper.el.querySelector(el) || swiper.hostEl.querySelector(el)); 5352 if (res) 5353 return res; 5354 } 5355 if (el) { 5356 if (typeof el === 'string') 5357 res = [...document.querySelectorAll(el)]; 5358 if (swiper.params.uniqueNavElements && 5359 typeof el === 'string' && 5360 res && 5361 res.length > 1 && 5362 swiper.el.querySelectorAll(el).length === 1) { 5363 res = swiper.el.querySelector(el); 5364 } 5365 else if (res && res.length === 1) { 5366 res = res[0]; 5367 } 5368 } 5369 if (el && !res) 5370 return el; 5371 return res; 5372 } 5373 function toggleEl(el, disabled) { 5374 const params = getParams(); 5375 const els = makeElementsArray(el); 5376 els.forEach((subEl) => { 5377 if (subEl) { 5378 subEl.classList[disabled ? 'add' : 'remove'](...params.disabledClass.split(' ')); 5379 if (subEl.tagName === 'BUTTON') 5380 subEl.disabled = disabled; 5381 if (swiper.params.watchOverflow && swiper.enabled) { 5382 subEl.classList[swiper.isLocked ? 'add' : 'remove'](params.lockClass); 5383 } 5384 } 5385 }); 5386 } 5387 function update() { 5388 // Update Navigation Buttons 5389 const { nextEl, prevEl } = swiper.navigation; 5390 if (swiper.params.loop) { 5391 toggleEl(prevEl, false); 5392 toggleEl(nextEl, false); 5393 return; 5394 } 5395 toggleEl(prevEl, swiper.isBeginning && !swiper.params.rewind); 5396 toggleEl(nextEl, swiper.isEnd && !swiper.params.rewind); 5397 } 5398 function onPrevClick(e) { 5399 e.preventDefault(); 5400 if (swiper.isBeginning && !swiper.params.loop && !swiper.params.rewind) 5401 return; 5402 swiper.slidePrev(); 5403 emit('navigationPrev'); 5404 } 5405 function onNextClick(e) { 5406 e.preventDefault(); 5407 if (swiper.isEnd && !swiper.params.loop && !swiper.params.rewind) 5408 return; 5409 swiper.slideNext(); 5410 emit('navigationNext'); 5411 } 5412 function init() { 5413 swiper.params.navigation = createElementIfNotDefined(swiper, swiper.originalParams.navigation, swiper.params.navigation, { 5414 nextEl: 'swiper-button-next', 5415 prevEl: 'swiper-button-prev', 5416 }); 5417 const params = getParams(); 5418 if (!(params.nextEl || params.prevEl)) 5419 return; 5420 const nextEl = getEl(params.nextEl); 5421 const prevEl = getEl(params.prevEl); 5422 Object.assign(swiper.navigation, { 5423 nextEl, 5424 prevEl, 5425 }); 5426 const nextEls = makeElementsArray(nextEl); 5427 const prevEls = makeElementsArray(prevEl); 5428 const initButton = (el, dir) => { 5429 if (el) { 5430 if (params.addIcons && 5431 el.matches('.swiper-button-next,.swiper-button-prev') && 5432 !el.querySelector('svg')) { 5433 const tempEl = document.createElement('div'); 5434 setInnerHTML(tempEl, arrowSvg); 5435 const svgEl = tempEl.querySelector('svg'); 5436 if (svgEl) 5437 el.appendChild(svgEl); 5438 tempEl.remove(); 5439 } 5440 el.addEventListener('click', dir === 'next' ? onNextClick : onPrevClick); 5441 } 5442 if (!swiper.enabled && el) { 5443 el.classList.add(...params.lockClass.split(' ')); 5444 } 5445 }; 5446 nextEls.forEach((el) => initButton(el, 'next')); 5447 prevEls.forEach((el) => initButton(el, 'prev')); 5448 } 5449 function destroy() { 5450 const params = getParams(); 5451 const { nextEl, prevEl } = swiper.navigation; 5452 const nextEls = makeElementsArray(nextEl); 5453 const prevEls = makeElementsArray(prevEl); 5454 const destroyButton = (el, dir) => { 5455 el.removeEventListener('click', dir === 'next' ? onNextClick : onPrevClick); 5456 el.classList.remove(...params.disabledClass.split(' ')); 5457 }; 5458 nextEls.forEach((el) => destroyButton(el, 'next')); 5459 prevEls.forEach((el) => destroyButton(el, 'prev')); 5460 } 5461 on('init', () => { 5462 if (getParams().enabled === false) { 5463 disable(); 5464 } 5465 else { 5466 init(); 5467 update(); 5468 } 5469 }); 5470 on('toEdge fromEdge lock unlock', () => { 5471 update(); 5472 }); 5473 on('destroy', () => { 5474 destroy(); 5475 }); 5476 on('enable disable', () => { 5477 const params = getParams(); 5478 const { nextEl, prevEl } = swiper.navigation; 5479 const nextEls = makeElementsArray(nextEl); 5480 const prevEls = makeElementsArray(prevEl); 5481 if (swiper.enabled) { 5482 update(); 5483 return; 5484 } 5485 [...nextEls, ...prevEls] 5486 .filter((el) => !!el) 5487 .forEach((el) => el.classList.add(params.lockClass)); 5488 }); 5489 on('click', (_s, e) => { 5490 const params = getParams(); 5491 const { nextEl, prevEl } = swiper.navigation; 5492 const nextEls = makeElementsArray(nextEl); 5493 const prevEls = makeElementsArray(prevEl); 5494 const targetEl = e.target; 5495 let targetIsButton = prevEls.includes(targetEl) || nextEls.includes(targetEl); 5496 if (swiper.isElement && !targetIsButton) { 5497 const path = e.composedPath ? e.composedPath() : []; 5498 if (path.length) { 5499 targetIsButton = path.find((pathEl) => nextEls.includes(pathEl) || prevEls.includes(pathEl)); 5500 } 5501 } 5502 if (params.hideOnClick && !targetIsButton) { 5503 if (swiper.pagination && 5504 swiper.params.pagination && 5505 swiper.params.pagination.clickable && 5506 (swiper.pagination.el === targetEl || swiper.pagination.el.contains(targetEl))) 5507 return; 5508 let isHidden; 5509 if (nextEls.length) { 5510 isHidden = nextEls[0].classList.contains(params.hiddenClass); 5511 } 5512 else if (prevEls.length) { 5513 isHidden = prevEls[0].classList.contains(params.hiddenClass); 5514 } 5515 if (isHidden === true) { 5516 emit('navigationShow'); 5517 } 5518 else { 5519 emit('navigationHide'); 5520 } 5521 [...nextEls, ...prevEls] 5522 .filter((el) => !!el) 5523 .forEach((el) => el.classList.toggle(params.hiddenClass)); 5524 } 5525 }); 5526 const enable = () => { 5527 const params = getParams(); 5528 swiper.el.classList.remove(...params.navigationDisabledClass.split(' ')); 5529 init(); 5530 update(); 5531 }; 5532 const disable = () => { 5533 const params = getParams(); 5534 swiper.el.classList.add(...params.navigationDisabledClass.split(' ')); 5535 destroy(); 5536 }; 5537 Object.assign(swiper.navigation, { 5538 enable, 5539 disable, 5540 update, 5541 init, 5542 destroy, 5543 }); 5544 }; 5545 5546 function classesToSelector(classes = '') { 5547 return `.${classes 5548 .trim() 5549 .replace(/([.:!+/()[\]#>~*^$|=,'"@{}\\])/g, '\\$1') 5550 .replace(/ /g, '.')}`; 5551 } 5552 5553 const isVirtualEnabled$2 = (swiper) => !!swiper.virtual && !!swiper.params.virtual?.enabled; 5554 const isFreeModeEnabled = (swiper) => !!swiper.params.freeMode?.enabled; 5555 // Slides count for bullets/fraction/progressbar totals: with grid rows the 5556 // slides that share a column collapse into one snap position. 5557 const getSlidesLength = (swiper) => { 5558 if (isVirtualEnabled$2(swiper)) 5559 return swiper.virtual.slides.length; 5560 const gridRows = swiper.params.grid?.rows; 5561 if (swiper.grid && gridRows && gridRows > 1) { 5562 return swiper.slides.length / Math.ceil(gridRows); 5563 } 5564 return swiper.slides.length; 5565 }; 5566 const Pagination = ({ swiper, extendParams, on, emit }) => { 5567 const pfx = 'swiper-pagination'; 5568 extendParams({ 5569 pagination: { 5570 el: null, 5571 bulletElement: 'span', 5572 clickable: false, 5573 hideOnClick: false, 5574 renderBullet: null, 5575 renderProgressbar: null, 5576 renderFraction: null, 5577 renderCustom: null, 5578 progressbarOpposite: false, 5579 type: 'bullets', // 'bullets' or 'progressbar' or 'fraction' or 'custom' 5580 dynamicBullets: false, 5581 dynamicMainBullets: 1, 5582 formatFractionCurrent: (number) => number, 5583 formatFractionTotal: (number) => number, 5584 bulletClass: `${pfx}-bullet`, 5585 bulletActiveClass: `${pfx}-bullet-active`, 5586 modifierClass: `${pfx}-`, 5587 currentClass: `${pfx}-current`, 5588 totalClass: `${pfx}-total`, 5589 hiddenClass: `${pfx}-hidden`, 5590 progressbarFillClass: `${pfx}-progressbar-fill`, 5591 progressbarOppositeClass: `${pfx}-progressbar-opposite`, 5592 clickableClass: `${pfx}-clickable`, 5593 lockClass: `${pfx}-lock`, 5594 horizontalClass: `${pfx}-horizontal`, 5595 verticalClass: `${pfx}-vertical`, 5596 paginationDisabledClass: `${pfx}-disabled`, 5597 }, 5598 }); 5599 // Initialized as a partial; remaining methods (render, update, init, 5600 // destroy, enable, disable) attach after their definitions below. 5601 swiper.pagination = { 5602 el: null, 5603 bullets: [], 5604 }; 5605 let bulletSize; 5606 let dynamicBulletIndex = 0; 5607 function getParams() { 5608 return swiper.params.pagination; 5609 } 5610 function isPaginationDisabled() { 5611 const elParam = getParams().el; 5612 return (!elParam || 5613 !swiper.pagination.el || 5614 (Array.isArray(swiper.pagination.el) && 5615 swiper.pagination.el.length === 0)); 5616 } 5617 function setSideBullets(bulletEl, position) { 5618 const { bulletActiveClass } = getParams(); 5619 if (!bulletEl) 5620 return; 5621 let current = bulletEl[`${position === 'prev' ? 'previous' : 'next'}ElementSibling`]; 5622 if (current) { 5623 current.classList.add(`${bulletActiveClass}-${position}`); 5624 current = current[`${position === 'prev' ? 'previous' : 'next'}ElementSibling`]; 5625 if (current) { 5626 current.classList.add(`${bulletActiveClass}-${position}-${position}`); 5627 } 5628 } 5629 } 5630 function getMoveDirection(prevIndex, nextIndex, length) { 5631 prevIndex = prevIndex % length; 5632 nextIndex = nextIndex % length; 5633 if (nextIndex === prevIndex + 1) { 5634 return 'next'; 5635 } 5636 else if (nextIndex === prevIndex - 1) { 5637 return 'previous'; 5638 } 5639 return undefined; 5640 } 5641 function onBulletClick(e) { 5642 const targetEl = e.target; 5643 const bulletEl = targetEl.closest(classesToSelector(getParams().bulletClass)); 5644 if (!bulletEl) { 5645 return; 5646 } 5647 e.preventDefault(); 5648 const index = (elementIndex(bulletEl) ?? 0) * (swiper.params.slidesPerGroup ?? 1); 5649 if (swiper.params.loop) { 5650 if (swiper.realIndex === index) 5651 return; 5652 const moveDirection = getMoveDirection(swiper.realIndex, index, swiper.slides.length); 5653 if (moveDirection === 'next') { 5654 swiper.slideNext(); 5655 } 5656 else if (moveDirection === 'previous') { 5657 swiper.slidePrev(); 5658 } 5659 else { 5660 swiper.slideToLoop(index); 5661 } 5662 } 5663 else { 5664 swiper.slideTo(index); 5665 } 5666 } 5667 function update() { 5668 // Render || Update Pagination bullets/items 5669 const rtl = swiper.rtl; 5670 const params = getParams(); 5671 if (isPaginationDisabled()) 5672 return; 5673 const els = makeElementsArray(swiper.pagination.el); 5674 // Current/Total 5675 let current; 5676 let previousIndex; 5677 const slidesLength = getSlidesLength(swiper); 5678 const total = swiper.params.loop 5679 ? Math.ceil(slidesLength / (swiper.params.slidesPerGroup ?? 1)) 5680 : swiper.snapGrid.length; 5681 if (swiper.params.loop) { 5682 previousIndex = swiper.previousRealIndex || 0; 5683 current = 5684 (swiper.params.slidesPerGroup ?? 1) > 1 5685 ? Math.floor(swiper.realIndex / (swiper.params.slidesPerGroup ?? 1)) 5686 : swiper.realIndex; 5687 } 5688 else if (typeof swiper.snapIndex !== 'undefined') { 5689 current = swiper.snapIndex; 5690 previousIndex = swiper.previousSnapIndex; 5691 } 5692 else { 5693 previousIndex = swiper.previousIndex || 0; 5694 current = swiper.activeIndex || 0; 5695 } 5696 // Types 5697 if (params.type === 'bullets' && 5698 swiper.pagination.bullets && 5699 swiper.pagination.bullets.length > 0) { 5700 const bullets = swiper.pagination.bullets; 5701 let firstIndex = 0; 5702 let lastIndex = 0; 5703 let midIndex = 0; 5704 if (params.dynamicBullets) { 5705 bulletSize = elementOuterSize(bullets[0], swiper.isHorizontal() ? 'width' : 'height'); 5706 const dim = swiper.isHorizontal() ? 'width' : 'height'; 5707 els.forEach((subEl) => { 5708 subEl.style[dim] = `${(bulletSize ?? 0) * (params.dynamicMainBullets + 4)}px`; 5709 }); 5710 if (params.dynamicMainBullets > 1 && previousIndex !== undefined) { 5711 dynamicBulletIndex += current - (previousIndex || 0); 5712 if (dynamicBulletIndex > params.dynamicMainBullets - 1) { 5713 dynamicBulletIndex = params.dynamicMainBullets - 1; 5714 } 5715 else if (dynamicBulletIndex < 0) { 5716 dynamicBulletIndex = 0; 5717 } 5718 } 5719 firstIndex = Math.max(current - dynamicBulletIndex, 0); 5720 lastIndex = firstIndex + (Math.min(bullets.length, params.dynamicMainBullets) - 1); 5721 midIndex = (lastIndex + firstIndex) / 2; 5722 } 5723 bullets.forEach((bulletEl) => { 5724 const classesToRemove = [ 5725 '', 5726 '-next', 5727 '-next-next', 5728 '-prev', 5729 '-prev-prev', 5730 '-main', 5731 ] 5732 .map((suffix) => `${params.bulletActiveClass}${suffix}`) 5733 .flatMap((s) => (typeof s === 'string' && s.includes(' ') ? s.split(' ') : [s])); 5734 bulletEl.classList.remove(...classesToRemove); 5735 }); 5736 if (els.length > 1) { 5737 bullets.forEach((bullet) => { 5738 const bulletIndex = elementIndex(bullet); 5739 if (bulletIndex === current) { 5740 bullet.classList.add(...params.bulletActiveClass.split(' ')); 5741 } 5742 else if (swiper.isElement) { 5743 bullet.setAttribute('part', 'bullet'); 5744 } 5745 if (params.dynamicBullets && bulletIndex !== undefined) { 5746 if (bulletIndex >= firstIndex && bulletIndex <= lastIndex) { 5747 bullet.classList.add(...`${params.bulletActiveClass}-main`.split(' ')); 5748 } 5749 if (bulletIndex === firstIndex) { 5750 setSideBullets(bullet, 'prev'); 5751 } 5752 if (bulletIndex === lastIndex) { 5753 setSideBullets(bullet, 'next'); 5754 } 5755 } 5756 }); 5757 } 5758 else { 5759 const bullet = bullets[current]; 5760 if (bullet) { 5761 bullet.classList.add(...params.bulletActiveClass.split(' ')); 5762 } 5763 if (swiper.isElement) { 5764 bullets.forEach((bulletEl, bulletIndex) => { 5765 bulletEl.setAttribute('part', bulletIndex === current ? 'bullet-active' : 'bullet'); 5766 }); 5767 } 5768 if (params.dynamicBullets) { 5769 const firstDisplayedBullet = bullets[firstIndex]; 5770 const lastDisplayedBullet = bullets[lastIndex]; 5771 for (let i = firstIndex; i <= lastIndex; i += 1) { 5772 if (bullets[i]) { 5773 bullets[i].classList.add(...`${params.bulletActiveClass}-main`.split(' ')); 5774 } 5775 } 5776 setSideBullets(firstDisplayedBullet, 'prev'); 5777 setSideBullets(lastDisplayedBullet, 'next'); 5778 } 5779 } 5780 if (params.dynamicBullets) { 5781 const dynamicBulletsLength = Math.min(bullets.length, params.dynamicMainBullets + 4); 5782 const bulletsOffset = ((bulletSize ?? 0) * dynamicBulletsLength - (bulletSize ?? 0)) / 2 - 5783 midIndex * (bulletSize ?? 0); 5784 const offsetProp = rtl ? 'right' : 'left'; 5785 const positionDim = swiper.isHorizontal() ? offsetProp : 'top'; 5786 bullets.forEach((bullet) => { 5787 bullet.style[positionDim] = `${bulletsOffset}px`; 5788 }); 5789 } 5790 } 5791 els.forEach((subEl, subElIndex) => { 5792 if (params.type === 'fraction') { 5793 subEl.querySelectorAll(classesToSelector(params.currentClass)).forEach((fractionEl) => { 5794 fractionEl.textContent = String(params.formatFractionCurrent(current + 1)); 5795 }); 5796 subEl.querySelectorAll(classesToSelector(params.totalClass)).forEach((totalEl) => { 5797 totalEl.textContent = String(params.formatFractionTotal(total)); 5798 }); 5799 } 5800 if (params.type === 'progressbar') { 5801 let progressbarDirection; 5802 if (params.progressbarOpposite) { 5803 progressbarDirection = swiper.isHorizontal() ? 'vertical' : 'horizontal'; 5804 } 5805 else { 5806 progressbarDirection = swiper.isHorizontal() ? 'horizontal' : 'vertical'; 5807 } 5808 const scale = (current + 1) / total; 5809 let scaleX = 1; 5810 let scaleY = 1; 5811 if (progressbarDirection === 'horizontal') { 5812 scaleX = scale; 5813 } 5814 else { 5815 scaleY = scale; 5816 } 5817 subEl 5818 .querySelectorAll(classesToSelector(params.progressbarFillClass)) 5819 .forEach((progressEl) => { 5820 progressEl.style.transform = `translate3d(0,0,0) scaleX(${scaleX}) scaleY(${scaleY})`; 5821 progressEl.style.transitionDuration = `${swiper.params.speed}ms`; 5822 }); 5823 } 5824 if (params.type === 'custom' && params.renderCustom) { 5825 setInnerHTML(subEl, params.renderCustom(swiper, current + 1, total)); 5826 if (subElIndex === 0) 5827 emit('paginationRender', subEl); 5828 } 5829 else { 5830 if (subElIndex === 0) 5831 emit('paginationRender', subEl); 5832 emit('paginationUpdate', subEl); 5833 } 5834 if (swiper.params.watchOverflow && swiper.enabled) { 5835 subEl.classList[swiper.isLocked ? 'add' : 'remove'](params.lockClass); 5836 } 5837 }); 5838 } 5839 function render() { 5840 // Render Container 5841 const params = getParams(); 5842 if (isPaginationDisabled()) 5843 return; 5844 const slidesLength = getSlidesLength(swiper); 5845 const els = makeElementsArray(swiper.pagination.el); 5846 let paginationHTML = ''; 5847 if (params.type === 'bullets') { 5848 let numberOfBullets = swiper.params.loop 5849 ? Math.ceil(slidesLength / (swiper.params.slidesPerGroup ?? 1)) 5850 : swiper.snapGrid.length; 5851 if (swiper.params.freeMode && isFreeModeEnabled(swiper) && numberOfBullets > slidesLength) { 5852 numberOfBullets = slidesLength; 5853 } 5854 for (let i = 0; i < numberOfBullets; i += 1) { 5855 if (params.renderBullet) { 5856 paginationHTML += params.renderBullet.call(swiper, i, params.bulletClass); 5857 } 5858 else { 5859 // oxfmt-ignore 5860 paginationHTML += `<${params.bulletElement} ${swiper.isElement ? 'part="bullet"' : ''} class="${params.bulletClass}"></${params.bulletElement}>`; 5861 } 5862 } 5863 } 5864 if (params.type === 'fraction') { 5865 if (params.renderFraction) { 5866 paginationHTML = params.renderFraction.call(swiper, params.currentClass, params.totalClass); 5867 } 5868 else { 5869 paginationHTML = 5870 `<span class="${params.currentClass}"></span>` + 5871 ' / ' + 5872 `<span class="${params.totalClass}"></span>`; 5873 } 5874 } 5875 if (params.type === 'progressbar') { 5876 if (params.renderProgressbar) { 5877 paginationHTML = params.renderProgressbar.call(swiper, params.progressbarFillClass); 5878 } 5879 else { 5880 paginationHTML = `<span class="${params.progressbarFillClass}"></span>`; 5881 } 5882 } 5883 swiper.pagination.bullets = []; 5884 els.forEach((subEl) => { 5885 if (params.type !== 'custom') { 5886 setInnerHTML(subEl, paginationHTML || ''); 5887 } 5888 if (params.type === 'bullets') { 5889 swiper.pagination.bullets.push(...Array.from(subEl.querySelectorAll(classesToSelector(params.bulletClass)))); 5890 } 5891 }); 5892 if (params.type !== 'custom') { 5893 emit('paginationRender', els[0]); 5894 } 5895 } 5896 function init() { 5897 swiper.params.pagination = createElementIfNotDefined(swiper, swiper.originalParams.pagination, swiper.params.pagination, { el: 'swiper-pagination' }); 5898 const params = getParams(); 5899 if (!params.el) 5900 return; 5901 let el; 5902 if (typeof params.el === 'string' && swiper.isElement) { 5903 el = swiper.el.querySelector(params.el); 5904 } 5905 if (!el && typeof params.el === 'string') { 5906 el = [...document.querySelectorAll(params.el)]; 5907 } 5908 if (!el) { 5909 el = params.el; 5910 } 5911 if (!el || (Array.isArray(el) && el.length === 0)) 5912 return; 5913 if (swiper.params.uniqueNavElements && 5914 typeof params.el === 'string' && 5915 Array.isArray(el) && 5916 el.length > 1) { 5917 el = [...swiper.el.querySelectorAll(params.el)]; 5918 // check if it belongs to another nested Swiper 5919 if (el.length > 1) { 5920 const found = el.find((subEl) => { 5921 if (elementParents(subEl, '.swiper')[0] !== swiper.el) 5922 return false; 5923 return true; 5924 }); 5925 if (found) 5926 el = found; 5927 } 5928 } 5929 if (Array.isArray(el) && el.length === 1) 5930 el = el[0]; 5931 Object.assign(swiper.pagination, { 5932 el, 5933 }); 5934 const els = makeElementsArray(el); 5935 els.forEach((subEl) => { 5936 if (params.type === 'bullets' && params.clickable) { 5937 subEl.classList.add(...(params.clickableClass || '').split(' ')); 5938 } 5939 subEl.classList.add(params.modifierClass + params.type); 5940 subEl.classList.add(swiper.isHorizontal() ? params.horizontalClass : params.verticalClass); 5941 if (params.type === 'bullets' && params.dynamicBullets) { 5942 subEl.classList.add(`${params.modifierClass}${params.type}-dynamic`); 5943 dynamicBulletIndex = 0; 5944 if (params.dynamicMainBullets < 1) { 5945 params.dynamicMainBullets = 1; 5946 } 5947 } 5948 if (params.type === 'progressbar' && params.progressbarOpposite) { 5949 subEl.classList.add(params.progressbarOppositeClass); 5950 } 5951 if (params.clickable) { 5952 subEl.addEventListener('click', onBulletClick); 5953 } 5954 if (!swiper.enabled) { 5955 subEl.classList.add(params.lockClass); 5956 } 5957 }); 5958 } 5959 function destroy() { 5960 const params = getParams(); 5961 if (isPaginationDisabled()) 5962 return; 5963 const el = swiper.pagination.el; 5964 if (el) { 5965 const els = makeElementsArray(el); 5966 els.forEach((subEl) => { 5967 subEl.classList.remove(params.hiddenClass); 5968 subEl.classList.remove(params.modifierClass + params.type); 5969 subEl.classList.remove(swiper.isHorizontal() ? params.horizontalClass : params.verticalClass); 5970 if (params.clickable) { 5971 subEl.classList.remove(...(params.clickableClass || '').split(' ')); 5972 subEl.removeEventListener('click', onBulletClick); 5973 } 5974 }); 5975 } 5976 if (swiper.pagination.bullets) 5977 swiper.pagination.bullets.forEach((subEl) => subEl.classList.remove(...params.bulletActiveClass.split(' '))); 5978 } 5979 on('changeDirection', () => { 5980 if (!swiper.pagination || !swiper.pagination.el) 5981 return; 5982 const params = getParams(); 5983 const els = makeElementsArray(swiper.pagination.el); 5984 els.forEach((subEl) => { 5985 subEl.classList.remove(params.horizontalClass, params.verticalClass); 5986 subEl.classList.add(swiper.isHorizontal() ? params.horizontalClass : params.verticalClass); 5987 }); 5988 }); 5989 on('init', () => { 5990 if (getParams().enabled === false) { 5991 disable(); 5992 } 5993 else { 5994 init(); 5995 render(); 5996 update(); 5997 } 5998 }); 5999 on('activeIndexChange', () => { 6000 if (typeof swiper.snapIndex === 'undefined') { 6001 update(); 6002 } 6003 }); 6004 on('snapIndexChange', () => { 6005 update(); 6006 }); 6007 on('snapGridLengthChange', () => { 6008 render(); 6009 update(); 6010 }); 6011 on('destroy', () => { 6012 destroy(); 6013 }); 6014 on('enable disable', () => { 6015 const { el } = swiper.pagination; 6016 if (el) { 6017 const params = getParams(); 6018 const els = makeElementsArray(el); 6019 els.forEach((subEl) => subEl.classList[swiper.enabled ? 'remove' : 'add'](params.lockClass)); 6020 } 6021 }); 6022 on('lock unlock', () => { 6023 update(); 6024 }); 6025 on('click', (_s, e) => { 6026 const targetEl = e.target; 6027 const els = makeElementsArray(swiper.pagination.el); 6028 const params = getParams(); 6029 if (params.el && 6030 params.hideOnClick && 6031 els && 6032 els.length > 0 && 6033 !targetEl.classList.contains(params.bulletClass)) { 6034 if (swiper.navigation && 6035 ((swiper.navigation.nextEl && targetEl === swiper.navigation.nextEl) || 6036 (swiper.navigation.prevEl && targetEl === swiper.navigation.prevEl))) 6037 return; 6038 const isHidden = els[0].classList.contains(params.hiddenClass); 6039 if (isHidden === true) { 6040 emit('paginationShow'); 6041 } 6042 else { 6043 emit('paginationHide'); 6044 } 6045 els.forEach((subEl) => subEl.classList.toggle(params.hiddenClass)); 6046 } 6047 }); 6048 const enable = () => { 6049 const params = getParams(); 6050 swiper.el.classList.remove(params.paginationDisabledClass); 6051 const { el } = swiper.pagination; 6052 if (el) { 6053 const els = makeElementsArray(el); 6054 els.forEach((subEl) => subEl.classList.remove(params.paginationDisabledClass)); 6055 } 6056 init(); 6057 render(); 6058 update(); 6059 }; 6060 const disable = () => { 6061 const params = getParams(); 6062 swiper.el.classList.add(params.paginationDisabledClass); 6063 const { el } = swiper.pagination; 6064 if (el) { 6065 const els = makeElementsArray(el); 6066 els.forEach((subEl) => subEl.classList.add(params.paginationDisabledClass)); 6067 } 6068 destroy(); 6069 }; 6070 Object.assign(swiper.pagination, { 6071 enable, 6072 disable, 6073 render, 6074 update, 6075 init, 6076 destroy, 6077 }); 6078 }; 6079 6080 const Scrollbar = ({ swiper, extendParams, on, emit }) => { 6081 let isTouched = false; 6082 let timeout = null; 6083 let dragTimeout = null; 6084 let dragStartPos = 0; 6085 let dragSize = 0; 6086 let trackSize = 0; 6087 let divider = 0; 6088 extendParams({ 6089 scrollbar: { 6090 el: null, 6091 dragSize: 'auto', 6092 hide: false, 6093 draggable: false, 6094 snapOnRelease: true, 6095 lockClass: 'swiper-scrollbar-lock', 6096 dragClass: 'swiper-scrollbar-drag', 6097 scrollbarDisabledClass: 'swiper-scrollbar-disabled', 6098 horizontalClass: `swiper-scrollbar-horizontal`, 6099 verticalClass: `swiper-scrollbar-vertical`, 6100 }, 6101 }); 6102 // Initialized as a partial; remaining methods (updateSize, setTranslate, 6103 // init, destroy, enable, disable) attach after their definitions below. 6104 swiper.scrollbar = { 6105 el: null, 6106 dragEl: null, 6107 }; 6108 function getParams() { 6109 return swiper.params.scrollbar; 6110 } 6111 function setTranslate() { 6112 const params = getParams(); 6113 if (!params.el || !swiper.scrollbar.el) 6114 return; 6115 const { scrollbar, rtlTranslate: rtl } = swiper; 6116 const { dragEl, el } = scrollbar; 6117 const progress = swiper.params.loop ? (swiper.progressLoop ?? 0) : swiper.progress; 6118 let newSize = dragSize; 6119 let newPos = (trackSize - dragSize) * progress; 6120 if (rtl) { 6121 newPos = -newPos; 6122 if (newPos > 0) { 6123 newSize = dragSize - newPos; 6124 newPos = 0; 6125 } 6126 else if (-newPos + dragSize > trackSize) { 6127 newSize = trackSize + newPos; 6128 } 6129 } 6130 else if (newPos < 0) { 6131 newSize = dragSize + newPos; 6132 newPos = 0; 6133 } 6134 else if (newPos + dragSize > trackSize) { 6135 newSize = trackSize - newPos; 6136 } 6137 if (swiper.isHorizontal()) { 6138 dragEl.style.transform = `translate3d(${newPos}px, 0, 0)`; 6139 dragEl.style.width = `${newSize}px`; 6140 } 6141 else { 6142 dragEl.style.transform = `translate3d(0px, ${newPos}px, 0)`; 6143 dragEl.style.height = `${newSize}px`; 6144 } 6145 if (params.hide) { 6146 if (timeout) 6147 clearTimeout(timeout); 6148 el.style.opacity = '1'; 6149 timeout = setTimeout(() => { 6150 el.style.opacity = '0'; 6151 el.style.transitionDuration = '400ms'; 6152 }, 1000); 6153 } 6154 } 6155 function setTransition(duration) { 6156 if (!getParams().el || !swiper.scrollbar.el) 6157 return; 6158 swiper.scrollbar.dragEl.style.transitionDuration = `${duration}ms`; 6159 } 6160 function updateSize() { 6161 const params = getParams(); 6162 if (!params.el || !swiper.scrollbar.el) 6163 return; 6164 const { scrollbar } = swiper; 6165 const { dragEl, el } = scrollbar; 6166 dragEl.style.width = ''; 6167 dragEl.style.height = ''; 6168 trackSize = swiper.isHorizontal() ? el.offsetWidth : el.offsetHeight; 6169 divider = 6170 swiper.size / 6171 (swiper.virtualSize + 6172 (swiper.params.slidesOffsetBefore ?? 0) - 6173 (swiper.params.centeredSlides ? swiper.snapGrid[0] : 0)); 6174 if (params.dragSize === 'auto') { 6175 dragSize = trackSize * divider; 6176 } 6177 else { 6178 dragSize = parseInt(String(params.dragSize), 10); 6179 } 6180 if (swiper.isHorizontal()) { 6181 dragEl.style.width = `${dragSize}px`; 6182 } 6183 else { 6184 dragEl.style.height = `${dragSize}px`; 6185 } 6186 if (divider >= 1) { 6187 el.style.display = 'none'; 6188 } 6189 else { 6190 el.style.display = ''; 6191 } 6192 if (params.hide) { 6193 el.style.opacity = '0'; 6194 } 6195 if (swiper.params.watchOverflow && swiper.enabled) { 6196 scrollbar.el.classList[swiper.isLocked ? 'add' : 'remove'](params.lockClass); 6197 } 6198 } 6199 function getPointerPosition(e) { 6200 if (swiper.isHorizontal()) { 6201 return e.clientX ?? e.touches?.[0]?.clientX ?? 0; 6202 } 6203 return e.clientY ?? e.touches?.[0]?.clientY ?? 0; 6204 } 6205 function setDragPosition(e) { 6206 const { scrollbar, rtlTranslate: rtl } = swiper; 6207 const { el } = scrollbar; 6208 let positionRatio; 6209 positionRatio = 6210 (getPointerPosition(e) - 6211 elementOffset(el)[swiper.isHorizontal() ? 'left' : 'top'] - 6212 (dragStartPos !== null ? dragStartPos : dragSize / 2)) / 6213 (trackSize - dragSize); 6214 positionRatio = Math.max(Math.min(positionRatio, 1), 0); 6215 if (rtl) { 6216 positionRatio = 1 - positionRatio; 6217 } 6218 const position = swiper.minTranslate() + (swiper.maxTranslate() - swiper.minTranslate()) * positionRatio; 6219 swiper.updateProgress(position); 6220 swiper.setTranslate(position); 6221 swiper.updateActiveIndex(); 6222 swiper.updateSlidesClasses(); 6223 } 6224 function onDragStart(e) { 6225 const params = getParams(); 6226 const { scrollbar, wrapperEl } = swiper; 6227 const { el, dragEl } = scrollbar; 6228 isTouched = true; 6229 dragStartPos = 6230 e.target === dragEl 6231 ? getPointerPosition(e) - 6232 e.target.getBoundingClientRect()[swiper.isHorizontal() ? 'left' : 'top'] 6233 : null; 6234 e.preventDefault(); 6235 e.stopPropagation(); 6236 wrapperEl.style.transitionDuration = '100ms'; 6237 dragEl.style.transitionDuration = '100ms'; 6238 setDragPosition(e); 6239 if (dragTimeout) 6240 clearTimeout(dragTimeout); 6241 el.style.transitionDuration = '0ms'; 6242 if (params.hide) { 6243 el.style.opacity = '1'; 6244 } 6245 if (swiper.params.cssMode) { 6246 swiper.wrapperEl.style.scrollSnapType = 'none'; 6247 } 6248 emit('scrollbarDragStart', e); 6249 } 6250 function onDragMove(e) { 6251 const { scrollbar, wrapperEl } = swiper; 6252 const { el, dragEl } = scrollbar; 6253 if (!isTouched) 6254 return; 6255 if (e.cancelable) 6256 e.preventDefault(); 6257 setDragPosition(e); 6258 wrapperEl.style.transitionDuration = '0ms'; 6259 el.style.transitionDuration = '0ms'; 6260 dragEl.style.transitionDuration = '0ms'; 6261 emit('scrollbarDragMove', e); 6262 } 6263 function onDragEnd(e) { 6264 const params = getParams(); 6265 const { scrollbar, wrapperEl } = swiper; 6266 const { el } = scrollbar; 6267 if (!isTouched) 6268 return; 6269 isTouched = false; 6270 if (swiper.params.cssMode) { 6271 swiper.wrapperEl.style.scrollSnapType = ''; 6272 wrapperEl.style.transitionDuration = ''; 6273 } 6274 if (params.hide) { 6275 if (dragTimeout) 6276 clearTimeout(dragTimeout); 6277 dragTimeout = nextTick(() => { 6278 el.style.opacity = '0'; 6279 el.style.transitionDuration = '400ms'; 6280 }, 1000); 6281 } 6282 emit('scrollbarDragEnd', e); 6283 if (params.snapOnRelease) { 6284 swiper.slideToClosest(); 6285 } 6286 } 6287 function events(method) { 6288 const { scrollbar, params } = swiper; 6289 const el = scrollbar.el; 6290 if (!el) 6291 return; 6292 const activeListener = params.passiveListeners ? { passive: false, capture: false } : false; 6293 const passiveListener = params.passiveListeners ? { passive: true, capture: false } : false; 6294 const eventMethod = method === 'on' ? 'addEventListener' : 'removeEventListener'; 6295 el[eventMethod]('pointerdown', onDragStart, activeListener); 6296 document[eventMethod]('pointermove', onDragMove, activeListener); 6297 document[eventMethod]('pointerup', onDragEnd, passiveListener); 6298 } 6299 function enableDraggable() { 6300 if (!getParams().el || !swiper.scrollbar.el) 6301 return; 6302 events('on'); 6303 } 6304 function disableDraggable() { 6305 if (!getParams().el || !swiper.scrollbar.el) 6306 return; 6307 events('off'); 6308 } 6309 function init() { 6310 const { scrollbar, el: swiperEl } = swiper; 6311 swiper.params.scrollbar = createElementIfNotDefined(swiper, swiper.originalParams.scrollbar, swiper.params.scrollbar, { el: 'swiper-scrollbar' }); 6312 const params = getParams(); 6313 if (!params.el) 6314 return; 6315 let el; 6316 if (typeof params.el === 'string' && swiper.isElement) { 6317 el = swiper.el.querySelector(params.el); 6318 } 6319 if (!el && typeof params.el === 'string') { 6320 el = document.querySelectorAll(params.el); 6321 if (!el.length) 6322 return; 6323 } 6324 else if (!el) { 6325 el = params.el; 6326 } 6327 if (swiper.params.uniqueNavElements && 6328 typeof params.el === 'string' && 6329 el.length > 1 && 6330 swiperEl.querySelectorAll(params.el).length === 1) { 6331 el = swiperEl.querySelector(params.el); 6332 } 6333 if (el.length > 0) { 6334 el = el[0]; 6335 } 6336 const elTyped = el; 6337 elTyped.classList.add(swiper.isHorizontal() ? params.horizontalClass : params.verticalClass); 6338 let dragEl = null; 6339 if (elTyped) { 6340 dragEl = elTyped.querySelector(classesToSelector(params.dragClass)); 6341 if (!dragEl) { 6342 dragEl = createElement('div', params.dragClass); 6343 elTyped.append(dragEl); 6344 } 6345 } 6346 Object.assign(scrollbar, { 6347 el: elTyped, 6348 dragEl, 6349 }); 6350 if (params.draggable) { 6351 enableDraggable(); 6352 } 6353 if (elTyped) { 6354 elTyped.classList[swiper.enabled ? 'remove' : 'add'](...classesToTokens(params.lockClass)); 6355 } 6356 } 6357 function destroy() { 6358 const params = getParams(); 6359 const el = swiper.scrollbar.el; 6360 if (el) { 6361 el.classList.remove(...classesToTokens(swiper.isHorizontal() ? params.horizontalClass : params.verticalClass)); 6362 } 6363 disableDraggable(); 6364 } 6365 on('changeDirection', () => { 6366 if (!swiper.scrollbar || !swiper.scrollbar.el) 6367 return; 6368 const params = getParams(); 6369 const els = makeElementsArray(swiper.scrollbar.el); 6370 els.forEach((subEl) => { 6371 subEl.classList.remove(params.horizontalClass, params.verticalClass); 6372 subEl.classList.add(swiper.isHorizontal() ? params.horizontalClass : params.verticalClass); 6373 }); 6374 }); 6375 on('init', () => { 6376 if (getParams().enabled === false) { 6377 disable(); 6378 } 6379 else { 6380 init(); 6381 updateSize(); 6382 setTranslate(); 6383 } 6384 }); 6385 on('update resize observerUpdate lock unlock changeDirection', () => { 6386 updateSize(); 6387 }); 6388 on('setTranslate', () => { 6389 setTranslate(); 6390 }); 6391 on('setTransition', (_s, duration) => { 6392 setTransition(duration); 6393 }); 6394 on('enable disable', () => { 6395 const { el } = swiper.scrollbar; 6396 if (el) { 6397 el.classList[swiper.enabled ? 'remove' : 'add'](...classesToTokens(getParams().lockClass)); 6398 } 6399 }); 6400 on('destroy', () => { 6401 destroy(); 6402 }); 6403 const enable = () => { 6404 const params = getParams(); 6405 swiper.el.classList.remove(...classesToTokens(params.scrollbarDisabledClass)); 6406 if (swiper.scrollbar.el) { 6407 swiper.scrollbar.el.classList.remove(...classesToTokens(params.scrollbarDisabledClass)); 6408 } 6409 init(); 6410 updateSize(); 6411 setTranslate(); 6412 }; 6413 const disable = () => { 6414 const params = getParams(); 6415 swiper.el.classList.add(...classesToTokens(params.scrollbarDisabledClass)); 6416 if (swiper.scrollbar.el) { 6417 swiper.scrollbar.el.classList.add(...classesToTokens(params.scrollbarDisabledClass)); 6418 } 6419 destroy(); 6420 }; 6421 Object.assign(swiper.scrollbar, { 6422 enable, 6423 disable, 6424 updateSize, 6425 setTranslate, 6426 init, 6427 destroy, 6428 }); 6429 }; 6430 6431 const Parallax = ({ swiper, extendParams, on }) => { 6432 extendParams({ 6433 parallax: { 6434 enabled: false, 6435 }, 6436 }); 6437 function getParams() { 6438 return swiper.params.parallax; 6439 } 6440 const elementsSelector = '[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y], [data-swiper-parallax-opacity], [data-swiper-parallax-scale]'; 6441 const setTransform = (el, progress) => { 6442 const { rtl } = swiper; 6443 const rtlFactor = rtl ? -1 : 1; 6444 const p = el.getAttribute('data-swiper-parallax') || '0'; 6445 let x = el.getAttribute('data-swiper-parallax-x'); 6446 let y = el.getAttribute('data-swiper-parallax-y'); 6447 const scale = el.getAttribute('data-swiper-parallax-scale'); 6448 const opacity = el.getAttribute('data-swiper-parallax-opacity'); 6449 const rotate = el.getAttribute('data-swiper-parallax-rotate'); 6450 if (x || y) { 6451 x = x || '0'; 6452 y = y || '0'; 6453 } 6454 else if (swiper.isHorizontal()) { 6455 x = p; 6456 y = '0'; 6457 } 6458 else { 6459 y = p; 6460 x = '0'; 6461 } 6462 if (x.indexOf('%') >= 0) { 6463 x = `${parseInt(x, 10) * progress * rtlFactor}%`; 6464 } 6465 else { 6466 x = `${Number(x) * progress * rtlFactor}px`; 6467 } 6468 if (y.indexOf('%') >= 0) { 6469 y = `${parseInt(y, 10) * progress}%`; 6470 } 6471 else { 6472 y = `${Number(y) * progress}px`; 6473 } 6474 if (typeof opacity !== 'undefined' && opacity !== null) { 6475 const opacityNum = Number(opacity); 6476 const currentOpacity = opacityNum - (opacityNum - 1) * (1 - Math.abs(progress)); 6477 el.style.opacity = String(currentOpacity); 6478 } 6479 let transform = `translate3d(${x}, ${y}, 0px)`; 6480 if (typeof scale !== 'undefined' && scale !== null) { 6481 const scaleNum = Number(scale); 6482 const currentScale = scaleNum - (scaleNum - 1) * (1 - Math.abs(progress)); 6483 transform += ` scale(${currentScale})`; 6484 } 6485 if (rotate && typeof rotate !== 'undefined' && rotate !== null) { 6486 const currentRotate = Number(rotate) * progress * -1; 6487 transform += ` rotate(${currentRotate}deg)`; 6488 } 6489 el.style.transform = transform; 6490 }; 6491 const setTranslate = () => { 6492 const { el, slides, progress, snapGrid } = swiper; 6493 const elements = elementChildren(el, elementsSelector); 6494 if (swiper.isElement) { 6495 elements.push(...elementChildren(swiper.hostEl, elementsSelector)); 6496 } 6497 elements.forEach((subEl) => { 6498 setTransform(subEl, progress); 6499 }); 6500 slides.forEach((slideEl, slideIndex) => { 6501 let slideProgress = slideEl.progress ?? 0; 6502 const slidesPerGroup = swiper.params.slidesPerGroup ?? 1; 6503 if (slidesPerGroup > 1 && swiper.params.slidesPerView !== 'auto') { 6504 slideProgress += Math.ceil(slideIndex / 2) - progress * (snapGrid.length - 1); 6505 } 6506 slideProgress = Math.min(Math.max(slideProgress, -1), 1); 6507 slideEl 6508 .querySelectorAll(`${elementsSelector}, [data-swiper-parallax-rotate]`) 6509 .forEach((subEl) => { 6510 setTransform(subEl, slideProgress); 6511 }); 6512 }); 6513 }; 6514 const setTransition = (duration = swiper.params.speed ?? 300) => { 6515 const { el, hostEl } = swiper; 6516 const elements = [...el.querySelectorAll(elementsSelector)]; 6517 if (swiper.isElement) { 6518 elements.push(...hostEl.querySelectorAll(elementsSelector)); 6519 } 6520 elements.forEach((parallaxEl) => { 6521 const attr = parallaxEl.getAttribute('data-swiper-parallax-duration'); 6522 let parallaxDuration = (attr ? parseInt(attr, 10) : 0) || duration; 6523 if (duration === 0) 6524 parallaxDuration = 0; 6525 parallaxEl.style.transitionDuration = `${parallaxDuration}ms`; 6526 }); 6527 }; 6528 on('beforeInit', () => { 6529 if (!getParams().enabled) 6530 return; 6531 swiper.params.watchSlidesProgress = true; 6532 swiper.originalParams.watchSlidesProgress = true; 6533 }); 6534 on('init', () => { 6535 if (!getParams().enabled) 6536 return; 6537 setTranslate(); 6538 }); 6539 on('setTranslate', () => { 6540 if (!getParams().enabled) 6541 return; 6542 setTranslate(); 6543 }); 6544 on('setTransition', (_swiper, duration) => { 6545 if (!getParams().enabled) 6546 return; 6547 setTransition(duration); 6548 }); 6549 }; 6550 6551 const Zoom = ({ swiper, extendParams, on, emit }) => { 6552 extendParams({ 6553 zoom: { 6554 enabled: false, 6555 limitToOriginalSize: false, 6556 maxRatio: 3, 6557 minRatio: 1, 6558 panOnMouseMove: false, 6559 toggle: true, 6560 containerClass: 'swiper-zoom-container', 6561 zoomedSlideClass: 'swiper-slide-zoomed', 6562 }, 6563 }); 6564 swiper.zoom = { 6565 enabled: false, 6566 }; 6567 function getParams() { 6568 return swiper.params.zoom; 6569 } 6570 let currentScale = 1; 6571 let isScaling = false; 6572 let isPanningWithMouse = false; 6573 let mousePanStart = { x: 0, y: 0 }; 6574 const mousePanSensitivity = -3; // Negative to invert pan direction 6575 let fakeGestureTouched = false; 6576 let fakeGestureMoved = false; 6577 const evCache = []; 6578 const gesture = { 6579 originX: 0, 6580 originY: 0, 6581 slideEl: undefined, 6582 slideWidth: undefined, 6583 slideHeight: undefined, 6584 imageEl: undefined, 6585 imageWrapEl: undefined, 6586 maxRatio: 3, 6587 }; 6588 const image = { 6589 isTouched: undefined, 6590 isMoved: undefined, 6591 currentX: undefined, 6592 currentY: undefined, 6593 minX: undefined, 6594 minY: undefined, 6595 maxX: undefined, 6596 maxY: undefined, 6597 width: undefined, 6598 height: undefined, 6599 startX: undefined, 6600 startY: undefined, 6601 touchesStart: {}, 6602 touchesCurrent: {}, 6603 }; 6604 const velocity = { 6605 x: undefined, 6606 y: undefined, 6607 prevPositionX: undefined, 6608 prevPositionY: undefined, 6609 prevTime: undefined, 6610 }; 6611 let scale = 1; 6612 Object.defineProperty(swiper.zoom, 'scale', { 6613 get() { 6614 return scale; 6615 }, 6616 set(value) { 6617 if (scale !== value) { 6618 const imageEl = gesture.imageEl; 6619 const slideEl = gesture.slideEl; 6620 emit('zoomChange', value, imageEl, slideEl); 6621 } 6622 scale = value; 6623 }, 6624 }); 6625 function getDistanceBetweenTouches() { 6626 if (evCache.length < 2) 6627 return 1; 6628 const x1 = evCache[0].pageX; 6629 const y1 = evCache[0].pageY; 6630 const x2 = evCache[1].pageX; 6631 const y2 = evCache[1].pageY; 6632 const distance = Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2); 6633 return distance; 6634 } 6635 function getMaxRatio() { 6636 const params = getParams(); 6637 const attr = gesture.imageWrapEl?.getAttribute('data-swiper-zoom'); 6638 const maxRatio = attr != null ? Number(attr) : params.maxRatio; 6639 const imageEl = gesture.imageEl; 6640 if (params.limitToOriginalSize && imageEl && imageEl.naturalWidth) { 6641 const imageMaxRatio = imageEl.naturalWidth / imageEl.offsetWidth; 6642 return Math.min(imageMaxRatio, maxRatio); 6643 } 6644 return maxRatio; 6645 } 6646 function getScaleOrigin() { 6647 if (evCache.length < 2 || !gesture.imageEl) 6648 return [null, null]; 6649 const box = gesture.imageEl.getBoundingClientRect(); 6650 return [ 6651 (evCache[0].pageX + (evCache[1].pageX - evCache[0].pageX) / 2 - box.x - window.scrollX) / 6652 currentScale, 6653 (evCache[0].pageY + (evCache[1].pageY - evCache[0].pageY) / 2 - box.y - window.scrollY) / 6654 currentScale, 6655 ]; 6656 } 6657 function getSlideSelector() { 6658 return swiper.isElement ? `swiper-slide` : `.${swiper.params.slideClass}`; 6659 } 6660 function eventWithinSlide(e) { 6661 const slideSelector = getSlideSelector(); 6662 const target = e.target; 6663 if (!target) 6664 return false; 6665 if (target.matches(slideSelector)) 6666 return true; 6667 if (swiper.slides.filter((slideEl) => slideEl.contains(target)).length > 0) 6668 return true; 6669 return false; 6670 } 6671 function eventWithinZoomContainer(e) { 6672 const selector = `.${getParams().containerClass}`; 6673 const target = e.target; 6674 if (!target) 6675 return false; 6676 if (target.matches(selector)) 6677 return true; 6678 if ([...swiper.hostEl.querySelectorAll(selector)].filter((containerEl) => containerEl.contains(target)).length > 0) 6679 return true; 6680 return false; 6681 } 6682 // Events 6683 function onGestureStart(e) { 6684 if (e.pointerType === 'mouse') { 6685 evCache.splice(0, evCache.length); 6686 } 6687 if (!eventWithinSlide(e)) 6688 return; 6689 const params = getParams(); 6690 fakeGestureTouched = false; 6691 fakeGestureMoved = false; 6692 evCache.push(e); 6693 if (evCache.length < 2) { 6694 return; 6695 } 6696 fakeGestureTouched = true; 6697 gesture.scaleStart = getDistanceBetweenTouches(); 6698 if (!gesture.slideEl) { 6699 const target = e.target; 6700 gesture.slideEl = 6701 target?.closest(`.${swiper.params.slideClass}, swiper-slide`) ?? 6702 undefined; 6703 if (!gesture.slideEl) 6704 gesture.slideEl = swiper.slides[swiper.activeIndex]; 6705 let imageEl = gesture.slideEl?.querySelector(`.${params.containerClass}`) ?? null; 6706 if (imageEl) { 6707 imageEl = 6708 imageEl.querySelectorAll('picture, img, svg, canvas, .swiper-zoom-target')[0] ?? null; 6709 } 6710 gesture.imageEl = imageEl ?? undefined; 6711 if (imageEl) { 6712 gesture.imageWrapEl = 6713 elementParents(imageEl, `.${params.containerClass}`)[0] ?? 6714 undefined; 6715 } 6716 else { 6717 gesture.imageWrapEl = undefined; 6718 } 6719 if (!gesture.imageWrapEl) { 6720 gesture.imageEl = undefined; 6721 return; 6722 } 6723 gesture.maxRatio = getMaxRatio(); 6724 } 6725 if (gesture.imageEl) { 6726 const [originX, originY] = getScaleOrigin(); 6727 gesture.originX = originX ?? 0; 6728 gesture.originY = originY ?? 0; 6729 gesture.imageEl.style.transitionDuration = '0ms'; 6730 } 6731 isScaling = true; 6732 } 6733 function onGestureChange(e) { 6734 if (!eventWithinSlide(e)) 6735 return; 6736 const params = getParams(); 6737 const zoom = swiper.zoom; 6738 const pointerIndex = evCache.findIndex((cachedEv) => cachedEv.pointerId === e.pointerId); 6739 if (pointerIndex >= 0) 6740 evCache[pointerIndex] = e; 6741 if (evCache.length < 2) { 6742 return; 6743 } 6744 fakeGestureMoved = true; 6745 gesture.scaleMove = getDistanceBetweenTouches(); 6746 if (!gesture.imageEl) { 6747 return; 6748 } 6749 zoom.scale = (gesture.scaleMove / (gesture.scaleStart ?? 1)) * currentScale; 6750 if (zoom.scale > gesture.maxRatio) { 6751 zoom.scale = gesture.maxRatio - 1 + (zoom.scale - gesture.maxRatio + 1) ** 0.5; 6752 } 6753 if (zoom.scale < params.minRatio) { 6754 zoom.scale = params.minRatio + 1 - (params.minRatio - zoom.scale + 1) ** 0.5; 6755 } 6756 gesture.imageEl.style.transform = `translate3d(0,0,0) scale(${zoom.scale})`; 6757 } 6758 function onGestureEnd(e) { 6759 if (!eventWithinSlide(e)) 6760 return; 6761 if (e.pointerType === 'mouse' && e.type === 'pointerout') 6762 return; 6763 const params = getParams(); 6764 const zoom = swiper.zoom; 6765 const pointerIndex = evCache.findIndex((cachedEv) => cachedEv.pointerId === e.pointerId); 6766 if (pointerIndex >= 0) 6767 evCache.splice(pointerIndex, 1); 6768 if (!fakeGestureTouched || !fakeGestureMoved) { 6769 return; 6770 } 6771 fakeGestureTouched = false; 6772 fakeGestureMoved = false; 6773 if (!gesture.imageEl) 6774 return; 6775 zoom.scale = Math.max(Math.min(zoom.scale, gesture.maxRatio), params.minRatio); 6776 gesture.imageEl.style.transitionDuration = `${swiper.params.speed}ms`; 6777 gesture.imageEl.style.transform = `translate3d(0,0,0) scale(${zoom.scale})`; 6778 currentScale = zoom.scale; 6779 isScaling = false; 6780 if (zoom.scale > 1 && gesture.slideEl) { 6781 gesture.slideEl.classList.add(`${params.zoomedSlideClass}`); 6782 } 6783 else if (zoom.scale <= 1 && gesture.slideEl) { 6784 gesture.slideEl.classList.remove(`${params.zoomedSlideClass}`); 6785 } 6786 if (zoom.scale === 1) { 6787 gesture.originX = 0; 6788 gesture.originY = 0; 6789 gesture.slideEl = undefined; 6790 } 6791 } 6792 let allowTouchMoveTimeout; 6793 function allowTouchMove() { 6794 swiper.touchEventsData.preventTouchMoveFromPointerMove = false; 6795 } 6796 function preventTouchMove() { 6797 if (allowTouchMoveTimeout !== undefined) 6798 clearTimeout(allowTouchMoveTimeout); 6799 swiper.touchEventsData.preventTouchMoveFromPointerMove = true; 6800 allowTouchMoveTimeout = setTimeout(() => { 6801 if (swiper.destroyed) 6802 return; 6803 allowTouchMove(); 6804 }); 6805 } 6806 function onTouchStart(e) { 6807 const device = swiper.device; 6808 if (image.isTouched) 6809 return; 6810 // Record the position before the imageEl guard, it is unset until the first pinch or zoom 6811 const event = evCache.length > 0 ? evCache[0] : e; 6812 image.touchesStart.x = event.pageX; 6813 image.touchesStart.y = event.pageY; 6814 if (!gesture.imageEl) 6815 return; 6816 if (device.android && e.cancelable) 6817 e.preventDefault(); 6818 image.isTouched = true; 6819 } 6820 function onTouchMove(e) { 6821 const isMouseEvent = e.pointerType === 'mouse'; 6822 const isMousePan = isMouseEvent && getParams().panOnMouseMove; 6823 if (!eventWithinSlide(e) || !eventWithinZoomContainer(e)) { 6824 return; 6825 } 6826 const zoom = swiper.zoom; 6827 if (!gesture.imageEl) { 6828 return; 6829 } 6830 if (!image.isTouched || !gesture.slideEl) { 6831 if (isMousePan) 6832 onMouseMove(e); 6833 return; 6834 } 6835 if (isMousePan) { 6836 onMouseMove(e); 6837 return; 6838 } 6839 if (!image.isMoved) { 6840 image.width = gesture.imageEl.offsetWidth || gesture.imageEl.clientWidth; 6841 image.height = gesture.imageEl.offsetHeight || gesture.imageEl.clientHeight; 6842 image.startX = getTranslate(gesture.imageWrapEl, 'x') || 0; 6843 image.startY = getTranslate(gesture.imageWrapEl, 'y') || 0; 6844 gesture.slideWidth = gesture.slideEl.offsetWidth; 6845 gesture.slideHeight = gesture.slideEl.offsetHeight; 6846 gesture.imageWrapEl.style.transitionDuration = '0ms'; 6847 } 6848 // Define if we need image drag 6849 const scaledWidth = image.width * zoom.scale; 6850 const scaledHeight = image.height * zoom.scale; 6851 image.minX = Math.min(gesture.slideWidth / 2 - scaledWidth / 2, 0); 6852 image.maxX = -image.minX; 6853 image.minY = Math.min(gesture.slideHeight / 2 - scaledHeight / 2, 0); 6854 image.maxY = -image.minY; 6855 image.touchesCurrent.x = evCache.length > 0 ? evCache[0].pageX : e.pageX; 6856 image.touchesCurrent.y = evCache.length > 0 ? evCache[0].pageY : e.pageY; 6857 const touchesDiff = Math.max(Math.abs(image.touchesCurrent.x - (image.touchesStart.x ?? 0)), Math.abs(image.touchesCurrent.y - (image.touchesStart.y ?? 0))); 6858 if (touchesDiff > 5) { 6859 swiper.allowClick = false; 6860 } 6861 const startX = image.startX ?? 0; 6862 const startY = image.startY ?? 0; 6863 if (!image.isMoved && !isScaling) { 6864 if (swiper.isHorizontal() && 6865 ((Math.floor(image.minX) === Math.floor(startX) && 6866 image.touchesCurrent.x < (image.touchesStart.x ?? 0)) || 6867 (Math.floor(image.maxX) === Math.floor(startX) && 6868 image.touchesCurrent.x > (image.touchesStart.x ?? 0)))) { 6869 image.isTouched = false; 6870 allowTouchMove(); 6871 return; 6872 } 6873 if (!swiper.isHorizontal() && 6874 ((Math.floor(image.minY) === Math.floor(startY) && 6875 image.touchesCurrent.y < (image.touchesStart.y ?? 0)) || 6876 (Math.floor(image.maxY) === Math.floor(startY) && 6877 image.touchesCurrent.y > (image.touchesStart.y ?? 0)))) { 6878 image.isTouched = false; 6879 allowTouchMove(); 6880 return; 6881 } 6882 } 6883 if (e.cancelable) { 6884 e.preventDefault(); 6885 } 6886 e.stopPropagation(); 6887 preventTouchMove(); 6888 image.isMoved = true; 6889 const scaleRatio = (zoom.scale - currentScale) / (gesture.maxRatio - getParams().minRatio); 6890 const { originX, originY } = gesture; 6891 image.currentX = 6892 image.touchesCurrent.x - 6893 (image.touchesStart.x ?? 0) + 6894 startX + 6895 scaleRatio * (image.width - originX * 2); 6896 image.currentY = 6897 image.touchesCurrent.y - 6898 (image.touchesStart.y ?? 0) + 6899 startY + 6900 scaleRatio * (image.height - originY * 2); 6901 if (image.currentX < image.minX) { 6902 image.currentX = image.minX + 1 - (image.minX - image.currentX + 1) ** 0.8; 6903 } 6904 if (image.currentX > image.maxX) { 6905 image.currentX = image.maxX - 1 + (image.currentX - image.maxX + 1) ** 0.8; 6906 } 6907 if (image.currentY < image.minY) { 6908 image.currentY = image.minY + 1 - (image.minY - image.currentY + 1) ** 0.8; 6909 } 6910 if (image.currentY > image.maxY) { 6911 image.currentY = image.maxY - 1 + (image.currentY - image.maxY + 1) ** 0.8; 6912 } 6913 // Velocity 6914 if (!velocity.prevPositionX) 6915 velocity.prevPositionX = image.touchesCurrent.x; 6916 if (!velocity.prevPositionY) 6917 velocity.prevPositionY = image.touchesCurrent.y; 6918 if (!velocity.prevTime) 6919 velocity.prevTime = Date.now(); 6920 velocity.x = 6921 (image.touchesCurrent.x - velocity.prevPositionX) / (Date.now() - velocity.prevTime) / 2; 6922 velocity.y = 6923 (image.touchesCurrent.y - velocity.prevPositionY) / (Date.now() - velocity.prevTime) / 2; 6924 if (Math.abs(image.touchesCurrent.x - velocity.prevPositionX) < 2) 6925 velocity.x = 0; 6926 if (Math.abs(image.touchesCurrent.y - velocity.prevPositionY) < 2) 6927 velocity.y = 0; 6928 velocity.prevPositionX = image.touchesCurrent.x; 6929 velocity.prevPositionY = image.touchesCurrent.y; 6930 velocity.prevTime = Date.now(); 6931 gesture.imageWrapEl.style.transform = `translate3d(${image.currentX}px, ${image.currentY}px,0)`; 6932 } 6933 function onTouchEnd() { 6934 const zoom = swiper.zoom; 6935 evCache.length = 0; 6936 if (!gesture.imageEl) 6937 return; 6938 if (!image.isTouched || !image.isMoved) { 6939 image.isTouched = false; 6940 image.isMoved = false; 6941 return; 6942 } 6943 image.isTouched = false; 6944 image.isMoved = false; 6945 let momentumDurationX = 300; 6946 let momentumDurationY = 300; 6947 const velocityX = velocity.x ?? 0; 6948 const velocityY = velocity.y ?? 0; 6949 const momentumDistanceX = velocityX * momentumDurationX; 6950 const newPositionX = image.currentX + momentumDistanceX; 6951 const momentumDistanceY = velocityY * momentumDurationY; 6952 const newPositionY = image.currentY + momentumDistanceY; 6953 // Fix duration 6954 if (velocityX !== 0) 6955 momentumDurationX = Math.abs((newPositionX - image.currentX) / velocityX); 6956 if (velocityY !== 0) 6957 momentumDurationY = Math.abs((newPositionY - image.currentY) / velocityY); 6958 const momentumDuration = Math.max(momentumDurationX, momentumDurationY); 6959 image.currentX = newPositionX; 6960 image.currentY = newPositionY; 6961 // Define if we need image drag 6962 const scaledWidth = image.width * zoom.scale; 6963 const scaledHeight = image.height * zoom.scale; 6964 image.minX = Math.min(gesture.slideWidth / 2 - scaledWidth / 2, 0); 6965 image.maxX = -image.minX; 6966 image.minY = Math.min(gesture.slideHeight / 2 - scaledHeight / 2, 0); 6967 image.maxY = -image.minY; 6968 image.currentX = Math.max(Math.min(image.currentX, image.maxX), image.minX); 6969 image.currentY = Math.max(Math.min(image.currentY, image.maxY), image.minY); 6970 gesture.imageWrapEl.style.transitionDuration = `${momentumDuration}ms`; 6971 gesture.imageWrapEl.style.transform = `translate3d(${image.currentX}px, ${image.currentY}px,0)`; 6972 } 6973 function onTransitionEnd() { 6974 const zoom = swiper.zoom; 6975 if (gesture.slideEl && swiper.activeIndex !== swiper.slides.indexOf(gesture.slideEl)) { 6976 if (gesture.imageEl) { 6977 gesture.imageEl.style.transform = 'translate3d(0,0,0) scale(1)'; 6978 } 6979 if (gesture.imageWrapEl) { 6980 gesture.imageWrapEl.style.transform = 'translate3d(0,0,0)'; 6981 } 6982 gesture.slideEl.classList.remove(`${getParams().zoomedSlideClass}`); 6983 zoom.scale = 1; 6984 currentScale = 1; 6985 gesture.slideEl = undefined; 6986 gesture.imageEl = undefined; 6987 gesture.imageWrapEl = undefined; 6988 gesture.originX = 0; 6989 gesture.originY = 0; 6990 } 6991 } 6992 function onMouseMove(e) { 6993 // Only pan if zoomed in and mouse panning is enabled 6994 if (currentScale <= 1 || !gesture.imageWrapEl) 6995 return; 6996 if (!eventWithinSlide(e) || !eventWithinZoomContainer(e)) 6997 return; 6998 const currentTransform = window.getComputedStyle(gesture.imageWrapEl).transform; 6999 const matrix = new window.DOMMatrix(currentTransform); 7000 if (!isPanningWithMouse) { 7001 isPanningWithMouse = true; 7002 mousePanStart.x = e.clientX; 7003 mousePanStart.y = e.clientY; 7004 image.startX = matrix.e; 7005 image.startY = matrix.f; 7006 image.width = gesture.imageEl.offsetWidth || gesture.imageEl.clientWidth; 7007 image.height = gesture.imageEl.offsetHeight || gesture.imageEl.clientHeight; 7008 gesture.slideWidth = gesture.slideEl.offsetWidth; 7009 gesture.slideHeight = gesture.slideEl.offsetHeight; 7010 return; 7011 } 7012 const deltaX = (e.clientX - mousePanStart.x) * mousePanSensitivity; 7013 const deltaY = (e.clientY - mousePanStart.y) * mousePanSensitivity; 7014 const scaledWidth = image.width * currentScale; 7015 const scaledHeight = image.height * currentScale; 7016 const slideWidth = gesture.slideWidth; 7017 const slideHeight = gesture.slideHeight; 7018 const minX = Math.min(slideWidth / 2 - scaledWidth / 2, 0); 7019 const maxX = -minX; 7020 const minY = Math.min(slideHeight / 2 - scaledHeight / 2, 0); 7021 const maxY = -minY; 7022 const newX = Math.max(Math.min(image.startX + deltaX, maxX), minX); 7023 const newY = Math.max(Math.min(image.startY + deltaY, maxY), minY); 7024 gesture.imageWrapEl.style.transitionDuration = '0ms'; 7025 gesture.imageWrapEl.style.transform = `translate3d(${newX}px, ${newY}px, 0)`; 7026 mousePanStart.x = e.clientX; 7027 mousePanStart.y = e.clientY; 7028 image.startX = newX; 7029 image.startY = newY; 7030 image.currentX = newX; 7031 image.currentY = newY; 7032 } 7033 function zoomIn(e) { 7034 const zoom = swiper.zoom; 7035 const params = getParams(); 7036 if (!gesture.slideEl) { 7037 if (e && typeof e !== 'number' && 'target' in e && e.target) { 7038 gesture.slideEl = 7039 e.target.closest(`.${swiper.params.slideClass}, swiper-slide`) ?? undefined; 7040 } 7041 if (!gesture.slideEl) { 7042 const virtual = swiper.params.virtual; 7043 if (virtual && virtual.enabled && swiper.virtual) { 7044 gesture.slideEl = 7045 elementChildren(swiper.slidesEl, `.${swiper.params.slideActiveClass}`)[0] ?? undefined; 7046 } 7047 else { 7048 gesture.slideEl = swiper.slides[swiper.activeIndex]; 7049 } 7050 } 7051 let imageEl = gesture.slideEl?.querySelector(`.${params.containerClass}`) ?? null; 7052 if (imageEl) { 7053 imageEl = 7054 imageEl.querySelectorAll('picture, img, svg, canvas, .swiper-zoom-target')[0] ?? null; 7055 } 7056 gesture.imageEl = imageEl ?? undefined; 7057 if (imageEl) { 7058 gesture.imageWrapEl = 7059 elementParents(imageEl, `.${params.containerClass}`)[0] ?? 7060 undefined; 7061 } 7062 else { 7063 gesture.imageWrapEl = undefined; 7064 } 7065 } 7066 if (!gesture.imageEl || !gesture.imageWrapEl || !gesture.slideEl) 7067 return; 7068 gesture.maxRatio = getMaxRatio(); 7069 if (swiper.params.cssMode) { 7070 swiper.wrapperEl.style.overflow = 'hidden'; 7071 swiper.wrapperEl.style.touchAction = 'none'; 7072 } 7073 gesture.slideEl.classList.add(`${params.zoomedSlideClass}`); 7074 let touchX; 7075 let touchY; 7076 let offsetX; 7077 let offsetY; 7078 let diffX; 7079 let diffY; 7080 let translateX; 7081 let translateY; 7082 let imageWidth; 7083 let imageHeight; 7084 let scaledWidth; 7085 let scaledHeight; 7086 let translateMinX; 7087 let translateMinY; 7088 let translateMaxX; 7089 let translateMaxY; 7090 let slideWidth; 7091 let slideHeight; 7092 const eventIsPointer = e && typeof e !== 'number'; 7093 if (typeof image.touchesStart.x === 'undefined' && eventIsPointer) { 7094 touchX = e.pageX; 7095 touchY = e.pageY; 7096 } 7097 else { 7098 touchX = image.touchesStart.x; 7099 touchY = image.touchesStart.y; 7100 } 7101 const prevScale = currentScale; 7102 const forceZoomRatio = typeof e === 'number' ? e : null; 7103 if (currentScale === 1 && forceZoomRatio) { 7104 touchX = undefined; 7105 touchY = undefined; 7106 image.touchesStart.x = undefined; 7107 image.touchesStart.y = undefined; 7108 } 7109 const maxRatio = getMaxRatio(); 7110 zoom.scale = forceZoomRatio || maxRatio; 7111 currentScale = forceZoomRatio || maxRatio; 7112 if (e && !(currentScale === 1 && forceZoomRatio)) { 7113 slideWidth = gesture.slideEl.offsetWidth; 7114 slideHeight = gesture.slideEl.offsetHeight; 7115 offsetX = elementOffset(gesture.slideEl).left + window.scrollX; 7116 offsetY = elementOffset(gesture.slideEl).top + window.scrollY; 7117 diffX = offsetX + slideWidth / 2 - (touchX ?? 0); 7118 diffY = offsetY + slideHeight / 2 - (touchY ?? 0); 7119 imageWidth = gesture.imageEl.offsetWidth || gesture.imageEl.clientWidth; 7120 imageHeight = gesture.imageEl.offsetHeight || gesture.imageEl.clientHeight; 7121 scaledWidth = imageWidth * zoom.scale; 7122 scaledHeight = imageHeight * zoom.scale; 7123 translateMinX = Math.min(slideWidth / 2 - scaledWidth / 2, 0); 7124 translateMinY = Math.min(slideHeight / 2 - scaledHeight / 2, 0); 7125 translateMaxX = -translateMinX; 7126 translateMaxY = -translateMinY; 7127 if (prevScale > 0 && 7128 forceZoomRatio && 7129 typeof image.currentX === 'number' && 7130 typeof image.currentY === 'number') { 7131 translateX = (image.currentX * zoom.scale) / prevScale; 7132 translateY = (image.currentY * zoom.scale) / prevScale; 7133 } 7134 else { 7135 translateX = diffX * zoom.scale; 7136 translateY = diffY * zoom.scale; 7137 } 7138 if (translateX < translateMinX) { 7139 translateX = translateMinX; 7140 } 7141 if (translateX > translateMaxX) { 7142 translateX = translateMaxX; 7143 } 7144 if (translateY < translateMinY) { 7145 translateY = translateMinY; 7146 } 7147 if (translateY > translateMaxY) { 7148 translateY = translateMaxY; 7149 } 7150 } 7151 else { 7152 translateX = 0; 7153 translateY = 0; 7154 } 7155 if (forceZoomRatio && zoom.scale === 1) { 7156 gesture.originX = 0; 7157 gesture.originY = 0; 7158 } 7159 image.currentX = translateX; 7160 image.currentY = translateY; 7161 gesture.imageWrapEl.style.transitionDuration = '300ms'; 7162 gesture.imageWrapEl.style.transform = `translate3d(${translateX}px, ${translateY}px,0)`; 7163 gesture.imageEl.style.transitionDuration = '300ms'; 7164 gesture.imageEl.style.transform = `translate3d(0,0,0) scale(${zoom.scale})`; 7165 } 7166 function zoomOut() { 7167 const zoom = swiper.zoom; 7168 const params = getParams(); 7169 if (!gesture.slideEl) { 7170 const virtual = swiper.params.virtual; 7171 if (virtual && virtual.enabled && swiper.virtual) { 7172 gesture.slideEl = 7173 elementChildren(swiper.slidesEl, `.${swiper.params.slideActiveClass}`)[0] ?? undefined; 7174 } 7175 else { 7176 gesture.slideEl = swiper.slides[swiper.activeIndex]; 7177 } 7178 let imageEl = gesture.slideEl?.querySelector(`.${params.containerClass}`) ?? null; 7179 if (imageEl) { 7180 imageEl = 7181 imageEl.querySelectorAll('picture, img, svg, canvas, .swiper-zoom-target')[0] ?? null; 7182 } 7183 gesture.imageEl = imageEl ?? undefined; 7184 if (imageEl) { 7185 gesture.imageWrapEl = 7186 elementParents(imageEl, `.${params.containerClass}`)[0] ?? 7187 undefined; 7188 } 7189 else { 7190 gesture.imageWrapEl = undefined; 7191 } 7192 } 7193 if (!gesture.imageEl || !gesture.imageWrapEl || !gesture.slideEl) 7194 return; 7195 gesture.maxRatio = getMaxRatio(); 7196 if (swiper.params.cssMode) { 7197 swiper.wrapperEl.style.overflow = ''; 7198 swiper.wrapperEl.style.touchAction = ''; 7199 } 7200 zoom.scale = 1; 7201 currentScale = 1; 7202 image.currentX = undefined; 7203 image.currentY = undefined; 7204 image.touchesStart.x = undefined; 7205 image.touchesStart.y = undefined; 7206 gesture.imageWrapEl.style.transitionDuration = '300ms'; 7207 gesture.imageWrapEl.style.transform = 'translate3d(0,0,0)'; 7208 gesture.imageEl.style.transitionDuration = '300ms'; 7209 gesture.imageEl.style.transform = 'translate3d(0,0,0) scale(1)'; 7210 gesture.slideEl.classList.remove(`${params.zoomedSlideClass}`); 7211 gesture.slideEl = undefined; 7212 gesture.originX = 0; 7213 gesture.originY = 0; 7214 if (params.panOnMouseMove) { 7215 mousePanStart = { x: 0, y: 0 }; 7216 if (isPanningWithMouse) { 7217 isPanningWithMouse = false; 7218 image.startX = 0; 7219 image.startY = 0; 7220 } 7221 } 7222 } 7223 // Toggle Zoom 7224 function zoomToggle(e) { 7225 const zoom = swiper.zoom; 7226 if (zoom.scale && zoom.scale !== 1) { 7227 // Zoom Out 7228 zoomOut(); 7229 } 7230 else { 7231 // Zoom In 7232 zoomIn(e); 7233 } 7234 } 7235 function getListeners() { 7236 const passiveListener = swiper.params.passiveListeners 7237 ? { passive: true, capture: false } 7238 : false; 7239 const activeListenerWithCapture = swiper.params.passiveListeners 7240 ? { passive: false, capture: true } 7241 : true; 7242 return { passiveListener, activeListenerWithCapture }; 7243 } 7244 // Attach/Detach Events 7245 function enable() { 7246 const zoom = swiper.zoom; 7247 if (zoom.enabled) 7248 return; 7249 zoom.enabled = true; 7250 const { passiveListener, activeListenerWithCapture } = getListeners(); 7251 // Scale image 7252 swiper.wrapperEl.addEventListener('pointerdown', onGestureStart, passiveListener); 7253 swiper.wrapperEl.addEventListener('pointermove', onGestureChange, activeListenerWithCapture); 7254 ['pointerup', 'pointercancel', 'pointerout'].forEach((eventName) => { 7255 swiper.wrapperEl.addEventListener(eventName, onGestureEnd, passiveListener); 7256 }); 7257 // Move image 7258 swiper.wrapperEl.addEventListener('pointermove', onTouchMove, activeListenerWithCapture); 7259 } 7260 function disable() { 7261 const zoom = swiper.zoom; 7262 if (!zoom.enabled) 7263 return; 7264 zoom.enabled = false; 7265 const { passiveListener, activeListenerWithCapture } = getListeners(); 7266 // Scale image 7267 swiper.wrapperEl.removeEventListener('pointerdown', onGestureStart, passiveListener); 7268 swiper.wrapperEl.removeEventListener('pointermove', onGestureChange, activeListenerWithCapture); 7269 ['pointerup', 'pointercancel', 'pointerout'].forEach((eventName) => { 7270 swiper.wrapperEl.removeEventListener(eventName, onGestureEnd, passiveListener); 7271 }); 7272 // Move image 7273 swiper.wrapperEl.removeEventListener('pointermove', onTouchMove, activeListenerWithCapture); 7274 } 7275 on('init', () => { 7276 if (getParams().enabled) { 7277 enable(); 7278 } 7279 }); 7280 on('destroy', () => { 7281 disable(); 7282 }); 7283 on('touchStart', (_s, e) => { 7284 if (!swiper.zoom.enabled) 7285 return; 7286 onTouchStart(e); 7287 }); 7288 on('touchEnd', () => { 7289 if (!swiper.zoom.enabled) 7290 return; 7291 onTouchEnd(); 7292 }); 7293 on('doubleTap', (_s, e) => { 7294 if (!swiper.animating && getParams().enabled && swiper.zoom.enabled && getParams().toggle) { 7295 zoomToggle(e); 7296 } 7297 }); 7298 on('transitionEnd', () => { 7299 if (swiper.zoom.enabled && getParams().enabled) { 7300 onTransitionEnd(); 7301 } 7302 }); 7303 on('slideChange', () => { 7304 if (swiper.zoom.enabled && getParams().enabled && swiper.params.cssMode) { 7305 onTransitionEnd(); 7306 } 7307 }); 7308 Object.assign(swiper.zoom, { 7309 enable, 7310 disable, 7311 in: zoomIn, 7312 out: zoomOut, 7313 toggle: zoomToggle, 7314 }); 7315 }; 7316 7317 class LinearSpline { 7318 x; 7319 y; 7320 lastIndex; 7321 binarySearch; 7322 constructor(x, y) { 7323 let maxIndex; 7324 let minIndex; 7325 let guess; 7326 this.binarySearch = (array, val) => { 7327 minIndex = -1; 7328 maxIndex = array.length; 7329 while (maxIndex - minIndex > 1) { 7330 guess = (maxIndex + minIndex) >> 1; 7331 if (array[guess] <= val) { 7332 minIndex = guess; 7333 } 7334 else { 7335 maxIndex = guess; 7336 } 7337 } 7338 return maxIndex; 7339 }; 7340 this.x = x; 7341 this.y = y; 7342 this.lastIndex = x.length - 1; 7343 } 7344 interpolate(x2) { 7345 if (!x2) 7346 return 0; 7347 const i3 = this.binarySearch(this.x, x2); 7348 const i1 = i3 - 1; 7349 // Given an x value (x2), return the expected y2 value: 7350 // (x1,y1) is the known point before given value, 7351 // (x3,y3) is the known point after given value. 7352 // y2 := ((x2−x1) × (y3−y1)) ÷ (x3−x1) + y1 7353 return (((x2 - this.x[i1]) * (this.y[i3] - this.y[i1])) / (this.x[i3] - this.x[i1]) + this.y[i1]); 7354 } 7355 } 7356 const Controller = ({ swiper, extendParams, on }) => { 7357 extendParams({ 7358 controller: { 7359 control: undefined, 7360 inverse: false, 7361 by: 'slide', // or 'container' 7362 }, 7363 }); 7364 swiper.controller = { 7365 control: undefined, 7366 }; 7367 function getParams() { 7368 return swiper.params.controller; 7369 } 7370 function getInterpolateFunction(c) { 7371 swiper.controller.spline = swiper.params.loop 7372 ? new LinearSpline(swiper.slidesGrid, c.slidesGrid) 7373 : new LinearSpline(swiper.snapGrid, c.snapGrid); 7374 } 7375 function setTranslate(_t, byController) { 7376 const controlled = swiper.controller.control; 7377 let multiplier; 7378 let controlledTranslate; 7379 const SwiperCtor = swiper.constructor; 7380 function setControlledTranslate(c) { 7381 if (c.destroyed) 7382 return; 7383 // this will create an Interpolate function based on the snapGrids 7384 // x is the Grid of the scrolled scroller and y will be the controlled scroller 7385 // it makes sense to create this only once and recall it for the interpolation 7386 // the function does a lot of value caching for performance 7387 const translate = swiper.rtlTranslate ? -swiper.translate : swiper.translate; 7388 const controllerParams = getParams(); 7389 if (controllerParams.by === 'slide') { 7390 getInterpolateFunction(c); 7391 // i am not sure why the values have to be multiplicated this way, tried to invert the snapGrid 7392 // but it did not work out 7393 controlledTranslate = -swiper.controller.spline.interpolate(-translate); 7394 } 7395 else { 7396 controlledTranslate = 0; 7397 } 7398 if (!controlledTranslate || controllerParams.by === 'container') { 7399 multiplier = 7400 (c.maxTranslate() - c.minTranslate()) / (swiper.maxTranslate() - swiper.minTranslate()); 7401 if (Number.isNaN(multiplier) || !Number.isFinite(multiplier)) { 7402 multiplier = 1; 7403 } 7404 controlledTranslate = (translate - swiper.minTranslate()) * multiplier + c.minTranslate(); 7405 } 7406 if (controllerParams.inverse) { 7407 controlledTranslate = c.maxTranslate() - controlledTranslate; 7408 } 7409 c.updateProgress(controlledTranslate); 7410 c.setTranslate(controlledTranslate, swiper); 7411 c.updateActiveIndex(); 7412 c.updateSlidesClasses(); 7413 } 7414 if (Array.isArray(controlled)) { 7415 for (let i = 0; i < controlled.length; i += 1) { 7416 const target = controlled[i]; 7417 if (target && target !== byController && target instanceof SwiperCtor) { 7418 setControlledTranslate(target); 7419 } 7420 } 7421 } 7422 else if (controlled instanceof SwiperCtor && byController !== controlled) { 7423 setControlledTranslate(controlled); 7424 } 7425 } 7426 function setTransition(duration, byController) { 7427 const SwiperCtor = swiper.constructor; 7428 const controlled = swiper.controller.control; 7429 function setControlledTransition(c) { 7430 if (c.destroyed) 7431 return; 7432 c.setTransition(duration, swiper); 7433 if (duration !== 0) { 7434 c.transitionStart(); 7435 if (c.params.autoHeight) { 7436 nextTick(() => { 7437 c.updateAutoHeight(); 7438 }); 7439 } 7440 elementTransitionEnd(c.wrapperEl, () => { 7441 if (!controlled) 7442 return; 7443 c.transitionEnd(); 7444 }); 7445 } 7446 } 7447 if (Array.isArray(controlled)) { 7448 for (let i = 0; i < controlled.length; i += 1) { 7449 const target = controlled[i]; 7450 if (target && target !== byController && target instanceof SwiperCtor) { 7451 setControlledTransition(target); 7452 } 7453 } 7454 } 7455 else if (controlled instanceof SwiperCtor && byController !== controlled) { 7456 setControlledTransition(controlled); 7457 } 7458 } 7459 function removeSpline() { 7460 if (!swiper.controller.control) 7461 return; 7462 if (swiper.controller.spline) { 7463 swiper.controller.spline = undefined; 7464 delete swiper.controller.spline; 7465 } 7466 } 7467 on('beforeInit', () => { 7468 const controllerParam = getParams().control; 7469 if (typeof window !== 'undefined' && 7470 (typeof controllerParam === 'string' || controllerParam instanceof HTMLElement)) { 7471 const controlElements = typeof controllerParam === 'string' 7472 ? [...document.querySelectorAll(controllerParam)] 7473 : [controllerParam]; 7474 controlElements.forEach((controlElement) => { 7475 if (!swiper.controller.control) 7476 swiper.controller.control = []; 7477 const list = swiper.controller.control; 7478 if (controlElement && controlElement.swiper) { 7479 list.push(controlElement.swiper); 7480 } 7481 else if (controlElement) { 7482 const eventName = `${swiper.params.eventsPrefix}init`; 7483 const onControllerSwiper = (e) => { 7484 const detail = e.detail; 7485 if (detail && detail[0]) 7486 list.push(detail[0]); 7487 swiper.update(); 7488 controlElement.removeEventListener(eventName, onControllerSwiper); 7489 }; 7490 controlElement.addEventListener(eventName, onControllerSwiper); 7491 } 7492 }); 7493 return; 7494 } 7495 // After this point control is either Swiper or Swiper[] (or null/undefined), 7496 // never the string/HTMLElement forms that the public option accepts. 7497 swiper.controller.control = controllerParam; 7498 }); 7499 on('update', () => { 7500 removeSpline(); 7501 }); 7502 on('resize', () => { 7503 removeSpline(); 7504 }); 7505 on('observerUpdate', () => { 7506 removeSpline(); 7507 }); 7508 // Event payloads come typed against the legacy public Swiper class 7509 // (src/types/swiper-class.d.ts) until Phase 5 deletes src/types/; cast the 7510 // forwarded byController back to the core Swiper so it lines up with the 7511 // controller-internal signatures. 7512 on('setTranslate', (_s, translate, byController) => { 7513 if (!swiper.controller.control) 7514 return; 7515 if (!Array.isArray(swiper.controller.control) && swiper.controller.control.destroyed) 7516 return; 7517 swiper.controller.setTranslate(translate, byController); 7518 }); 7519 on('setTransition', (_s, duration, byController) => { 7520 if (!swiper.controller.control) 7521 return; 7522 if (!Array.isArray(swiper.controller.control) && swiper.controller.control.destroyed) 7523 return; 7524 swiper.controller.setTransition(duration, byController); 7525 }); 7526 Object.assign(swiper.controller, { 7527 setTranslate, 7528 setTransition, 7529 }); 7530 }; 7531 7532 const isVirtualEnabled$1 = (swiper) => !!swiper.virtual && !!swiper.params.virtual?.enabled; 7533 const A11y = ({ swiper, extendParams, on }) => { 7534 extendParams({ 7535 a11y: { 7536 enabled: true, 7537 notificationClass: 'swiper-notification', 7538 prevSlideMessage: 'Previous slide', 7539 nextSlideMessage: 'Next slide', 7540 firstSlideMessage: 'This is the first slide', 7541 lastSlideMessage: 'This is the last slide', 7542 paginationBulletMessage: 'Go to slide {{index}}', 7543 slideLabelMessage: '{{index}} / {{slidesLength}}', 7544 containerMessage: null, 7545 containerRoleDescriptionMessage: null, 7546 containerRole: null, 7547 itemRoleDescriptionMessage: null, 7548 slideRole: 'group', 7549 id: null, 7550 scrollOnFocus: true, 7551 wrapperLiveRegion: true, 7552 }, 7553 }); 7554 swiper.a11y = { 7555 clicked: false, 7556 }; 7557 let liveRegion = null; 7558 let preventFocusHandler = false; 7559 let focusTargetSlideEl; 7560 let visibilityChangedTimestamp = new Date().getTime(); 7561 function getParams() { 7562 return swiper.params.a11y; 7563 } 7564 function notify(message) { 7565 const notification = liveRegion; 7566 if (!notification || !message) 7567 return; 7568 setInnerHTML(notification, message); 7569 } 7570 function getRandomNumber(size = 16) { 7571 const randomChar = () => Math.round(16 * Math.random()).toString(16); 7572 return 'x'.repeat(size).replace(/x/g, randomChar); 7573 } 7574 function makeElFocusable(el) { 7575 const els = makeElementsArray(el); 7576 els.forEach((subEl) => { 7577 subEl.setAttribute('tabIndex', '0'); 7578 }); 7579 } 7580 function makeElNotFocusable(el) { 7581 const els = makeElementsArray(el); 7582 els.forEach((subEl) => { 7583 subEl.setAttribute('tabIndex', '-1'); 7584 }); 7585 } 7586 function addElRole(el, role) { 7587 const els = makeElementsArray(el); 7588 els.forEach((subEl) => { 7589 subEl.setAttribute('role', role); 7590 }); 7591 } 7592 function addElRoleDescription(el, description) { 7593 const els = makeElementsArray(el); 7594 els.forEach((subEl) => { 7595 subEl.setAttribute('aria-roledescription', description); 7596 }); 7597 } 7598 function addElLabel(el, label) { 7599 const els = makeElementsArray(el); 7600 els.forEach((subEl) => { 7601 subEl.setAttribute('aria-label', label); 7602 }); 7603 } 7604 function addElId(el, id) { 7605 const els = makeElementsArray(el); 7606 els.forEach((subEl) => { 7607 subEl.setAttribute('id', id); 7608 }); 7609 } 7610 function addElLive(el, live) { 7611 const els = makeElementsArray(el); 7612 els.forEach((subEl) => { 7613 subEl.setAttribute('aria-live', live); 7614 }); 7615 } 7616 function disableEl(el) { 7617 const els = makeElementsArray(el); 7618 els.forEach((subEl) => { 7619 subEl.setAttribute('aria-disabled', 'true'); 7620 }); 7621 } 7622 function enableEl(el) { 7623 const els = makeElementsArray(el); 7624 els.forEach((subEl) => { 7625 subEl.removeAttribute('aria-disabled'); 7626 }); 7627 } 7628 function onEnterOrSpaceKey(e) { 7629 if (e.keyCode !== 13 && e.keyCode !== 32) 7630 return; 7631 const params = getParams(); 7632 const paginationParams = swiper.params.pagination; 7633 const targetEl = e.target; 7634 if (swiper.pagination && 7635 swiper.pagination.el && 7636 (targetEl === swiper.pagination.el || swiper.pagination.el.contains(targetEl))) { 7637 if (!targetEl.matches(classesToSelector(paginationParams?.bulletClass))) 7638 return; 7639 } 7640 if (swiper.navigation && swiper.navigation.prevEl && swiper.navigation.nextEl) { 7641 const prevEls = makeElementsArray(swiper.navigation.prevEl); 7642 const nextEls = makeElementsArray(swiper.navigation.nextEl); 7643 if (nextEls.includes(targetEl)) { 7644 if (!(swiper.isEnd && !swiper.params.loop)) { 7645 swiper.slideNext(); 7646 } 7647 if (swiper.isEnd) { 7648 notify(params.lastSlideMessage); 7649 } 7650 else { 7651 notify(params.nextSlideMessage); 7652 } 7653 } 7654 if (prevEls.includes(targetEl)) { 7655 if (!(swiper.isBeginning && !swiper.params.loop)) { 7656 swiper.slidePrev(); 7657 } 7658 if (swiper.isBeginning) { 7659 notify(params.firstSlideMessage); 7660 } 7661 else { 7662 notify(params.prevSlideMessage); 7663 } 7664 } 7665 } 7666 if (swiper.pagination && targetEl.matches(classesToSelector(paginationParams?.bulletClass))) { 7667 targetEl.click(); 7668 } 7669 } 7670 function updateNavigation() { 7671 if (swiper.params.loop || swiper.params.rewind || !swiper.navigation) 7672 return; 7673 const { nextEl, prevEl } = swiper.navigation; 7674 if (prevEl) { 7675 if (swiper.isBeginning) { 7676 disableEl(prevEl); 7677 makeElNotFocusable(prevEl); 7678 } 7679 else { 7680 enableEl(prevEl); 7681 makeElFocusable(prevEl); 7682 } 7683 } 7684 if (nextEl) { 7685 if (swiper.isEnd) { 7686 disableEl(nextEl); 7687 makeElNotFocusable(nextEl); 7688 } 7689 else { 7690 enableEl(nextEl); 7691 makeElFocusable(nextEl); 7692 } 7693 } 7694 } 7695 function hasPagination() { 7696 return !!(swiper.pagination && swiper.pagination.bullets && swiper.pagination.bullets.length); 7697 } 7698 function hasClickablePagination() { 7699 const paginationParams = swiper.params.pagination; 7700 return hasPagination() && !!paginationParams?.clickable; 7701 } 7702 function updatePagination() { 7703 const params = getParams(); 7704 if (!hasPagination()) 7705 return; 7706 const paginationParams = swiper.params.pagination; 7707 swiper.pagination.bullets.forEach((bulletEl) => { 7708 if (paginationParams.clickable) { 7709 makeElFocusable(bulletEl); 7710 if (!paginationParams.renderBullet) { 7711 addElRole(bulletEl, 'button'); 7712 addElLabel(bulletEl, params.paginationBulletMessage.replace(/\{\{index\}\}/, String((elementIndex(bulletEl) ?? 0) + 1))); 7713 } 7714 } 7715 if (bulletEl.matches(classesToSelector(paginationParams.bulletActiveClass))) { 7716 bulletEl.setAttribute('aria-current', 'true'); 7717 } 7718 else { 7719 bulletEl.removeAttribute('aria-current'); 7720 } 7721 }); 7722 } 7723 const initNavEl = (el, _wrapperId, message) => { 7724 makeElFocusable(el); 7725 if (el.tagName !== 'BUTTON') { 7726 addElRole(el, 'button'); 7727 el.addEventListener('keydown', onEnterOrSpaceKey); 7728 } 7729 addElLabel(el, message); 7730 }; 7731 const handlePointerDown = (e) => { 7732 if (focusTargetSlideEl && 7733 focusTargetSlideEl !== e.target && 7734 !focusTargetSlideEl.contains(e.target)) { 7735 preventFocusHandler = true; 7736 } 7737 swiper.a11y.clicked = true; 7738 }; 7739 const handlePointerUp = () => { 7740 preventFocusHandler = false; 7741 requestAnimationFrame(() => { 7742 requestAnimationFrame(() => { 7743 if (!swiper.destroyed) { 7744 swiper.a11y.clicked = false; 7745 } 7746 }); 7747 }); 7748 }; 7749 const onVisibilityChange = (_e) => { 7750 visibilityChangedTimestamp = new Date().getTime(); 7751 }; 7752 const handleFocus = (e) => { 7753 const params = getParams(); 7754 if (swiper.a11y.clicked || !params.scrollOnFocus) 7755 return; 7756 if (new Date().getTime() - visibilityChangedTimestamp < 100) 7757 return; 7758 const target = e.target; 7759 const slideEl = target.closest(`.${swiper.params.slideClass}, swiper-slide`); 7760 if (!slideEl || !swiper.slides.includes(slideEl)) 7761 return; 7762 focusTargetSlideEl = slideEl; 7763 const isVirtual = isVirtualEnabled$1(swiper); 7764 const isActive = (isVirtual 7765 ? parseInt(slideEl.getAttribute('data-swiper-slide-index') || '0', 10) 7766 : swiper.slides.indexOf(slideEl)) === swiper.activeIndex; 7767 const isVisible = swiper.params.watchSlidesProgress && 7768 swiper.visibleSlides && 7769 swiper.visibleSlides.includes(slideEl); 7770 if (isActive || isVisible) 7771 return; 7772 const sourceCapabilities = e.sourceCapabilities; 7773 if (sourceCapabilities && sourceCapabilities.firesTouchEvents) 7774 return; 7775 if (swiper.isHorizontal()) { 7776 swiper.el.scrollLeft = 0; 7777 } 7778 else { 7779 swiper.el.scrollTop = 0; 7780 } 7781 requestAnimationFrame(() => { 7782 if (preventFocusHandler) 7783 return; 7784 if (swiper.params.loop) { 7785 swiper.slideToLoop(swiper.getSlideIndexWhenGrid(parseInt(slideEl.getAttribute('data-swiper-slide-index') || '0', 10)), 0); 7786 } 7787 else if (isVirtual) { 7788 swiper.slideTo(swiper.getSlideIndexWhenGrid(parseInt(slideEl.getAttribute('data-swiper-slide-index') || '0', 10)), 0); 7789 } 7790 else { 7791 swiper.slideTo(swiper.getSlideIndexWhenGrid(swiper.slides.indexOf(slideEl)), 0); 7792 } 7793 preventFocusHandler = false; 7794 }); 7795 }; 7796 const initSlides = () => { 7797 const params = getParams(); 7798 if (params.itemRoleDescriptionMessage) { 7799 addElRoleDescription(swiper.slides, params.itemRoleDescriptionMessage); 7800 } 7801 if (params.slideRole) { 7802 addElRole(swiper.slides, params.slideRole); 7803 } 7804 const slidesLength = swiper.slides.length; 7805 const slideLabelMessage = params.slideLabelMessage; 7806 if (slideLabelMessage) { 7807 swiper.slides.forEach((slideEl, index) => { 7808 const slideIndex = swiper.params.loop 7809 ? parseInt(slideEl.getAttribute('data-swiper-slide-index') || '0', 10) 7810 : index; 7811 const ariaLabelMessage = slideLabelMessage 7812 .replace(/\{\{index\}\}/, String(slideIndex + 1)) 7813 .replace(/\{\{slidesLength\}\}/, String(slidesLength)); 7814 addElLabel(slideEl, ariaLabelMessage); 7815 }); 7816 } 7817 }; 7818 const init = () => { 7819 const params = getParams(); 7820 if (liveRegion) 7821 swiper.el.append(liveRegion); 7822 // Container 7823 const containerEl = swiper.el; 7824 if (params.containerRoleDescriptionMessage) { 7825 addElRoleDescription(containerEl, params.containerRoleDescriptionMessage); 7826 } 7827 if (params.containerMessage) { 7828 addElLabel(containerEl, params.containerMessage); 7829 } 7830 if (params.containerRole) { 7831 addElRole(containerEl, params.containerRole); 7832 } 7833 // Wrapper 7834 const wrapperEl = swiper.wrapperEl; 7835 const wrapperId = String(params.id || wrapperEl.getAttribute('id') || `swiper-wrapper-${getRandomNumber(16)}`); 7836 addElId(wrapperEl, wrapperId); 7837 if (params.wrapperLiveRegion) { 7838 const autoplayParams = swiper.params.autoplay; 7839 const live = swiper.params.autoplay && autoplayParams?.enabled ? 'off' : 'polite'; 7840 addElLive(wrapperEl, live); 7841 } 7842 // Slide 7843 initSlides(); 7844 // Navigation 7845 const nav = swiper.navigation 7846 ? swiper.navigation 7847 : { nextEl: undefined, prevEl: undefined }; 7848 const nextEls = makeElementsArray(nav.nextEl); 7849 const prevEls = makeElementsArray(nav.prevEl); 7850 if (nextEls) { 7851 nextEls.forEach((el) => initNavEl(el, wrapperId, params.nextSlideMessage)); 7852 } 7853 if (prevEls) { 7854 prevEls.forEach((el) => initNavEl(el, wrapperId, params.prevSlideMessage)); 7855 } 7856 // Pagination 7857 if (hasClickablePagination()) { 7858 const paginationEl = makeElementsArray(swiper.pagination.el); 7859 paginationEl.forEach((el) => { 7860 el.addEventListener('keydown', onEnterOrSpaceKey); 7861 }); 7862 } 7863 // Tab focus 7864 document.addEventListener('visibilitychange', onVisibilityChange); 7865 swiper.el.addEventListener('focus', handleFocus, true); 7866 swiper.el.addEventListener('pointerdown', handlePointerDown, true); 7867 swiper.el.addEventListener('pointerup', handlePointerUp, true); 7868 }; 7869 function destroy() { 7870 if (liveRegion) 7871 liveRegion.remove(); 7872 const nav = swiper.navigation 7873 ? swiper.navigation 7874 : { nextEl: undefined, prevEl: undefined }; 7875 const nextEls = makeElementsArray(nav.nextEl); 7876 const prevEls = makeElementsArray(nav.prevEl); 7877 if (nextEls) { 7878 nextEls.forEach((el) => el.removeEventListener('keydown', onEnterOrSpaceKey)); 7879 } 7880 if (prevEls) { 7881 prevEls.forEach((el) => el.removeEventListener('keydown', onEnterOrSpaceKey)); 7882 } 7883 // Pagination 7884 if (hasClickablePagination()) { 7885 const paginationEl = makeElementsArray(swiper.pagination.el); 7886 paginationEl.forEach((el) => { 7887 el.removeEventListener('keydown', onEnterOrSpaceKey); 7888 }); 7889 } 7890 document.removeEventListener('visibilitychange', onVisibilityChange); 7891 // Tab focus 7892 if (swiper.el && typeof swiper.el !== 'string') { 7893 swiper.el.removeEventListener('focus', handleFocus, true); 7894 swiper.el.removeEventListener('pointerdown', handlePointerDown, true); 7895 swiper.el.removeEventListener('pointerup', handlePointerUp, true); 7896 } 7897 } 7898 on('beforeInit', () => { 7899 liveRegion = createElement('span', getParams().notificationClass); 7900 liveRegion.setAttribute('aria-live', 'assertive'); 7901 liveRegion.setAttribute('aria-atomic', 'true'); 7902 }); 7903 on('afterInit', () => { 7904 if (!getParams().enabled) 7905 return; 7906 init(); 7907 }); 7908 on('slidesLengthChange snapGridLengthChange slidesGridLengthChange', () => { 7909 if (!getParams().enabled) 7910 return; 7911 initSlides(); 7912 }); 7913 on('fromEdge toEdge afterInit lock unlock', () => { 7914 if (!getParams().enabled) 7915 return; 7916 updateNavigation(); 7917 }); 7918 on('paginationUpdate', () => { 7919 if (!getParams().enabled) 7920 return; 7921 updatePagination(); 7922 }); 7923 on('destroy', () => { 7924 if (!getParams().enabled) 7925 return; 7926 destroy(); 7927 }); 7928 }; 7929 7930 const History = ({ swiper, extendParams, on }) => { 7931 extendParams({ 7932 history: { 7933 enabled: false, 7934 root: '', 7935 replaceState: false, 7936 key: 'slides', 7937 keepQuery: false, 7938 }, 7939 }); 7940 let initialized = false; 7941 let paths = { key: undefined, value: undefined }; 7942 function getParams() { 7943 return swiper.params.history; 7944 } 7945 const slugify = (text) => { 7946 return text 7947 .toString() 7948 .replace(/\s+/g, '-') 7949 .replace(/[^\w-]+/g, '') 7950 .replace(/--+/g, '-') 7951 .replace(/^-+/, '') 7952 .replace(/-+$/, ''); 7953 }; 7954 const getPathValues = (urlOverride) => { 7955 let location; 7956 if (urlOverride) { 7957 location = new URL(urlOverride); 7958 } 7959 else { 7960 location = window.location; 7961 } 7962 const pathArray = location.pathname 7963 .slice(1) 7964 .split('/') 7965 .filter((part) => part !== ''); 7966 const total = pathArray.length; 7967 const key = pathArray[total - 2]; 7968 const value = pathArray[total - 1]; 7969 return { key, value }; 7970 }; 7971 const setHistory = (key, index) => { 7972 const params = getParams(); 7973 if (!initialized || !params.enabled) 7974 return; 7975 let location; 7976 if (swiper.params.url) { 7977 location = new URL(swiper.params.url); 7978 } 7979 else { 7980 location = window.location; 7981 } 7982 const isVirtualEnabled = !!swiper.params.virtual 7983 ?.enabled; 7984 const slide = swiper.virtual && isVirtualEnabled 7985 ? swiper.slidesEl.querySelector(`[data-swiper-slide-index="${index}"]`) 7986 : swiper.slides[index]; 7987 if (!slide) 7988 return; 7989 let value = slugify(slide.getAttribute('data-history') || ''); 7990 const root = params.root; 7991 if (root.length > 0) { 7992 const trimmedRoot = root[root.length - 1] === '/' ? root.slice(0, root.length - 1) : root; 7993 value = `${trimmedRoot}/${key ? `${key}/` : ''}${value}`; 7994 } 7995 else if (!location.pathname.includes(key || '')) { 7996 value = `${key ? `${key}/` : ''}${value}`; 7997 } 7998 if (params.keepQuery) { 7999 value += location.search; 8000 } 8001 const currentState = window.history.state; 8002 if (currentState && currentState.value === value) { 8003 return; 8004 } 8005 if (params.replaceState) { 8006 window.history.replaceState({ value }, '', value); 8007 } 8008 else { 8009 window.history.pushState({ value }, '', value); 8010 } 8011 }; 8012 const scrollToSlide = (speed, value, runCallbacks) => { 8013 if (value) { 8014 for (let i = 0, length = swiper.slides.length; i < length; i += 1) { 8015 const slide = swiper.slides[i]; 8016 const slideHistory = slugify(slide.getAttribute('data-history') || ''); 8017 if (slideHistory === value) { 8018 const index = swiper.getSlideIndex(slide); 8019 swiper.slideTo(index, speed, runCallbacks); 8020 } 8021 } 8022 } 8023 else { 8024 swiper.slideTo(0, speed, runCallbacks); 8025 } 8026 }; 8027 const setHistoryPopState = () => { 8028 paths = getPathValues(swiper.params.url); 8029 scrollToSlide(swiper.params.speed, paths.value, false); 8030 }; 8031 const init = () => { 8032 const params = swiper.params.history; 8033 if (!params) 8034 return; 8035 if (!window.history || !window.history.pushState) { 8036 params.enabled = false; 8037 const hashParams = swiper.params.hashNavigation; 8038 if (hashParams) 8039 hashParams.enabled = true; 8040 return; 8041 } 8042 initialized = true; 8043 paths = getPathValues(swiper.params.url); 8044 if (!paths.key && !paths.value) { 8045 if (!params.replaceState) { 8046 window.addEventListener('popstate', setHistoryPopState); 8047 } 8048 return; 8049 } 8050 scrollToSlide(0, paths.value, swiper.params.runCallbacksOnInit); 8051 if (!params.replaceState) { 8052 window.addEventListener('popstate', setHistoryPopState); 8053 } 8054 }; 8055 const destroy = () => { 8056 if (!getParams().replaceState) { 8057 window.removeEventListener('popstate', setHistoryPopState); 8058 } 8059 }; 8060 on('init', () => { 8061 if (getParams().enabled) { 8062 init(); 8063 } 8064 }); 8065 on('destroy', () => { 8066 if (getParams().enabled) { 8067 destroy(); 8068 } 8069 }); 8070 on('transitionEnd _freeModeNoMomentumRelease', () => { 8071 if (initialized) { 8072 setHistory(getParams().key, swiper.activeIndex); 8073 } 8074 }); 8075 on('slideChange', () => { 8076 if (initialized && swiper.params.cssMode) { 8077 setHistory(getParams().key, swiper.activeIndex); 8078 } 8079 }); 8080 }; 8081 8082 const isVirtualEnabled = (swiper) => !!swiper.virtual && !!swiper.params.virtual?.enabled; 8083 const HashNavigation = ({ swiper, extendParams, emit, on }) => { 8084 let initialized = false; 8085 extendParams({ 8086 hashNavigation: { 8087 enabled: false, 8088 replaceState: false, 8089 watchState: false, 8090 getSlideIndex(_s, hash) { 8091 if (isVirtualEnabled(swiper)) { 8092 const slideWithHash = swiper.slides.find((slideEl) => slideEl.getAttribute('data-hash') === hash); 8093 if (!slideWithHash) 8094 return 0; 8095 const index = parseInt(slideWithHash.getAttribute('data-swiper-slide-index') || '0', 10); 8096 return index; 8097 } 8098 const matched = elementChildren(swiper.slidesEl, `.${swiper.params.slideClass}[data-hash="${hash}"], swiper-slide[data-hash="${hash}"]`)[0]; 8099 return matched ? swiper.getSlideIndex(matched) : 0; 8100 }, 8101 }, 8102 }); 8103 function getParams() { 8104 return swiper.params.hashNavigation; 8105 } 8106 const onHashChange = () => { 8107 emit('hashChange'); 8108 const newHash = document.location.hash.replace('#', ''); 8109 const activeSlideEl = isVirtualEnabled(swiper) 8110 ? swiper.slidesEl.querySelector(`[data-swiper-slide-index="${swiper.activeIndex}"]`) 8111 : swiper.slides[swiper.activeIndex]; 8112 const activeSlideHash = activeSlideEl ? activeSlideEl.getAttribute('data-hash') : ''; 8113 if (newHash !== activeSlideHash) { 8114 const newIndex = getParams().getSlideIndex(swiper, newHash); 8115 if (typeof newIndex === 'undefined' || Number.isNaN(newIndex)) 8116 return; 8117 swiper.slideTo(newIndex); 8118 } 8119 }; 8120 const setHash = () => { 8121 const params = getParams(); 8122 if (!initialized || !params.enabled) 8123 return; 8124 const activeSlideEl = isVirtualEnabled(swiper) 8125 ? swiper.slidesEl.querySelector(`[data-swiper-slide-index="${swiper.activeIndex}"]`) 8126 : swiper.slides[swiper.activeIndex]; 8127 const activeSlideHash = activeSlideEl 8128 ? activeSlideEl.getAttribute('data-hash') || activeSlideEl.getAttribute('data-history') 8129 : ''; 8130 if (params.replaceState && window.history && window.history.replaceState) { 8131 window.history.replaceState(null, '', `#${activeSlideHash}` || ''); 8132 emit('hashSet'); 8133 } 8134 else { 8135 document.location.hash = activeSlideHash || ''; 8136 emit('hashSet'); 8137 } 8138 }; 8139 const init = () => { 8140 const params = getParams(); 8141 const historyParams = swiper.params.history; 8142 if (!params.enabled || (historyParams && historyParams.enabled)) 8143 return; 8144 initialized = true; 8145 const hash = document.location.hash.replace('#', ''); 8146 if (hash) { 8147 const speed = 0; 8148 const index = params.getSlideIndex(swiper, hash); 8149 swiper.slideTo(index || 0, speed, swiper.params.runCallbacksOnInit, true); 8150 } 8151 if (params.watchState) { 8152 window.addEventListener('hashchange', onHashChange); 8153 } 8154 }; 8155 const destroy = () => { 8156 if (getParams().watchState) { 8157 window.removeEventListener('hashchange', onHashChange); 8158 } 8159 }; 8160 on('init', () => { 8161 if (getParams().enabled) { 8162 init(); 8163 } 8164 }); 8165 on('destroy', () => { 8166 if (getParams().enabled) { 8167 destroy(); 8168 } 8169 }); 8170 on('transitionEnd _freeModeNoMomentumRelease', () => { 8171 if (initialized) { 8172 setHash(); 8173 } 8174 }); 8175 on('slideChange', () => { 8176 if (initialized && swiper.params.cssMode) { 8177 setHash(); 8178 } 8179 }); 8180 }; 8181 8182 const Autoplay = ({ swiper, extendParams, on, emit, params }) => { 8183 swiper.autoplay = { 8184 running: false, 8185 paused: false, 8186 timeLeft: 0, 8187 }; 8188 extendParams({ 8189 autoplay: { 8190 enabled: false, 8191 delay: 3000, 8192 waitForTransition: true, 8193 disableOnInteraction: false, 8194 stopOnLastSlide: false, 8195 reverseDirection: false, 8196 pauseOnMouseEnter: false, 8197 }, 8198 }); 8199 function getParams() { 8200 return swiper.params.autoplay; 8201 } 8202 // params here is the user-supplied passedParams; extendParams hasn't yet 8203 // merged the defaults into swiper.params.autoplay at this point. 8204 const initialAutoplayDelay = typeof params.autoplay === 'object' && 8205 params.autoplay && 8206 typeof params.autoplay.delay === 'number' 8207 ? params.autoplay.delay 8208 : 3000; 8209 let timeout; 8210 let raf; 8211 let autoplayDelayTotal = initialAutoplayDelay; 8212 let autoplayDelayCurrent = initialAutoplayDelay; 8213 let autoplayTimeLeft = 0; 8214 let autoplayStartTime = new Date().getTime(); 8215 let wasPaused = false; 8216 let isTouched = false; 8217 let pausedByTouch = false; 8218 let touchStartTimeout; 8219 let pausedByInteraction = false; 8220 let pausedByPointerEnter = false; 8221 function onTransitionEnd(e) { 8222 if (!swiper || swiper.destroyed || !swiper.wrapperEl) 8223 return; 8224 if (e.target !== swiper.wrapperEl) 8225 return; 8226 swiper.wrapperEl.removeEventListener('transitionend', onTransitionEnd); 8227 const detail = e.detail; 8228 if (pausedByPointerEnter || (detail && detail.bySwiperTouchMove)) { 8229 return; 8230 } 8231 resume(); 8232 } 8233 const calcTimeLeft = () => { 8234 if (swiper.destroyed || !swiper.autoplay.running) 8235 return; 8236 if (swiper.autoplay.paused) { 8237 wasPaused = true; 8238 } 8239 else if (wasPaused) { 8240 autoplayDelayCurrent = autoplayTimeLeft; 8241 wasPaused = false; 8242 } 8243 const timeLeft = swiper.autoplay.paused 8244 ? autoplayTimeLeft 8245 : autoplayStartTime + autoplayDelayCurrent - new Date().getTime(); 8246 swiper.autoplay.timeLeft = timeLeft; 8247 emit('autoplayTimeLeft', timeLeft, timeLeft / autoplayDelayTotal); 8248 raf = requestAnimationFrame(() => { 8249 calcTimeLeft(); 8250 }); 8251 }; 8252 const getSlideDelay = () => { 8253 let activeSlideEl; 8254 const virtualEnabled = !!swiper.params.virtual?.enabled; 8255 if (swiper.virtual && virtualEnabled) { 8256 activeSlideEl = swiper.slides.find((slideEl) => slideEl.classList.contains('swiper-slide-active')); 8257 } 8258 else { 8259 activeSlideEl = swiper.slides[swiper.activeIndex]; 8260 } 8261 if (!activeSlideEl) 8262 return undefined; 8263 const attr = activeSlideEl.getAttribute('data-swiper-autoplay'); 8264 if (attr == null) 8265 return undefined; 8266 return parseInt(attr, 10); 8267 }; 8268 const getTotalDelay = () => { 8269 let totalDelay = getParams().delay; 8270 const currentSlideDelay = getSlideDelay(); 8271 if (typeof currentSlideDelay === 'number' && 8272 !Number.isNaN(currentSlideDelay) && 8273 currentSlideDelay > 0) { 8274 totalDelay = currentSlideDelay; 8275 } 8276 return totalDelay; 8277 }; 8278 const run = (delayForce) => { 8279 if (swiper.destroyed || !swiper.autoplay.running) 8280 return 0; 8281 if (raf !== undefined) 8282 cancelAnimationFrame(raf); 8283 calcTimeLeft(); 8284 let delay = delayForce; 8285 if (typeof delay === 'undefined') { 8286 delay = getTotalDelay(); 8287 autoplayDelayTotal = delay; 8288 autoplayDelayCurrent = delay; 8289 } 8290 autoplayTimeLeft = delay; 8291 const speed = swiper.params.speed; 8292 const proceed = () => { 8293 if (!swiper || swiper.destroyed) 8294 return; 8295 const autoplayParams = getParams(); 8296 if (autoplayParams.reverseDirection) { 8297 if (!swiper.isBeginning || swiper.params.loop || swiper.params.rewind) { 8298 swiper.slidePrev(speed, true, true); 8299 emit('autoplay'); 8300 } 8301 else if (!autoplayParams.stopOnLastSlide) { 8302 swiper.slideTo(swiper.slides.length - 1, speed, true, true); 8303 emit('autoplay'); 8304 } 8305 } 8306 else { 8307 if (!swiper.isEnd || swiper.params.loop || swiper.params.rewind) { 8308 swiper.slideNext(speed, true, true); 8309 emit('autoplay'); 8310 } 8311 else if (!autoplayParams.stopOnLastSlide) { 8312 swiper.slideTo(0, speed, true, true); 8313 emit('autoplay'); 8314 } 8315 } 8316 if (swiper.params.cssMode) { 8317 autoplayStartTime = new Date().getTime(); 8318 requestAnimationFrame(() => { 8319 run(); 8320 }); 8321 } 8322 }; 8323 if (delay > 0) { 8324 if (timeout !== undefined) 8325 clearTimeout(timeout); 8326 timeout = setTimeout(() => { 8327 proceed(); 8328 }, delay); 8329 } 8330 else { 8331 requestAnimationFrame(() => { 8332 proceed(); 8333 }); 8334 } 8335 return delay; 8336 }; 8337 const start = () => { 8338 autoplayStartTime = new Date().getTime(); 8339 swiper.autoplay.running = true; 8340 run(); 8341 emit('autoplayStart'); 8342 return true; 8343 }; 8344 const stop = () => { 8345 swiper.autoplay.running = false; 8346 if (timeout !== undefined) 8347 clearTimeout(timeout); 8348 if (raf !== undefined) 8349 cancelAnimationFrame(raf); 8350 emit('autoplayStop'); 8351 return true; 8352 }; 8353 const pause = (internal, reset) => { 8354 if (swiper.destroyed || !swiper.autoplay.running) 8355 return; 8356 if (timeout !== undefined) 8357 clearTimeout(timeout); 8358 if (!internal) { 8359 pausedByInteraction = true; 8360 } 8361 const proceed = () => { 8362 emit('autoplayPause'); 8363 if (getParams().waitForTransition) { 8364 swiper.wrapperEl.addEventListener('transitionend', onTransitionEnd); 8365 } 8366 else { 8367 resume(); 8368 } 8369 }; 8370 swiper.autoplay.paused = true; 8371 if (reset) { 8372 proceed(); 8373 return; 8374 } 8375 const delay = autoplayTimeLeft || getParams().delay; 8376 autoplayTimeLeft = delay - (new Date().getTime() - autoplayStartTime); 8377 if (swiper.isEnd && autoplayTimeLeft < 0 && !swiper.params.loop) 8378 return; 8379 if (autoplayTimeLeft < 0) 8380 autoplayTimeLeft = 0; 8381 proceed(); 8382 }; 8383 const resume = () => { 8384 if ((swiper.isEnd && autoplayTimeLeft < 0 && !swiper.params.loop) || 8385 swiper.destroyed || 8386 !swiper.autoplay.running) 8387 return; 8388 autoplayStartTime = new Date().getTime(); 8389 if (pausedByInteraction) { 8390 pausedByInteraction = false; 8391 run(autoplayTimeLeft); 8392 } 8393 else { 8394 run(); 8395 } 8396 swiper.autoplay.paused = false; 8397 emit('autoplayResume'); 8398 }; 8399 const onVisibilityChange = () => { 8400 if (swiper.destroyed || !swiper.autoplay.running) 8401 return; 8402 if (document.visibilityState === 'hidden') { 8403 pausedByInteraction = true; 8404 pause(true); 8405 } 8406 if (document.visibilityState === 'visible') { 8407 resume(); 8408 } 8409 }; 8410 const onPointerEnter = (e) => { 8411 if (e.pointerType !== 'mouse') 8412 return; 8413 pausedByInteraction = true; 8414 pausedByPointerEnter = true; 8415 if (swiper.animating || swiper.autoplay.paused) 8416 return; 8417 pause(true); 8418 }; 8419 const onPointerLeave = (e) => { 8420 if (e.pointerType !== 'mouse') 8421 return; 8422 pausedByPointerEnter = false; 8423 if (swiper.autoplay.paused) { 8424 resume(); 8425 } 8426 }; 8427 const attachMouseEvents = () => { 8428 if (getParams().pauseOnMouseEnter) { 8429 swiper.el.addEventListener('pointerenter', onPointerEnter); 8430 swiper.el.addEventListener('pointerleave', onPointerLeave); 8431 } 8432 }; 8433 const detachMouseEvents = () => { 8434 if (swiper.el && typeof swiper.el !== 'string') { 8435 swiper.el.removeEventListener('pointerenter', onPointerEnter); 8436 swiper.el.removeEventListener('pointerleave', onPointerLeave); 8437 } 8438 }; 8439 const attachDocumentEvents = () => { 8440 document.addEventListener('visibilitychange', onVisibilityChange); 8441 }; 8442 const detachDocumentEvents = () => { 8443 document.removeEventListener('visibilitychange', onVisibilityChange); 8444 }; 8445 on('init', () => { 8446 if (getParams().enabled) { 8447 attachMouseEvents(); 8448 attachDocumentEvents(); 8449 start(); 8450 } 8451 }); 8452 on('destroy', () => { 8453 detachMouseEvents(); 8454 detachDocumentEvents(); 8455 if (swiper.autoplay.running) { 8456 stop(); 8457 } 8458 }); 8459 on('_freeModeStaticRelease', () => { 8460 if (pausedByTouch || pausedByInteraction) { 8461 resume(); 8462 } 8463 }); 8464 on('_freeModeNoMomentumRelease', () => { 8465 if (!getParams().disableOnInteraction) { 8466 pause(true, true); 8467 } 8468 else { 8469 stop(); 8470 } 8471 }); 8472 on('beforeTransitionStart', (_s, _speed, internal) => { 8473 if (swiper.destroyed || !swiper.autoplay.running) 8474 return; 8475 if (internal || !getParams().disableOnInteraction) { 8476 pause(true, true); 8477 } 8478 else { 8479 stop(); 8480 } 8481 }); 8482 on('sliderFirstMove', () => { 8483 if (swiper.destroyed || !swiper.autoplay.running) 8484 return; 8485 if (getParams().disableOnInteraction) { 8486 stop(); 8487 return; 8488 } 8489 isTouched = true; 8490 pausedByTouch = false; 8491 pausedByInteraction = false; 8492 touchStartTimeout = setTimeout(() => { 8493 pausedByInteraction = true; 8494 pausedByTouch = true; 8495 pause(true); 8496 }, 200); 8497 }); 8498 on('touchEnd', () => { 8499 if (swiper.destroyed || !swiper.autoplay.running || !isTouched) 8500 return; 8501 if (touchStartTimeout !== undefined) 8502 clearTimeout(touchStartTimeout); 8503 if (timeout !== undefined) 8504 clearTimeout(timeout); 8505 if (getParams().disableOnInteraction) { 8506 pausedByTouch = false; 8507 isTouched = false; 8508 return; 8509 } 8510 if (pausedByTouch && swiper.params.cssMode) 8511 resume(); 8512 pausedByTouch = false; 8513 isTouched = false; 8514 }); 8515 on('slideChange', () => { 8516 if (swiper.destroyed || !swiper.autoplay.running) 8517 return; 8518 if (swiper.autoplay.paused) { 8519 autoplayTimeLeft = getTotalDelay(); 8520 autoplayDelayTotal = getTotalDelay(); 8521 } 8522 }); 8523 Object.assign(swiper.autoplay, { 8524 start, 8525 stop, 8526 pause, 8527 resume, 8528 }); 8529 }; 8530 8531 const Thumb = ({ swiper, extendParams, on }) => { 8532 extendParams({ 8533 thumbs: { 8534 swiper: null, 8535 multipleActiveThumbs: true, 8536 autoScrollOffset: 0, 8537 slideThumbActiveClass: 'swiper-slide-thumb-active', 8538 thumbsContainerClass: 'swiper-thumbs', 8539 }, 8540 }); 8541 let initialized = false; 8542 let swiperCreated = false; 8543 swiper.thumbs = { 8544 swiper: null, 8545 }; 8546 function getParams() { 8547 return swiper.params.thumbs; 8548 } 8549 function isVirtualEnabled() { 8550 const thumbsSwiper = swiper.thumbs.swiper; 8551 if (!thumbsSwiper || thumbsSwiper.destroyed) 8552 return false; 8553 const virtual = thumbsSwiper.params.virtual; 8554 return !!virtual && !!virtual.enabled; 8555 } 8556 function onThumbClick() { 8557 const thumbsSwiper = swiper.thumbs.swiper; 8558 if (!thumbsSwiper || thumbsSwiper.destroyed) 8559 return; 8560 const clickedIndex = thumbsSwiper.clickedIndex; 8561 const clickedSlide = thumbsSwiper.clickedSlide; 8562 const thumbsParams = getParams(); 8563 if (clickedSlide && clickedSlide.classList.contains(thumbsParams.slideThumbActiveClass)) 8564 return; 8565 if (typeof clickedIndex === 'undefined' || clickedIndex === null) 8566 return; 8567 let slideToIndex; 8568 if (thumbsSwiper.params.loop) { 8569 const attr = thumbsSwiper.clickedSlide?.getAttribute('data-swiper-slide-index'); 8570 slideToIndex = attr == null ? clickedIndex : parseInt(attr, 10); 8571 } 8572 else { 8573 slideToIndex = clickedIndex; 8574 } 8575 if (swiper.params.loop) { 8576 swiper.slideToLoop(slideToIndex); 8577 } 8578 else { 8579 swiper.slideTo(slideToIndex); 8580 } 8581 } 8582 function init() { 8583 const thumbsParams = getParams(); 8584 if (initialized) 8585 return false; 8586 initialized = true; 8587 const SwiperClass = swiper.constructor; 8588 if (thumbsParams.swiper instanceof SwiperClass) { 8589 if (thumbsParams.swiper.destroyed) { 8590 initialized = false; 8591 return false; 8592 } 8593 const thumbsSwiper = thumbsParams.swiper; 8594 swiper.thumbs.swiper = thumbsSwiper; 8595 Object.assign(thumbsSwiper.originalParams, { 8596 watchSlidesProgress: true, 8597 slideToClickedSlide: false, 8598 }); 8599 Object.assign(thumbsSwiper.params, { 8600 watchSlidesProgress: true, 8601 slideToClickedSlide: false, 8602 });
vendor: 6,134 bytes, lines 8603-8725
8603 thumbsSwiper.update(); 8604 } 8605 else if (isObject(thumbsParams.swiper)) { 8606 const thumbsSwiperParams = Object.assign({}, thumbsParams.swiper); 8607 Object.assign(thumbsSwiperParams, { 8608 watchSlidesProgress: true, 8609 slideToClickedSlide: false, 8610 }); 8611 swiper.thumbs.swiper = new SwiperClass(thumbsSwiperParams); 8612 swiperCreated = true; 8613 } 8614 const thumbsSwiper = swiper.thumbs.swiper; 8615 if (!thumbsSwiper) 8616 return false; 8617 thumbsSwiper.el.classList.add(thumbsParams.thumbsContainerClass); 8618 thumbsSwiper.on('tap', onThumbClick); 8619 if (isVirtualEnabled()) { 8620 thumbsSwiper.on('virtualUpdate', () => { 8621 update(false, { autoScroll: false }); 8622 }); 8623 } 8624 return true; 8625 } 8626 function update(initial, p) { 8627 const thumbsSwiper = swiper.thumbs.swiper; 8628 if (!thumbsSwiper || thumbsSwiper.destroyed) 8629 return; 8630 // Activate thumbs 8631 let thumbsToActivate = 1; 8632 const thumbsParams = getParams(); 8633 const thumbActiveClass = thumbsParams.slideThumbActiveClass; 8634 const slidesPerView = swiper.params.slidesPerView; 8635 if (typeof slidesPerView === 'number' && slidesPerView > 1 && !swiper.params.centeredSlides) { 8636 thumbsToActivate = slidesPerView; 8637 } 8638 if (!thumbsParams.multipleActiveThumbs) { 8639 thumbsToActivate = 1; 8640 } 8641 thumbsToActivate = Math.floor(thumbsToActivate); 8642 thumbsSwiper.slides.forEach((slideEl) => slideEl.classList.remove(thumbActiveClass)); 8643 if (thumbsSwiper.params.loop || isVirtualEnabled()) { 8644 for (let i = 0; i < thumbsToActivate; i += 1) { 8645 elementChildren(thumbsSwiper.slidesEl, `[data-swiper-slide-index="${swiper.realIndex + i}"]`).forEach((slideEl) => { 8646 slideEl.classList.add(thumbActiveClass); 8647 }); 8648 } 8649 } 8650 else { 8651 for (let i = 0; i < thumbsToActivate; i += 1) { 8652 const slide = thumbsSwiper.slides[swiper.realIndex + i]; 8653 if (slide) { 8654 slide.classList.add(thumbActiveClass); 8655 } 8656 } 8657 } 8658 if (p?.autoScroll ?? true) { 8659 autoScroll(initial ? 0 : undefined); 8660 } 8661 } 8662 function autoScroll(slideSpeed) { 8663 const thumbsSwiper = swiper.thumbs.swiper; 8664 if (!thumbsSwiper || thumbsSwiper.destroyed) 8665 return; 8666 const thumbsSlidesPerView = thumbsSwiper.params.slidesPerView; 8667 const slidesPerView = thumbsSlidesPerView === 'auto' 8668 ? thumbsSwiper.slidesPerViewDynamic() 8669 : (thumbsSlidesPerView ?? 1); 8670 const autoScrollOffset = getParams().autoScrollOffset; 8671 const useOffset = autoScrollOffset && !thumbsSwiper.params.loop; 8672 if (swiper.realIndex !== thumbsSwiper.realIndex || useOffset) { 8673 const currentThumbsIndex = thumbsSwiper.activeIndex; 8674 let newThumbsIndex; 8675 let direction; 8676 if (thumbsSwiper.params.loop) { 8677 const newThumbsSlide = thumbsSwiper.slides.find((slideEl) => slideEl.getAttribute('data-swiper-slide-index') === `${swiper.realIndex}`); 8678 newThumbsIndex = newThumbsSlide ? thumbsSwiper.slides.indexOf(newThumbsSlide) : -1; 8679 direction = swiper.activeIndex > swiper.previousIndex ? 'next' : 'prev'; 8680 } 8681 else { 8682 newThumbsIndex = swiper.realIndex; 8683 direction = newThumbsIndex > swiper.previousIndex ? 'next' : 'prev'; 8684 } 8685 if (useOffset) { 8686 newThumbsIndex += direction === 'next' ? autoScrollOffset : -1 * autoScrollOffset; 8687 } 8688 if (thumbsSwiper.visibleSlidesIndexes && 8689 thumbsSwiper.visibleSlidesIndexes.indexOf(newThumbsIndex) < 0) { 8690 if (thumbsSwiper.params.centeredSlides) { 8691 if (newThumbsIndex > currentThumbsIndex) { 8692 newThumbsIndex = newThumbsIndex - Math.floor(slidesPerView / 2) + 1; 8693 } 8694 else { 8695 newThumbsIndex = newThumbsIndex + Math.floor(slidesPerView / 2) - 1; 8696 } 8697 } 8698 else if (newThumbsIndex > currentThumbsIndex && 8699 thumbsSwiper.params.slidesPerGroup === 1) ; 8700 thumbsSwiper.slideTo(newThumbsIndex, slideSpeed); 8701 } 8702 } 8703 } 8704 on('beforeInit', () => { 8705 const thumbs = swiper.params.thumbs; 8706 if (!thumbs || !thumbs.swiper) 8707 return; 8708 if (typeof thumbs.swiper === 'string' || thumbs.swiper instanceof HTMLElement) { 8709 const getThumbsElementAndInit = () => { 8710 const thumbsElement = typeof thumbs.swiper === 'string' 8711 ? document.querySelector(thumbs.swiper) 8712 : thumbs.swiper; 8713 if (thumbsElement && thumbsElement.swiper) { 8714 thumbs.swiper = thumbsElement.swiper; 8715 init(); 8716 update(true); 8717 } 8718 else if (thumbsElement) { 8719 const eventName = `${swiper.params.eventsPrefix}init`; 8720 const onThumbsSwiper = (e) => { 8721 const detail = e.detail; 8722 thumbs.swiper = detail[0]; 8723 thumbsElement.removeEventListener(eventName, onThumbsSwiper); 8724 init(); 8725 update(true);
vendor: 30,707 bytes, lines 8726-9474
8726 thumbs.swiper.update(); 8727 swiper.update(); 8728 }; 8729 thumbsElement.addEventListener(eventName, onThumbsSwiper); 8730 } 8731 return thumbsElement; 8732 }; 8733 const watchForThumbsToAppear = () => { 8734 if (swiper.destroyed) 8735 return; 8736 const thumbsElement = getThumbsElementAndInit(); 8737 if (!thumbsElement) { 8738 requestAnimationFrame(watchForThumbsToAppear); 8739 } 8740 }; 8741 requestAnimationFrame(watchForThumbsToAppear); 8742 } 8743 else { 8744 init(); 8745 update(true); 8746 } 8747 }); 8748 on('slideChange update resize observerUpdate', () => { 8749 update(); 8750 }); 8751 on('setTransition', (_s, duration) => { 8752 const thumbsSwiper = swiper.thumbs.swiper; 8753 if (!thumbsSwiper || thumbsSwiper.destroyed) 8754 return; 8755 thumbsSwiper.setTransition(duration); 8756 }); 8757 on('beforeDestroy', () => { 8758 const thumbsSwiper = swiper.thumbs.swiper; 8759 if (!thumbsSwiper || thumbsSwiper.destroyed) 8760 return; 8761 if (swiperCreated) { 8762 thumbsSwiper.destroy(); 8763 } 8764 }); 8765 Object.assign(swiper.thumbs, { 8766 init, 8767 update, 8768 }); 8769 }; 8770 8771 const FreeMode = ({ swiper, extendParams, emit, once }) => { 8772 extendParams({ 8773 freeMode: { 8774 enabled: false, 8775 momentum: true, 8776 momentumRatio: 1, 8777 momentumBounce: true, 8778 momentumBounceRatio: 1, 8779 momentumVelocityRatio: 1, 8780 sticky: false, 8781 minimumVelocity: 0.02, 8782 }, 8783 }); 8784 function getParams() { 8785 return swiper.params.freeMode; 8786 } 8787 function onTouchStart() { 8788 if (swiper.params.cssMode) 8789 return; 8790 const translate = swiper.getTranslate(); 8791 swiper.setTranslate(translate); 8792 swiper.setTransition(0); 8793 swiper.touchEventsData.velocities.length = 0; 8794 swiper.freeMode.onTouchEnd({ currentPos: swiper.rtl ? swiper.translate : -swiper.translate }); 8795 } 8796 function onTouchMove() { 8797 if (swiper.params.cssMode) 8798 return; 8799 const { touchEventsData: data, touches } = swiper; 8800 // Velocity 8801 if (data.velocities.length === 0) { 8802 data.velocities.push({ 8803 position: touches[swiper.isHorizontal() ? 'startX' : 'startY'], 8804 time: data.touchStartTime ?? now(), 8805 }); 8806 } 8807 data.velocities.push({ 8808 position: touches[swiper.isHorizontal() ? 'currentX' : 'currentY'], 8809 time: now(), 8810 }); 8811 } 8812 function onTouchEnd({ currentPos }) { 8813 if (swiper.params.cssMode) 8814 return; 8815 const { wrapperEl, rtlTranslate: rtl, snapGrid, touchEventsData: data } = swiper; 8816 const params = swiper.params; 8817 const freeModeParams = getParams(); 8818 // Time diff 8819 const touchEndTime = now(); 8820 const timeDiff = touchEndTime - (data.touchStartTime ?? touchEndTime); 8821 if (currentPos < -swiper.minTranslate()) { 8822 swiper.slideTo(swiper.activeIndex); 8823 return; 8824 } 8825 if (currentPos > -swiper.maxTranslate()) { 8826 if (swiper.slides.length < snapGrid.length) { 8827 swiper.slideTo(snapGrid.length - 1); 8828 } 8829 else { 8830 swiper.slideTo(swiper.slides.length - 1); 8831 } 8832 return; 8833 } 8834 if (freeModeParams.momentum) { 8835 if (data.velocities.length > 1) { 8836 const lastMoveEvent = data.velocities.pop(); 8837 const velocityEvent = data.velocities.pop(); 8838 const distance = lastMoveEvent.position - velocityEvent.position; 8839 const time = lastMoveEvent.time - velocityEvent.time; 8840 swiper.velocity = distance / time; 8841 swiper.velocity /= 2; 8842 if (Math.abs(swiper.velocity) < freeModeParams.minimumVelocity) { 8843 swiper.velocity = 0; 8844 } 8845 // this implies that the user stopped moving a finger then released. 8846 // There would be no events with distance zero, so the last event is stale. 8847 if (time > 150 || now() - lastMoveEvent.time > 300) { 8848 swiper.velocity = 0; 8849 } 8850 } 8851 else { 8852 swiper.velocity = 0; 8853 } 8854 swiper.velocity *= freeModeParams.momentumVelocityRatio; 8855 data.velocities.length = 0; 8856 let momentumDuration = 1000 * freeModeParams.momentumRatio; 8857 const momentumDistance = swiper.velocity * momentumDuration; 8858 let newPosition = swiper.translate + momentumDistance; 8859 if (rtl) 8860 newPosition = -newPosition; 8861 let doBounce = false; 8862 let afterBouncePosition; 8863 const bounceAmount = Math.abs(swiper.velocity) * 20 * freeModeParams.momentumBounceRatio; 8864 let needsLoopFix = false; 8865 if (newPosition < swiper.maxTranslate()) { 8866 if (freeModeParams.momentumBounce) { 8867 if (newPosition + swiper.maxTranslate() < -bounceAmount) { 8868 newPosition = swiper.maxTranslate() - bounceAmount; 8869 } 8870 afterBouncePosition = swiper.maxTranslate(); 8871 doBounce = true; 8872 data.allowMomentumBounce = true; 8873 } 8874 else { 8875 newPosition = swiper.maxTranslate(); 8876 } 8877 if (params.loop && params.centeredSlides) 8878 needsLoopFix = true; 8879 } 8880 else if (newPosition > swiper.minTranslate()) { 8881 if (freeModeParams.momentumBounce) { 8882 if (newPosition - swiper.minTranslate() > bounceAmount) { 8883 newPosition = swiper.minTranslate() + bounceAmount; 8884 } 8885 afterBouncePosition = swiper.minTranslate(); 8886 doBounce = true; 8887 data.allowMomentumBounce = true; 8888 } 8889 else { 8890 newPosition = swiper.minTranslate(); 8891 } 8892 if (params.loop && params.centeredSlides) 8893 needsLoopFix = true; 8894 } 8895 else if (freeModeParams.sticky) { 8896 let nextSlide = 0; 8897 for (let j = 0; j < snapGrid.length; j += 1) { 8898 if (snapGrid[j] > -newPosition) { 8899 nextSlide = j; 8900 break; 8901 } 8902 } 8903 if (Math.abs(snapGrid[nextSlide] - newPosition) < 8904 Math.abs((snapGrid[nextSlide - 1] ?? snapGrid[nextSlide]) - newPosition) || 8905 swiper.swipeDirection === 'next') { 8906 newPosition = snapGrid[nextSlide]; 8907 } 8908 else { 8909 newPosition = snapGrid[nextSlide - 1]; 8910 } 8911 newPosition = -newPosition; 8912 } 8913 if (needsLoopFix) { 8914 once('transitionEnd', () => { 8915 swiper.loopFix(); 8916 }); 8917 } 8918 // Fix duration 8919 if (swiper.velocity !== 0) { 8920 if (rtl) { 8921 momentumDuration = Math.abs((-newPosition - swiper.translate) / swiper.velocity); 8922 } 8923 else { 8924 momentumDuration = Math.abs((newPosition - swiper.translate) / swiper.velocity); 8925 } 8926 if (freeModeParams.sticky) { 8927 // If freeMode.sticky is active and the user ends a swipe with a slow-velocity 8928 // event, then durations can be 20+ seconds to slide one (or zero!) slides. 8929 // It's easy to see this when simulating touch with mouse events. To fix this, 8930 // limit single-slide swipes to the default slide duration. This also has the 8931 // nice side effect of matching slide speed if the user stopped moving before 8932 // lifting finger or mouse vs. moving slowly before lifting the finger/mouse. 8933 // For faster swipes, also apply limits (albeit higher ones). 8934 const moveDistance = Math.abs((rtl ? -newPosition : newPosition) - swiper.translate); 8935 const currentSlideSize = swiper.slidesSizesGrid[swiper.activeIndex]; 8936 const speed = params.speed; 8937 if (moveDistance < currentSlideSize) { 8938 momentumDuration = speed; 8939 } 8940 else if (moveDistance < 2 * currentSlideSize) { 8941 momentumDuration = speed * 1.5; 8942 } 8943 else { 8944 momentumDuration = speed * 2.5; 8945 } 8946 } 8947 } 8948 else if (freeModeParams.sticky) { 8949 swiper.slideToClosest(); 8950 return; 8951 } 8952 if (freeModeParams.momentumBounce && doBounce && afterBouncePosition !== undefined) { 8953 swiper.updateProgress(afterBouncePosition); 8954 swiper.setTransition(momentumDuration); 8955 swiper.setTranslate(newPosition); 8956 swiper.transitionStart(true, swiper.swipeDirection); 8957 swiper.animating = true; 8958 elementTransitionEnd(wrapperEl, () => { 8959 if (!swiper || swiper.destroyed || !data.allowMomentumBounce) 8960 return; 8961 emit('momentumBounce'); 8962 swiper.setTransition(params.speed); 8963 setTimeout(() => { 8964 swiper.setTranslate(afterBouncePosition); 8965 elementTransitionEnd(wrapperEl, () => { 8966 if (!swiper || swiper.destroyed) 8967 return; 8968 swiper.transitionEnd(); 8969 }); 8970 }, 0); 8971 }); 8972 } 8973 else if (swiper.velocity) { 8974 emit('_freeModeNoMomentumRelease'); 8975 swiper.updateProgress(newPosition); 8976 swiper.setTransition(momentumDuration); 8977 swiper.setTranslate(newPosition); 8978 swiper.transitionStart(true, swiper.swipeDirection); 8979 if (!swiper.animating) { 8980 swiper.animating = true; 8981 elementTransitionEnd(wrapperEl, () => { 8982 if (!swiper || swiper.destroyed) 8983 return; 8984 swiper.transitionEnd(); 8985 }); 8986 } 8987 } 8988 else { 8989 swiper.updateProgress(newPosition); 8990 } 8991 swiper.updateActiveIndex(); 8992 swiper.updateSlidesClasses(); 8993 } 8994 else if (freeModeParams.sticky) { 8995 swiper.slideToClosest(); 8996 return; 8997 } 8998 else { 8999 emit('_freeModeNoMomentumRelease'); 9000 } 9001 if (!freeModeParams.momentum || timeDiff >= params.longSwipesMs) { 9002 emit('_freeModeStaticRelease'); 9003 swiper.updateProgress(); 9004 swiper.updateActiveIndex(); 9005 swiper.updateSlidesClasses(); 9006 } 9007 } 9008 swiper.freeMode = { 9009 onTouchStart, 9010 onTouchMove, 9011 onTouchEnd, 9012 }; 9013 }; 9014 9015 const Grid = ({ swiper, extendParams, on }) => { 9016 extendParams({ 9017 grid: { 9018 rows: 1, 9019 fill: 'column', 9020 }, 9021 }); 9022 function getParams() { 9023 return swiper.params.grid; 9024 } 9025 let slidesNumberEvenToRows; 9026 let slidesPerRow; 9027 let numFullColumns; 9028 let wasMultiRow; 9029 const getSpaceBetween = () => { 9030 let spaceBetween = swiper.params.spaceBetween ?? 0; 9031 if (typeof spaceBetween === 'string' && spaceBetween.indexOf('%') >= 0) { 9032 spaceBetween = (parseFloat(spaceBetween.replace('%', '')) / 100) * swiper.size; 9033 } 9034 else if (typeof spaceBetween === 'string') { 9035 spaceBetween = parseFloat(spaceBetween); 9036 } 9037 return spaceBetween; 9038 }; 9039 const isVirtualEnabled = () => { 9040 const virtualParams = swiper.params.virtual; 9041 return (!!swiper.virtual && 9042 typeof virtualParams === 'object' && 9043 virtualParams !== null && 9044 !!virtualParams.enabled); 9045 }; 9046 const initSlides = (slides) => { 9047 const { slidesPerView } = swiper.params; 9048 const { rows, fill } = getParams(); 9049 const slidesLength = isVirtualEnabled() ? swiper.virtual.slides.length : slides.length; 9050 numFullColumns = Math.floor(slidesLength / rows); 9051 if (Math.floor(slidesLength / rows) === slidesLength / rows) { 9052 slidesNumberEvenToRows = slidesLength; 9053 } 9054 else { 9055 slidesNumberEvenToRows = Math.ceil(slidesLength / rows) * rows; 9056 } 9057 if (slidesPerView !== 'auto' && fill === 'row') { 9058 slidesNumberEvenToRows = Math.max(slidesNumberEvenToRows, Math.floor(slidesPerView ?? 1) * rows); 9059 } 9060 slidesPerRow = slidesNumberEvenToRows / rows; 9061 }; 9062 const unsetSlides = () => { 9063 if (swiper.slides) { 9064 swiper.slides.forEach((slide) => { 9065 const gridSlide = slide; 9066 if (gridSlide.swiperSlideGridSet) { 9067 slide.style.height = ''; 9068 slide.style.setProperty(swiper.getDirectionLabel('margin-top'), ''); 9069 } 9070 }); 9071 } 9072 }; 9073 const updateSlide = (i, slide, slides) => { 9074 const { slidesPerGroup } = swiper.params; 9075 const spaceBetween = getSpaceBetween(); 9076 const { rows, fill } = getParams(); 9077 const slidesLength = isVirtualEnabled() ? swiper.virtual.slides.length : slides.length; 9078 // Set slides order 9079 let newSlideOrderIndex; 9080 let column; 9081 let row; 9082 if (fill === 'row' && (slidesPerGroup ?? 1) > 1) { 9083 const groupsPer = slidesPerGroup ?? 1; 9084 const groupIndex = Math.floor(i / (groupsPer * rows)); 9085 const slideIndexInGroup = i - rows * groupsPer * groupIndex; 9086 const columnsInGroup = groupIndex === 0 9087 ? groupsPer 9088 : Math.min(Math.ceil((slidesLength - groupIndex * rows * groupsPer) / rows), groupsPer); 9089 row = Math.floor(slideIndexInGroup / columnsInGroup); 9090 column = slideIndexInGroup - row * columnsInGroup + groupIndex * groupsPer; 9091 newSlideOrderIndex = column + (row * slidesNumberEvenToRows) / rows; 9092 slide.style.order = String(newSlideOrderIndex); 9093 } 9094 else if (fill === 'column') { 9095 column = Math.floor(i / rows); 9096 row = i - column * rows; 9097 if (column > numFullColumns || (column === numFullColumns && row === rows - 1)) { 9098 row += 1; 9099 if (row >= rows) { 9100 row = 0; 9101 column += 1; 9102 } 9103 } 9104 } 9105 else { 9106 row = Math.floor(i / slidesPerRow); 9107 column = i - row * slidesPerRow; 9108 } 9109 const gridSlide = slide; 9110 gridSlide.row = row; 9111 gridSlide.column = column; 9112 slide.style.height = `calc((100% - ${(rows - 1) * spaceBetween}px) / ${rows})`; 9113 slide.style.setProperty(swiper.getDirectionLabel('margin-top'), row !== 0 && spaceBetween ? `${spaceBetween}px` : ''); 9114 gridSlide.swiperSlideGridSet = true; 9115 }; 9116 const updateWrapperSize = (slideSize, snapGrid) => { 9117 const { centeredSlides, roundLengths } = swiper.params; 9118 const spaceBetween = getSpaceBetween(); 9119 const { rows } = getParams(); 9120 swiper.virtualSize = (slideSize + spaceBetween) * slidesNumberEvenToRows; 9121 swiper.virtualSize = Math.ceil(swiper.virtualSize / rows) - spaceBetween; 9122 if (!swiper.params.cssMode) { 9123 swiper.wrapperEl.style.setProperty(swiper.getDirectionLabel('width'), `${swiper.virtualSize + spaceBetween}px`); 9124 } 9125 if (centeredSlides) { 9126 const newSlidesGrid = []; 9127 for (let i = 0; i < snapGrid.length; i += 1) { 9128 let slidesGridItem = snapGrid[i]; 9129 if (roundLengths) 9130 slidesGridItem = Math.floor(slidesGridItem); 9131 if (snapGrid[i] < swiper.virtualSize + snapGrid[0]) 9132 newSlidesGrid.push(slidesGridItem); 9133 } 9134 snapGrid.splice(0, snapGrid.length); 9135 snapGrid.push(...newSlidesGrid); 9136 } 9137 }; 9138 const onInit = () => { 9139 const gridParams = swiper.params.grid; 9140 wasMultiRow = !!(gridParams && (gridParams.rows ?? 1) > 1); 9141 }; 9142 const onUpdate = () => { 9143 const { params, el } = swiper; 9144 const gridParams = params.grid; 9145 const isMultiRow = !!(gridParams && (gridParams.rows ?? 1) > 1); 9146 if (wasMultiRow && !isMultiRow) { 9147 el.classList.remove(`${params.containerModifierClass}grid`, `${params.containerModifierClass}grid-column`); 9148 numFullColumns = 1; 9149 swiper.emitContainerClasses(); 9150 } 9151 else if (!wasMultiRow && isMultiRow) { 9152 el.classList.add(`${params.containerModifierClass}grid`); 9153 if (gridParams.fill === 'column') { 9154 el.classList.add(`${params.containerModifierClass}grid-column`); 9155 } 9156 swiper.emitContainerClasses(); 9157 } 9158 wasMultiRow = isMultiRow; 9159 }; 9160 on('init', onInit); 9161 on('update', onUpdate); 9162 swiper.grid = { 9163 initSlides, 9164 unsetSlides, 9165 updateSlide, 9166 updateWrapperSize, 9167 }; 9168 }; 9169 9170 function addSlide(index, slides) { 9171 const swiper = this; 9172 const { params, activeIndex, slidesEl } = swiper; 9173 let activeIndexBuffer = activeIndex; 9174 if (params.loop) { 9175 activeIndexBuffer -= swiper.loopedSlides ?? 0; 9176 swiper.loopDestroy(); 9177 swiper.recalcSlides(); 9178 } 9179 const baseLength = swiper.slides.length; 9180 if (index <= 0) { 9181 swiper.prependSlide(slides); 9182 return; 9183 } 9184 if (index >= baseLength) { 9185 swiper.appendSlide(slides); 9186 return; 9187 } 9188 let newActiveIndex = activeIndexBuffer > index ? activeIndexBuffer + 1 : activeIndexBuffer; 9189 const slidesBuffer = []; 9190 for (let i = baseLength - 1; i >= index; i -= 1) { 9191 const currentSlide = swiper.slides[i]; 9192 if (!currentSlide) 9193 continue; 9194 currentSlide.remove(); 9195 slidesBuffer.unshift(currentSlide); 9196 } 9197 if (Array.isArray(slides)) { 9198 for (let i = 0; i < slides.length; i += 1) { 9199 const slide = slides[i]; 9200 if (slide) 9201 slidesEl.append(slide); 9202 } 9203 newActiveIndex = 9204 activeIndexBuffer > index ? activeIndexBuffer + slides.length : activeIndexBuffer; 9205 } 9206 else { 9207 slidesEl.append(slides); 9208 } 9209 for (let i = 0; i < slidesBuffer.length; i += 1) { 9210 slidesEl.append(slidesBuffer[i]); 9211 } 9212 swiper.recalcSlides(); 9213 if (params.loop) { 9214 swiper.loopCreate(); 9215 } 9216 if (!params.observer || swiper.isElement) { 9217 swiper.update(); 9218 } 9219 if (params.loop) { 9220 swiper.slideTo(newActiveIndex + (swiper.loopedSlides ?? 0), 0, false); 9221 } 9222 else { 9223 swiper.slideTo(newActiveIndex, 0, false); 9224 } 9225 } 9226 9227 function appendSlide(slides) { 9228 const swiper = this; 9229 const { params, slidesEl } = swiper; 9230 if (params.loop) { 9231 swiper.loopDestroy(); 9232 } 9233 const appendElement = (slideEl) => { 9234 if (typeof slideEl === 'string') { 9235 const tempDOM = document.createElement('div'); 9236 setInnerHTML(tempDOM, slideEl); 9237 const child = tempDOM.children[0]; 9238 if (child) 9239 slidesEl.append(child); 9240 setInnerHTML(tempDOM, ''); 9241 } 9242 else { 9243 slidesEl.append(slideEl); 9244 } 9245 }; 9246 if (Array.isArray(slides)) { 9247 for (let i = 0; i < slides.length; i += 1) { 9248 const slide = slides[i]; 9249 if (slide) 9250 appendElement(slide); 9251 } 9252 } 9253 else { 9254 appendElement(slides); 9255 } 9256 swiper.recalcSlides(); 9257 if (params.loop) { 9258 swiper.loopCreate(); 9259 } 9260 if (!params.observer || swiper.isElement) { 9261 swiper.update(); 9262 } 9263 } 9264 9265 function prependSlide(slides) { 9266 const swiper = this; 9267 const { params, activeIndex, slidesEl } = swiper; 9268 if (params.loop) { 9269 swiper.loopDestroy(); 9270 } 9271 let newActiveIndex = activeIndex + 1; 9272 const prependElement = (slideEl) => { 9273 if (typeof slideEl === 'string') { 9274 const tempDOM = document.createElement('div'); 9275 setInnerHTML(tempDOM, slideEl); 9276 const child = tempDOM.children[0]; 9277 if (child) 9278 slidesEl.prepend(child); 9279 setInnerHTML(tempDOM, ''); 9280 } 9281 else { 9282 slidesEl.prepend(slideEl); 9283 } 9284 }; 9285 if (Array.isArray(slides)) { 9286 for (let i = 0; i < slides.length; i += 1) { 9287 const slide = slides[i]; 9288 if (slide) 9289 prependElement(slide); 9290 } 9291 newActiveIndex = activeIndex + slides.length; 9292 } 9293 else { 9294 prependElement(slides); 9295 } 9296 swiper.recalcSlides(); 9297 if (params.loop) { 9298 swiper.loopCreate(); 9299 } 9300 if (!params.observer || swiper.isElement) { 9301 swiper.update(); 9302 } 9303 swiper.slideTo(newActiveIndex, 0, false); 9304 } 9305 9306 function removeAllSlides() { 9307 const swiper = this; 9308 const slidesIndexes = []; 9309 for (let i = 0; i < swiper.slides.length; i += 1) { 9310 slidesIndexes.push(i); 9311 } 9312 swiper.removeSlide(slidesIndexes); 9313 } 9314 9315 function removeSlide(slidesIndexes) { 9316 const swiper = this; 9317 const { params, activeIndex } = swiper; 9318 let activeIndexBuffer = activeIndex; 9319 if (params.loop) { 9320 activeIndexBuffer -= swiper.loopedSlides ?? 0; 9321 swiper.loopDestroy(); 9322 } 9323 let newActiveIndex = activeIndexBuffer; 9324 if (Array.isArray(slidesIndexes)) { 9325 for (let i = 0; i < slidesIndexes.length; i += 1) { 9326 const indexToRemove = slidesIndexes[i]; 9327 if (swiper.slides[indexToRemove]) 9328 swiper.slides[indexToRemove].remove(); 9329 if (indexToRemove < newActiveIndex) 9330 newActiveIndex -= 1; 9331 } 9332 newActiveIndex = Math.max(newActiveIndex, 0); 9333 } 9334 else { 9335 const indexToRemove = slidesIndexes; 9336 if (swiper.slides[indexToRemove]) 9337 swiper.slides[indexToRemove].remove(); 9338 if (indexToRemove < newActiveIndex) 9339 newActiveIndex -= 1; 9340 newActiveIndex = Math.max(newActiveIndex, 0); 9341 } 9342 swiper.recalcSlides(); 9343 if (params.loop) { 9344 swiper.loopCreate(); 9345 } 9346 if (!params.observer || swiper.isElement) { 9347 swiper.update(); 9348 } 9349 if (params.loop) { 9350 swiper.slideTo(newActiveIndex + (swiper.loopedSlides ?? 0), 0, false); 9351 } 9352 else { 9353 swiper.slideTo(newActiveIndex, 0, false); 9354 } 9355 } 9356 9357 const Manipulation = ({ swiper }) => { 9358 Object.assign(swiper, { 9359 appendSlide: appendSlide.bind(swiper), 9360 prependSlide: prependSlide.bind(swiper), 9361 addSlide: addSlide.bind(swiper), 9362 removeSlide: removeSlide.bind(swiper), 9363 removeAllSlides: removeAllSlides.bind(swiper), 9364 }); 9365 }; 9366 9367 function effectInit(params) { 9368 const { effect, swiper, on, setTranslate, setTransition, overwriteParams, perspective, recreateShadows, getEffectParams, } = params; 9369 on('beforeInit', () => { 9370 if (swiper.params.effect !== effect) 9371 return; 9372 swiper.classNames.push(`${swiper.params.containerModifierClass}${effect}`); 9373 if (perspective && perspective()) { 9374 swiper.classNames.push(`${swiper.params.containerModifierClass}3d`); 9375 } 9376 const overwriteParamsResult = overwriteParams ? overwriteParams() : {}; 9377 Object.assign(swiper.params, overwriteParamsResult); 9378 Object.assign(swiper.originalParams, overwriteParamsResult); 9379 }); 9380 on('setTranslate _virtualUpdated', () => { 9381 if (swiper.params.effect !== effect) 9382 return; 9383 setTranslate(); 9384 }); 9385 on('setTransition', (_s, duration) => { 9386 if (swiper.params.effect !== effect) 9387 return; 9388 setTransition(duration); 9389 }); 9390 on('transitionEnd', () => { 9391 if (swiper.params.effect !== effect) 9392 return; 9393 if (recreateShadows) { 9394 const effectParams = getEffectParams ? getEffectParams() : undefined; 9395 if (!effectParams || !effectParams.slideShadows) 9396 return; 9397 swiper.slides.forEach((slideEl) => { 9398 slideEl 9399 .querySelectorAll('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left') 9400 .forEach((shadowEl) => shadowEl.remove()); 9401 }); 9402 recreateShadows(); 9403 } 9404 }); 9405 let requireUpdateOnVirtual = false; 9406 on('virtualUpdate', () => { 9407 if (swiper.params.effect !== effect) 9408 return; 9409 if (!swiper.slides.length) { 9410 requireUpdateOnVirtual = true; 9411 } 9412 requestAnimationFrame(() => { 9413 if (requireUpdateOnVirtual && swiper.slides && swiper.slides.length) { 9414 setTranslate(); 9415 requireUpdateOnVirtual = false; 9416 } 9417 }); 9418 }); 9419 } 9420 9421 function effectTarget(_effectParams, slideEl) { 9422 const transformEl = getSlideTransformEl(slideEl); 9423 if (transformEl !== slideEl) { 9424 transformEl.style.backfaceVisibility = 'hidden'; 9425 transformEl.style.setProperty('-webkit-backface-visibility', 'hidden'); 9426 } 9427 return transformEl; 9428 } 9429 9430 function effectVirtualTransitionEnd({ swiper, duration, transformElements, allSlides, }) { 9431 const { activeIndex } = swiper; 9432 const getSlide = (el) => { 9433 if (!el.parentElement) { 9434 // assume shadow root 9435 return swiper.slides.find((slideEl) => slideEl.shadowRoot && slideEl.shadowRoot === el.parentNode); 9436 } 9437 if (el.parentElement instanceof HTMLElement) 9438 return el.parentElement; 9439 return undefined; 9440 }; 9441 if (swiper.params.virtualTranslate && duration !== 0) { 9442 let eventTriggered = false; 9443 let transitionEndTarget; 9444 if (allSlides) { 9445 transitionEndTarget = transformElements; 9446 } 9447 else { 9448 transitionEndTarget = transformElements.filter((transformEl) => { 9449 const el = transformEl.classList.contains('swiper-slide-transform') 9450 ? getSlide(transformEl) 9451 : transformEl; 9452 return !!el && swiper.getSlideIndex(el) === activeIndex; 9453 }); 9454 } 9455 transitionEndTarget.forEach((el) => { 9456 elementTransitionEnd(el, () => { 9457 if (eventTriggered) 9458 return; 9459 if (!swiper || swiper.destroyed) 9460 return; 9461 eventTriggered = true; 9462 swiper.animating = false; 9463 const evt = new CustomEvent('transitionend', { bubbles: true, cancelable: true }); 9464 swiper.wrapperEl.dispatchEvent(evt); 9465 }); 9466 }); 9467 } 9468 } 9469 9470 const EffectFade = ({ swiper, extendParams, on }) => { 9471 extendParams({ 9472 fadeEffect: { 9473 crossFade: false, 9474
9474}, 9475 }); 9476 function getParams() { 9477 return swiper.params.fadeEffect; 9478 } 9479 const setTranslate = () => { 9480 const { slides } = swiper; 9481 const params = getParams(); 9482 for (let i = 0; i < slides.length; i += 1) { 9483 const slideEl = slides[i]; 9484 const offset = slideEl.swiperSlideOffset ?? 0; 9485 let tx = -offset; 9486 if (!swiper.params.virtualTranslate) 9487 tx -= swiper.translate; 9488 let ty = 0; 9489 if (!swiper.isHorizontal()) { 9490 ty = tx; 9491 tx = 0; 9492 } 9493 const slideProgress = slideEl.progress ?? 0; 9494 const slideOpacity = params.crossFade 9495 ? Math.max(1 - Math.abs(slideProgress), 0) 9496 : 1 + Math.min(Math.max(slideProgress, -1), 0); 9497 const targetEl = effectTarget(params, slideEl); 9498 targetEl.style.opacity = String(slideOpacity); 9499 targetEl.style.transform = `translate3d(${tx}px, ${ty}px, 0px)`; 9500 } 9501 }; 9502 const setTransition = (duration) => { 9503 const transformElements = swiper.slides.map((slideEl) => getSlideTransformEl(slideEl));
9504 transformElements.forEach((el) => { 9505 el.style.transitionDuration = `${duration}ms`; 9506 });
vendor: 27,984 bytes, lines 9506-10107
9506 9507 effectVirtualTransitionEnd({ swiper, duration, transformElements, allSlides: true }); 9508 }; 9509 effectInit({ 9510 effect: 'fade', 9511 swiper, 9512 on, 9513 setTranslate, 9514 setTransition, 9515 overwriteParams: () => ({ 9516 slidesPerView: 1, 9517 slidesPerGroup: 1, 9518 watchSlidesProgress: true, 9519 spaceBetween: 0, 9520 virtualTranslate: !swiper.params.cssMode, 9521 }), 9522 }); 9523 }; 9524 9525 const EffectCube = ({ swiper, extendParams, on }) => { 9526 extendParams({ 9527 cubeEffect: { 9528 slideShadows: true, 9529 shadow: true, 9530 shadowOffset: 20, 9531 shadowScale: 0.94, 9532 }, 9533 }); 9534 function getParams() { 9535 return swiper.params.cubeEffect; 9536 } 9537 const createSlideShadows = (slideEl, progress, isHorizontal) => { 9538 let shadowBefore = isHorizontal 9539 ? slideEl.querySelector('.swiper-slide-shadow-left') 9540 : slideEl.querySelector('.swiper-slide-shadow-top'); 9541 let shadowAfter = isHorizontal 9542 ? slideEl.querySelector('.swiper-slide-shadow-right') 9543 : slideEl.querySelector('.swiper-slide-shadow-bottom'); 9544 if (!shadowBefore) { 9545 shadowBefore = createElement('div', `swiper-slide-shadow-cube swiper-slide-shadow-${isHorizontal ? 'left' : 'top'}`.split(' ')); 9546 slideEl.append(shadowBefore); 9547 } 9548 if (!shadowAfter) { 9549 shadowAfter = createElement('div', `swiper-slide-shadow-cube swiper-slide-shadow-${isHorizontal ? 'right' : 'bottom'}`.split(' ')); 9550 slideEl.append(shadowAfter); 9551 } 9552 if (shadowBefore) 9553 shadowBefore.style.opacity = String(Math.max(-progress, 0)); 9554 if (shadowAfter) 9555 shadowAfter.style.opacity = String(Math.max(progress, 0)); 9556 }; 9557 const recreateShadows = () => { 9558 // create new ones 9559 const isHorizontal = swiper.isHorizontal(); 9560 swiper.slides.forEach((slideEl) => { 9561 const progress = Math.max(Math.min(slideEl.progress ?? 0, 1), -1); 9562 createSlideShadows(slideEl, progress, isHorizontal); 9563 }); 9564 }; 9565 const setTranslate = () => { 9566 const { el, wrapperEl, slides, width: swiperWidth, height: swiperHeight, rtlTranslate: rtl, size: swiperSize, } = swiper; 9567 const r = getRotateFix(swiper); 9568 const params = getParams(); 9569 const isHorizontal = swiper.isHorizontal(); 9570 const isVirtual = !!(swiper.virtual && swiper.params.virtual?.enabled); 9571 let wrapperRotate = 0; 9572 let cubeShadowEl = null; 9573 if (params.shadow) { 9574 if (isHorizontal) { 9575 cubeShadowEl = swiper.wrapperEl.querySelector('.swiper-cube-shadow'); 9576 if (!cubeShadowEl) { 9577 cubeShadowEl = createElement('div', 'swiper-cube-shadow'); 9578 swiper.wrapperEl.append(cubeShadowEl); 9579 } 9580 cubeShadowEl.style.height = `${swiperWidth}px`; 9581 } 9582 else { 9583 cubeShadowEl = el.querySelector('.swiper-cube-shadow'); 9584 if (!cubeShadowEl) { 9585 cubeShadowEl = createElement('div', 'swiper-cube-shadow'); 9586 el.append(cubeShadowEl); 9587 } 9588 } 9589 } 9590 for (let i = 0; i < slides.length; i += 1) { 9591 const slideEl = slides[i]; 9592 let slideIndex = i; 9593 if (isVirtual) { 9594 slideIndex = parseInt(slideEl.getAttribute('data-swiper-slide-index') ?? '0', 10); 9595 } 9596 let slideAngle = slideIndex * 90; 9597 let round = Math.floor(slideAngle / 360); 9598 if (rtl) { 9599 slideAngle = -slideAngle; 9600 round = Math.floor(-slideAngle / 360); 9601 } 9602 const progress = Math.max(Math.min(slideEl.progress ?? 0, 1), -1); 9603 let tx = 0; 9604 let ty = 0; 9605 let tz = 0; 9606 if (slideIndex % 4 === 0) { 9607 tx = -round * 4 * swiperSize; 9608 tz = 0; 9609 } 9610 else if ((slideIndex - 1) % 4 === 0) { 9611 tx = 0; 9612 tz = -round * 4 * swiperSize; 9613 } 9614 else if ((slideIndex - 2) % 4 === 0) { 9615 tx = swiperSize + round * 4 * swiperSize; 9616 tz = swiperSize; 9617 } 9618 else if ((slideIndex - 3) % 4 === 0) { 9619 tx = -swiperSize; 9620 tz = 3 * swiperSize + swiperSize * 4 * round; 9621 } 9622 if (rtl) { 9623 tx = -tx; 9624 } 9625 if (!isHorizontal) { 9626 ty = tx; 9627 tx = 0; 9628 } 9629 const transform = `rotateX(${r(isHorizontal ? 0 : -slideAngle)}deg) rotateY(${r(isHorizontal ? slideAngle : 0)}deg) translate3d(${tx}px, ${ty}px, ${tz}px)`; 9630 if (progress <= 1 && progress > -1) { 9631 wrapperRotate = slideIndex * 90 + progress * 90; 9632 if (rtl) 9633 wrapperRotate = -slideIndex * 90 - progress * 90; 9634 } 9635 slideEl.style.transform = transform; 9636 if (params.slideShadows) { 9637 createSlideShadows(slideEl, progress, isHorizontal); 9638 } 9639 } 9640 wrapperEl.style.transformOrigin = `50% 50% -${swiperSize / 2}px`; 9641 wrapperEl.style.setProperty('-webkit-transform-origin', `50% 50% -${swiperSize / 2}px`); 9642 if (params.shadow && cubeShadowEl) { 9643 if (isHorizontal) { 9644 cubeShadowEl.style.transform = `translate3d(0px, ${swiperWidth / 2 + params.shadowOffset}px, ${-swiperWidth / 2}px) rotateX(89.99deg) rotateZ(0deg) scale(${params.shadowScale})`; 9645 } 9646 else { 9647 const shadowAngle = Math.abs(wrapperRotate) - Math.floor(Math.abs(wrapperRotate) / 90) * 90; 9648 const multiplier = 1.5 - 9649 (Math.sin((shadowAngle * 2 * Math.PI) / 360) / 2 + 9650 Math.cos((shadowAngle * 2 * Math.PI) / 360) / 2); 9651 const scale1 = params.shadowScale; 9652 const scale2 = params.shadowScale / multiplier; 9653 const offset = params.shadowOffset; 9654 cubeShadowEl.style.transform = `scale3d(${scale1}, 1, ${scale2}) translate3d(0px, ${swiperHeight / 2 + offset}px, ${-swiperHeight / 2 / scale2}px) rotateX(-89.99deg)`; 9655 } 9656 } 9657 wrapperEl.style.transform = `translate3d(0px,0,0px) rotateX(${r(swiper.isHorizontal() ? 0 : wrapperRotate)}deg) rotateY(${r(swiper.isHorizontal() ? -wrapperRotate : 0)}deg)`; 9658 wrapperEl.style.setProperty('--swiper-cube-translate-z', '0px'); 9659 }; 9660 const setTransition = (duration) => { 9661 const { el, slides } = swiper; 9662 slides.forEach((slideEl) => { 9663 slideEl.style.transitionDuration = `${duration}ms`; 9664 slideEl 9665 .querySelectorAll('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left') 9666 .forEach((subEl) => { 9667 subEl.style.transitionDuration = `${duration}ms`; 9668 }); 9669 }); 9670 if (swiper.params.cubeEffect?.shadow && !swiper.isHorizontal()) { 9671 const shadowEl = el.querySelector('.swiper-cube-shadow'); 9672 if (shadowEl) 9673 shadowEl.style.transitionDuration = `${duration}ms`; 9674 } 9675 }; 9676 effectInit({ 9677 effect: 'cube', 9678 swiper, 9679 on, 9680 setTranslate, 9681 setTransition, 9682 recreateShadows, 9683 getEffectParams: () => swiper.params.cubeEffect, 9684 perspective: () => true, 9685 overwriteParams: () => ({ 9686 slidesPerView: 1, 9687 slidesPerGroup: 1, 9688 watchSlidesProgress: true, 9689 resistanceRatio: 0, 9690 spaceBetween: 0, 9691 centeredSlides: false, 9692 virtualTranslate: true, 9693 }), 9694 }); 9695 }; 9696 9697 function createShadow(suffix, slideEl, side) { 9698 const shadowClass = `swiper-slide-shadow${side ? `-${side}` : ''}${suffix ? ` swiper-slide-shadow-${suffix}` : ''}`; 9699 const shadowContainer = getSlideTransformEl(slideEl); 9700 const selector = `.${shadowClass.split(' ').join('.')}`; 9701 const existing = shadowContainer.querySelector(selector); 9702 if (existing) 9703 return existing; 9704 const created = createElement('div', shadowClass.split(' ')); 9705 shadowContainer.append(created); 9706 return created; 9707 } 9708 9709 const EffectFlip = ({ swiper, extendParams, on }) => { 9710 extendParams({ 9711 flipEffect: { 9712 slideShadows: true, 9713 limitRotation: true, 9714 }, 9715 }); 9716 function getParams() { 9717 return swiper.params.flipEffect; 9718 } 9719 const createSlideShadows = (slideEl, progress) => { 9720 let shadowBefore = swiper.isHorizontal() 9721 ? slideEl.querySelector('.swiper-slide-shadow-left') 9722 : slideEl.querySelector('.swiper-slide-shadow-top'); 9723 let shadowAfter = swiper.isHorizontal() 9724 ? slideEl.querySelector('.swiper-slide-shadow-right') 9725 : slideEl.querySelector('.swiper-slide-shadow-bottom'); 9726 if (!shadowBefore) { 9727 shadowBefore = createShadow('flip', slideEl, swiper.isHorizontal() ? 'left' : 'top'); 9728 } 9729 if (!shadowAfter) { 9730 shadowAfter = createShadow('flip', slideEl, swiper.isHorizontal() ? 'right' : 'bottom'); 9731 } 9732 if (shadowBefore) 9733 shadowBefore.style.opacity = String(Math.max(-progress, 0)); 9734 if (shadowAfter) 9735 shadowAfter.style.opacity = String(Math.max(progress, 0)); 9736 }; 9737 const recreateShadows = () => { 9738 // Set shadows 9739 const params = getParams(); 9740 swiper.slides.forEach((slideEl) => { 9741 let progress = slideEl.progress ?? 0; 9742 if (params.limitRotation) { 9743 progress = Math.max(Math.min(progress, 1), -1); 9744 } 9745 createSlideShadows(slideEl, progress); 9746 }); 9747 }; 9748 const setTranslate = () => { 9749 const { slides, rtlTranslate: rtl } = swiper; 9750 const params = getParams(); 9751 const rotateFix = getRotateFix(swiper); 9752 for (let i = 0; i < slides.length; i += 1) { 9753 const slideEl = slides[i]; 9754 let progress = slideEl.progress ?? 0; 9755 if (params.limitRotation) { 9756 progress = Math.max(Math.min(progress, 1), -1); 9757 } 9758 const offset = slideEl.swiperSlideOffset ?? 0; 9759 const rotate = -180 * progress; 9760 let rotateY = rotate; 9761 let rotateX = 0; 9762 let tx = swiper.params.cssMode ? -offset - swiper.translate : -offset; 9763 let ty = 0; 9764 if (!swiper.isHorizontal()) { 9765 ty = tx; 9766 tx = 0; 9767 rotateX = -rotateY; 9768 rotateY = 0; 9769 } 9770 else if (rtl) { 9771 rotateY = -rotateY; 9772 } 9773 slideEl.style.zIndex = String(-Math.abs(Math.round(progress)) + slides.length); 9774 if (params.slideShadows) { 9775 createSlideShadows(slideEl, progress); 9776 } 9777 const transform = `translate3d(${tx}px, ${ty}px, 0px) rotateX(${rotateFix(rotateX)}deg) rotateY(${rotateFix(rotateY)}deg)`; 9778 const targetEl = effectTarget(params, slideEl); 9779 targetEl.style.transform = transform; 9780 } 9781 }; 9782 const setTransition = (duration) => { 9783 const transformElements = swiper.slides.map((slideEl) => getSlideTransformEl(slideEl)); 9784 transformElements.forEach((el) => { 9785 el.style.transitionDuration = `${duration}ms`; 9786 el.querySelectorAll('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').forEach((shadowEl) => { 9787 shadowEl.style.transitionDuration = `${duration}ms`; 9788 }); 9789 }); 9790 effectVirtualTransitionEnd({ swiper, duration, transformElements }); 9791 }; 9792 effectInit({ 9793 effect: 'flip', 9794 swiper, 9795 on, 9796 setTranslate, 9797 setTransition, 9798 recreateShadows, 9799 getEffectParams: () => swiper.params.flipEffect, 9800 perspective: () => true, 9801 overwriteParams: () => ({ 9802 slidesPerView: 1, 9803 slidesPerGroup: 1, 9804 watchSlidesProgress: true, 9805 spaceBetween: 0, 9806 virtualTranslate: !swiper.params.cssMode, 9807 }), 9808 }); 9809 }; 9810 9811 const EffectCoverflow = ({ swiper, extendParams, on }) => { 9812 extendParams({ 9813 coverflowEffect: { 9814 rotate: 50, 9815 stretch: 0, 9816 depth: 100, 9817 scale: 1, 9818 modifier: 1, 9819 slideShadows: true, 9820 }, 9821 }); 9822 function getParams() { 9823 return swiper.params.coverflowEffect; 9824 } 9825 const setTranslate = () => { 9826 const { width: swiperWidth, height: swiperHeight, slides, slidesSizesGrid } = swiper; 9827 const params = getParams(); 9828 const isHorizontal = swiper.isHorizontal(); 9829 const transform = swiper.translate; 9830 const center = isHorizontal ? -transform + swiperWidth / 2 : -transform + swiperHeight / 2; 9831 const rotate = isHorizontal ? params.rotate : -params.rotate; 9832 const translate = params.depth; 9833 const r = getRotateFix(swiper); 9834 // Each slide offset from center 9835 for (let i = 0, length = slides.length; i < length; i += 1) { 9836 const slideEl = slides[i]; 9837 const slideSize = slidesSizesGrid[i]; 9838 const slideOffset = slideEl.swiperSlideOffset ?? 0; 9839 const centerOffset = (center - slideOffset - slideSize / 2) / slideSize; 9840 const offsetMultiplier = typeof params.modifier === 'function' 9841 ? params.modifier(centerOffset) 9842 : centerOffset * params.modifier; 9843 let rotateY = isHorizontal ? rotate * offsetMultiplier : 0; 9844 let rotateX = isHorizontal ? 0 : rotate * offsetMultiplier; 9845 // var rotateZ = 0 9846 let translateZ = -translate * Math.abs(offsetMultiplier); 9847 let stretch = typeof params.stretch === 'string' && params.stretch.indexOf('%') !== -1 9848 ? (parseFloat(params.stretch) / 100) * slideSize 9849 : params.stretch; 9850 let translateY = isHorizontal ? 0 : stretch * offsetMultiplier; 9851 let translateX = isHorizontal ? stretch * offsetMultiplier : 0; 9852 let scale = 1 - (1 - params.scale) * Math.abs(offsetMultiplier); 9853 // Fix for ultra small values 9854 if (Math.abs(translateX) < 0.001) 9855 translateX = 0; 9856 if (Math.abs(translateY) < 0.001) 9857 translateY = 0; 9858 if (Math.abs(translateZ) < 0.001) 9859 translateZ = 0; 9860 if (Math.abs(rotateY) < 0.001) 9861 rotateY = 0; 9862 if (Math.abs(rotateX) < 0.001) 9863 rotateX = 0; 9864 if (Math.abs(scale) < 0.001) 9865 scale = 0; 9866 const slideTransform = `translate3d(${translateX}px,${translateY}px,${translateZ}px) rotateX(${r(rotateX)}deg) rotateY(${r(rotateY)}deg) scale(${scale})`; 9867 const targetEl = effectTarget(params, slideEl); 9868 targetEl.style.transform = slideTransform; 9869 slideEl.style.zIndex = String(-Math.abs(Math.round(offsetMultiplier)) + 1); 9870 if (params.slideShadows) { 9871 // Set shadows 9872 let shadowBeforeEl = isHorizontal 9873 ? slideEl.querySelector('.swiper-slide-shadow-left') 9874 : slideEl.querySelector('.swiper-slide-shadow-top'); 9875 let shadowAfterEl = isHorizontal 9876 ? slideEl.querySelector('.swiper-slide-shadow-right') 9877 : slideEl.querySelector('.swiper-slide-shadow-bottom'); 9878 if (!shadowBeforeEl) { 9879 shadowBeforeEl = createShadow('coverflow', slideEl, isHorizontal ? 'left' : 'top'); 9880 } 9881 if (!shadowAfterEl) { 9882 shadowAfterEl = createShadow('coverflow', slideEl, isHorizontal ? 'right' : 'bottom'); 9883 } 9884 if (shadowBeforeEl) 9885 shadowBeforeEl.style.opacity = String(offsetMultiplier > 0 ? offsetMultiplier : 0); 9886 if (shadowAfterEl) 9887 shadowAfterEl.style.opacity = String(-offsetMultiplier > 0 ? -offsetMultiplier : 0); 9888 } 9889 } 9890 }; 9891 const setTransition = (duration) => { 9892 const transformElements = swiper.slides.map((slideEl) => getSlideTransformEl(slideEl)); 9893 transformElements.forEach((el) => { 9894 el.style.transitionDuration = `${duration}ms`; 9895 el.querySelectorAll('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').forEach((shadowEl) => { 9896 shadowEl.style.transitionDuration = `${duration}ms`; 9897 }); 9898 }); 9899 }; 9900 effectInit({ 9901 effect: 'coverflow', 9902 swiper, 9903 on, 9904 setTranslate, 9905 setTransition, 9906 perspective: () => true, 9907 overwriteParams: () => ({ 9908 watchSlidesProgress: true, 9909 }), 9910 }); 9911 }; 9912 9913 const EffectCreative = ({ swiper, extendParams, on }) => { 9914 extendParams({ 9915 creativeEffect: { 9916 limitProgress: 1, 9917 shadowPerProgress: false, 9918 progressMultiplier: 1, 9919 perspective: true, 9920 prev: { 9921 translate: [0, 0, 0], 9922 rotate: [0, 0, 0], 9923 opacity: 1, 9924 scale: 1, 9925 }, 9926 next: { 9927 translate: [0, 0, 0], 9928 rotate: [0, 0, 0], 9929 opacity: 1, 9930 scale: 1, 9931 }, 9932 }, 9933 }); 9934 function getParams() { 9935 return swiper.params.creativeEffect; 9936 } 9937 const getTranslateValue = (value) => { 9938 if (typeof value === 'string') 9939 return value; 9940 return `${value}px`; 9941 }; 9942 const setTranslate = () => { 9943 const { slides, wrapperEl, slidesSizesGrid } = swiper; 9944 const params = getParams(); 9945 const { progressMultiplier: multiplier } = params; 9946 const isCenteredSlides = swiper.params.centeredSlides; 9947 const rotateFix = getRotateFix(swiper); 9948 if (isCenteredSlides) { 9949 const margin = slidesSizesGrid[0] / 2 - (swiper.params.slidesOffsetBefore ?? 0); 9950 wrapperEl.style.transform = `translateX(calc(50% - ${margin}px))`; 9951 } 9952 for (let i = 0; i < slides.length; i += 1) { 9953 const slideEl = slides[i]; 9954 const slideProgress = slideEl.progress ?? 0; 9955 const progress = Math.min(Math.max(slideProgress, -params.limitProgress), params.limitProgress); 9956 let originalProgress = progress; 9957 if (!isCenteredSlides) { 9958 originalProgress = Math.min(Math.max(slideEl.originalProgress ?? 0, -params.limitProgress), params.limitProgress); 9959 } 9960 const offset = slideEl.swiperSlideOffset ?? 0; 9961 const t = [ 9962 swiper.params.cssMode ? -offset - swiper.translate : -offset, 9963 0, 9964 0, 9965 ]; 9966 const r = [0, 0, 0]; 9967 let custom = false; 9968 if (!swiper.isHorizontal()) { 9969 t[1] = t[0]; 9970 t[0] = 0; 9971 } 9972 let data = { 9973 translate: [0, 0, 0], 9974 rotate: [0, 0, 0], 9975 scale: 1, 9976 opacity: 1, 9977 }; 9978 if (progress < 0) { 9979 data = params.next; 9980 custom = true; 9981 } 9982 else if (progress > 0) { 9983 data = params.prev; 9984 custom = true; 9985 } 9986 // set translate 9987 t.forEach((value, index) => { 9988 t[index] = `calc(${value}px + (${getTranslateValue(data.translate[index])} * ${Math.abs(progress * multiplier)}))`; 9989 }); 9990 // set rotates 9991 r.forEach((_value, index) => { 9992 r[index] = data.rotate[index] * Math.abs(progress * multiplier); 9993 }); 9994 slideEl.style.zIndex = String(-Math.abs(Math.round(slideProgress)) + slides.length); 9995 const translateString = t.join(', '); 9996 const rotateString = `rotateX(${rotateFix(r[0])}deg) rotateY(${rotateFix(r[1])}deg) rotateZ(${rotateFix(r[2])}deg)`; 9997 const scaleString = originalProgress < 0 9998 ? `scale(${1 + (1 - data.scale) * originalProgress * multiplier})` 9999 : `scale(${1 - (1 - data.scale) * originalProgress * multiplier})`; 10000 const opacityString = originalProgress < 0 10001 ? 1 + (1 - data.opacity) * originalProgress * multiplier 10002 : 1 - (1 - data.opacity) * originalProgress * multiplier; 10003 const transform = `translate3d(${translateString}) ${rotateString} ${scaleString}`; 10004 // Set shadows 10005 if ((custom && data.shadow) || !custom) { 10006 let shadowEl = slideEl.querySelector('.swiper-slide-shadow'); 10007 if (!shadowEl && data.shadow) { 10008 shadowEl = createShadow('creative', slideEl); 10009 } 10010 if (shadowEl) { 10011 const shadowOpacity = params.shadowPerProgress 10012 ? progress * (1 / params.limitProgress) 10013 : progress; 10014 shadowEl.style.opacity = String(Math.min(Math.max(Math.abs(shadowOpacity), 0), 1)); 10015 } 10016 } 10017 const targetEl = effectTarget(params, slideEl); 10018 targetEl.style.transform = transform; 10019 targetEl.style.opacity = String(opacityString); 10020 if (data.origin) { 10021 targetEl.style.transformOrigin = data.origin; 10022 } 10023 } 10024 }; 10025 const setTransition = (duration) => { 10026 const transformElements = swiper.slides.map((slideEl) => getSlideTransformEl(slideEl)); 10027 transformElements.forEach((el) => { 10028 el.style.transitionDuration = `${duration}ms`; 10029 el.querySelectorAll('.swiper-slide-shadow').forEach((shadowEl) => { 10030 shadowEl.style.transitionDuration = `${duration}ms`; 10031 }); 10032 }); 10033 effectVirtualTransitionEnd({ swiper, duration, transformElements, allSlides: true }); 10034 }; 10035 effectInit({ 10036 effect: 'creative', 10037 swiper, 10038 on, 10039 setTranslate, 10040 setTransition, 10041 perspective: () => getParams().perspective, 10042 overwriteParams: () => ({ 10043 watchSlidesProgress: true, 10044 virtualTranslate: !swiper.params.cssMode, 10045 }), 10046 }); 10047 }; 10048 10049 const EffectCards = ({ swiper, extendParams, on }) => { 10050 extendParams({ 10051 cardsEffect: { 10052 slideShadows: true, 10053 rotate: true, 10054 perSlideRotate: 2, 10055 perSlideOffset: 8, 10056 }, 10057 }); 10058 function getParams() { 10059 return swiper.params.cardsEffect; 10060 } 10061 const setTranslate = () => { 10062 const { slides, activeIndex, rtlTranslate: rtl } = swiper; 10063 const params = getParams(); 10064 const { startTranslate, isTouched } = swiper.touchEventsData; 10065 const currentTranslate = rtl ? -swiper.translate : swiper.translate; 10066 for (let i = 0; i < slides.length; i += 1) { 10067 const slideEl = slides[i]; 10068 const slideProgress = slideEl.progress ?? 0; 10069 const progress = Math.min(Math.max(slideProgress, -4), 4); 10070 let offset = slideEl.swiperSlideOffset ?? 0; 10071 if (swiper.params.centeredSlides && !swiper.params.cssMode) { 10072 swiper.wrapperEl.style.transform = `translateX(${swiper.minTranslate()}px)`; 10073 } 10074 if (swiper.params.centeredSlides && swiper.params.cssMode) { 10075 offset -= slides[0].swiperSlideOffset ?? 0; 10076 } 10077 let tX = swiper.params.cssMode ? -offset - swiper.translate : -offset; 10078 let tY = 0; 10079 const tZ = -100 * Math.abs(progress); 10080 let scale = 1; 10081 let rotate = -params.perSlideRotate * progress; 10082 let tXAdd = params.perSlideOffset - Math.abs(progress) * 0.75; 10083 const slideIndex = swiper.virtual && swiper.params.virtual?.enabled ? swiper.virtual.from + i : i; 10084 const isSwipeToNext = (slideIndex === activeIndex || slideIndex === activeIndex - 1) && 10085 progress > 0 && 10086 progress < 1 && 10087 (isTouched || swiper.params.cssMode) && 10088 (currentTranslate ?? 0) < (startTranslate ?? 0); 10089 const isSwipeToPrev = (slideIndex === activeIndex || slideIndex === activeIndex + 1) && 10090 progress < 0 && 10091 progress > -1 && 10092 (isTouched || swiper.params.cssMode) && 10093 (currentTranslate ?? 0) > (startTranslate ?? 0); 10094 if (isSwipeToNext || isSwipeToPrev) { 10095 const subProgress = (1 - Math.abs((Math.abs(progress) - 0.5) / 0.5)) ** 0.5; 10096 rotate += -28 * progress * subProgress; 10097 scale += -0.5 * subProgress; 10098 tXAdd += 96 * subProgress; 10099 tY = `${(params.rotate || swiper.isHorizontal() ? -25 : 0) * subProgress * Math.abs(progress)}%`; 10100 } 10101 if (progress < 0) { 10102 // next 10103 tX = `calc(${tX}px ${rtl ? '-' : '+'} (${tXAdd * Math.abs(progress)}%))`; 10104 } 10105 else if (progress > 0) { 10106 // prev 10107
vendor: 3,161 bytes, lines 10107-10207
10107tX = `calc(${tX}px ${rtl ? '-' : '+'} (-${tXAdd * Math.abs(progress)}%))`; 10108 } 10109 else { 10110 tX = `${tX}px`; 10111 } 10112 if (!swiper.isHorizontal()) { 10113 const prevY = tY; 10114 tY = tX; 10115 tX = prevY; 10116 } 10117 const scaleString = progress < 0 ? `${1 + (1 - scale) * progress}` : `${1 - (1 - scale) * progress}`; 10118 const transform = ` 10119 translate3d(${tX}, ${tY}, ${tZ}px) 10120 rotateZ(${params.rotate ? (rtl ? -rotate : rotate) : 0}deg) 10121 scale(${scaleString}) 10122 `; 10123 if (params.slideShadows) { 10124 // Set shadows 10125 let shadowEl = slideEl.querySelector('.swiper-slide-shadow'); 10126 if (!shadowEl) { 10127 shadowEl = createShadow('cards', slideEl); 10128 } 10129 if (shadowEl) 10130 shadowEl.style.opacity = String(Math.min(Math.max((Math.abs(progress) - 0.5) / 0.5, 0), 1)); 10131 } 10132 slideEl.style.zIndex = String(-Math.abs(Math.round(slideProgress)) + slides.length); 10133 const targetEl = effectTarget(params, slideEl); 10134 targetEl.style.transform = transform; 10135 } 10136 }; 10137 const setTransition = (duration) => { 10138 const transformElements = swiper.slides.map((slideEl) => getSlideTransformEl(slideEl)); 10139 transformElements.forEach((el) => { 10140 el.style.transitionDuration = `${duration}ms`; 10141 el.querySelectorAll('.swiper-slide-shadow').forEach((shadowEl) => { 10142 shadowEl.style.transitionDuration = `${duration}ms`; 10143 }); 10144 }); 10145 effectVirtualTransitionEnd({ swiper, duration, transformElements }); 10146 }; 10147 effectInit({ 10148 effect: 'cards', 10149 swiper, 10150 on, 10151 setTranslate, 10152 setTransition, 10153 perspective: () => true, 10154 overwriteParams: () => ({ 10155 _loopSwapReset: false, 10156 watchSlidesProgress: true, 10157 loopAdditionalSlides: getParams().rotate ? 3 : 2, 10158 centeredSlides: true, 10159 virtualTranslate: !swiper.params.cssMode, 10160 }), 10161 }); 10162 }; 10163 10164 /** 10165 * Swiper 14.0.7 10166 * Most modern mobile touch slider and framework with hardware accelerated transitions 10167 * https://swiperjs.com 10168 * 10169 * Copyright 2014-2026 Vladimir Kharlampidi 10170 * 10171 * Released under the MIT License 10172 * 10173 * Released on: July 28, 2026 10174 */ 10175 10176 10177 // Swiper Class 10178 const modules = [ 10179 Virtual, 10180 Keyboard, 10181 Mousewheel, 10182 Navigation, 10183 Pagination, 10184 Scrollbar, 10185 Parallax, 10186 Zoom, 10187 Controller, 10188 A11y, 10189 History, 10190 HashNavigation, 10191 Autoplay, 10192 Thumb, 10193 FreeMode, 10194 Grid, 10195 Manipulation, 10196 EffectFade, 10197 EffectCube, 10198 EffectFlip, 10199 EffectCoverflow, 10200 EffectCreative, 10201 EffectCards 10202 ]; 10203 Swiper.use(modules); 10204 10205 return Swiper; 10206 10207})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.