swiper.jquery.umd.js (213120B)
1 /** 2 * Swiper 3.4.2 3 * Most modern mobile touch slider and framework with hardware accelerated transitions 4 * 5 * http://www.idangero.us/swiper/ 6 * 7 * Copyright 2017, Vladimir Kharlampidi 8 * The iDangero.us 9 * http://www.idangero.us/ 10 * 11 * Licensed under MIT 12 * 13 * Released on: March 10, 2017 14 */ 15 (function (root, factory) { 16 'use strict'; 17 18 if (typeof define === 'function' && define.amd) { 19 // AMD. Register as an anonymous module. 20 define(['jquery'], factory); 21 } else if (typeof exports === 'object') { 22 // Node. Does not work with strict CommonJS, but 23 // only CommonJS-like environments that support module.exports, 24 // like Node. 25 module.exports = factory(require('jquery')); 26 } else { 27 // Browser globals (root is window) 28 root.Swiper = factory(root.jQuery); 29 } 30 }(this, function ($) { 31 'use strict'; 32 33 /*=========================== 34 Swiper 35 ===========================*/ 36 var Swiper = function (container, params) { 37 if (!(this instanceof Swiper)) return new Swiper(container, params); 38 39 40 var defaults = { 41 direction: 'horizontal', 42 touchEventsTarget: 'container', 43 initialSlide: 0, 44 speed: 300, 45 // autoplay 46 autoplay: false, 47 autoplayDisableOnInteraction: true, 48 autoplayStopOnLast: false, 49 // To support iOS's swipe-to-go-back gesture (when being used in-app, with UIWebView). 50 iOSEdgeSwipeDetection: false, 51 iOSEdgeSwipeThreshold: 20, 52 // Free mode 53 freeMode: false, 54 freeModeMomentum: true, 55 freeModeMomentumRatio: 1, 56 freeModeMomentumBounce: true, 57 freeModeMomentumBounceRatio: 1, 58 freeModeMomentumVelocityRatio: 1, 59 freeModeSticky: false, 60 freeModeMinimumVelocity: 0.02, 61 // Autoheight 62 autoHeight: false, 63 // Set wrapper width 64 setWrapperSize: false, 65 // Virtual Translate 66 virtualTranslate: false, 67 // Effects 68 effect: 'slide', // 'slide' or 'fade' or 'cube' or 'coverflow' or 'flip' 69 coverflow: { 70 rotate: 50, 71 stretch: 0, 72 depth: 100, 73 modifier: 1, 74 slideShadows : true 75 }, 76 flip: { 77 slideShadows : true, 78 limitRotation: true 79 }, 80 cube: { 81 slideShadows: true, 82 shadow: true, 83 shadowOffset: 20, 84 shadowScale: 0.94 85 }, 86 fade: { 87 crossFade: false 88 }, 89 // Parallax 90 parallax: false, 91 // Zoom 92 zoom: false, 93 zoomMax: 3, 94 zoomMin: 1, 95 zoomToggle: true, 96 // Scrollbar 97 scrollbar: null, 98 scrollbarHide: true, 99 scrollbarDraggable: false, 100 scrollbarSnapOnRelease: false, 101 // Keyboard Mousewheel 102 keyboardControl: false, 103 mousewheelControl: false, 104 mousewheelReleaseOnEdges: false, 105 mousewheelInvert: false, 106 mousewheelForceToAxis: false, 107 mousewheelSensitivity: 1, 108 mousewheelEventsTarged: 'container', 109 // Hash Navigation 110 hashnav: false, 111 hashnavWatchState: false, 112 // History 113 history: false, 114 // Commong Nav State 115 replaceState: false, 116 // Breakpoints 117 breakpoints: undefined, 118 // Slides grid 119 spaceBetween: 0, 120 slidesPerView: 1, 121 slidesPerColumn: 1, 122 slidesPerColumnFill: 'column', 123 slidesPerGroup: 1, 124 centeredSlides: false, 125 slidesOffsetBefore: 0, // in px 126 slidesOffsetAfter: 0, // in px 127 // Round length 128 roundLengths: false, 129 // Touches 130 touchRatio: 1, 131 touchAngle: 45, 132 simulateTouch: true, 133 shortSwipes: true, 134 longSwipes: true, 135 longSwipesRatio: 0.5, 136 longSwipesMs: 300, 137 followFinger: true, 138 onlyExternal: false, 139 threshold: 0, 140 touchMoveStopPropagation: true, 141 touchReleaseOnEdges: false, 142 // Unique Navigation Elements 143 uniqueNavElements: true, 144 // Pagination 145 pagination: null, 146 paginationElement: 'span', 147 paginationClickable: false, 148 paginationHide: false, 149 paginationBulletRender: null, 150 paginationProgressRender: null, 151 paginationFractionRender: null, 152 paginationCustomRender: null, 153 paginationType: 'bullets', // 'bullets' or 'progress' or 'fraction' or 'custom' 154 // Resistance 155 resistance: true, 156 resistanceRatio: 0.85, 157 // Next/prev buttons 158 nextButton: null, 159 prevButton: null, 160 // Progress 161 watchSlidesProgress: false, 162 watchSlidesVisibility: false, 163 // Cursor 164 grabCursor: false, 165 // Clicks 166 preventClicks: true, 167 preventClicksPropagation: true, 168 slideToClickedSlide: false, 169 // Lazy Loading 170 lazyLoading: false, 171 lazyLoadingInPrevNext: false, 172 lazyLoadingInPrevNextAmount: 1, 173 lazyLoadingOnTransitionStart: false, 174 // Images 175 preloadImages: true, 176 updateOnImagesReady: true, 177 // loop 178 loop: false, 179 loopAdditionalSlides: 0, 180 loopedSlides: null, 181 // Control 182 control: undefined, 183 controlInverse: false, 184 controlBy: 'slide', //or 'container' 185 normalizeSlideIndex: true, 186 // Swiping/no swiping 187 allowSwipeToPrev: true, 188 allowSwipeToNext: true, 189 swipeHandler: null, //'.swipe-handler', 190 noSwiping: true, 191 noSwipingClass: 'swiper-no-swiping', 192 // Passive Listeners 193 passiveListeners: true, 194 // NS 195 containerModifierClass: 'swiper-container-', // NEW 196 slideClass: 'swiper-slide', 197 slideActiveClass: 'swiper-slide-active', 198 slideDuplicateActiveClass: 'swiper-slide-duplicate-active', 199 slideVisibleClass: 'swiper-slide-visible', 200 slideDuplicateClass: 'swiper-slide-duplicate', 201 slideNextClass: 'swiper-slide-next', 202 slideDuplicateNextClass: 'swiper-slide-duplicate-next', 203 slidePrevClass: 'swiper-slide-prev', 204 slideDuplicatePrevClass: 'swiper-slide-duplicate-prev', 205 wrapperClass: 'swiper-wrapper', 206 bulletClass: 'swiper-pagination-bullet', 207 bulletActiveClass: 'swiper-pagination-bullet-active', 208 buttonDisabledClass: 'swiper-button-disabled', 209 paginationCurrentClass: 'swiper-pagination-current', 210 paginationTotalClass: 'swiper-pagination-total', 211 paginationHiddenClass: 'swiper-pagination-hidden', 212 paginationProgressbarClass: 'swiper-pagination-progressbar', 213 paginationClickableClass: 'swiper-pagination-clickable', // NEW 214 paginationModifierClass: 'swiper-pagination-', // NEW 215 lazyLoadingClass: 'swiper-lazy', 216 lazyStatusLoadingClass: 'swiper-lazy-loading', 217 lazyStatusLoadedClass: 'swiper-lazy-loaded', 218 lazyPreloaderClass: 'swiper-lazy-preloader', 219 notificationClass: 'swiper-notification', 220 preloaderClass: 'preloader', 221 zoomContainerClass: 'swiper-zoom-container', 222 223 // Observer 224 observer: false, 225 observeParents: false, 226 // Accessibility 227 a11y: false, 228 prevSlideMessage: 'Previous slide', 229 nextSlideMessage: 'Next slide', 230 firstSlideMessage: 'This is the first slide', 231 lastSlideMessage: 'This is the last slide', 232 paginationBulletMessage: 'Go to slide {{index}}', 233 // Callbacks 234 runCallbacksOnInit: true 235 /* 236 Callbacks: 237 onInit: function (swiper) 238 onDestroy: function (swiper) 239 onBeforeResize: function (swiper) 240 onAfterResize: function (swiper) 241 onClick: function (swiper, e) 242 onTap: function (swiper, e) 243 onDoubleTap: function (swiper, e) 244 onSliderMove: function (swiper, e) 245 onSlideChangeStart: function (swiper) 246 onSlideChangeEnd: function (swiper) 247 onTransitionStart: function (swiper) 248 onTransitionEnd: function (swiper) 249 onImagesReady: function (swiper) 250 onProgress: function (swiper, progress) 251 onTouchStart: function (swiper, e) 252 onTouchMove: function (swiper, e) 253 onTouchMoveOpposite: function (swiper, e) 254 onTouchEnd: function (swiper, e) 255 onReachBeginning: function (swiper) 256 onReachEnd: function (swiper) 257 onSetTransition: function (swiper, duration) 258 onSetTranslate: function (swiper, translate) 259 onAutoplayStart: function (swiper) 260 onAutoplayStop: function (swiper), 261 onLazyImageLoad: function (swiper, slide, image) 262 onLazyImageReady: function (swiper, slide, image) 263 onKeyPress: function (swiper, keyCode) 264 */ 265 266 }; 267 var initialVirtualTranslate = params && params.virtualTranslate; 268 269 params = params || {}; 270 var originalParams = {}; 271 for (var param in params) { 272 if (typeof params[param] === 'object' && params[param] !== null && !(params[param].nodeType || params[param] === window || params[param] === document || (typeof Dom7 !== 'undefined' && params[param] instanceof Dom7) || (typeof jQuery !== 'undefined' && params[param] instanceof jQuery))) { 273 originalParams[param] = {}; 274 for (var deepParam in params[param]) { 275 originalParams[param][deepParam] = params[param][deepParam]; 276 } 277 } 278 else { 279 originalParams[param] = params[param]; 280 } 281 } 282 for (var def in defaults) { 283 if (typeof params[def] === 'undefined') { 284 params[def] = defaults[def]; 285 } 286 else if (typeof params[def] === 'object') { 287 for (var deepDef in defaults[def]) { 288 if (typeof params[def][deepDef] === 'undefined') { 289 params[def][deepDef] = defaults[def][deepDef]; 290 } 291 } 292 } 293 } 294 295 // Swiper 296 var s = this; 297 298 // Params 299 s.params = params; 300 s.originalParams = originalParams; 301 302 // Classname 303 s.classNames = []; 304 /*========================= 305 Dom Library and plugins 306 ===========================*/ 307 if (typeof $ !== 'undefined' && typeof Dom7 !== 'undefined'){ 308 $ = Dom7; 309 } 310 if (typeof $ === 'undefined') { 311 if (typeof Dom7 === 'undefined') { 312 $ = window.Dom7 || window.Zepto || window.jQuery; 313 } 314 else { 315 $ = Dom7; 316 } 317 if (!$) return; 318 } 319 // Export it to Swiper instance 320 s.$ = $; 321 322 /*========================= 323 Breakpoints 324 ===========================*/ 325 s.currentBreakpoint = undefined; 326 s.getActiveBreakpoint = function () { 327 //Get breakpoint for window width 328 if (!s.params.breakpoints) return false; 329 var breakpoint = false; 330 var points = [], point; 331 for ( point in s.params.breakpoints ) { 332 if (s.params.breakpoints.hasOwnProperty(point)) { 333 points.push(point); 334 } 335 } 336 points.sort(function (a, b) { 337 return parseInt(a, 10) > parseInt(b, 10); 338 }); 339 for (var i = 0; i < points.length; i++) { 340 point = points[i]; 341 if (point >= window.innerWidth && !breakpoint) { 342 breakpoint = point; 343 } 344 } 345 return breakpoint || 'max'; 346 }; 347 s.setBreakpoint = function () { 348 //Set breakpoint for window width and update parameters 349 var breakpoint = s.getActiveBreakpoint(); 350 if (breakpoint && s.currentBreakpoint !== breakpoint) { 351 var breakPointsParams = breakpoint in s.params.breakpoints ? s.params.breakpoints[breakpoint] : s.originalParams; 352 var needsReLoop = s.params.loop && (breakPointsParams.slidesPerView !== s.params.slidesPerView); 353 for ( var param in breakPointsParams ) { 354 s.params[param] = breakPointsParams[param]; 355 } 356 s.currentBreakpoint = breakpoint; 357 if(needsReLoop && s.destroyLoop) { 358 s.reLoop(true); 359 } 360 } 361 }; 362 // Set breakpoint on load 363 if (s.params.breakpoints) { 364 s.setBreakpoint(); 365 } 366 367 /*========================= 368 Preparation - Define Container, Wrapper and Pagination 369 ===========================*/ 370 s.container = $(container); 371 if (s.container.length === 0) return; 372 if (s.container.length > 1) { 373 var swipers = []; 374 s.container.each(function () { 375 var container = this; 376 swipers.push(new Swiper(this, params)); 377 }); 378 return swipers; 379 } 380 381 // Save instance in container HTML Element and in data 382 s.container[0].swiper = s; 383 s.container.data('swiper', s); 384 385 s.classNames.push(s.params.containerModifierClass + s.params.direction); 386 387 if (s.params.freeMode) { 388 s.classNames.push(s.params.containerModifierClass + 'free-mode'); 389 } 390 if (!s.support.flexbox) { 391 s.classNames.push(s.params.containerModifierClass + 'no-flexbox'); 392 s.params.slidesPerColumn = 1; 393 } 394 if (s.params.autoHeight) { 395 s.classNames.push(s.params.containerModifierClass + 'autoheight'); 396 } 397 // Enable slides progress when required 398 if (s.params.parallax || s.params.watchSlidesVisibility) { 399 s.params.watchSlidesProgress = true; 400 } 401 // Max resistance when touchReleaseOnEdges 402 if (s.params.touchReleaseOnEdges) { 403 s.params.resistanceRatio = 0; 404 } 405 // Coverflow / 3D 406 if (['cube', 'coverflow', 'flip'].indexOf(s.params.effect) >= 0) { 407 if (s.support.transforms3d) { 408 s.params.watchSlidesProgress = true; 409 s.classNames.push(s.params.containerModifierClass + '3d'); 410 } 411 else { 412 s.params.effect = 'slide'; 413 } 414 } 415 if (s.params.effect !== 'slide') { 416 s.classNames.push(s.params.containerModifierClass + s.params.effect); 417 } 418 if (s.params.effect === 'cube') { 419 s.params.resistanceRatio = 0; 420 s.params.slidesPerView = 1; 421 s.params.slidesPerColumn = 1; 422 s.params.slidesPerGroup = 1; 423 s.params.centeredSlides = false; 424 s.params.spaceBetween = 0; 425 s.params.virtualTranslate = true; 426 } 427 if (s.params.effect === 'fade' || s.params.effect === 'flip') { 428 s.params.slidesPerView = 1; 429 s.params.slidesPerColumn = 1; 430 s.params.slidesPerGroup = 1; 431 s.params.watchSlidesProgress = true; 432 s.params.spaceBetween = 0; 433 if (typeof initialVirtualTranslate === 'undefined') { 434 s.params.virtualTranslate = true; 435 } 436 } 437 438 // Grab Cursor 439 if (s.params.grabCursor && s.support.touch) { 440 s.params.grabCursor = false; 441 } 442 443 // Wrapper 444 s.wrapper = s.container.children('.' + s.params.wrapperClass); 445 446 // Pagination 447 if (s.params.pagination) { 448 s.paginationContainer = $(s.params.pagination); 449 if (s.params.uniqueNavElements && typeof s.params.pagination === 'string' && s.paginationContainer.length > 1 && s.container.find(s.params.pagination).length === 1) { 450 s.paginationContainer = s.container.find(s.params.pagination); 451 } 452 453 if (s.params.paginationType === 'bullets' && s.params.paginationClickable) { 454 s.paginationContainer.addClass(s.params.paginationModifierClass + 'clickable'); 455 } 456 else { 457 s.params.paginationClickable = false; 458 } 459 s.paginationContainer.addClass(s.params.paginationModifierClass + s.params.paginationType); 460 } 461 // Next/Prev Buttons 462 if (s.params.nextButton || s.params.prevButton) { 463 if (s.params.nextButton) { 464 s.nextButton = $(s.params.nextButton); 465 if (s.params.uniqueNavElements && typeof s.params.nextButton === 'string' && s.nextButton.length > 1 && s.container.find(s.params.nextButton).length === 1) { 466 s.nextButton = s.container.find(s.params.nextButton); 467 } 468 } 469 if (s.params.prevButton) { 470 s.prevButton = $(s.params.prevButton); 471 if (s.params.uniqueNavElements && typeof s.params.prevButton === 'string' && s.prevButton.length > 1 && s.container.find(s.params.prevButton).length === 1) { 472 s.prevButton = s.container.find(s.params.prevButton); 473 } 474 } 475 } 476 477 // Is Horizontal 478 s.isHorizontal = function () { 479 return s.params.direction === 'horizontal'; 480 }; 481 // s.isH = isH; 482 483 // RTL 484 s.rtl = s.isHorizontal() && (s.container[0].dir.toLowerCase() === 'rtl' || s.container.css('direction') === 'rtl'); 485 if (s.rtl) { 486 s.classNames.push(s.params.containerModifierClass + 'rtl'); 487 } 488 489 // Wrong RTL support 490 if (s.rtl) { 491 s.wrongRTL = s.wrapper.css('display') === '-webkit-box'; 492 } 493 494 // Columns 495 if (s.params.slidesPerColumn > 1) { 496 s.classNames.push(s.params.containerModifierClass + 'multirow'); 497 } 498 499 // Check for Android 500 if (s.device.android) { 501 s.classNames.push(s.params.containerModifierClass + 'android'); 502 } 503 504 // Add classes 505 s.container.addClass(s.classNames.join(' ')); 506 507 // Translate 508 s.translate = 0; 509 510 // Progress 511 s.progress = 0; 512 513 // Velocity 514 s.velocity = 0; 515 516 /*========================= 517 Locks, unlocks 518 ===========================*/ 519 s.lockSwipeToNext = function () { 520 s.params.allowSwipeToNext = false; 521 if (s.params.allowSwipeToPrev === false && s.params.grabCursor) { 522 s.unsetGrabCursor(); 523 } 524 }; 525 s.lockSwipeToPrev = function () { 526 s.params.allowSwipeToPrev = false; 527 if (s.params.allowSwipeToNext === false && s.params.grabCursor) { 528 s.unsetGrabCursor(); 529 } 530 }; 531 s.lockSwipes = function () { 532 s.params.allowSwipeToNext = s.params.allowSwipeToPrev = false; 533 if (s.params.grabCursor) s.unsetGrabCursor(); 534 }; 535 s.unlockSwipeToNext = function () { 536 s.params.allowSwipeToNext = true; 537 if (s.params.allowSwipeToPrev === true && s.params.grabCursor) { 538 s.setGrabCursor(); 539 } 540 }; 541 s.unlockSwipeToPrev = function () { 542 s.params.allowSwipeToPrev = true; 543 if (s.params.allowSwipeToNext === true && s.params.grabCursor) { 544 s.setGrabCursor(); 545 } 546 }; 547 s.unlockSwipes = function () { 548 s.params.allowSwipeToNext = s.params.allowSwipeToPrev = true; 549 if (s.params.grabCursor) s.setGrabCursor(); 550 }; 551 552 /*========================= 553 Round helper 554 ===========================*/ 555 function round(a) { 556 return Math.floor(a); 557 } 558 /*========================= 559 Set grab cursor 560 ===========================*/ 561 s.setGrabCursor = function(moving) { 562 s.container[0].style.cursor = 'move'; 563 s.container[0].style.cursor = moving ? '-webkit-grabbing' : '-webkit-grab'; 564 s.container[0].style.cursor = moving ? '-moz-grabbin' : '-moz-grab'; 565 s.container[0].style.cursor = moving ? 'grabbing': 'grab'; 566 }; 567 s.unsetGrabCursor = function () { 568 s.container[0].style.cursor = ''; 569 }; 570 if (s.params.grabCursor) { 571 s.setGrabCursor(); 572 } 573 /*========================= 574 Update on Images Ready 575 ===========================*/ 576 s.imagesToLoad = []; 577 s.imagesLoaded = 0; 578 579 s.loadImage = function (imgElement, src, srcset, sizes, checkForComplete, callback) { 580 var image; 581 function onReady () { 582 if (callback) callback(); 583 } 584 if (!imgElement.complete || !checkForComplete) { 585 if (src) { 586 image = new window.Image(); 587 image.onload = onReady; 588 image.onerror = onReady; 589 if (sizes) { 590 image.sizes = sizes; 591 } 592 if (srcset) { 593 image.srcset = srcset; 594 } 595 if (src) { 596 image.src = src; 597 } 598 } else { 599 onReady(); 600 } 601 602 } else {//image already loaded... 603 onReady(); 604 } 605 }; 606 s.preloadImages = function () { 607 s.imagesToLoad = s.container.find('img'); 608 function _onReady() { 609 if (typeof s === 'undefined' || s === null || !s) return; 610 if (s.imagesLoaded !== undefined) s.imagesLoaded++; 611 if (s.imagesLoaded === s.imagesToLoad.length) { 612 if (s.params.updateOnImagesReady) s.update(); 613 s.emit('onImagesReady', s); 614 } 615 } 616 for (var i = 0; i < s.imagesToLoad.length; i++) { 617 s.loadImage(s.imagesToLoad[i], (s.imagesToLoad[i].currentSrc || s.imagesToLoad[i].getAttribute('src')), (s.imagesToLoad[i].srcset || s.imagesToLoad[i].getAttribute('srcset')), s.imagesToLoad[i].sizes || s.imagesToLoad[i].getAttribute('sizes'), true, _onReady); 618 } 619 }; 620 621 /*========================= 622 Autoplay 623 ===========================*/ 624 s.autoplayTimeoutId = undefined; 625 s.autoplaying = false; 626 s.autoplayPaused = false; 627 function autoplay() { 628 var autoplayDelay = s.params.autoplay; 629 var activeSlide = s.slides.eq(s.activeIndex); 630 if (activeSlide.attr('data-swiper-autoplay')) { 631 autoplayDelay = activeSlide.attr('data-swiper-autoplay') || s.params.autoplay; 632 } 633 s.autoplayTimeoutId = setTimeout(function () { 634 if (s.params.loop) { 635 s.fixLoop(); 636 s._slideNext(); 637 s.emit('onAutoplay', s); 638 } 639 else { 640 if (!s.isEnd) { 641 s._slideNext(); 642 s.emit('onAutoplay', s); 643 } 644 else { 645 if (!params.autoplayStopOnLast) { 646 s._slideTo(0); 647 s.emit('onAutoplay', s); 648 } 649 else { 650 s.stopAutoplay(); 651 } 652 } 653 } 654 }, autoplayDelay); 655 } 656 s.startAutoplay = function () { 657 if (typeof s.autoplayTimeoutId !== 'undefined') return false; 658 if (!s.params.autoplay) return false; 659 if (s.autoplaying) return false; 660 s.autoplaying = true; 661 s.emit('onAutoplayStart', s); 662 autoplay(); 663 }; 664 s.stopAutoplay = function (internal) { 665 if (!s.autoplayTimeoutId) return; 666 if (s.autoplayTimeoutId) clearTimeout(s.autoplayTimeoutId); 667 s.autoplaying = false; 668 s.autoplayTimeoutId = undefined; 669 s.emit('onAutoplayStop', s); 670 }; 671 s.pauseAutoplay = function (speed) { 672 if (s.autoplayPaused) return; 673 if (s.autoplayTimeoutId) clearTimeout(s.autoplayTimeoutId); 674 s.autoplayPaused = true; 675 if (speed === 0) { 676 s.autoplayPaused = false; 677 autoplay(); 678 } 679 else { 680 s.wrapper.transitionEnd(function () { 681 if (!s) return; 682 s.autoplayPaused = false; 683 if (!s.autoplaying) { 684 s.stopAutoplay(); 685 } 686 else { 687 autoplay(); 688 } 689 }); 690 } 691 }; 692 /*========================= 693 Min/Max Translate 694 ===========================*/ 695 s.minTranslate = function () { 696 return (-s.snapGrid[0]); 697 }; 698 s.maxTranslate = function () { 699 return (-s.snapGrid[s.snapGrid.length - 1]); 700 }; 701 /*========================= 702 Slider/slides sizes 703 ===========================*/ 704 s.updateAutoHeight = function () { 705 var activeSlides = []; 706 var newHeight = 0; 707 var i; 708 709 // Find slides currently in view 710 if(s.params.slidesPerView !== 'auto' && s.params.slidesPerView > 1) { 711 for (i = 0; i < Math.ceil(s.params.slidesPerView); i++) { 712 var index = s.activeIndex + i; 713 if(index > s.slides.length) break; 714 activeSlides.push(s.slides.eq(index)[0]); 715 } 716 } else { 717 activeSlides.push(s.slides.eq(s.activeIndex)[0]); 718 } 719 720 // Find new height from heighest slide in view 721 for (i = 0; i < activeSlides.length; i++) { 722 if (typeof activeSlides[i] !== 'undefined') { 723 var height = activeSlides[i].offsetHeight; 724 newHeight = height > newHeight ? height : newHeight; 725 } 726 } 727 728 // Update Height 729 if (newHeight) s.wrapper.css('height', newHeight + 'px'); 730 }; 731 s.updateContainerSize = function () { 732 var width, height; 733 if (typeof s.params.width !== 'undefined') { 734 width = s.params.width; 735 } 736 else { 737 width = s.container[0].clientWidth; 738 } 739 if (typeof s.params.height !== 'undefined') { 740 height = s.params.height; 741 } 742 else { 743 height = s.container[0].clientHeight; 744 } 745 if (width === 0 && s.isHorizontal() || height === 0 && !s.isHorizontal()) { 746 return; 747 } 748 749 //Subtract paddings 750 width = width - parseInt(s.container.css('padding-left'), 10) - parseInt(s.container.css('padding-right'), 10); 751 height = height - parseInt(s.container.css('padding-top'), 10) - parseInt(s.container.css('padding-bottom'), 10); 752 753 // Store values 754 s.width = width; 755 s.height = height; 756 s.size = s.isHorizontal() ? s.width : s.height; 757 }; 758 759 s.updateSlidesSize = function () { 760 s.slides = s.wrapper.children('.' + s.params.slideClass); 761 s.snapGrid = []; 762 s.slidesGrid = []; 763 s.slidesSizesGrid = []; 764 765 var spaceBetween = s.params.spaceBetween, 766 slidePosition = -s.params.slidesOffsetBefore, 767 i, 768 prevSlideSize = 0, 769 index = 0; 770 if (typeof s.size === 'undefined') return; 771 if (typeof spaceBetween === 'string' && spaceBetween.indexOf('%') >= 0) { 772 spaceBetween = parseFloat(spaceBetween.replace('%', '')) / 100 * s.size; 773 } 774 775 s.virtualSize = -spaceBetween; 776 // reset margins 777 if (s.rtl) s.slides.css({marginLeft: '', marginTop: ''}); 778 else s.slides.css({marginRight: '', marginBottom: ''}); 779 780 var slidesNumberEvenToRows; 781 if (s.params.slidesPerColumn > 1) { 782 if (Math.floor(s.slides.length / s.params.slidesPerColumn) === s.slides.length / s.params.slidesPerColumn) { 783 slidesNumberEvenToRows = s.slides.length; 784 } 785 else { 786 slidesNumberEvenToRows = Math.ceil(s.slides.length / s.params.slidesPerColumn) * s.params.slidesPerColumn; 787 } 788 if (s.params.slidesPerView !== 'auto' && s.params.slidesPerColumnFill === 'row') { 789 slidesNumberEvenToRows = Math.max(slidesNumberEvenToRows, s.params.slidesPerView * s.params.slidesPerColumn); 790 } 791 } 792 793 // Calc slides 794 var slideSize; 795 var slidesPerColumn = s.params.slidesPerColumn; 796 var slidesPerRow = slidesNumberEvenToRows / slidesPerColumn; 797 var numFullColumns = slidesPerRow - (s.params.slidesPerColumn * slidesPerRow - s.slides.length); 798 for (i = 0; i < s.slides.length; i++) { 799 slideSize = 0; 800 var slide = s.slides.eq(i); 801 if (s.params.slidesPerColumn > 1) { 802 // Set slides order 803 var newSlideOrderIndex; 804 var column, row; 805 if (s.params.slidesPerColumnFill === 'column') { 806 column = Math.floor(i / slidesPerColumn); 807 row = i - column * slidesPerColumn; 808 if (column > numFullColumns || (column === numFullColumns && row === slidesPerColumn-1)) { 809 if (++row >= slidesPerColumn) { 810 row = 0; 811 column++; 812 } 813 } 814 newSlideOrderIndex = column + row * slidesNumberEvenToRows / slidesPerColumn; 815 slide 816 .css({ 817 '-webkit-box-ordinal-group': newSlideOrderIndex, 818 '-moz-box-ordinal-group': newSlideOrderIndex, 819 '-ms-flex-order': newSlideOrderIndex, 820 '-webkit-order': newSlideOrderIndex, 821 'order': newSlideOrderIndex 822 }); 823 } 824 else { 825 row = Math.floor(i / slidesPerRow); 826 column = i - row * slidesPerRow; 827 } 828 slide 829 .css( 830 'margin-' + (s.isHorizontal() ? 'top' : 'left'), 831 (row !== 0 && s.params.spaceBetween) && (s.params.spaceBetween + 'px') 832 ) 833 .attr('data-swiper-column', column) 834 .attr('data-swiper-row', row); 835 836 } 837 if (slide.css('display') === 'none') continue; 838 if (s.params.slidesPerView === 'auto') { 839 slideSize = s.isHorizontal() ? slide.outerWidth(true) : slide.outerHeight(true); 840 if (s.params.roundLengths) slideSize = round(slideSize); 841 } 842 else { 843 slideSize = (s.size - (s.params.slidesPerView - 1) * spaceBetween) / s.params.slidesPerView; 844 if (s.params.roundLengths) slideSize = round(slideSize); 845 846 if (s.isHorizontal()) { 847 s.slides[i].style.width = slideSize + 'px'; 848 } 849 else { 850 s.slides[i].style.height = slideSize + 'px'; 851 } 852 } 853 s.slides[i].swiperSlideSize = slideSize; 854 s.slidesSizesGrid.push(slideSize); 855 856 857 if (s.params.centeredSlides) { 858 slidePosition = slidePosition + slideSize / 2 + prevSlideSize / 2 + spaceBetween; 859 if(prevSlideSize === 0 && i !== 0) slidePosition = slidePosition - s.size / 2 - spaceBetween; 860 if (i === 0) slidePosition = slidePosition - s.size / 2 - spaceBetween; 861 if (Math.abs(slidePosition) < 1 / 1000) slidePosition = 0; 862 if ((index) % s.params.slidesPerGroup === 0) s.snapGrid.push(slidePosition); 863 s.slidesGrid.push(slidePosition); 864 } 865 else { 866 if ((index) % s.params.slidesPerGroup === 0) s.snapGrid.push(slidePosition); 867 s.slidesGrid.push(slidePosition); 868 slidePosition = slidePosition + slideSize + spaceBetween; 869 } 870 871 s.virtualSize += slideSize + spaceBetween; 872 873 prevSlideSize = slideSize; 874 875 index ++; 876 } 877 s.virtualSize = Math.max(s.virtualSize, s.size) + s.params.slidesOffsetAfter; 878 var newSlidesGrid; 879 880 if ( 881 s.rtl && s.wrongRTL && (s.params.effect === 'slide' || s.params.effect === 'coverflow')) { 882 s.wrapper.css({width: s.virtualSize + s.params.spaceBetween + 'px'}); 883 } 884 if (!s.support.flexbox || s.params.setWrapperSize) { 885 if (s.isHorizontal()) s.wrapper.css({width: s.virtualSize + s.params.spaceBetween + 'px'}); 886 else s.wrapper.css({height: s.virtualSize + s.params.spaceBetween + 'px'}); 887 } 888 889 if (s.params.slidesPerColumn > 1) { 890 s.virtualSize = (slideSize + s.params.spaceBetween) * slidesNumberEvenToRows; 891 s.virtualSize = Math.ceil(s.virtualSize / s.params.slidesPerColumn) - s.params.spaceBetween; 892 if (s.isHorizontal()) s.wrapper.css({width: s.virtualSize + s.params.spaceBetween + 'px'}); 893 else s.wrapper.css({height: s.virtualSize + s.params.spaceBetween + 'px'}); 894 if (s.params.centeredSlides) { 895 newSlidesGrid = []; 896 for (i = 0; i < s.snapGrid.length; i++) { 897 if (s.snapGrid[i] < s.virtualSize + s.snapGrid[0]) newSlidesGrid.push(s.snapGrid[i]); 898 } 899 s.snapGrid = newSlidesGrid; 900 } 901 } 902 903 // Remove last grid elements depending on width 904 if (!s.params.centeredSlides) { 905 newSlidesGrid = []; 906 for (i = 0; i < s.snapGrid.length; i++) { 907 if (s.snapGrid[i] <= s.virtualSize - s.size) { 908 newSlidesGrid.push(s.snapGrid[i]); 909 } 910 } 911 s.snapGrid = newSlidesGrid; 912 if (Math.floor(s.virtualSize - s.size) - Math.floor(s.snapGrid[s.snapGrid.length - 1]) > 1) { 913 s.snapGrid.push(s.virtualSize - s.size); 914 } 915 } 916 if (s.snapGrid.length === 0) s.snapGrid = [0]; 917 918 if (s.params.spaceBetween !== 0) { 919 if (s.isHorizontal()) { 920 if (s.rtl) s.slides.css({marginLeft: spaceBetween + 'px'}); 921 else s.slides.css({marginRight: spaceBetween + 'px'}); 922 } 923 else s.slides.css({marginBottom: spaceBetween + 'px'}); 924 } 925 if (s.params.watchSlidesProgress) { 926 s.updateSlidesOffset(); 927 } 928 }; 929 s.updateSlidesOffset = function () { 930 for (var i = 0; i < s.slides.length; i++) { 931 s.slides[i].swiperSlideOffset = s.isHorizontal() ? s.slides[i].offsetLeft : s.slides[i].offsetTop; 932 } 933 }; 934 935 /*========================= 936 Dynamic Slides Per View 937 ===========================*/ 938 s.currentSlidesPerView = function () { 939 var spv = 1, i, j; 940 if (s.params.centeredSlides) { 941 var size = s.slides[s.activeIndex].swiperSlideSize; 942 var breakLoop; 943 for (i = s.activeIndex + 1; i < s.slides.length; i++) { 944 if (s.slides[i] && !breakLoop) { 945 size += s.slides[i].swiperSlideSize; 946 spv ++; 947 if (size > s.size) breakLoop = true; 948 } 949 } 950 for (j = s.activeIndex - 1; j >= 0; j--) { 951 if (s.slides[j] && !breakLoop) { 952 size += s.slides[j].swiperSlideSize; 953 spv ++; 954 if (size > s.size) breakLoop = true; 955 } 956 } 957 } 958 else { 959 for (i = s.activeIndex + 1; i < s.slides.length; i++) { 960 if (s.slidesGrid[i] - s.slidesGrid[s.activeIndex] < s.size) { 961 spv++; 962 } 963 } 964 } 965 return spv; 966 }; 967 /*========================= 968 Slider/slides progress 969 ===========================*/ 970 s.updateSlidesProgress = function (translate) { 971 if (typeof translate === 'undefined') { 972 translate = s.translate || 0; 973 } 974 if (s.slides.length === 0) return; 975 if (typeof s.slides[0].swiperSlideOffset === 'undefined') s.updateSlidesOffset(); 976 977 var offsetCenter = -translate; 978 if (s.rtl) offsetCenter = translate; 979 980 // Visible Slides 981 s.slides.removeClass(s.params.slideVisibleClass); 982 for (var i = 0; i < s.slides.length; i++) { 983 var slide = s.slides[i]; 984 var slideProgress = (offsetCenter + (s.params.centeredSlides ? s.minTranslate() : 0) - slide.swiperSlideOffset) / (slide.swiperSlideSize + s.params.spaceBetween); 985 if (s.params.watchSlidesVisibility) { 986 var slideBefore = -(offsetCenter - slide.swiperSlideOffset); 987 var slideAfter = slideBefore + s.slidesSizesGrid[i]; 988 var isVisible = 989 (slideBefore >= 0 && slideBefore < s.size) || 990 (slideAfter > 0 && slideAfter <= s.size) || 991 (slideBefore <= 0 && slideAfter >= s.size); 992 if (isVisible) { 993 s.slides.eq(i).addClass(s.params.slideVisibleClass); 994 } 995 } 996 slide.progress = s.rtl ? -slideProgress : slideProgress; 997 } 998 }; 999 s.updateProgress = function (translate) { 1000 if (typeof translate === 'undefined') { 1001 translate = s.translate || 0; 1002 } 1003 var translatesDiff = s.maxTranslate() - s.minTranslate(); 1004 var wasBeginning = s.isBeginning; 1005 var wasEnd = s.isEnd; 1006 if (translatesDiff === 0) { 1007 s.progress = 0; 1008 s.isBeginning = s.isEnd = true; 1009 } 1010 else { 1011 s.progress = (translate - s.minTranslate()) / (translatesDiff); 1012 s.isBeginning = s.progress <= 0; 1013 s.isEnd = s.progress >= 1; 1014 } 1015 if (s.isBeginning && !wasBeginning) s.emit('onReachBeginning', s); 1016 if (s.isEnd && !wasEnd) s.emit('onReachEnd', s); 1017 1018 if (s.params.watchSlidesProgress) s.updateSlidesProgress(translate); 1019 s.emit('onProgress', s, s.progress); 1020 }; 1021 s.updateActiveIndex = function () { 1022 var translate = s.rtl ? s.translate : -s.translate; 1023 var newActiveIndex, i, snapIndex; 1024 for (i = 0; i < s.slidesGrid.length; i ++) { 1025 if (typeof s.slidesGrid[i + 1] !== 'undefined') { 1026 if (translate >= s.slidesGrid[i] && translate < s.slidesGrid[i + 1] - (s.slidesGrid[i + 1] - s.slidesGrid[i]) / 2) { 1027 newActiveIndex = i; 1028 } 1029 else if (translate >= s.slidesGrid[i] && translate < s.slidesGrid[i + 1]) { 1030 newActiveIndex = i + 1; 1031 } 1032 } 1033 else { 1034 if (translate >= s.slidesGrid[i]) { 1035 newActiveIndex = i; 1036 } 1037 } 1038 } 1039 // Normalize slideIndex 1040 if(s.params.normalizeSlideIndex){ 1041 if (newActiveIndex < 0 || typeof newActiveIndex === 'undefined') newActiveIndex = 0; 1042 } 1043 // for (i = 0; i < s.slidesGrid.length; i++) { 1044 // if (- translate >= s.slidesGrid[i]) { 1045 // newActiveIndex = i; 1046 // } 1047 // } 1048 snapIndex = Math.floor(newActiveIndex / s.params.slidesPerGroup); 1049 if (snapIndex >= s.snapGrid.length) snapIndex = s.snapGrid.length - 1; 1050 1051 if (newActiveIndex === s.activeIndex) { 1052 return; 1053 } 1054 s.snapIndex = snapIndex; 1055 s.previousIndex = s.activeIndex; 1056 s.activeIndex = newActiveIndex; 1057 s.updateClasses(); 1058 s.updateRealIndex(); 1059 }; 1060 s.updateRealIndex = function(){ 1061 s.realIndex = parseInt(s.slides.eq(s.activeIndex).attr('data-swiper-slide-index') || s.activeIndex, 10); 1062 }; 1063 1064 /*========================= 1065 Classes 1066 ===========================*/ 1067 s.updateClasses = function () { 1068 s.slides.removeClass(s.params.slideActiveClass + ' ' + s.params.slideNextClass + ' ' + s.params.slidePrevClass + ' ' + s.params.slideDuplicateActiveClass + ' ' + s.params.slideDuplicateNextClass + ' ' + s.params.slideDuplicatePrevClass); 1069 var activeSlide = s.slides.eq(s.activeIndex); 1070 // Active classes 1071 activeSlide.addClass(s.params.slideActiveClass); 1072 if (params.loop) { 1073 // Duplicate to all looped slides 1074 if (activeSlide.hasClass(s.params.slideDuplicateClass)) { 1075 s.wrapper.children('.' + s.params.slideClass + ':not(.' + s.params.slideDuplicateClass + ')[data-swiper-slide-index="' + s.realIndex + '"]').addClass(s.params.slideDuplicateActiveClass); 1076 } 1077 else { 1078 s.wrapper.children('.' + s.params.slideClass + '.' + s.params.slideDuplicateClass + '[data-swiper-slide-index="' + s.realIndex + '"]').addClass(s.params.slideDuplicateActiveClass); 1079 } 1080 } 1081 // Next Slide 1082 var nextSlide = activeSlide.next('.' + s.params.slideClass).addClass(s.params.slideNextClass); 1083 if (s.params.loop && nextSlide.length === 0) { 1084 nextSlide = s.slides.eq(0); 1085 nextSlide.addClass(s.params.slideNextClass); 1086 } 1087 // Prev Slide 1088 var prevSlide = activeSlide.prev('.' + s.params.slideClass).addClass(s.params.slidePrevClass); 1089 if (s.params.loop && prevSlide.length === 0) { 1090 prevSlide = s.slides.eq(-1); 1091 prevSlide.addClass(s.params.slidePrevClass); 1092 } 1093 if (params.loop) { 1094 // Duplicate to all looped slides 1095 if (nextSlide.hasClass(s.params.slideDuplicateClass)) { 1096 s.wrapper.children('.' + s.params.slideClass + ':not(.' + s.params.slideDuplicateClass + ')[data-swiper-slide-index="' + nextSlide.attr('data-swiper-slide-index') + '"]').addClass(s.params.slideDuplicateNextClass); 1097 } 1098 else { 1099 s.wrapper.children('.' + s.params.slideClass + '.' + s.params.slideDuplicateClass + '[data-swiper-slide-index="' + nextSlide.attr('data-swiper-slide-index') + '"]').addClass(s.params.slideDuplicateNextClass); 1100 } 1101 if (prevSlide.hasClass(s.params.slideDuplicateClass)) { 1102 s.wrapper.children('.' + s.params.slideClass + ':not(.' + s.params.slideDuplicateClass + ')[data-swiper-slide-index="' + prevSlide.attr('data-swiper-slide-index') + '"]').addClass(s.params.slideDuplicatePrevClass); 1103 } 1104 else { 1105 s.wrapper.children('.' + s.params.slideClass + '.' + s.params.slideDuplicateClass + '[data-swiper-slide-index="' + prevSlide.attr('data-swiper-slide-index') + '"]').addClass(s.params.slideDuplicatePrevClass); 1106 } 1107 } 1108 1109 // Pagination 1110 if (s.paginationContainer && s.paginationContainer.length > 0) { 1111 // Current/Total 1112 var current, 1113 total = s.params.loop ? Math.ceil((s.slides.length - s.loopedSlides * 2) / s.params.slidesPerGroup) : s.snapGrid.length; 1114 if (s.params.loop) { 1115 current = Math.ceil((s.activeIndex - s.loopedSlides)/s.params.slidesPerGroup); 1116 if (current > s.slides.length - 1 - s.loopedSlides * 2) { 1117 current = current - (s.slides.length - s.loopedSlides * 2); 1118 } 1119 if (current > total - 1) current = current - total; 1120 if (current < 0 && s.params.paginationType !== 'bullets') current = total + current; 1121 } 1122 else { 1123 if (typeof s.snapIndex !== 'undefined') { 1124 current = s.snapIndex; 1125 } 1126 else { 1127 current = s.activeIndex || 0; 1128 } 1129 } 1130 // Types 1131 if (s.params.paginationType === 'bullets' && s.bullets && s.bullets.length > 0) { 1132 s.bullets.removeClass(s.params.bulletActiveClass); 1133 if (s.paginationContainer.length > 1) { 1134 s.bullets.each(function () { 1135 if ($(this).index() === current) $(this).addClass(s.params.bulletActiveClass); 1136 }); 1137 } 1138 else { 1139 s.bullets.eq(current).addClass(s.params.bulletActiveClass); 1140 } 1141 } 1142 if (s.params.paginationType === 'fraction') { 1143 s.paginationContainer.find('.' + s.params.paginationCurrentClass).text(current + 1); 1144 s.paginationContainer.find('.' + s.params.paginationTotalClass).text(total); 1145 } 1146 if (s.params.paginationType === 'progress') { 1147 var scale = (current + 1) / total, 1148 scaleX = scale, 1149 scaleY = 1; 1150 if (!s.isHorizontal()) { 1151 scaleY = scale; 1152 scaleX = 1; 1153 } 1154 s.paginationContainer.find('.' + s.params.paginationProgressbarClass).transform('translate3d(0,0,0) scaleX(' + scaleX + ') scaleY(' + scaleY + ')').transition(s.params.speed); 1155 } 1156 if (s.params.paginationType === 'custom' && s.params.paginationCustomRender) { 1157 s.paginationContainer.html(s.params.paginationCustomRender(s, current + 1, total)); 1158 s.emit('onPaginationRendered', s, s.paginationContainer[0]); 1159 } 1160 } 1161 1162 // Next/active buttons 1163 if (!s.params.loop) { 1164 if (s.params.prevButton && s.prevButton && s.prevButton.length > 0) { 1165 if (s.isBeginning) { 1166 s.prevButton.addClass(s.params.buttonDisabledClass); 1167 if (s.params.a11y && s.a11y) s.a11y.disable(s.prevButton); 1168 } 1169 else { 1170 s.prevButton.removeClass(s.params.buttonDisabledClass); 1171 if (s.params.a11y && s.a11y) s.a11y.enable(s.prevButton); 1172 } 1173 } 1174 if (s.params.nextButton && s.nextButton && s.nextButton.length > 0) { 1175 if (s.isEnd) { 1176 s.nextButton.addClass(s.params.buttonDisabledClass); 1177 if (s.params.a11y && s.a11y) s.a11y.disable(s.nextButton); 1178 } 1179 else { 1180 s.nextButton.removeClass(s.params.buttonDisabledClass); 1181 if (s.params.a11y && s.a11y) s.a11y.enable(s.nextButton); 1182 } 1183 } 1184 } 1185 }; 1186 1187 /*========================= 1188 Pagination 1189 ===========================*/ 1190 s.updatePagination = function () { 1191 if (!s.params.pagination) return; 1192 if (s.paginationContainer && s.paginationContainer.length > 0) { 1193 var paginationHTML = ''; 1194 if (s.params.paginationType === 'bullets') { 1195 var numberOfBullets = s.params.loop ? Math.ceil((s.slides.length - s.loopedSlides * 2) / s.params.slidesPerGroup) : s.snapGrid.length; 1196 for (var i = 0; i < numberOfBullets; i++) { 1197 if (s.params.paginationBulletRender) { 1198 paginationHTML += s.params.paginationBulletRender(s, i, s.params.bulletClass); 1199 } 1200 else { 1201 paginationHTML += '<' + s.params.paginationElement+' class="' + s.params.bulletClass + '"></' + s.params.paginationElement + '>'; 1202 } 1203 } 1204 s.paginationContainer.html(paginationHTML); 1205 s.bullets = s.paginationContainer.find('.' + s.params.bulletClass); 1206 if (s.params.paginationClickable && s.params.a11y && s.a11y) { 1207 s.a11y.initPagination(); 1208 } 1209 } 1210 if (s.params.paginationType === 'fraction') { 1211 if (s.params.paginationFractionRender) { 1212 paginationHTML = s.params.paginationFractionRender(s, s.params.paginationCurrentClass, s.params.paginationTotalClass); 1213 } 1214 else { 1215 paginationHTML = 1216 '<span class="' + s.params.paginationCurrentClass + '"></span>' + 1217 ' / ' + 1218 '<span class="' + s.params.paginationTotalClass+'"></span>'; 1219 } 1220 s.paginationContainer.html(paginationHTML); 1221 } 1222 if (s.params.paginationType === 'progress') { 1223 if (s.params.paginationProgressRender) { 1224 paginationHTML = s.params.paginationProgressRender(s, s.params.paginationProgressbarClass); 1225 } 1226 else { 1227 paginationHTML = '<span class="' + s.params.paginationProgressbarClass + '"></span>'; 1228 } 1229 s.paginationContainer.html(paginationHTML); 1230 } 1231 if (s.params.paginationType !== 'custom') { 1232 s.emit('onPaginationRendered', s, s.paginationContainer[0]); 1233 } 1234 } 1235 }; 1236 /*========================= 1237 Common update method 1238 ===========================*/ 1239 s.update = function (updateTranslate) { 1240 if (!s) return; 1241 s.updateContainerSize(); 1242 s.updateSlidesSize(); 1243 s.updateProgress(); 1244 s.updatePagination(); 1245 s.updateClasses(); 1246 if (s.params.scrollbar && s.scrollbar) { 1247 s.scrollbar.set(); 1248 } 1249 var newTranslate; 1250 function forceSetTranslate() { 1251 var translate = s.rtl ? -s.translate : s.translate; 1252 newTranslate = Math.min(Math.max(s.translate, s.maxTranslate()), s.minTranslate()); 1253 s.setWrapperTranslate(newTranslate); 1254 s.updateActiveIndex(); 1255 s.updateClasses(); 1256 } 1257 if (updateTranslate) { 1258 var translated; 1259 if (s.controller && s.controller.spline) { 1260 s.controller.spline = undefined; 1261 } 1262 if (s.params.freeMode) { 1263 forceSetTranslate(); 1264 if (s.params.autoHeight) { 1265 s.updateAutoHeight(); 1266 } 1267 } 1268 else { 1269 if ((s.params.slidesPerView === 'auto' || s.params.slidesPerView > 1) && s.isEnd && !s.params.centeredSlides) { 1270 translated = s.slideTo(s.slides.length - 1, 0, false, true); 1271 } 1272 else { 1273 translated = s.slideTo(s.activeIndex, 0, false, true); 1274 } 1275 if (!translated) { 1276 forceSetTranslate(); 1277 } 1278 } 1279 } 1280 else if (s.params.autoHeight) { 1281 s.updateAutoHeight(); 1282 } 1283 }; 1284 1285 /*========================= 1286 Resize Handler 1287 ===========================*/ 1288 s.onResize = function (forceUpdatePagination) { 1289 if (s.params.onBeforeResize) s.params.onBeforeResize(s); 1290 //Breakpoints 1291 if (s.params.breakpoints) { 1292 s.setBreakpoint(); 1293 } 1294 1295 // Disable locks on resize 1296 var allowSwipeToPrev = s.params.allowSwipeToPrev; 1297 var allowSwipeToNext = s.params.allowSwipeToNext; 1298 s.params.allowSwipeToPrev = s.params.allowSwipeToNext = true; 1299 1300 s.updateContainerSize(); 1301 s.updateSlidesSize(); 1302 if (s.params.slidesPerView === 'auto' || s.params.freeMode || forceUpdatePagination) s.updatePagination(); 1303 if (s.params.scrollbar && s.scrollbar) { 1304 s.scrollbar.set(); 1305 } 1306 if (s.controller && s.controller.spline) { 1307 s.controller.spline = undefined; 1308 } 1309 var slideChangedBySlideTo = false; 1310 if (s.params.freeMode) { 1311 var newTranslate = Math.min(Math.max(s.translate, s.maxTranslate()), s.minTranslate()); 1312 s.setWrapperTranslate(newTranslate); 1313 s.updateActiveIndex(); 1314 s.updateClasses(); 1315 1316 if (s.params.autoHeight) { 1317 s.updateAutoHeight(); 1318 } 1319 } 1320 else { 1321 s.updateClasses(); 1322 if ((s.params.slidesPerView === 'auto' || s.params.slidesPerView > 1) && s.isEnd && !s.params.centeredSlides) { 1323 slideChangedBySlideTo = s.slideTo(s.slides.length - 1, 0, false, true); 1324 } 1325 else { 1326 slideChangedBySlideTo = s.slideTo(s.activeIndex, 0, false, true); 1327 } 1328 } 1329 if (s.params.lazyLoading && !slideChangedBySlideTo && s.lazy) { 1330 s.lazy.load(); 1331 } 1332 // Return locks after resize 1333 s.params.allowSwipeToPrev = allowSwipeToPrev; 1334 s.params.allowSwipeToNext = allowSwipeToNext; 1335 if (s.params.onAfterResize) s.params.onAfterResize(s); 1336 }; 1337 1338 /*========================= 1339 Events 1340 ===========================*/ 1341 1342 //Define Touch Events 1343 s.touchEventsDesktop = {start: 'mousedown', move: 'mousemove', end: 'mouseup'}; 1344 if (window.navigator.pointerEnabled) s.touchEventsDesktop = {start: 'pointerdown', move: 'pointermove', end: 'pointerup'}; 1345 else if (window.navigator.msPointerEnabled) s.touchEventsDesktop = {start: 'MSPointerDown', move: 'MSPointerMove', end: 'MSPointerUp'}; 1346 s.touchEvents = { 1347 start : s.support.touch || !s.params.simulateTouch ? 'touchstart' : s.touchEventsDesktop.start, 1348 move : s.support.touch || !s.params.simulateTouch ? 'touchmove' : s.touchEventsDesktop.move, 1349 end : s.support.touch || !s.params.simulateTouch ? 'touchend' : s.touchEventsDesktop.end 1350 }; 1351 1352 1353 // WP8 Touch Events Fix 1354 if (window.navigator.pointerEnabled || window.navigator.msPointerEnabled) { 1355 (s.params.touchEventsTarget === 'container' ? s.container : s.wrapper).addClass('swiper-wp8-' + s.params.direction); 1356 } 1357 1358 // Attach/detach events 1359 s.initEvents = function (detach) { 1360 var actionDom = detach ? 'off' : 'on'; 1361 var action = detach ? 'removeEventListener' : 'addEventListener'; 1362 var touchEventsTarget = s.params.touchEventsTarget === 'container' ? s.container[0] : s.wrapper[0]; 1363 var target = s.support.touch ? touchEventsTarget : document; 1364 1365 var moveCapture = s.params.nested ? true : false; 1366 1367 //Touch Events 1368 if (s.browser.ie) { 1369 touchEventsTarget[action](s.touchEvents.start, s.onTouchStart, false); 1370 target[action](s.touchEvents.move, s.onTouchMove, moveCapture); 1371 target[action](s.touchEvents.end, s.onTouchEnd, false); 1372 } 1373 else { 1374 if (s.support.touch) { 1375 var passiveListener = s.touchEvents.start === 'touchstart' && s.support.passiveListener && s.params.passiveListeners ? {passive: true, capture: false} : false; 1376 touchEventsTarget[action](s.touchEvents.start, s.onTouchStart, passiveListener); 1377 touchEventsTarget[action](s.touchEvents.move, s.onTouchMove, moveCapture); 1378 touchEventsTarget[action](s.touchEvents.end, s.onTouchEnd, passiveListener); 1379 } 1380 if ((params.simulateTouch && !s.device.ios && !s.device.android) || (params.simulateTouch && !s.support.touch && s.device.ios)) { 1381 touchEventsTarget[action]('mousedown', s.onTouchStart, false); 1382 document[action]('mousemove', s.onTouchMove, moveCapture); 1383 document[action]('mouseup', s.onTouchEnd, false); 1384 } 1385 } 1386 window[action]('resize', s.onResize); 1387 1388 // Next, Prev, Index 1389 if (s.params.nextButton && s.nextButton && s.nextButton.length > 0) { 1390 s.nextButton[actionDom]('click', s.onClickNext); 1391 if (s.params.a11y && s.a11y) s.nextButton[actionDom]('keydown', s.a11y.onEnterKey); 1392 } 1393 if (s.params.prevButton && s.prevButton && s.prevButton.length > 0) { 1394 s.prevButton[actionDom]('click', s.onClickPrev); 1395 if (s.params.a11y && s.a11y) s.prevButton[actionDom]('keydown', s.a11y.onEnterKey); 1396 } 1397 if (s.params.pagination && s.params.paginationClickable) { 1398 s.paginationContainer[actionDom]('click', '.' + s.params.bulletClass, s.onClickIndex); 1399 if (s.params.a11y && s.a11y) s.paginationContainer[actionDom]('keydown', '.' + s.params.bulletClass, s.a11y.onEnterKey); 1400 } 1401 1402 // Prevent Links Clicks 1403 if (s.params.preventClicks || s.params.preventClicksPropagation) touchEventsTarget[action]('click', s.preventClicks, true); 1404 }; 1405 s.attachEvents = function () { 1406 s.initEvents(); 1407 }; 1408 s.detachEvents = function () { 1409 s.initEvents(true); 1410 }; 1411 1412 /*========================= 1413 Handle Clicks 1414 ===========================*/ 1415 // Prevent Clicks 1416 s.allowClick = true; 1417 s.preventClicks = function (e) { 1418 if (!s.allowClick) { 1419 if (s.params.preventClicks) e.preventDefault(); 1420 if (s.params.preventClicksPropagation && s.animating) { 1421 e.stopPropagation(); 1422 e.stopImmediatePropagation(); 1423 } 1424 } 1425 }; 1426 // Clicks 1427 s.onClickNext = function (e) { 1428 e.preventDefault(); 1429 if (s.isEnd && !s.params.loop) return; 1430 s.slideNext(); 1431 }; 1432 s.onClickPrev = function (e) { 1433 e.preventDefault(); 1434 if (s.isBeginning && !s.params.loop) return; 1435 s.slidePrev(); 1436 }; 1437 s.onClickIndex = function (e) { 1438 e.preventDefault(); 1439 var index = $(this).index() * s.params.slidesPerGroup; 1440 if (s.params.loop) index = index + s.loopedSlides; 1441 s.slideTo(index); 1442 }; 1443 1444 /*========================= 1445 Handle Touches 1446 ===========================*/ 1447 function findElementInEvent(e, selector) { 1448 var el = $(e.target); 1449 if (!el.is(selector)) { 1450 if (typeof selector === 'string') { 1451 el = el.parents(selector); 1452 } 1453 else if (selector.nodeType) { 1454 var found; 1455 el.parents().each(function (index, _el) { 1456 if (_el === selector) found = selector; 1457 }); 1458 if (!found) return undefined; 1459 else return selector; 1460 } 1461 } 1462 if (el.length === 0) { 1463 return undefined; 1464 } 1465 return el[0]; 1466 } 1467 s.updateClickedSlide = function (e) { 1468 var slide = findElementInEvent(e, '.' + s.params.slideClass); 1469 var slideFound = false; 1470 if (slide) { 1471 for (var i = 0; i < s.slides.length; i++) { 1472 if (s.slides[i] === slide) slideFound = true; 1473 } 1474 } 1475 1476 if (slide && slideFound) { 1477 s.clickedSlide = slide; 1478 s.clickedIndex = $(slide).index(); 1479 } 1480 else { 1481 s.clickedSlide = undefined; 1482 s.clickedIndex = undefined; 1483 return; 1484 } 1485 if (s.params.slideToClickedSlide && s.clickedIndex !== undefined && s.clickedIndex !== s.activeIndex) { 1486 var slideToIndex = s.clickedIndex, 1487 realIndex, 1488 duplicatedSlides, 1489 slidesPerView = s.params.slidesPerView === 'auto' ? s.currentSlidesPerView() : s.params.slidesPerView; 1490 if (s.params.loop) { 1491 if (s.animating) return; 1492 realIndex = parseInt($(s.clickedSlide).attr('data-swiper-slide-index'), 10); 1493 if (s.params.centeredSlides) { 1494 if ((slideToIndex < s.loopedSlides - slidesPerView/2) || (slideToIndex > s.slides.length - s.loopedSlides + slidesPerView/2)) { 1495 s.fixLoop(); 1496 slideToIndex = s.wrapper.children('.' + s.params.slideClass + '[data-swiper-slide-index="' + realIndex + '"]:not(.' + s.params.slideDuplicateClass + ')').eq(0).index(); 1497 setTimeout(function () { 1498 s.slideTo(slideToIndex); 1499 }, 0); 1500 } 1501 else { 1502 s.slideTo(slideToIndex); 1503 } 1504 } 1505 else { 1506 if (slideToIndex > s.slides.length - slidesPerView) { 1507 s.fixLoop(); 1508 slideToIndex = s.wrapper.children('.' + s.params.slideClass + '[data-swiper-slide-index="' + realIndex + '"]:not(.' + s.params.slideDuplicateClass + ')').eq(0).index(); 1509 setTimeout(function () { 1510 s.slideTo(slideToIndex); 1511 }, 0); 1512 } 1513 else { 1514 s.slideTo(slideToIndex); 1515 } 1516 } 1517 } 1518 else { 1519 s.slideTo(slideToIndex); 1520 } 1521 } 1522 }; 1523 1524 var isTouched, 1525 isMoved, 1526 allowTouchCallbacks, 1527 touchStartTime, 1528 isScrolling, 1529 currentTranslate, 1530 startTranslate, 1531 allowThresholdMove, 1532 // Form elements to match 1533 formElements = 'input, select, textarea, button, video', 1534 // Last click time 1535 lastClickTime = Date.now(), clickTimeout, 1536 //Velocities 1537 velocities = [], 1538 allowMomentumBounce; 1539 1540 // Animating Flag 1541 s.animating = false; 1542 1543 // Touches information 1544 s.touches = { 1545 startX: 0, 1546 startY: 0, 1547 currentX: 0, 1548 currentY: 0, 1549 diff: 0 1550 }; 1551 1552 // Touch handlers 1553 var isTouchEvent, startMoving; 1554 s.onTouchStart = function (e) { 1555 if (e.originalEvent) e = e.originalEvent; 1556 isTouchEvent = e.type === 'touchstart'; 1557 if (!isTouchEvent && 'which' in e && e.which === 3) return; 1558 if (s.params.noSwiping && findElementInEvent(e, '.' + s.params.noSwipingClass)) { 1559 s.allowClick = true; 1560 return; 1561 } 1562 if (s.params.swipeHandler) { 1563 if (!findElementInEvent(e, s.params.swipeHandler)) return; 1564 } 1565 1566 var startX = s.touches.currentX = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX; 1567 var startY = s.touches.currentY = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY; 1568 1569 // Do NOT start if iOS edge swipe is detected. Otherwise iOS app (UIWebView) cannot swipe-to-go-back anymore 1570 if(s.device.ios && s.params.iOSEdgeSwipeDetection && startX <= s.params.iOSEdgeSwipeThreshold) { 1571 return; 1572 } 1573 1574 isTouched = true; 1575 isMoved = false; 1576 allowTouchCallbacks = true; 1577 isScrolling = undefined; 1578 startMoving = undefined; 1579 s.touches.startX = startX; 1580 s.touches.startY = startY; 1581 touchStartTime = Date.now(); 1582 s.allowClick = true; 1583 s.updateContainerSize(); 1584 s.swipeDirection = undefined; 1585 if (s.params.threshold > 0) allowThresholdMove = false; 1586 if (e.type !== 'touchstart') { 1587 var preventDefault = true; 1588 if ($(e.target).is(formElements)) preventDefault = false; 1589 if (document.activeElement && $(document.activeElement).is(formElements)) { 1590 document.activeElement.blur(); 1591 } 1592 if (preventDefault) { 1593 e.preventDefault(); 1594 } 1595 } 1596 s.emit('onTouchStart', s, e); 1597 }; 1598 1599 s.onTouchMove = function (e) { 1600 if (e.originalEvent) e = e.originalEvent; 1601 if (isTouchEvent && e.type === 'mousemove') return; 1602 if (e.preventedByNestedSwiper) { 1603 s.touches.startX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX; 1604 s.touches.startY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY; 1605 return; 1606 } 1607 if (s.params.onlyExternal) { 1608 // isMoved = true; 1609 s.allowClick = false; 1610 if (isTouched) { 1611 s.touches.startX = s.touches.currentX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX; 1612 s.touches.startY = s.touches.currentY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY; 1613 touchStartTime = Date.now(); 1614 } 1615 return; 1616 } 1617 if (isTouchEvent && s.params.touchReleaseOnEdges && !s.params.loop) { 1618 if (!s.isHorizontal()) { 1619 // Vertical 1620 if ( 1621 (s.touches.currentY < s.touches.startY && s.translate <= s.maxTranslate()) || 1622 (s.touches.currentY > s.touches.startY && s.translate >= s.minTranslate()) 1623 ) { 1624 return; 1625 } 1626 } 1627 else { 1628 if ( 1629 (s.touches.currentX < s.touches.startX && s.translate <= s.maxTranslate()) || 1630 (s.touches.currentX > s.touches.startX && s.translate >= s.minTranslate()) 1631 ) { 1632 return; 1633 } 1634 } 1635 } 1636 if (isTouchEvent && document.activeElement) { 1637 if (e.target === document.activeElement && $(e.target).is(formElements)) { 1638 isMoved = true; 1639 s.allowClick = false; 1640 return; 1641 } 1642 } 1643 if (allowTouchCallbacks) { 1644 s.emit('onTouchMove', s, e); 1645 } 1646 if (e.targetTouches && e.targetTouches.length > 1) return; 1647 1648 s.touches.currentX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX; 1649 s.touches.currentY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY; 1650 1651 if (typeof isScrolling === 'undefined') { 1652 var touchAngle; 1653 if (s.isHorizontal() && s.touches.currentY === s.touches.startY || !s.isHorizontal() && s.touches.currentX === s.touches.startX) { 1654 isScrolling = false; 1655 } 1656 else { 1657 touchAngle = Math.atan2(Math.abs(s.touches.currentY - s.touches.startY), Math.abs(s.touches.currentX - s.touches.startX)) * 180 / Math.PI; 1658 isScrolling = s.isHorizontal() ? touchAngle > s.params.touchAngle : (90 - touchAngle > s.params.touchAngle); 1659 } 1660 } 1661 if (isScrolling) { 1662 s.emit('onTouchMoveOpposite', s, e); 1663 } 1664 if (typeof startMoving === 'undefined') { 1665 if (s.touches.currentX !== s.touches.startX || s.touches.currentY !== s.touches.startY) { 1666 startMoving = true; 1667 } 1668 } 1669 if (!isTouched) return; 1670 if (isScrolling) { 1671 isTouched = false; 1672 return; 1673 } 1674 if (!startMoving) { 1675 return; 1676 } 1677 s.allowClick = false; 1678 s.emit('onSliderMove', s, e); 1679 e.preventDefault(); 1680 if (s.params.touchMoveStopPropagation && !s.params.nested) { 1681 e.stopPropagation(); 1682 } 1683 1684 if (!isMoved) { 1685 if (params.loop) { 1686 s.fixLoop(); 1687 } 1688 startTranslate = s.getWrapperTranslate(); 1689 s.setWrapperTransition(0); 1690 if (s.animating) { 1691 s.wrapper.trigger('webkitTransitionEnd transitionend oTransitionEnd MSTransitionEnd msTransitionEnd'); 1692 } 1693 if (s.params.autoplay && s.autoplaying) { 1694 if (s.params.autoplayDisableOnInteraction) { 1695 s.stopAutoplay(); 1696 } 1697 else { 1698 s.pauseAutoplay(); 1699 } 1700 } 1701 allowMomentumBounce = false; 1702 //Grab Cursor 1703 if (s.params.grabCursor && (s.params.allowSwipeToNext === true || s.params.allowSwipeToPrev === true)) { 1704 s.setGrabCursor(true); 1705 } 1706 } 1707 isMoved = true; 1708 1709 var diff = s.touches.diff = s.isHorizontal() ? s.touches.currentX - s.touches.startX : s.touches.currentY - s.touches.startY; 1710 1711 diff = diff * s.params.touchRatio; 1712 if (s.rtl) diff = -diff; 1713 1714 s.swipeDirection = diff > 0 ? 'prev' : 'next'; 1715 currentTranslate = diff + startTranslate; 1716 1717 var disableParentSwiper = true; 1718 if ((diff > 0 && currentTranslate > s.minTranslate())) { 1719 disableParentSwiper = false; 1720 if (s.params.resistance) currentTranslate = s.minTranslate() - 1 + Math.pow(-s.minTranslate() + startTranslate + diff, s.params.resistanceRatio); 1721 } 1722 else if (diff < 0 && currentTranslate < s.maxTranslate()) { 1723 disableParentSwiper = false; 1724 if (s.params.resistance) currentTranslate = s.maxTranslate() + 1 - Math.pow(s.maxTranslate() - startTranslate - diff, s.params.resistanceRatio); 1725 } 1726 1727 if (disableParentSwiper) { 1728 e.preventedByNestedSwiper = true; 1729 } 1730 1731 // Directions locks 1732 if (!s.params.allowSwipeToNext && s.swipeDirection === 'next' && currentTranslate < startTranslate) { 1733 currentTranslate = startTranslate; 1734 } 1735 if (!s.params.allowSwipeToPrev && s.swipeDirection === 'prev' && currentTranslate > startTranslate) { 1736 currentTranslate = startTranslate; 1737 } 1738 1739 1740 // Threshold 1741 if (s.params.threshold > 0) { 1742 if (Math.abs(diff) > s.params.threshold || allowThresholdMove) { 1743 if (!allowThresholdMove) { 1744 allowThresholdMove = true; 1745 s.touches.startX = s.touches.currentX; 1746 s.touches.startY = s.touches.currentY; 1747 currentTranslate = startTranslate; 1748 s.touches.diff = s.isHorizontal() ? s.touches.currentX - s.touches.startX : s.touches.currentY - s.touches.startY; 1749 return; 1750 } 1751 } 1752 else { 1753 currentTranslate = startTranslate; 1754 return; 1755 } 1756 } 1757 1758 if (!s.params.followFinger) return; 1759 1760 // Update active index in free mode 1761 if (s.params.freeMode || s.params.watchSlidesProgress) { 1762 s.updateActiveIndex(); 1763 } 1764 if (s.params.freeMode) { 1765 //Velocity 1766 if (velocities.length === 0) { 1767 velocities.push({ 1768 position: s.touches[s.isHorizontal() ? 'startX' : 'startY'], 1769 time: touchStartTime 1770 }); 1771 } 1772 velocities.push({ 1773 position: s.touches[s.isHorizontal() ? 'currentX' : 'currentY'], 1774 time: (new window.Date()).getTime() 1775 }); 1776 } 1777 // Update progress 1778 s.updateProgress(currentTranslate); 1779 // Update translate 1780 s.setWrapperTranslate(currentTranslate); 1781 }; 1782 s.onTouchEnd = function (e) { 1783 if (e.originalEvent) e = e.originalEvent; 1784 if (allowTouchCallbacks) { 1785 s.emit('onTouchEnd', s, e); 1786 } 1787 allowTouchCallbacks = false; 1788 if (!isTouched) return; 1789 //Return Grab Cursor 1790 if (s.params.grabCursor && isMoved && isTouched && (s.params.allowSwipeToNext === true || s.params.allowSwipeToPrev === true)) { 1791 s.setGrabCursor(false); 1792 } 1793 1794 // Time diff 1795 var touchEndTime = Date.now(); 1796 var timeDiff = touchEndTime - touchStartTime; 1797 1798 // Tap, doubleTap, Click 1799 if (s.allowClick) { 1800 s.updateClickedSlide(e); 1801 s.emit('onTap', s, e); 1802 if (timeDiff < 300 && (touchEndTime - lastClickTime) > 300) { 1803 if (clickTimeout) clearTimeout(clickTimeout); 1804 clickTimeout = setTimeout(function () { 1805 if (!s) return; 1806 if (s.params.paginationHide && s.paginationContainer.length > 0 && !$(e.target).hasClass(s.params.bulletClass)) { 1807 s.paginationContainer.toggleClass(s.params.paginationHiddenClass); 1808 } 1809 s.emit('onClick', s, e); 1810 }, 300); 1811 1812 } 1813 if (timeDiff < 300 && (touchEndTime - lastClickTime) < 300) { 1814 if (clickTimeout) clearTimeout(clickTimeout); 1815 s.emit('onDoubleTap', s, e); 1816 } 1817 } 1818 1819 lastClickTime = Date.now(); 1820 setTimeout(function () { 1821 if (s) s.allowClick = true; 1822 }, 0); 1823 1824 if (!isTouched || !isMoved || !s.swipeDirection || s.touches.diff === 0 || currentTranslate === startTranslate) { 1825 isTouched = isMoved = false; 1826 return; 1827 } 1828 isTouched = isMoved = false; 1829 1830 var currentPos; 1831 if (s.params.followFinger) { 1832 currentPos = s.rtl ? s.translate : -s.translate; 1833 } 1834 else { 1835 currentPos = -currentTranslate; 1836 } 1837 if (s.params.freeMode) { 1838 if (currentPos < -s.minTranslate()) { 1839 s.slideTo(s.activeIndex); 1840 return; 1841 } 1842 else if (currentPos > -s.maxTranslate()) { 1843 if (s.slides.length < s.snapGrid.length) { 1844 s.slideTo(s.snapGrid.length - 1); 1845 } 1846 else { 1847 s.slideTo(s.slides.length - 1); 1848 } 1849 return; 1850 } 1851 1852 if (s.params.freeModeMomentum) { 1853 if (velocities.length > 1) { 1854 var lastMoveEvent = velocities.pop(), velocityEvent = velocities.pop(); 1855 1856 var distance = lastMoveEvent.position - velocityEvent.position; 1857 var time = lastMoveEvent.time - velocityEvent.time; 1858 s.velocity = distance / time; 1859 s.velocity = s.velocity / 2; 1860 if (Math.abs(s.velocity) < s.params.freeModeMinimumVelocity) { 1861 s.velocity = 0; 1862 } 1863 // this implies that the user stopped moving a finger then released. 1864 // There would be no events with distance zero, so the last event is stale. 1865 if (time > 150 || (new window.Date().getTime() - lastMoveEvent.time) > 300) { 1866 s.velocity = 0; 1867 } 1868 } else { 1869 s.velocity = 0; 1870 } 1871 s.velocity = s.velocity * s.params.freeModeMomentumVelocityRatio; 1872 1873 velocities.length = 0; 1874 var momentumDuration = 1000 * s.params.freeModeMomentumRatio; 1875 var momentumDistance = s.velocity * momentumDuration; 1876 1877 var newPosition = s.translate + momentumDistance; 1878 if (s.rtl) newPosition = - newPosition; 1879 var doBounce = false; 1880 var afterBouncePosition; 1881 var bounceAmount = Math.abs(s.velocity) * 20 * s.params.freeModeMomentumBounceRatio; 1882 if (newPosition < s.maxTranslate()) { 1883 if (s.params.freeModeMomentumBounce) { 1884 if (newPosition + s.maxTranslate() < -bounceAmount) { 1885 newPosition = s.maxTranslate() - bounceAmount; 1886 } 1887 afterBouncePosition = s.maxTranslate(); 1888 doBounce = true; 1889 allowMomentumBounce = true; 1890 } 1891 else { 1892 newPosition = s.maxTranslate(); 1893 } 1894 } 1895 else if (newPosition > s.minTranslate()) { 1896 if (s.params.freeModeMomentumBounce) { 1897 if (newPosition - s.minTranslate() > bounceAmount) { 1898 newPosition = s.minTranslate() + bounceAmount; 1899 } 1900 afterBouncePosition = s.minTranslate(); 1901 doBounce = true; 1902 allowMomentumBounce = true; 1903 } 1904 else { 1905 newPosition = s.minTranslate(); 1906 } 1907 } 1908 else if (s.params.freeModeSticky) { 1909 var j = 0, 1910 nextSlide; 1911 for (j = 0; j < s.snapGrid.length; j += 1) { 1912 if (s.snapGrid[j] > -newPosition) { 1913 nextSlide = j; 1914 break; 1915 } 1916 1917 } 1918 if (Math.abs(s.snapGrid[nextSlide] - newPosition) < Math.abs(s.snapGrid[nextSlide - 1] - newPosition) || s.swipeDirection === 'next') { 1919 newPosition = s.snapGrid[nextSlide]; 1920 } else { 1921 newPosition = s.snapGrid[nextSlide - 1]; 1922 } 1923 if (!s.rtl) newPosition = - newPosition; 1924 } 1925 //Fix duration 1926 if (s.velocity !== 0) { 1927 if (s.rtl) { 1928 momentumDuration = Math.abs((-newPosition - s.translate) / s.velocity); 1929 } 1930 else { 1931 momentumDuration = Math.abs((newPosition - s.translate) / s.velocity); 1932 } 1933 } 1934 else if (s.params.freeModeSticky) { 1935 s.slideReset(); 1936 return; 1937 } 1938 1939 if (s.params.freeModeMomentumBounce && doBounce) { 1940 s.updateProgress(afterBouncePosition); 1941 s.setWrapperTransition(momentumDuration); 1942 s.setWrapperTranslate(newPosition); 1943 s.onTransitionStart(); 1944 s.animating = true; 1945 s.wrapper.transitionEnd(function () { 1946 if (!s || !allowMomentumBounce) return; 1947 s.emit('onMomentumBounce', s); 1948 1949 s.setWrapperTransition(s.params.speed); 1950 s.setWrapperTranslate(afterBouncePosition); 1951 s.wrapper.transitionEnd(function () { 1952 if (!s) return; 1953 s.onTransitionEnd(); 1954 }); 1955 }); 1956 } else if (s.velocity) { 1957 s.updateProgress(newPosition); 1958 s.setWrapperTransition(momentumDuration); 1959 s.setWrapperTranslate(newPosition); 1960 s.onTransitionStart(); 1961 if (!s.animating) { 1962 s.animating = true; 1963 s.wrapper.transitionEnd(function () { 1964 if (!s) return; 1965 s.onTransitionEnd(); 1966 }); 1967 } 1968 1969 } else { 1970 s.updateProgress(newPosition); 1971 } 1972 1973 s.updateActiveIndex(); 1974 } 1975 if (!s.params.freeModeMomentum || timeDiff >= s.params.longSwipesMs) { 1976 s.updateProgress(); 1977 s.updateActiveIndex(); 1978 } 1979 return; 1980 } 1981 1982 // Find current slide 1983 var i, stopIndex = 0, groupSize = s.slidesSizesGrid[0]; 1984 for (i = 0; i < s.slidesGrid.length; i += s.params.slidesPerGroup) { 1985 if (typeof s.slidesGrid[i + s.params.slidesPerGroup] !== 'undefined') { 1986 if (currentPos >= s.slidesGrid[i] && currentPos < s.slidesGrid[i + s.params.slidesPerGroup]) { 1987 stopIndex = i; 1988 groupSize = s.slidesGrid[i + s.params.slidesPerGroup] - s.slidesGrid[i]; 1989 } 1990 } 1991 else { 1992 if (currentPos >= s.slidesGrid[i]) { 1993 stopIndex = i; 1994 groupSize = s.slidesGrid[s.slidesGrid.length - 1] - s.slidesGrid[s.slidesGrid.length - 2]; 1995 } 1996 } 1997 } 1998 1999 // Find current slide size 2000 var ratio = (currentPos - s.slidesGrid[stopIndex]) / groupSize; 2001 2002 if (timeDiff > s.params.longSwipesMs) { 2003 // Long touches 2004 if (!s.params.longSwipes) { 2005 s.slideTo(s.activeIndex); 2006 return; 2007 } 2008 if (s.swipeDirection === 'next') { 2009 if (ratio >= s.params.longSwipesRatio) s.slideTo(stopIndex + s.params.slidesPerGroup); 2010 else s.slideTo(stopIndex); 2011 2012 } 2013 if (s.swipeDirection === 'prev') { 2014 if (ratio > (1 - s.params.longSwipesRatio)) s.slideTo(stopIndex + s.params.slidesPerGroup); 2015 else s.slideTo(stopIndex); 2016 } 2017 } 2018 else { 2019 // Short swipes 2020 if (!s.params.shortSwipes) { 2021 s.slideTo(s.activeIndex); 2022 return; 2023 } 2024 if (s.swipeDirection === 'next') { 2025 s.slideTo(stopIndex + s.params.slidesPerGroup); 2026 2027 } 2028 if (s.swipeDirection === 'prev') { 2029 s.slideTo(stopIndex); 2030 } 2031 } 2032 }; 2033 /*========================= 2034 Transitions 2035 ===========================*/ 2036 s._slideTo = function (slideIndex, speed) { 2037 return s.slideTo(slideIndex, speed, true, true); 2038 }; 2039 s.slideTo = function (slideIndex, speed, runCallbacks, internal) { 2040 if (typeof runCallbacks === 'undefined') runCallbacks = true; 2041 if (typeof slideIndex === 'undefined') slideIndex = 0; 2042 if (slideIndex < 0) slideIndex = 0; 2043 s.snapIndex = Math.floor(slideIndex / s.params.slidesPerGroup); 2044 if (s.snapIndex >= s.snapGrid.length) s.snapIndex = s.snapGrid.length - 1; 2045 2046 var translate = - s.snapGrid[s.snapIndex]; 2047 // Stop autoplay 2048 if (s.params.autoplay && s.autoplaying) { 2049 if (internal || !s.params.autoplayDisableOnInteraction) { 2050 s.pauseAutoplay(speed); 2051 } 2052 else { 2053 s.stopAutoplay(); 2054 } 2055 } 2056 // Update progress 2057 s.updateProgress(translate); 2058 2059 // Normalize slideIndex 2060 if(s.params.normalizeSlideIndex){ 2061 for (var i = 0; i < s.slidesGrid.length; i++) { 2062 if (- Math.floor(translate * 100) >= Math.floor(s.slidesGrid[i] * 100)) { 2063 slideIndex = i; 2064 } 2065 } 2066 } 2067 2068 // Directions locks 2069 if (!s.params.allowSwipeToNext && translate < s.translate && translate < s.minTranslate()) { 2070 return false; 2071 } 2072 if (!s.params.allowSwipeToPrev && translate > s.translate && translate > s.maxTranslate()) { 2073 if ((s.activeIndex || 0) !== slideIndex ) return false; 2074 } 2075 2076 // Update Index 2077 if (typeof speed === 'undefined') speed = s.params.speed; 2078 s.previousIndex = s.activeIndex || 0; 2079 s.activeIndex = slideIndex; 2080 s.updateRealIndex(); 2081 if ((s.rtl && -translate === s.translate) || (!s.rtl && translate === s.translate)) { 2082 // Update Height 2083 if (s.params.autoHeight) { 2084 s.updateAutoHeight(); 2085 } 2086 s.updateClasses(); 2087 if (s.params.effect !== 'slide') { 2088 s.setWrapperTranslate(translate); 2089 } 2090 return false; 2091 } 2092 s.updateClasses(); 2093 s.onTransitionStart(runCallbacks); 2094 2095 if (speed === 0 || s.browser.lteIE9) { 2096 s.setWrapperTranslate(translate); 2097 s.setWrapperTransition(0); 2098 s.onTransitionEnd(runCallbacks); 2099 } 2100 else { 2101 s.setWrapperTranslate(translate); 2102 s.setWrapperTransition(speed); 2103 if (!s.animating) { 2104 s.animating = true; 2105 s.wrapper.transitionEnd(function () { 2106 if (!s) return; 2107 s.onTransitionEnd(runCallbacks); 2108 }); 2109 } 2110 2111 } 2112 2113 return true; 2114 }; 2115 2116 s.onTransitionStart = function (runCallbacks) { 2117 if (typeof runCallbacks === 'undefined') runCallbacks = true; 2118 if (s.params.autoHeight) { 2119 s.updateAutoHeight(); 2120 } 2121 if (s.lazy) s.lazy.onTransitionStart(); 2122 if (runCallbacks) { 2123 s.emit('onTransitionStart', s); 2124 if (s.activeIndex !== s.previousIndex) { 2125 s.emit('onSlideChangeStart', s); 2126 if (s.activeIndex > s.previousIndex) { 2127 s.emit('onSlideNextStart', s); 2128 } 2129 else { 2130 s.emit('onSlidePrevStart', s); 2131 } 2132 } 2133 2134 } 2135 }; 2136 s.onTransitionEnd = function (runCallbacks) { 2137 s.animating = false; 2138 s.setWrapperTransition(0); 2139 if (typeof runCallbacks === 'undefined') runCallbacks = true; 2140 if (s.lazy) s.lazy.onTransitionEnd(); 2141 if (runCallbacks) { 2142 s.emit('onTransitionEnd', s); 2143 if (s.activeIndex !== s.previousIndex) { 2144 s.emit('onSlideChangeEnd', s); 2145 if (s.activeIndex > s.previousIndex) { 2146 s.emit('onSlideNextEnd', s); 2147 } 2148 else { 2149 s.emit('onSlidePrevEnd', s); 2150 } 2151 } 2152 } 2153 if (s.params.history && s.history) { 2154 s.history.setHistory(s.params.history, s.activeIndex); 2155 } 2156 if (s.params.hashnav && s.hashnav) { 2157 s.hashnav.setHash(); 2158 } 2159 2160 }; 2161 s.slideNext = function (runCallbacks, speed, internal) { 2162 if (s.params.loop) { 2163 if (s.animating) return false; 2164 s.fixLoop(); 2165 var clientLeft = s.container[0].clientLeft; 2166 return s.slideTo(s.activeIndex + s.params.slidesPerGroup, speed, runCallbacks, internal); 2167 } 2168 else return s.slideTo(s.activeIndex + s.params.slidesPerGroup, speed, runCallbacks, internal); 2169 }; 2170 s._slideNext = function (speed) { 2171 return s.slideNext(true, speed, true); 2172 }; 2173 s.slidePrev = function (runCallbacks, speed, internal) { 2174 if (s.params.loop) { 2175 if (s.animating) return false; 2176 s.fixLoop(); 2177 var clientLeft = s.container[0].clientLeft; 2178 return s.slideTo(s.activeIndex - 1, speed, runCallbacks, internal); 2179 } 2180 else return s.slideTo(s.activeIndex - 1, speed, runCallbacks, internal); 2181 }; 2182 s._slidePrev = function (speed) { 2183 return s.slidePrev(true, speed, true); 2184 }; 2185 s.slideReset = function (runCallbacks, speed, internal) { 2186 return s.slideTo(s.activeIndex, speed, runCallbacks); 2187 }; 2188 2189 s.disableTouchControl = function () { 2190 s.params.onlyExternal = true; 2191 return true; 2192 }; 2193 s.enableTouchControl = function () { 2194 s.params.onlyExternal = false; 2195 return true; 2196 }; 2197 2198 /*========================= 2199 Translate/transition helpers 2200 ===========================*/ 2201 s.setWrapperTransition = function (duration, byController) { 2202 s.wrapper.transition(duration); 2203 if (s.params.effect !== 'slide' && s.effects[s.params.effect]) { 2204 s.effects[s.params.effect].setTransition(duration); 2205 } 2206 if (s.params.parallax && s.parallax) { 2207 s.parallax.setTransition(duration); 2208 } 2209 if (s.params.scrollbar && s.scrollbar) { 2210 s.scrollbar.setTransition(duration); 2211 } 2212 if (s.params.control && s.controller) { 2213 s.controller.setTransition(duration, byController); 2214 } 2215 s.emit('onSetTransition', s, duration); 2216 }; 2217 s.setWrapperTranslate = function (translate, updateActiveIndex, byController) { 2218 var x = 0, y = 0, z = 0; 2219 if (s.isHorizontal()) { 2220 x = s.rtl ? -translate : translate; 2221 } 2222 else { 2223 y = translate; 2224 } 2225 2226 if (s.params.roundLengths) { 2227 x = round(x); 2228 y = round(y); 2229 } 2230 2231 if (!s.params.virtualTranslate) { 2232 if (s.support.transforms3d) s.wrapper.transform('translate3d(' + x + 'px, ' + y + 'px, ' + z + 'px)'); 2233 else s.wrapper.transform('translate(' + x + 'px, ' + y + 'px)'); 2234 } 2235 2236 s.translate = s.isHorizontal() ? x : y; 2237 2238 // Check if we need to update progress 2239 var progress; 2240 var translatesDiff = s.maxTranslate() - s.minTranslate(); 2241 if (translatesDiff === 0) { 2242 progress = 0; 2243 } 2244 else { 2245 progress = (translate - s.minTranslate()) / (translatesDiff); 2246 } 2247 if (progress !== s.progress) { 2248 s.updateProgress(translate); 2249 } 2250 2251 if (updateActiveIndex) s.updateActiveIndex(); 2252 if (s.params.effect !== 'slide' && s.effects[s.params.effect]) { 2253 s.effects[s.params.effect].setTranslate(s.translate); 2254 } 2255 if (s.params.parallax && s.parallax) { 2256 s.parallax.setTranslate(s.translate); 2257 } 2258 if (s.params.scrollbar && s.scrollbar) { 2259 s.scrollbar.setTranslate(s.translate); 2260 } 2261 if (s.params.control && s.controller) { 2262 s.controller.setTranslate(s.translate, byController); 2263 } 2264 s.emit('onSetTranslate', s, s.translate); 2265 }; 2266 2267 s.getTranslate = function (el, axis) { 2268 var matrix, curTransform, curStyle, transformMatrix; 2269 2270 // automatic axis detection 2271 if (typeof axis === 'undefined') { 2272 axis = 'x'; 2273 } 2274 2275 if (s.params.virtualTranslate) { 2276 return s.rtl ? -s.translate : s.translate; 2277 } 2278 2279 curStyle = window.getComputedStyle(el, null); 2280 if (window.WebKitCSSMatrix) { 2281 curTransform = curStyle.transform || curStyle.webkitTransform; 2282 if (curTransform.split(',').length > 6) { 2283 curTransform = curTransform.split(', ').map(function(a){ 2284 return a.replace(',','.'); 2285 }).join(', '); 2286 } 2287 // Some old versions of Webkit choke when 'none' is passed; pass 2288 // empty string instead in this case 2289 transformMatrix = new window.WebKitCSSMatrix(curTransform === 'none' ? '' : curTransform); 2290 } 2291 else { 2292 transformMatrix = curStyle.MozTransform || curStyle.OTransform || curStyle.MsTransform || curStyle.msTransform || curStyle.transform || curStyle.getPropertyValue('transform').replace('translate(', 'matrix(1, 0, 0, 1,'); 2293 matrix = transformMatrix.toString().split(','); 2294 } 2295 2296 if (axis === 'x') { 2297 //Latest Chrome and webkits Fix 2298 if (window.WebKitCSSMatrix) 2299 curTransform = transformMatrix.m41; 2300 //Crazy IE10 Matrix 2301 else if (matrix.length === 16) 2302 curTransform = parseFloat(matrix[12]); 2303 //Normal Browsers 2304 else 2305 curTransform = parseFloat(matrix[4]); 2306 } 2307 if (axis === 'y') { 2308 //Latest Chrome and webkits Fix 2309 if (window.WebKitCSSMatrix) 2310 curTransform = transformMatrix.m42; 2311 //Crazy IE10 Matrix 2312 else if (matrix.length === 16) 2313 curTransform = parseFloat(matrix[13]); 2314 //Normal Browsers 2315 else 2316 curTransform = parseFloat(matrix[5]); 2317 } 2318 if (s.rtl && curTransform) curTransform = -curTransform; 2319 return curTransform || 0; 2320 }; 2321 s.getWrapperTranslate = function (axis) { 2322 if (typeof axis === 'undefined') { 2323 axis = s.isHorizontal() ? 'x' : 'y'; 2324 } 2325 return s.getTranslate(s.wrapper[0], axis); 2326 }; 2327 2328 /*========================= 2329 Observer 2330 ===========================*/ 2331 s.observers = []; 2332 function initObserver(target, options) { 2333 options = options || {}; 2334 // create an observer instance 2335 var ObserverFunc = window.MutationObserver || window.WebkitMutationObserver; 2336 var observer = new ObserverFunc(function (mutations) { 2337 mutations.forEach(function (mutation) { 2338 s.onResize(true); 2339 s.emit('onObserverUpdate', s, mutation); 2340 }); 2341 }); 2342 2343 observer.observe(target, { 2344 attributes: typeof options.attributes === 'undefined' ? true : options.attributes, 2345 childList: typeof options.childList === 'undefined' ? true : options.childList, 2346 characterData: typeof options.characterData === 'undefined' ? true : options.characterData 2347 }); 2348 2349 s.observers.push(observer); 2350 } 2351 s.initObservers = function () { 2352 if (s.params.observeParents) { 2353 var containerParents = s.container.parents(); 2354 for (var i = 0; i < containerParents.length; i++) { 2355 initObserver(containerParents[i]); 2356 } 2357 } 2358 2359 // Observe container 2360 initObserver(s.container[0], {childList: false}); 2361 2362 // Observe wrapper 2363 initObserver(s.wrapper[0], {attributes: false}); 2364 }; 2365 s.disconnectObservers = function () { 2366 for (var i = 0; i < s.observers.length; i++) { 2367 s.observers[i].disconnect(); 2368 } 2369 s.observers = []; 2370 }; 2371 /*========================= 2372 Loop 2373 ===========================*/ 2374 // Create looped slides 2375 s.createLoop = function () { 2376 // Remove duplicated slides 2377 s.wrapper.children('.' + s.params.slideClass + '.' + s.params.slideDuplicateClass).remove(); 2378 2379 var slides = s.wrapper.children('.' + s.params.slideClass); 2380 2381 if(s.params.slidesPerView === 'auto' && !s.params.loopedSlides) s.params.loopedSlides = slides.length; 2382 2383 s.loopedSlides = parseInt(s.params.loopedSlides || s.params.slidesPerView, 10); 2384 s.loopedSlides = s.loopedSlides + s.params.loopAdditionalSlides; 2385 if (s.loopedSlides > slides.length) { 2386 s.loopedSlides = slides.length; 2387 } 2388 2389 var prependSlides = [], appendSlides = [], i; 2390 slides.each(function (index, el) { 2391 var slide = $(this); 2392 if (index < s.loopedSlides) appendSlides.push(el); 2393 if (index < slides.length && index >= slides.length - s.loopedSlides) prependSlides.push(el); 2394 slide.attr('data-swiper-slide-index', index); 2395 }); 2396 for (i = 0; i < appendSlides.length; i++) { 2397 s.wrapper.append($(appendSlides[i].cloneNode(true)).addClass(s.params.slideDuplicateClass)); 2398 } 2399 for (i = prependSlides.length - 1; i >= 0; i--) { 2400 s.wrapper.prepend($(prependSlides[i].cloneNode(true)).addClass(s.params.slideDuplicateClass)); 2401 } 2402 }; 2403 s.destroyLoop = function () { 2404 s.wrapper.children('.' + s.params.slideClass + '.' + s.params.slideDuplicateClass).remove(); 2405 s.slides.removeAttr('data-swiper-slide-index'); 2406 }; 2407 s.reLoop = function (updatePosition) { 2408 var oldIndex = s.activeIndex - s.loopedSlides; 2409 s.destroyLoop(); 2410 s.createLoop(); 2411 s.updateSlidesSize(); 2412 if (updatePosition) { 2413 s.slideTo(oldIndex + s.loopedSlides, 0, false); 2414 } 2415 2416 }; 2417 s.fixLoop = function () { 2418 var newIndex; 2419 //Fix For Negative Oversliding 2420 if (s.activeIndex < s.loopedSlides) { 2421 newIndex = s.slides.length - s.loopedSlides * 3 + s.activeIndex; 2422 newIndex = newIndex + s.loopedSlides; 2423 s.slideTo(newIndex, 0, false, true); 2424 } 2425 //Fix For Positive Oversliding 2426 else if ((s.params.slidesPerView === 'auto' && s.activeIndex >= s.loopedSlides * 2) || (s.activeIndex > s.slides.length - s.params.slidesPerView * 2)) { 2427 newIndex = -s.slides.length + s.activeIndex + s.loopedSlides; 2428 newIndex = newIndex + s.loopedSlides; 2429 s.slideTo(newIndex, 0, false, true); 2430 } 2431 }; 2432 /*========================= 2433 Append/Prepend/Remove Slides 2434 ===========================*/ 2435 s.appendSlide = function (slides) { 2436 if (s.params.loop) { 2437 s.destroyLoop(); 2438 } 2439 if (typeof slides === 'object' && slides.length) { 2440 for (var i = 0; i < slides.length; i++) { 2441 if (slides[i]) s.wrapper.append(slides[i]); 2442 } 2443 } 2444 else { 2445 s.wrapper.append(slides); 2446 } 2447 if (s.params.loop) { 2448 s.createLoop(); 2449 } 2450 if (!(s.params.observer && s.support.observer)) { 2451 s.update(true); 2452 } 2453 }; 2454 s.prependSlide = function (slides) { 2455 if (s.params.loop) { 2456 s.destroyLoop(); 2457 } 2458 var newActiveIndex = s.activeIndex + 1; 2459 if (typeof slides === 'object' && slides.length) { 2460 for (var i = 0; i < slides.length; i++) { 2461 if (slides[i]) s.wrapper.prepend(slides[i]); 2462 } 2463 newActiveIndex = s.activeIndex + slides.length; 2464 } 2465 else { 2466 s.wrapper.prepend(slides); 2467 } 2468 if (s.params.loop) { 2469 s.createLoop(); 2470 } 2471 if (!(s.params.observer && s.support.observer)) { 2472 s.update(true); 2473 } 2474 s.slideTo(newActiveIndex, 0, false); 2475 }; 2476 s.removeSlide = function (slidesIndexes) { 2477 if (s.params.loop) { 2478 s.destroyLoop(); 2479 s.slides = s.wrapper.children('.' + s.params.slideClass); 2480 } 2481 var newActiveIndex = s.activeIndex, 2482 indexToRemove; 2483 if (typeof slidesIndexes === 'object' && slidesIndexes.length) { 2484 for (var i = 0; i < slidesIndexes.length; i++) { 2485 indexToRemove = slidesIndexes[i]; 2486 if (s.slides[indexToRemove]) s.slides.eq(indexToRemove).remove(); 2487 if (indexToRemove < newActiveIndex) newActiveIndex--; 2488 } 2489 newActiveIndex = Math.max(newActiveIndex, 0); 2490 } 2491 else { 2492 indexToRemove = slidesIndexes; 2493 if (s.slides[indexToRemove]) s.slides.eq(indexToRemove).remove(); 2494 if (indexToRemove < newActiveIndex) newActiveIndex--; 2495 newActiveIndex = Math.max(newActiveIndex, 0); 2496 } 2497 2498 if (s.params.loop) { 2499 s.createLoop(); 2500 } 2501 2502 if (!(s.params.observer && s.support.observer)) { 2503 s.update(true); 2504 } 2505 if (s.params.loop) { 2506 s.slideTo(newActiveIndex + s.loopedSlides, 0, false); 2507 } 2508 else { 2509 s.slideTo(newActiveIndex, 0, false); 2510 } 2511 2512 }; 2513 s.removeAllSlides = function () { 2514 var slidesIndexes = []; 2515 for (var i = 0; i < s.slides.length; i++) { 2516 slidesIndexes.push(i); 2517 } 2518 s.removeSlide(slidesIndexes); 2519 }; 2520 2521 2522 /*========================= 2523 Effects 2524 ===========================*/ 2525 s.effects = { 2526 fade: { 2527 setTranslate: function () { 2528 for (var i = 0; i < s.slides.length; i++) { 2529 var slide = s.slides.eq(i); 2530 var offset = slide[0].swiperSlideOffset; 2531 var tx = -offset; 2532 if (!s.params.virtualTranslate) tx = tx - s.translate; 2533 var ty = 0; 2534 if (!s.isHorizontal()) { 2535 ty = tx; 2536 tx = 0; 2537 } 2538 var slideOpacity = s.params.fade.crossFade ? 2539 Math.max(1 - Math.abs(slide[0].progress), 0) : 2540 1 + Math.min(Math.max(slide[0].progress, -1), 0); 2541 slide 2542 .css({ 2543 opacity: slideOpacity 2544 }) 2545 .transform('translate3d(' + tx + 'px, ' + ty + 'px, 0px)'); 2546 2547 } 2548 2549 }, 2550 setTransition: function (duration) { 2551 s.slides.transition(duration); 2552 if (s.params.virtualTranslate && duration !== 0) { 2553 var eventTriggered = false; 2554 s.slides.transitionEnd(function () { 2555 if (eventTriggered) return; 2556 if (!s) return; 2557 eventTriggered = true; 2558 s.animating = false; 2559 var triggerEvents = ['webkitTransitionEnd', 'transitionend', 'oTransitionEnd', 'MSTransitionEnd', 'msTransitionEnd']; 2560 for (var i = 0; i < triggerEvents.length; i++) { 2561 s.wrapper.trigger(triggerEvents[i]); 2562 } 2563 }); 2564 } 2565 } 2566 }, 2567 flip: { 2568 setTranslate: function () { 2569 for (var i = 0; i < s.slides.length; i++) { 2570 var slide = s.slides.eq(i); 2571 var progress = slide[0].progress; 2572 if (s.params.flip.limitRotation) { 2573 progress = Math.max(Math.min(slide[0].progress, 1), -1); 2574 } 2575 var offset = slide[0].swiperSlideOffset; 2576 var rotate = -180 * progress, 2577 rotateY = rotate, 2578 rotateX = 0, 2579 tx = -offset, 2580 ty = 0; 2581 if (!s.isHorizontal()) { 2582 ty = tx; 2583 tx = 0; 2584 rotateX = -rotateY; 2585 rotateY = 0; 2586 } 2587 else if (s.rtl) { 2588 rotateY = -rotateY; 2589 } 2590 2591 slide[0].style.zIndex = -Math.abs(Math.round(progress)) + s.slides.length; 2592 2593 if (s.params.flip.slideShadows) { 2594 //Set shadows 2595 var shadowBefore = s.isHorizontal() ? slide.find('.swiper-slide-shadow-left') : slide.find('.swiper-slide-shadow-top'); 2596 var shadowAfter = s.isHorizontal() ? slide.find('.swiper-slide-shadow-right') : slide.find('.swiper-slide-shadow-bottom'); 2597 if (shadowBefore.length === 0) { 2598 shadowBefore = $('<div class="swiper-slide-shadow-' + (s.isHorizontal() ? 'left' : 'top') + '"></div>'); 2599 slide.append(shadowBefore); 2600 } 2601 if (shadowAfter.length === 0) { 2602 shadowAfter = $('<div class="swiper-slide-shadow-' + (s.isHorizontal() ? 'right' : 'bottom') + '"></div>'); 2603 slide.append(shadowAfter); 2604 } 2605 if (shadowBefore.length) shadowBefore[0].style.opacity = Math.max(-progress, 0); 2606 if (shadowAfter.length) shadowAfter[0].style.opacity = Math.max(progress, 0); 2607 } 2608 2609 slide 2610 .transform('translate3d(' + tx + 'px, ' + ty + 'px, 0px) rotateX(' + rotateX + 'deg) rotateY(' + rotateY + 'deg)'); 2611 } 2612 }, 2613 setTransition: function (duration) { 2614 s.slides.transition(duration).find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').transition(duration); 2615 if (s.params.virtualTranslate && duration !== 0) { 2616 var eventTriggered = false; 2617 s.slides.eq(s.activeIndex).transitionEnd(function () { 2618 if (eventTriggered) return; 2619 if (!s) return; 2620 if (!$(this).hasClass(s.params.slideActiveClass)) return; 2621 eventTriggered = true; 2622 s.animating = false; 2623 var triggerEvents = ['webkitTransitionEnd', 'transitionend', 'oTransitionEnd', 'MSTransitionEnd', 'msTransitionEnd']; 2624 for (var i = 0; i < triggerEvents.length; i++) { 2625 s.wrapper.trigger(triggerEvents[i]); 2626 } 2627 }); 2628 } 2629 } 2630 }, 2631 cube: { 2632 setTranslate: function () { 2633 var wrapperRotate = 0, cubeShadow; 2634 if (s.params.cube.shadow) { 2635 if (s.isHorizontal()) { 2636 cubeShadow = s.wrapper.find('.swiper-cube-shadow'); 2637 if (cubeShadow.length === 0) { 2638 cubeShadow = $('<div class="swiper-cube-shadow"></div>'); 2639 s.wrapper.append(cubeShadow); 2640 } 2641 cubeShadow.css({height: s.width + 'px'}); 2642 } 2643 else { 2644 cubeShadow = s.container.find('.swiper-cube-shadow'); 2645 if (cubeShadow.length === 0) { 2646 cubeShadow = $('<div class="swiper-cube-shadow"></div>'); 2647 s.container.append(cubeShadow); 2648 } 2649 } 2650 } 2651 for (var i = 0; i < s.slides.length; i++) { 2652 var slide = s.slides.eq(i); 2653 var slideAngle = i * 90; 2654 var round = Math.floor(slideAngle / 360); 2655 if (s.rtl) { 2656 slideAngle = -slideAngle; 2657 round = Math.floor(-slideAngle / 360); 2658 } 2659 var progress = Math.max(Math.min(slide[0].progress, 1), -1); 2660 var tx = 0, ty = 0, tz = 0; 2661 if (i % 4 === 0) { 2662 tx = - round * 4 * s.size; 2663 tz = 0; 2664 } 2665 else if ((i - 1) % 4 === 0) { 2666 tx = 0; 2667 tz = - round * 4 * s.size; 2668 } 2669 else if ((i - 2) % 4 === 0) { 2670 tx = s.size + round * 4 * s.size; 2671 tz = s.size; 2672 } 2673 else if ((i - 3) % 4 === 0) { 2674 tx = - s.size; 2675 tz = 3 * s.size + s.size * 4 * round; 2676 } 2677 if (s.rtl) { 2678 tx = -tx; 2679 } 2680 2681 if (!s.isHorizontal()) { 2682 ty = tx; 2683 tx = 0; 2684 } 2685 2686 var transform = 'rotateX(' + (s.isHorizontal() ? 0 : -slideAngle) + 'deg) rotateY(' + (s.isHorizontal() ? slideAngle : 0) + 'deg) translate3d(' + tx + 'px, ' + ty + 'px, ' + tz + 'px)'; 2687 if (progress <= 1 && progress > -1) { 2688 wrapperRotate = i * 90 + progress * 90; 2689 if (s.rtl) wrapperRotate = -i * 90 - progress * 90; 2690 } 2691 slide.transform(transform); 2692 if (s.params.cube.slideShadows) { 2693 //Set shadows 2694 var shadowBefore = s.isHorizontal() ? slide.find('.swiper-slide-shadow-left') : slide.find('.swiper-slide-shadow-top'); 2695 var shadowAfter = s.isHorizontal() ? slide.find('.swiper-slide-shadow-right') : slide.find('.swiper-slide-shadow-bottom'); 2696 if (shadowBefore.length === 0) { 2697 shadowBefore = $('<div class="swiper-slide-shadow-' + (s.isHorizontal() ? 'left' : 'top') + '"></div>'); 2698 slide.append(shadowBefore); 2699 } 2700 if (shadowAfter.length === 0) { 2701 shadowAfter = $('<div class="swiper-slide-shadow-' + (s.isHorizontal() ? 'right' : 'bottom') + '"></div>'); 2702 slide.append(shadowAfter); 2703 } 2704 if (shadowBefore.length) shadowBefore[0].style.opacity = Math.max(-progress, 0); 2705 if (shadowAfter.length) shadowAfter[0].style.opacity = Math.max(progress, 0); 2706 } 2707 } 2708 s.wrapper.css({ 2709 '-webkit-transform-origin': '50% 50% -' + (s.size / 2) + 'px', 2710 '-moz-transform-origin': '50% 50% -' + (s.size / 2) + 'px', 2711 '-ms-transform-origin': '50% 50% -' + (s.size / 2) + 'px', 2712 'transform-origin': '50% 50% -' + (s.size / 2) + 'px' 2713 }); 2714 2715 if (s.params.cube.shadow) { 2716 if (s.isHorizontal()) { 2717 cubeShadow.transform('translate3d(0px, ' + (s.width / 2 + s.params.cube.shadowOffset) + 'px, ' + (-s.width / 2) + 'px) rotateX(90deg) rotateZ(0deg) scale(' + (s.params.cube.shadowScale) + ')'); 2718 } 2719 else { 2720 var shadowAngle = Math.abs(wrapperRotate) - Math.floor(Math.abs(wrapperRotate) / 90) * 90; 2721 var multiplier = 1.5 - (Math.sin(shadowAngle * 2 * Math.PI / 360) / 2 + Math.cos(shadowAngle * 2 * Math.PI / 360) / 2); 2722 var scale1 = s.params.cube.shadowScale, 2723 scale2 = s.params.cube.shadowScale / multiplier, 2724 offset = s.params.cube.shadowOffset; 2725 cubeShadow.transform('scale3d(' + scale1 + ', 1, ' + scale2 + ') translate3d(0px, ' + (s.height / 2 + offset) + 'px, ' + (-s.height / 2 / scale2) + 'px) rotateX(-90deg)'); 2726 } 2727 } 2728 var zFactor = (s.isSafari || s.isUiWebView) ? (-s.size / 2) : 0; 2729 s.wrapper.transform('translate3d(0px,0,' + zFactor + 'px) rotateX(' + (s.isHorizontal() ? 0 : wrapperRotate) + 'deg) rotateY(' + (s.isHorizontal() ? -wrapperRotate : 0) + 'deg)'); 2730 }, 2731 setTransition: function (duration) { 2732 s.slides.transition(duration).find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').transition(duration); 2733 if (s.params.cube.shadow && !s.isHorizontal()) { 2734 s.container.find('.swiper-cube-shadow').transition(duration); 2735 } 2736 } 2737 }, 2738 coverflow: { 2739 setTranslate: function () { 2740 var transform = s.translate; 2741 var center = s.isHorizontal() ? -transform + s.width / 2 : -transform + s.height / 2; 2742 var rotate = s.isHorizontal() ? s.params.coverflow.rotate: -s.params.coverflow.rotate; 2743 var translate = s.params.coverflow.depth; 2744 //Each slide offset from center 2745 for (var i = 0, length = s.slides.length; i < length; i++) { 2746 var slide = s.slides.eq(i); 2747 var slideSize = s.slidesSizesGrid[i]; 2748 var slideOffset = slide[0].swiperSlideOffset; 2749 var offsetMultiplier = (center - slideOffset - slideSize / 2) / slideSize * s.params.coverflow.modifier; 2750 2751 var rotateY = s.isHorizontal() ? rotate * offsetMultiplier : 0; 2752 var rotateX = s.isHorizontal() ? 0 : rotate * offsetMultiplier; 2753 // var rotateZ = 0 2754 var translateZ = -translate * Math.abs(offsetMultiplier); 2755 2756 var translateY = s.isHorizontal() ? 0 : s.params.coverflow.stretch * (offsetMultiplier); 2757 var translateX = s.isHorizontal() ? s.params.coverflow.stretch * (offsetMultiplier) : 0; 2758 2759 //Fix for ultra small values 2760 if (Math.abs(translateX) < 0.001) translateX = 0; 2761 if (Math.abs(translateY) < 0.001) translateY = 0; 2762 if (Math.abs(translateZ) < 0.001) translateZ = 0; 2763 if (Math.abs(rotateY) < 0.001) rotateY = 0; 2764 if (Math.abs(rotateX) < 0.001) rotateX = 0; 2765 2766 var slideTransform = 'translate3d(' + translateX + 'px,' + translateY + 'px,' + translateZ + 'px) rotateX(' + rotateX + 'deg) rotateY(' + rotateY + 'deg)'; 2767 2768 slide.transform(slideTransform); 2769 slide[0].style.zIndex = -Math.abs(Math.round(offsetMultiplier)) + 1; 2770 if (s.params.coverflow.slideShadows) { 2771 //Set shadows 2772 var shadowBefore = s.isHorizontal() ? slide.find('.swiper-slide-shadow-left') : slide.find('.swiper-slide-shadow-top'); 2773 var shadowAfter = s.isHorizontal() ? slide.find('.swiper-slide-shadow-right') : slide.find('.swiper-slide-shadow-bottom'); 2774 if (shadowBefore.length === 0) { 2775 shadowBefore = $('<div class="swiper-slide-shadow-' + (s.isHorizontal() ? 'left' : 'top') + '"></div>'); 2776 slide.append(shadowBefore); 2777 } 2778 if (shadowAfter.length === 0) { 2779 shadowAfter = $('<div class="swiper-slide-shadow-' + (s.isHorizontal() ? 'right' : 'bottom') + '"></div>'); 2780 slide.append(shadowAfter); 2781 } 2782 if (shadowBefore.length) shadowBefore[0].style.opacity = offsetMultiplier > 0 ? offsetMultiplier : 0; 2783 if (shadowAfter.length) shadowAfter[0].style.opacity = (-offsetMultiplier) > 0 ? -offsetMultiplier : 0; 2784 } 2785 } 2786 2787 //Set correct perspective for IE10 2788 if (s.browser.ie) { 2789 var ws = s.wrapper[0].style; 2790 ws.perspectiveOrigin = center + 'px 50%'; 2791 } 2792 }, 2793 setTransition: function (duration) { 2794 s.slides.transition(duration).find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').transition(duration); 2795 } 2796 } 2797 }; 2798 2799 2800 /*========================= 2801 Images Lazy Loading 2802 ===========================*/ 2803 s.lazy = { 2804 initialImageLoaded: false, 2805 loadImageInSlide: function (index, loadInDuplicate) { 2806 if (typeof index === 'undefined') return; 2807 if (typeof loadInDuplicate === 'undefined') loadInDuplicate = true; 2808 if (s.slides.length === 0) return; 2809 2810 var slide = s.slides.eq(index); 2811 var img = slide.find('.' + s.params.lazyLoadingClass + ':not(.' + s.params.lazyStatusLoadedClass + '):not(.' + s.params.lazyStatusLoadingClass + ')'); 2812 if (slide.hasClass(s.params.lazyLoadingClass) && !slide.hasClass(s.params.lazyStatusLoadedClass) && !slide.hasClass(s.params.lazyStatusLoadingClass)) { 2813 img = img.add(slide[0]); 2814 } 2815 if (img.length === 0) return; 2816 2817 img.each(function () { 2818 var _img = $(this); 2819 _img.addClass(s.params.lazyStatusLoadingClass); 2820 var background = _img.attr('data-background'); 2821 var src = _img.attr('data-src'), 2822 srcset = _img.attr('data-srcset'), 2823 sizes = _img.attr('data-sizes'); 2824 s.loadImage(_img[0], (src || background), srcset, sizes, false, function () { 2825 if (typeof s === 'undefined' || s === null || !s) return; 2826 if (background) { 2827 _img.css('background-image', 'url("' + background + '")'); 2828 _img.removeAttr('data-background'); 2829 } 2830 else { 2831 if (srcset) { 2832 _img.attr('srcset', srcset); 2833 _img.removeAttr('data-srcset'); 2834 } 2835 if (sizes) { 2836 _img.attr('sizes', sizes); 2837 _img.removeAttr('data-sizes'); 2838 } 2839 if (src) { 2840 _img.attr('src', src); 2841 _img.removeAttr('data-src'); 2842 } 2843 2844 } 2845 2846 _img.addClass(s.params.lazyStatusLoadedClass).removeClass(s.params.lazyStatusLoadingClass); 2847 slide.find('.' + s.params.lazyPreloaderClass + ', .' + s.params.preloaderClass).remove(); 2848 if (s.params.loop && loadInDuplicate) { 2849 var slideOriginalIndex = slide.attr('data-swiper-slide-index'); 2850 if (slide.hasClass(s.params.slideDuplicateClass)) { 2851 var originalSlide = s.wrapper.children('[data-swiper-slide-index="' + slideOriginalIndex + '"]:not(.' + s.params.slideDuplicateClass + ')'); 2852 s.lazy.loadImageInSlide(originalSlide.index(), false); 2853 } 2854 else { 2855 var duplicatedSlide = s.wrapper.children('.' + s.params.slideDuplicateClass + '[data-swiper-slide-index="' + slideOriginalIndex + '"]'); 2856 s.lazy.loadImageInSlide(duplicatedSlide.index(), false); 2857 } 2858 } 2859 s.emit('onLazyImageReady', s, slide[0], _img[0]); 2860 }); 2861 2862 s.emit('onLazyImageLoad', s, slide[0], _img[0]); 2863 }); 2864 2865 }, 2866 load: function () { 2867 var i; 2868 var slidesPerView = s.params.slidesPerView; 2869 if (slidesPerView === 'auto') { 2870 slidesPerView = 0; 2871 } 2872 if (!s.lazy.initialImageLoaded) s.lazy.initialImageLoaded = true; 2873 if (s.params.watchSlidesVisibility) { 2874 s.wrapper.children('.' + s.params.slideVisibleClass).each(function () { 2875 s.lazy.loadImageInSlide($(this).index()); 2876 }); 2877 } 2878 else { 2879 if (slidesPerView > 1) { 2880 for (i = s.activeIndex; i < s.activeIndex + slidesPerView ; i++) { 2881 if (s.slides[i]) s.lazy.loadImageInSlide(i); 2882 } 2883 } 2884 else { 2885 s.lazy.loadImageInSlide(s.activeIndex); 2886 } 2887 } 2888 if (s.params.lazyLoadingInPrevNext) { 2889 if (slidesPerView > 1 || (s.params.lazyLoadingInPrevNextAmount && s.params.lazyLoadingInPrevNextAmount > 1)) { 2890 var amount = s.params.lazyLoadingInPrevNextAmount; 2891 var spv = slidesPerView; 2892 var maxIndex = Math.min(s.activeIndex + spv + Math.max(amount, spv), s.slides.length); 2893 var minIndex = Math.max(s.activeIndex - Math.max(spv, amount), 0); 2894 // Next Slides 2895 for (i = s.activeIndex + slidesPerView; i < maxIndex; i++) { 2896 if (s.slides[i]) s.lazy.loadImageInSlide(i); 2897 } 2898 // Prev Slides 2899 for (i = minIndex; i < s.activeIndex ; i++) { 2900 if (s.slides[i]) s.lazy.loadImageInSlide(i); 2901 } 2902 } 2903 else { 2904 var nextSlide = s.wrapper.children('.' + s.params.slideNextClass); 2905 if (nextSlide.length > 0) s.lazy.loadImageInSlide(nextSlide.index()); 2906 2907 var prevSlide = s.wrapper.children('.' + s.params.slidePrevClass); 2908 if (prevSlide.length > 0) s.lazy.loadImageInSlide(prevSlide.index()); 2909 } 2910 } 2911 }, 2912 onTransitionStart: function () { 2913 if (s.params.lazyLoading) { 2914 if (s.params.lazyLoadingOnTransitionStart || (!s.params.lazyLoadingOnTransitionStart && !s.lazy.initialImageLoaded)) { 2915 s.lazy.load(); 2916 } 2917 } 2918 }, 2919 onTransitionEnd: function () { 2920 if (s.params.lazyLoading && !s.params.lazyLoadingOnTransitionStart) { 2921 s.lazy.load(); 2922 } 2923 } 2924 }; 2925 2926 2927 /*========================= 2928 Scrollbar 2929 ===========================*/ 2930 s.scrollbar = { 2931 isTouched: false, 2932 setDragPosition: function (e) { 2933 var sb = s.scrollbar; 2934 var x = 0, y = 0; 2935 var translate; 2936 var pointerPosition = s.isHorizontal() ? 2937 ((e.type === 'touchstart' || e.type === 'touchmove') ? e.targetTouches[0].pageX : e.pageX || e.clientX) : 2938 ((e.type === 'touchstart' || e.type === 'touchmove') ? e.targetTouches[0].pageY : e.pageY || e.clientY) ; 2939 var position = (pointerPosition) - sb.track.offset()[s.isHorizontal() ? 'left' : 'top'] - sb.dragSize / 2; 2940 var positionMin = -s.minTranslate() * sb.moveDivider; 2941 var positionMax = -s.maxTranslate() * sb.moveDivider; 2942 if (position < positionMin) { 2943 position = positionMin; 2944 } 2945 else if (position > positionMax) { 2946 position = positionMax; 2947 } 2948 position = -position / sb.moveDivider; 2949 s.updateProgress(position); 2950 s.setWrapperTranslate(position, true); 2951 }, 2952 dragStart: function (e) { 2953 var sb = s.scrollbar; 2954 sb.isTouched = true; 2955 e.preventDefault(); 2956 e.stopPropagation(); 2957 2958 sb.setDragPosition(e); 2959 clearTimeout(sb.dragTimeout); 2960 2961 sb.track.transition(0); 2962 if (s.params.scrollbarHide) { 2963 sb.track.css('opacity', 1); 2964 } 2965 s.wrapper.transition(100); 2966 sb.drag.transition(100); 2967 s.emit('onScrollbarDragStart', s); 2968 }, 2969 dragMove: function (e) { 2970 var sb = s.scrollbar; 2971 if (!sb.isTouched) return; 2972 if (e.preventDefault) e.preventDefault(); 2973 else e.returnValue = false; 2974 sb.setDragPosition(e); 2975 s.wrapper.transition(0); 2976 sb.track.transition(0); 2977 sb.drag.transition(0); 2978 s.emit('onScrollbarDragMove', s); 2979 }, 2980 dragEnd: function (e) { 2981 var sb = s.scrollbar; 2982 if (!sb.isTouched) return; 2983 sb.isTouched = false; 2984 if (s.params.scrollbarHide) { 2985 clearTimeout(sb.dragTimeout); 2986 sb.dragTimeout = setTimeout(function () { 2987 sb.track.css('opacity', 0); 2988 sb.track.transition(400); 2989 }, 1000); 2990 2991 } 2992 s.emit('onScrollbarDragEnd', s); 2993 if (s.params.scrollbarSnapOnRelease) { 2994 s.slideReset(); 2995 } 2996 }, 2997 draggableEvents: (function () { 2998 if ((s.params.simulateTouch === false && !s.support.touch)) return s.touchEventsDesktop; 2999 else return s.touchEvents; 3000 })(), 3001 enableDraggable: function () { 3002 var sb = s.scrollbar; 3003 var target = s.support.touch ? sb.track : document; 3004 $(sb.track).on(sb.draggableEvents.start, sb.dragStart); 3005 $(target).on(sb.draggableEvents.move, sb.dragMove); 3006 $(target).on(sb.draggableEvents.end, sb.dragEnd); 3007 }, 3008 disableDraggable: function () { 3009 var sb = s.scrollbar; 3010 var target = s.support.touch ? sb.track : document; 3011 $(sb.track).off(sb.draggableEvents.start, sb.dragStart); 3012 $(target).off(sb.draggableEvents.move, sb.dragMove); 3013 $(target).off(sb.draggableEvents.end, sb.dragEnd); 3014 }, 3015 set: function () { 3016 if (!s.params.scrollbar) return; 3017 var sb = s.scrollbar; 3018 sb.track = $(s.params.scrollbar); 3019 if (s.params.uniqueNavElements && typeof s.params.scrollbar === 'string' && sb.track.length > 1 && s.container.find(s.params.scrollbar).length === 1) { 3020 sb.track = s.container.find(s.params.scrollbar); 3021 } 3022 sb.drag = sb.track.find('.swiper-scrollbar-drag'); 3023 if (sb.drag.length === 0) { 3024 sb.drag = $('<div class="swiper-scrollbar-drag"></div>'); 3025 sb.track.append(sb.drag); 3026 } 3027 sb.drag[0].style.width = ''; 3028 sb.drag[0].style.height = ''; 3029 sb.trackSize = s.isHorizontal() ? sb.track[0].offsetWidth : sb.track[0].offsetHeight; 3030 3031 sb.divider = s.size / s.virtualSize; 3032 sb.moveDivider = sb.divider * (sb.trackSize / s.size); 3033 sb.dragSize = sb.trackSize * sb.divider; 3034 3035 if (s.isHorizontal()) { 3036 sb.drag[0].style.width = sb.dragSize + 'px'; 3037 } 3038 else { 3039 sb.drag[0].style.height = sb.dragSize + 'px'; 3040 } 3041 3042 if (sb.divider >= 1) { 3043 sb.track[0].style.display = 'none'; 3044 } 3045 else { 3046 sb.track[0].style.display = ''; 3047 } 3048 if (s.params.scrollbarHide) { 3049 sb.track[0].style.opacity = 0; 3050 } 3051 }, 3052 setTranslate: function () { 3053 if (!s.params.scrollbar) return; 3054 var diff; 3055 var sb = s.scrollbar; 3056 var translate = s.translate || 0; 3057 var newPos; 3058 3059 var newSize = sb.dragSize; 3060 newPos = (sb.trackSize - sb.dragSize) * s.progress; 3061 if (s.rtl && s.isHorizontal()) { 3062 newPos = -newPos; 3063 if (newPos > 0) { 3064 newSize = sb.dragSize - newPos; 3065 newPos = 0; 3066 } 3067 else if (-newPos + sb.dragSize > sb.trackSize) { 3068 newSize = sb.trackSize + newPos; 3069 } 3070 } 3071 else { 3072 if (newPos < 0) { 3073 newSize = sb.dragSize + newPos; 3074 newPos = 0; 3075 } 3076 else if (newPos + sb.dragSize > sb.trackSize) { 3077 newSize = sb.trackSize - newPos; 3078 } 3079 } 3080 if (s.isHorizontal()) { 3081 if (s.support.transforms3d) { 3082 sb.drag.transform('translate3d(' + (newPos) + 'px, 0, 0)'); 3083 } 3084 else { 3085 sb.drag.transform('translateX(' + (newPos) + 'px)'); 3086 } 3087 sb.drag[0].style.width = newSize + 'px'; 3088 } 3089 else { 3090 if (s.support.transforms3d) { 3091 sb.drag.transform('translate3d(0px, ' + (newPos) + 'px, 0)'); 3092 } 3093 else { 3094 sb.drag.transform('translateY(' + (newPos) + 'px)'); 3095 } 3096 sb.drag[0].style.height = newSize + 'px'; 3097 } 3098 if (s.params.scrollbarHide) { 3099 clearTimeout(sb.timeout); 3100 sb.track[0].style.opacity = 1; 3101 sb.timeout = setTimeout(function () { 3102 sb.track[0].style.opacity = 0; 3103 sb.track.transition(400); 3104 }, 1000); 3105 } 3106 }, 3107 setTransition: function (duration) { 3108 if (!s.params.scrollbar) return; 3109 s.scrollbar.drag.transition(duration); 3110 } 3111 }; 3112 3113 3114 /*========================= 3115 Controller 3116 ===========================*/ 3117 s.controller = { 3118 LinearSpline: function (x, y) { 3119 var binarySearch = (function() { 3120 var maxIndex, minIndex, guess; 3121 return function(array, val) { 3122 minIndex = -1; 3123 maxIndex = array.length; 3124 while (maxIndex - minIndex > 1) 3125 if (array[guess = maxIndex + minIndex >> 1] <= val) { 3126 minIndex = guess; 3127 } else { 3128 maxIndex = guess; 3129 } 3130 return maxIndex; 3131 }; 3132 })(); 3133 this.x = x; 3134 this.y = y; 3135 this.lastIndex = x.length - 1; 3136 // Given an x value (x2), return the expected y2 value: 3137 // (x1,y1) is the known point before given value, 3138 // (x3,y3) is the known point after given value. 3139 var i1, i3; 3140 var l = this.x.length; 3141 3142 this.interpolate = function (x2) { 3143 if (!x2) return 0; 3144 3145 // Get the indexes of x1 and x3 (the array indexes before and after given x2): 3146 i3 = binarySearch(this.x, x2); 3147 i1 = i3 - 1; 3148 3149 // We have our indexes i1 & i3, so we can calculate already: 3150 // y2 := ((x2−x1) × (y3−y1)) ÷ (x3−x1) + y1 3151 return ((x2 - this.x[i1]) * (this.y[i3] - this.y[i1])) / (this.x[i3] - this.x[i1]) + this.y[i1]; 3152 }; 3153 }, 3154 //xxx: for now i will just save one spline function to to 3155 getInterpolateFunction: function(c){ 3156 if(!s.controller.spline) s.controller.spline = s.params.loop ? 3157 new s.controller.LinearSpline(s.slidesGrid, c.slidesGrid) : 3158 new s.controller.LinearSpline(s.snapGrid, c.snapGrid); 3159 }, 3160 setTranslate: function (translate, byController) { 3161 var controlled = s.params.control; 3162 var multiplier, controlledTranslate; 3163 function setControlledTranslate(c) { 3164 // this will create an Interpolate function based on the snapGrids 3165 // x is the Grid of the scrolled scroller and y will be the controlled scroller 3166 // it makes sense to create this only once and recall it for the interpolation 3167 // the function does a lot of value caching for performance 3168 translate = c.rtl && c.params.direction === 'horizontal' ? -s.translate : s.translate; 3169 if (s.params.controlBy === 'slide') { 3170 s.controller.getInterpolateFunction(c); 3171 // i am not sure why the values have to be multiplicated this way, tried to invert the snapGrid 3172 // but it did not work out 3173 controlledTranslate = -s.controller.spline.interpolate(-translate); 3174 } 3175 3176 if(!controlledTranslate || s.params.controlBy === 'container'){ 3177 multiplier = (c.maxTranslate() - c.minTranslate()) / (s.maxTranslate() - s.minTranslate()); 3178 controlledTranslate = (translate - s.minTranslate()) * multiplier + c.minTranslate(); 3179 } 3180 3181 if (s.params.controlInverse) { 3182 controlledTranslate = c.maxTranslate() - controlledTranslate; 3183 } 3184 c.updateProgress(controlledTranslate); 3185 c.setWrapperTranslate(controlledTranslate, false, s); 3186 c.updateActiveIndex(); 3187 } 3188 if (Array.isArray(controlled)) { 3189 for (var i = 0; i < controlled.length; i++) { 3190 if (controlled[i] !== byController && controlled[i] instanceof Swiper) { 3191 setControlledTranslate(controlled[i]); 3192 } 3193 } 3194 } 3195 else if (controlled instanceof Swiper && byController !== controlled) { 3196 3197 setControlledTranslate(controlled); 3198 } 3199 }, 3200 setTransition: function (duration, byController) { 3201 var controlled = s.params.control; 3202 var i; 3203 function setControlledTransition(c) { 3204 c.setWrapperTransition(duration, s); 3205 if (duration !== 0) { 3206 c.onTransitionStart(); 3207 c.wrapper.transitionEnd(function(){ 3208 if (!controlled) return; 3209 if (c.params.loop && s.params.controlBy === 'slide') { 3210 c.fixLoop(); 3211 } 3212 c.onTransitionEnd(); 3213 3214 }); 3215 } 3216 } 3217 if (Array.isArray(controlled)) { 3218 for (i = 0; i < controlled.length; i++) { 3219 if (controlled[i] !== byController && controlled[i] instanceof Swiper) { 3220 setControlledTransition(controlled[i]); 3221 } 3222 } 3223 } 3224 else if (controlled instanceof Swiper && byController !== controlled) { 3225 setControlledTransition(controlled); 3226 } 3227 } 3228 }; 3229 3230 3231 /*========================= 3232 Hash Navigation 3233 ===========================*/ 3234 s.hashnav = { 3235 onHashCange: function (e, a) { 3236 var newHash = document.location.hash.replace('#', ''); 3237 var activeSlideHash = s.slides.eq(s.activeIndex).attr('data-hash'); 3238 if (newHash !== activeSlideHash) { 3239 s.slideTo(s.wrapper.children('.' + s.params.slideClass + '[data-hash="' + (newHash) + '"]').index()); 3240 } 3241 }, 3242 attachEvents: function (detach) { 3243 var action = detach ? 'off' : 'on'; 3244 $(window)[action]('hashchange', s.hashnav.onHashCange); 3245 }, 3246 setHash: function () { 3247 if (!s.hashnav.initialized || !s.params.hashnav) return; 3248 if (s.params.replaceState && window.history && window.history.replaceState) { 3249 window.history.replaceState(null, null, ('#' + s.slides.eq(s.activeIndex).attr('data-hash') || '')); 3250 } else { 3251 var slide = s.slides.eq(s.activeIndex); 3252 var hash = slide.attr('data-hash') || slide.attr('data-history'); 3253 document.location.hash = hash || ''; 3254 } 3255 }, 3256 init: function () { 3257 if (!s.params.hashnav || s.params.history) return; 3258 s.hashnav.initialized = true; 3259 var hash = document.location.hash.replace('#', ''); 3260 if (hash) { 3261 var speed = 0; 3262 for (var i = 0, length = s.slides.length; i < length; i++) { 3263 var slide = s.slides.eq(i); 3264 var slideHash = slide.attr('data-hash') || slide.attr('data-history'); 3265 if (slideHash === hash && !slide.hasClass(s.params.slideDuplicateClass)) { 3266 var index = slide.index(); 3267 s.slideTo(index, speed, s.params.runCallbacksOnInit, true); 3268 } 3269 } 3270 } 3271 if (s.params.hashnavWatchState) s.hashnav.attachEvents(); 3272 }, 3273 destroy: function () { 3274 if (s.params.hashnavWatchState) s.hashnav.attachEvents(true); 3275 } 3276 }; 3277 3278 3279 /*========================= 3280 History Api with fallback to Hashnav 3281 ===========================*/ 3282 s.history = { 3283 init: function () { 3284 if (!s.params.history) return; 3285 if (!window.history || !window.history.pushState) { 3286 s.params.history = false; 3287 s.params.hashnav = true; 3288 return; 3289 } 3290 s.history.initialized = true; 3291 this.paths = this.getPathValues(); 3292 if (!this.paths.key && !this.paths.value) return; 3293 this.scrollToSlide(0, this.paths.value, s.params.runCallbacksOnInit); 3294 if (!s.params.replaceState) { 3295 window.addEventListener('popstate', this.setHistoryPopState); 3296 } 3297 }, 3298 setHistoryPopState: function() { 3299 s.history.paths = s.history.getPathValues(); 3300 s.history.scrollToSlide(s.params.speed, s.history.paths.value, false); 3301 }, 3302 getPathValues: function() { 3303 var pathArray = window.location.pathname.slice(1).split('/'); 3304 var total = pathArray.length; 3305 var key = pathArray[total - 2]; 3306 var value = pathArray[total - 1]; 3307 return { key: key, value: value }; 3308 }, 3309 setHistory: function (key, index) { 3310 if (!s.history.initialized || !s.params.history) return; 3311 var slide = s.slides.eq(index); 3312 var value = this.slugify(slide.attr('data-history')); 3313 if (!window.location.pathname.includes(key)) { 3314 value = key + '/' + value; 3315 } 3316 if (s.params.replaceState) { 3317 window.history.replaceState(null, null, value); 3318 } else { 3319 window.history.pushState(null, null, value); 3320 } 3321 }, 3322 slugify: function(text) { 3323 return text.toString().toLowerCase() 3324 .replace(/\s+/g, '-') 3325 .replace(/[^\w\-]+/g, '') 3326 .replace(/\-\-+/g, '-') 3327 .replace(/^-+/, '') 3328 .replace(/-+$/, ''); 3329 }, 3330 scrollToSlide: function(speed, value, runCallbacks) { 3331 if (value) { 3332 for (var i = 0, length = s.slides.length; i < length; i++) { 3333 var slide = s.slides.eq(i); 3334 var slideHistory = this.slugify(slide.attr('data-history')); 3335 if (slideHistory === value && !slide.hasClass(s.params.slideDuplicateClass)) { 3336 var index = slide.index(); 3337 s.slideTo(index, speed, runCallbacks); 3338 } 3339 } 3340 } else { 3341 s.slideTo(0, speed, runCallbacks); 3342 } 3343 } 3344 }; 3345 3346 3347 /*========================= 3348 Keyboard Control 3349 ===========================*/ 3350 function handleKeyboard(e) { 3351 if (e.originalEvent) e = e.originalEvent; //jquery fix 3352 var kc = e.keyCode || e.charCode; 3353 // Directions locks 3354 if (!s.params.allowSwipeToNext && (s.isHorizontal() && kc === 39 || !s.isHorizontal() && kc === 40)) { 3355 return false; 3356 } 3357 if (!s.params.allowSwipeToPrev && (s.isHorizontal() && kc === 37 || !s.isHorizontal() && kc === 38)) { 3358 return false; 3359 } 3360 if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) { 3361 return; 3362 } 3363 if (document.activeElement && document.activeElement.nodeName && (document.activeElement.nodeName.toLowerCase() === 'input' || document.activeElement.nodeName.toLowerCase() === 'textarea')) { 3364 return; 3365 } 3366 if (kc === 37 || kc === 39 || kc === 38 || kc === 40) { 3367 var inView = false; 3368 //Check that swiper should be inside of visible area of window 3369 if (s.container.parents('.' + s.params.slideClass).length > 0 && s.container.parents('.' + s.params.slideActiveClass).length === 0) { 3370 return; 3371 } 3372 var windowScroll = { 3373 left: window.pageXOffset, 3374 top: window.pageYOffset 3375 }; 3376 var windowWidth = window.innerWidth; 3377 var windowHeight = window.innerHeight; 3378 var swiperOffset = s.container.offset(); 3379 if (s.rtl) swiperOffset.left = swiperOffset.left - s.container[0].scrollLeft; 3380 var swiperCoord = [ 3381 [swiperOffset.left, swiperOffset.top], 3382 [swiperOffset.left + s.width, swiperOffset.top], 3383 [swiperOffset.left, swiperOffset.top + s.height], 3384 [swiperOffset.left + s.width, swiperOffset.top + s.height] 3385 ]; 3386 for (var i = 0; i < swiperCoord.length; i++) { 3387 var point = swiperCoord[i]; 3388 if ( 3389 point[0] >= windowScroll.left && point[0] <= windowScroll.left + windowWidth && 3390 point[1] >= windowScroll.top && point[1] <= windowScroll.top + windowHeight 3391 ) { 3392 inView = true; 3393 } 3394 3395 } 3396 if (!inView) return; 3397 } 3398 if (s.isHorizontal()) { 3399 if (kc === 37 || kc === 39) { 3400 if (e.preventDefault) e.preventDefault(); 3401 else e.returnValue = false; 3402 } 3403 if ((kc === 39 && !s.rtl) || (kc === 37 && s.rtl)) s.slideNext(); 3404 if ((kc === 37 && !s.rtl) || (kc === 39 && s.rtl)) s.slidePrev(); 3405 } 3406 else { 3407 if (kc === 38 || kc === 40) { 3408 if (e.preventDefault) e.preventDefault(); 3409 else e.returnValue = false; 3410 } 3411 if (kc === 40) s.slideNext(); 3412 if (kc === 38) s.slidePrev(); 3413 } 3414 s.emit('onKeyPress', s, kc); 3415 } 3416 s.disableKeyboardControl = function () { 3417 s.params.keyboardControl = false; 3418 $(document).off('keydown', handleKeyboard); 3419 }; 3420 s.enableKeyboardControl = function () { 3421 s.params.keyboardControl = true; 3422 $(document).on('keydown', handleKeyboard); 3423 }; 3424 3425 3426 /*========================= 3427 Mousewheel Control 3428 ===========================*/ 3429 s.mousewheel = { 3430 event: false, 3431 lastScrollTime: (new window.Date()).getTime() 3432 }; 3433 function isEventSupported() { 3434 var eventName = 'onwheel'; 3435 var isSupported = eventName in document; 3436 3437 if (!isSupported) { 3438 var element = document.createElement('div'); 3439 element.setAttribute(eventName, 'return;'); 3440 isSupported = typeof element[eventName] === 'function'; 3441 } 3442 3443 if (!isSupported && 3444 document.implementation && 3445 document.implementation.hasFeature && 3446 // always returns true in newer browsers as per the standard. 3447 // @see http://dom.spec.whatwg.org/#dom-domimplementation-hasfeature 3448 document.implementation.hasFeature('', '') !== true ) { 3449 // This is the only way to test support for the `wheel` event in IE9+. 3450 isSupported = document.implementation.hasFeature('Events.wheel', '3.0'); 3451 } 3452 3453 return isSupported; 3454 } 3455 /** 3456 * Mouse wheel (and 2-finger trackpad) support on the web sucks. It is 3457 * complicated, thus this doc is long and (hopefully) detailed enough to answer 3458 * your questions. 3459 * 3460 * If you need to react to the mouse wheel in a predictable way, this code is 3461 * like your bestest friend. * hugs * 3462 * 3463 * As of today, there are 4 DOM event types you can listen to: 3464 * 3465 * 'wheel' -- Chrome(31+), FF(17+), IE(9+) 3466 * 'mousewheel' -- Chrome, IE(6+), Opera, Safari 3467 * 'MozMousePixelScroll' -- FF(3.5 only!) (2010-2013) -- don't bother! 3468 * 'DOMMouseScroll' -- FF(0.9.7+) since 2003 3469 * 3470 * So what to do? The is the best: 3471 * 3472 * normalizeWheel.getEventType(); 3473 * 3474 * In your event callback, use this code to get sane interpretation of the 3475 * deltas. This code will return an object with properties: 3476 * 3477 * spinX -- normalized spin speed (use for zoom) - x plane 3478 * spinY -- " - y plane 3479 * pixelX -- normalized distance (to pixels) - x plane 3480 * pixelY -- " - y plane 3481 * 3482 * Wheel values are provided by the browser assuming you are using the wheel to 3483 * scroll a web page by a number of lines or pixels (or pages). Values can vary 3484 * significantly on different platforms and browsers, forgetting that you can 3485 * scroll at different speeds. Some devices (like trackpads) emit more events 3486 * at smaller increments with fine granularity, and some emit massive jumps with 3487 * linear speed or acceleration. 3488 * 3489 * This code does its best to normalize the deltas for you: 3490 * 3491 * - spin is trying to normalize how far the wheel was spun (or trackpad 3492 * dragged). This is super useful for zoom support where you want to 3493 * throw away the chunky scroll steps on the PC and make those equal to 3494 * the slow and smooth tiny steps on the Mac. Key data: This code tries to 3495 * resolve a single slow step on a wheel to 1. 3496 * 3497 * - pixel is normalizing the desired scroll delta in pixel units. You'll 3498 * get the crazy differences between browsers, but at least it'll be in 3499 * pixels! 3500 * 3501 * - positive value indicates scrolling DOWN/RIGHT, negative UP/LEFT. This 3502 * should translate to positive value zooming IN, negative zooming OUT. 3503 * This matches the newer 'wheel' event. 3504 * 3505 * Why are there spinX, spinY (or pixels)? 3506 * 3507 * - spinX is a 2-finger side drag on the trackpad, and a shift + wheel turn 3508 * with a mouse. It results in side-scrolling in the browser by default. 3509 * 3510 * - spinY is what you expect -- it's the classic axis of a mouse wheel. 3511 * 3512 * - I dropped spinZ/pixelZ. It is supported by the DOM 3 'wheel' event and 3513 * probably is by browsers in conjunction with fancy 3D controllers .. but 3514 * you know. 3515 * 3516 * Implementation info: 3517 * 3518 * Examples of 'wheel' event if you scroll slowly (down) by one step with an 3519 * average mouse: 3520 * 3521 * OS X + Chrome (mouse) - 4 pixel delta (wheelDelta -120) 3522 * OS X + Safari (mouse) - N/A pixel delta (wheelDelta -12) 3523 * OS X + Firefox (mouse) - 0.1 line delta (wheelDelta N/A) 3524 * Win8 + Chrome (mouse) - 100 pixel delta (wheelDelta -120) 3525 * Win8 + Firefox (mouse) - 3 line delta (wheelDelta -120) 3526 * 3527 * On the trackpad: 3528 * 3529 * OS X + Chrome (trackpad) - 2 pixel delta (wheelDelta -6) 3530 * OS X + Firefox (trackpad) - 1 pixel delta (wheelDelta N/A) 3531 * 3532 * On other/older browsers.. it's more complicated as there can be multiple and 3533 * also missing delta values. 3534 * 3535 * The 'wheel' event is more standard: 3536 * 3537 * http://www.w3.org/TR/DOM-Level-3-Events/#events-wheelevents 3538 * 3539 * The basics is that it includes a unit, deltaMode (pixels, lines, pages), and 3540 * deltaX, deltaY and deltaZ. Some browsers provide other values to maintain 3541 * backward compatibility with older events. Those other values help us 3542 * better normalize spin speed. Example of what the browsers provide: 3543 * 3544 * | event.wheelDelta | event.detail 3545 * ------------------+------------------+-------------- 3546 * Safari v5/OS X | -120 | 0 3547 * Safari v5/Win7 | -120 | 0 3548 * Chrome v17/OS X | -120 | 0 3549 * Chrome v17/Win7 | -120 | 0 3550 * IE9/Win7 | -120 | undefined 3551 * Firefox v4/OS X | undefined | 1 3552 * Firefox v4/Win7 | undefined | 3 3553 * 3554 */ 3555 function normalizeWheel( /*object*/ event ) /*object*/ { 3556 // Reasonable defaults 3557 var PIXEL_STEP = 10; 3558 var LINE_HEIGHT = 40; 3559 var PAGE_HEIGHT = 800; 3560 3561 var sX = 0, sY = 0, // spinX, spinY 3562 pX = 0, pY = 0; // pixelX, pixelY 3563 3564 // Legacy 3565 if( 'detail' in event ) { 3566 sY = event.detail; 3567 } 3568 if( 'wheelDelta' in event ) { 3569 sY = -event.wheelDelta / 120; 3570 } 3571 if( 'wheelDeltaY' in event ) { 3572 sY = -event.wheelDeltaY / 120; 3573 } 3574 if( 'wheelDeltaX' in event ) { 3575 sX = -event.wheelDeltaX / 120; 3576 } 3577 3578 // side scrolling on FF with DOMMouseScroll 3579 if( 'axis' in event && event.axis === event.HORIZONTAL_AXIS ) { 3580 sX = sY; 3581 sY = 0; 3582 } 3583 3584 pX = sX * PIXEL_STEP; 3585 pY = sY * PIXEL_STEP; 3586 3587 if( 'deltaY' in event ) { 3588 pY = event.deltaY; 3589 } 3590 if( 'deltaX' in event ) { 3591 pX = event.deltaX; 3592 } 3593 3594 if( (pX || pY) && event.deltaMode ) { 3595 if( event.deltaMode === 1 ) { // delta in LINE units 3596 pX *= LINE_HEIGHT; 3597 pY *= LINE_HEIGHT; 3598 } else { // delta in PAGE units 3599 pX *= PAGE_HEIGHT; 3600 pY *= PAGE_HEIGHT; 3601 } 3602 } 3603 3604 // Fall-back if spin cannot be determined 3605 if( pX && !sX ) { 3606 sX = (pX < 1) ? -1 : 1; 3607 } 3608 if( pY && !sY ) { 3609 sY = (pY < 1) ? -1 : 1; 3610 } 3611 3612 return { 3613 spinX: sX, 3614 spinY: sY, 3615 pixelX: pX, 3616 pixelY: pY 3617 }; 3618 } 3619 if (s.params.mousewheelControl) { 3620 /** 3621 * The best combination if you prefer spinX + spinY normalization. It favors 3622 * the older DOMMouseScroll for Firefox, as FF does not include wheelDelta with 3623 * 'wheel' event, making spin speed determination impossible. 3624 */ 3625 s.mousewheel.event = (navigator.userAgent.indexOf('firefox') > -1) ? 3626 'DOMMouseScroll' : 3627 isEventSupported() ? 3628 'wheel' : 'mousewheel'; 3629 } 3630 function handleMousewheel(e) { 3631 if (e.originalEvent) e = e.originalEvent; //jquery fix 3632 var delta = 0; 3633 var rtlFactor = s.rtl ? -1 : 1; 3634 3635 var data = normalizeWheel( e ); 3636 3637 if (s.params.mousewheelForceToAxis) { 3638 if (s.isHorizontal()) { 3639 if (Math.abs(data.pixelX) > Math.abs(data.pixelY)) delta = data.pixelX * rtlFactor; 3640 else return; 3641 } 3642 else { 3643 if (Math.abs(data.pixelY) > Math.abs(data.pixelX)) delta = data.pixelY; 3644 else return; 3645 } 3646 } 3647 else { 3648 delta = Math.abs(data.pixelX) > Math.abs(data.pixelY) ? - data.pixelX * rtlFactor : - data.pixelY; 3649 } 3650 3651 if (delta === 0) return; 3652 3653 if (s.params.mousewheelInvert) delta = -delta; 3654 3655 if (!s.params.freeMode) { 3656 if ((new window.Date()).getTime() - s.mousewheel.lastScrollTime > 60) { 3657 if (delta < 0) { 3658 if ((!s.isEnd || s.params.loop) && !s.animating) { 3659 s.slideNext(); 3660 s.emit('onScroll', s, e); 3661 } 3662 else if (s.params.mousewheelReleaseOnEdges) return true; 3663 } 3664 else { 3665 if ((!s.isBeginning || s.params.loop) && !s.animating) { 3666 s.slidePrev(); 3667 s.emit('onScroll', s, e); 3668 } 3669 else if (s.params.mousewheelReleaseOnEdges) return true; 3670 } 3671 } 3672 s.mousewheel.lastScrollTime = (new window.Date()).getTime(); 3673 3674 } 3675 else { 3676 //Freemode or scrollContainer: 3677 var position = s.getWrapperTranslate() + delta * s.params.mousewheelSensitivity; 3678 var wasBeginning = s.isBeginning, 3679 wasEnd = s.isEnd; 3680 3681 if (position >= s.minTranslate()) position = s.minTranslate(); 3682 if (position <= s.maxTranslate()) position = s.maxTranslate(); 3683 3684 s.setWrapperTransition(0); 3685 s.setWrapperTranslate(position); 3686 s.updateProgress(); 3687 s.updateActiveIndex(); 3688 3689 if (!wasBeginning && s.isBeginning || !wasEnd && s.isEnd) { 3690 s.updateClasses(); 3691 } 3692 3693 if (s.params.freeModeSticky) { 3694 clearTimeout(s.mousewheel.timeout); 3695 s.mousewheel.timeout = setTimeout(function () { 3696 s.slideReset(); 3697 }, 300); 3698 } 3699 else { 3700 if (s.params.lazyLoading && s.lazy) { 3701 s.lazy.load(); 3702 } 3703 } 3704 // Emit event 3705 s.emit('onScroll', s, e); 3706 3707 // Stop autoplay 3708 if (s.params.autoplay && s.params.autoplayDisableOnInteraction) s.stopAutoplay(); 3709 3710 // Return page scroll on edge positions 3711 if (position === 0 || position === s.maxTranslate()) return; 3712 } 3713 3714 if (e.preventDefault) e.preventDefault(); 3715 else e.returnValue = false; 3716 return false; 3717 } 3718 s.disableMousewheelControl = function () { 3719 if (!s.mousewheel.event) return false; 3720 var target = s.container; 3721 if (s.params.mousewheelEventsTarged !== 'container') { 3722 target = $(s.params.mousewheelEventsTarged); 3723 } 3724 target.off(s.mousewheel.event, handleMousewheel); 3725 s.params.mousewheelControl = false; 3726 return true; 3727 }; 3728 3729 s.enableMousewheelControl = function () { 3730 if (!s.mousewheel.event) return false; 3731 var target = s.container; 3732 if (s.params.mousewheelEventsTarged !== 'container') { 3733 target = $(s.params.mousewheelEventsTarged); 3734 } 3735 target.on(s.mousewheel.event, handleMousewheel); 3736 s.params.mousewheelControl = true; 3737 return true; 3738 }; 3739 3740 3741 /*========================= 3742 Parallax 3743 ===========================*/ 3744 function setParallaxTransform(el, progress) { 3745 el = $(el); 3746 var p, pX, pY; 3747 var rtlFactor = s.rtl ? -1 : 1; 3748 3749 p = el.attr('data-swiper-parallax') || '0'; 3750 pX = el.attr('data-swiper-parallax-x'); 3751 pY = el.attr('data-swiper-parallax-y'); 3752 if (pX || pY) { 3753 pX = pX || '0'; 3754 pY = pY || '0'; 3755 } 3756 else { 3757 if (s.isHorizontal()) { 3758 pX = p; 3759 pY = '0'; 3760 } 3761 else { 3762 pY = p; 3763 pX = '0'; 3764 } 3765 } 3766 3767 if ((pX).indexOf('%') >= 0) { 3768 pX = parseInt(pX, 10) * progress * rtlFactor + '%'; 3769 } 3770 else { 3771 pX = pX * progress * rtlFactor + 'px' ; 3772 } 3773 if ((pY).indexOf('%') >= 0) { 3774 pY = parseInt(pY, 10) * progress + '%'; 3775 } 3776 else { 3777 pY = pY * progress + 'px' ; 3778 } 3779 3780 el.transform('translate3d(' + pX + ', ' + pY + ',0px)'); 3781 } 3782 s.parallax = { 3783 setTranslate: function () { 3784 s.container.children('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]').each(function(){ 3785 setParallaxTransform(this, s.progress); 3786 3787 }); 3788 s.slides.each(function () { 3789 var slide = $(this); 3790 slide.find('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]').each(function () { 3791 var progress = Math.min(Math.max(slide[0].progress, -1), 1); 3792 setParallaxTransform(this, progress); 3793 }); 3794 }); 3795 }, 3796 setTransition: function (duration) { 3797 if (typeof duration === 'undefined') duration = s.params.speed; 3798 s.container.find('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]').each(function(){ 3799 var el = $(this); 3800 var parallaxDuration = parseInt(el.attr('data-swiper-parallax-duration'), 10) || duration; 3801 if (duration === 0) parallaxDuration = 0; 3802 el.transition(parallaxDuration); 3803 }); 3804 } 3805 }; 3806 3807 3808 /*========================= 3809 Zoom 3810 ===========================*/ 3811 s.zoom = { 3812 // "Global" Props 3813 scale: 1, 3814 currentScale: 1, 3815 isScaling: false, 3816 gesture: { 3817 slide: undefined, 3818 slideWidth: undefined, 3819 slideHeight: undefined, 3820 image: undefined, 3821 imageWrap: undefined, 3822 zoomMax: s.params.zoomMax 3823 }, 3824 image: { 3825 isTouched: undefined, 3826 isMoved: undefined, 3827 currentX: undefined, 3828 currentY: undefined, 3829 minX: undefined, 3830 minY: undefined, 3831 maxX: undefined, 3832 maxY: undefined, 3833 width: undefined, 3834 height: undefined, 3835 startX: undefined, 3836 startY: undefined, 3837 touchesStart: {}, 3838 touchesCurrent: {} 3839 }, 3840 velocity: { 3841 x: undefined, 3842 y: undefined, 3843 prevPositionX: undefined, 3844 prevPositionY: undefined, 3845 prevTime: undefined 3846 }, 3847 // Calc Scale From Multi-touches 3848 getDistanceBetweenTouches: function (e) { 3849 if (e.targetTouches.length < 2) return 1; 3850 var x1 = e.targetTouches[0].pageX, 3851 y1 = e.targetTouches[0].pageY, 3852 x2 = e.targetTouches[1].pageX, 3853 y2 = e.targetTouches[1].pageY; 3854 var distance = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); 3855 return distance; 3856 }, 3857 // Events 3858 onGestureStart: function (e) { 3859 var z = s.zoom; 3860 if (!s.support.gestures) { 3861 if (e.type !== 'touchstart' || e.type === 'touchstart' && e.targetTouches.length < 2) { 3862 return; 3863 } 3864 z.gesture.scaleStart = z.getDistanceBetweenTouches(e); 3865 } 3866 if (!z.gesture.slide || !z.gesture.slide.length) { 3867 z.gesture.slide = $(this); 3868 if (z.gesture.slide.length === 0) z.gesture.slide = s.slides.eq(s.activeIndex); 3869 z.gesture.image = z.gesture.slide.find('img, svg, canvas'); 3870 z.gesture.imageWrap = z.gesture.image.parent('.' + s.params.zoomContainerClass); 3871 z.gesture.zoomMax = z.gesture.imageWrap.attr('data-swiper-zoom') || s.params.zoomMax ; 3872 if (z.gesture.imageWrap.length === 0) { 3873 z.gesture.image = undefined; 3874 return; 3875 } 3876 } 3877 z.gesture.image.transition(0); 3878 z.isScaling = true; 3879 }, 3880 onGestureChange: function (e) { 3881 var z = s.zoom; 3882 if (!s.support.gestures) { 3883 if (e.type !== 'touchmove' || e.type === 'touchmove' && e.targetTouches.length < 2) { 3884 return; 3885 } 3886 z.gesture.scaleMove = z.getDistanceBetweenTouches(e); 3887 } 3888 if (!z.gesture.image || z.gesture.image.length === 0) return; 3889 if (s.support.gestures) { 3890 z.scale = e.scale * z.currentScale; 3891 } 3892 else { 3893 z.scale = (z.gesture.scaleMove / z.gesture.scaleStart) * z.currentScale; 3894 } 3895 if (z.scale > z.gesture.zoomMax) { 3896 z.scale = z.gesture.zoomMax - 1 + Math.pow((z.scale - z.gesture.zoomMax + 1), 0.5); 3897 } 3898 if (z.scale < s.params.zoomMin) { 3899 z.scale = s.params.zoomMin + 1 - Math.pow((s.params.zoomMin - z.scale + 1), 0.5); 3900 } 3901 z.gesture.image.transform('translate3d(0,0,0) scale(' + z.scale + ')'); 3902 }, 3903 onGestureEnd: function (e) { 3904 var z = s.zoom; 3905 if (!s.support.gestures) { 3906 if (e.type !== 'touchend' || e.type === 'touchend' && e.changedTouches.length < 2) { 3907 return; 3908 } 3909 } 3910 if (!z.gesture.image || z.gesture.image.length === 0) return; 3911 z.scale = Math.max(Math.min(z.scale, z.gesture.zoomMax), s.params.zoomMin); 3912 z.gesture.image.transition(s.params.speed).transform('translate3d(0,0,0) scale(' + z.scale + ')'); 3913 z.currentScale = z.scale; 3914 z.isScaling = false; 3915 if (z.scale === 1) z.gesture.slide = undefined; 3916 }, 3917 onTouchStart: function (s, e) { 3918 var z = s.zoom; 3919 if (!z.gesture.image || z.gesture.image.length === 0) return; 3920 if (z.image.isTouched) return; 3921 if (s.device.os === 'android') e.preventDefault(); 3922 z.image.isTouched = true; 3923 z.image.touchesStart.x = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX; 3924 z.image.touchesStart.y = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY; 3925 }, 3926 onTouchMove: function (e) { 3927 var z = s.zoom; 3928 if (!z.gesture.image || z.gesture.image.length === 0) return; 3929 s.allowClick = false; 3930 if (!z.image.isTouched || !z.gesture.slide) return; 3931 3932 if (!z.image.isMoved) { 3933 z.image.width = z.gesture.image[0].offsetWidth; 3934 z.image.height = z.gesture.image[0].offsetHeight; 3935 z.image.startX = s.getTranslate(z.gesture.imageWrap[0], 'x') || 0; 3936 z.image.startY = s.getTranslate(z.gesture.imageWrap[0], 'y') || 0; 3937 z.gesture.slideWidth = z.gesture.slide[0].offsetWidth; 3938 z.gesture.slideHeight = z.gesture.slide[0].offsetHeight; 3939 z.gesture.imageWrap.transition(0); 3940 if (s.rtl) z.image.startX = -z.image.startX; 3941 if (s.rtl) z.image.startY = -z.image.startY; 3942 } 3943 // Define if we need image drag 3944 var scaledWidth = z.image.width * z.scale; 3945 var scaledHeight = z.image.height * z.scale; 3946 3947 if (scaledWidth < z.gesture.slideWidth && scaledHeight < z.gesture.slideHeight) return; 3948 3949 z.image.minX = Math.min((z.gesture.slideWidth / 2 - scaledWidth / 2), 0); 3950 z.image.maxX = -z.image.minX; 3951 z.image.minY = Math.min((z.gesture.slideHeight / 2 - scaledHeight / 2), 0); 3952 z.image.maxY = -z.image.minY; 3953 3954 z.image.touchesCurrent.x = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX; 3955 z.image.touchesCurrent.y = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY; 3956 3957 if (!z.image.isMoved && !z.isScaling) { 3958 if (s.isHorizontal() && 3959 (Math.floor(z.image.minX) === Math.floor(z.image.startX) && z.image.touchesCurrent.x < z.image.touchesStart.x) || 3960 (Math.floor(z.image.maxX) === Math.floor(z.image.startX) && z.image.touchesCurrent.x > z.image.touchesStart.x) 3961 ) { 3962 z.image.isTouched = false; 3963 return; 3964 } 3965 else if (!s.isHorizontal() && 3966 (Math.floor(z.image.minY) === Math.floor(z.image.startY) && z.image.touchesCurrent.y < z.image.touchesStart.y) || 3967 (Math.floor(z.image.maxY) === Math.floor(z.image.startY) && z.image.touchesCurrent.y > z.image.touchesStart.y) 3968 ) { 3969 z.image.isTouched = false; 3970 return; 3971 } 3972 } 3973 e.preventDefault(); 3974 e.stopPropagation(); 3975 3976 z.image.isMoved = true; 3977 z.image.currentX = z.image.touchesCurrent.x - z.image.touchesStart.x + z.image.startX; 3978 z.image.currentY = z.image.touchesCurrent.y - z.image.touchesStart.y + z.image.startY; 3979 3980 if (z.image.currentX < z.image.minX) { 3981 z.image.currentX = z.image.minX + 1 - Math.pow((z.image.minX - z.image.currentX + 1), 0.8); 3982 } 3983 if (z.image.currentX > z.image.maxX) { 3984 z.image.currentX = z.image.maxX - 1 + Math.pow((z.image.currentX - z.image.maxX + 1), 0.8); 3985 } 3986 3987 if (z.image.currentY < z.image.minY) { 3988 z.image.currentY = z.image.minY + 1 - Math.pow((z.image.minY - z.image.currentY + 1), 0.8); 3989 } 3990 if (z.image.currentY > z.image.maxY) { 3991 z.image.currentY = z.image.maxY - 1 + Math.pow((z.image.currentY - z.image.maxY + 1), 0.8); 3992 } 3993 3994 //Velocity 3995 if (!z.velocity.prevPositionX) z.velocity.prevPositionX = z.image.touchesCurrent.x; 3996 if (!z.velocity.prevPositionY) z.velocity.prevPositionY = z.image.touchesCurrent.y; 3997 if (!z.velocity.prevTime) z.velocity.prevTime = Date.now(); 3998 z.velocity.x = (z.image.touchesCurrent.x - z.velocity.prevPositionX) / (Date.now() - z.velocity.prevTime) / 2; 3999 z.velocity.y = (z.image.touchesCurrent.y - z.velocity.prevPositionY) / (Date.now() - z.velocity.prevTime) / 2; 4000 if (Math.abs(z.image.touchesCurrent.x - z.velocity.prevPositionX) < 2) z.velocity.x = 0; 4001 if (Math.abs(z.image.touchesCurrent.y - z.velocity.prevPositionY) < 2) z.velocity.y = 0; 4002 z.velocity.prevPositionX = z.image.touchesCurrent.x; 4003 z.velocity.prevPositionY = z.image.touchesCurrent.y; 4004 z.velocity.prevTime = Date.now(); 4005 4006 z.gesture.imageWrap.transform('translate3d(' + z.image.currentX + 'px, ' + z.image.currentY + 'px,0)'); 4007 }, 4008 onTouchEnd: function (s, e) { 4009 var z = s.zoom; 4010 if (!z.gesture.image || z.gesture.image.length === 0) return; 4011 if (!z.image.isTouched || !z.image.isMoved) { 4012 z.image.isTouched = false; 4013 z.image.isMoved = false; 4014 return; 4015 } 4016 z.image.isTouched = false; 4017 z.image.isMoved = false; 4018 var momentumDurationX = 300; 4019 var momentumDurationY = 300; 4020 var momentumDistanceX = z.velocity.x * momentumDurationX; 4021 var newPositionX = z.image.currentX + momentumDistanceX; 4022 var momentumDistanceY = z.velocity.y * momentumDurationY; 4023 var newPositionY = z.image.currentY + momentumDistanceY; 4024 4025 //Fix duration 4026 if (z.velocity.x !== 0) momentumDurationX = Math.abs((newPositionX - z.image.currentX) / z.velocity.x); 4027 if (z.velocity.y !== 0) momentumDurationY = Math.abs((newPositionY - z.image.currentY) / z.velocity.y); 4028 var momentumDuration = Math.max(momentumDurationX, momentumDurationY); 4029 4030 z.image.currentX = newPositionX; 4031 z.image.currentY = newPositionY; 4032 4033 // Define if we need image drag 4034 var scaledWidth = z.image.width * z.scale; 4035 var scaledHeight = z.image.height * z.scale; 4036 z.image.minX = Math.min((z.gesture.slideWidth / 2 - scaledWidth / 2), 0); 4037 z.image.maxX = -z.image.minX; 4038 z.image.minY = Math.min((z.gesture.slideHeight / 2 - scaledHeight / 2), 0); 4039 z.image.maxY = -z.image.minY; 4040 z.image.currentX = Math.max(Math.min(z.image.currentX, z.image.maxX), z.image.minX); 4041 z.image.currentY = Math.max(Math.min(z.image.currentY, z.image.maxY), z.image.minY); 4042 4043 z.gesture.imageWrap.transition(momentumDuration).transform('translate3d(' + z.image.currentX + 'px, ' + z.image.currentY + 'px,0)'); 4044 }, 4045 onTransitionEnd: function (s) { 4046 var z = s.zoom; 4047 if (z.gesture.slide && s.previousIndex !== s.activeIndex) { 4048 z.gesture.image.transform('translate3d(0,0,0) scale(1)'); 4049 z.gesture.imageWrap.transform('translate3d(0,0,0)'); 4050 z.gesture.slide = z.gesture.image = z.gesture.imageWrap = undefined; 4051 z.scale = z.currentScale = 1; 4052 } 4053 }, 4054 // Toggle Zoom 4055 toggleZoom: function (s, e) { 4056 var z = s.zoom; 4057 if (!z.gesture.slide) { 4058 z.gesture.slide = s.clickedSlide ? $(s.clickedSlide) : s.slides.eq(s.activeIndex); 4059 z.gesture.image = z.gesture.slide.find('img, svg, canvas'); 4060 z.gesture.imageWrap = z.gesture.image.parent('.' + s.params.zoomContainerClass); 4061 } 4062 if (!z.gesture.image || z.gesture.image.length === 0) return; 4063 4064 var touchX, touchY, offsetX, offsetY, diffX, diffY, translateX, translateY, imageWidth, imageHeight, scaledWidth, scaledHeight, translateMinX, translateMinY, translateMaxX, translateMaxY, slideWidth, slideHeight; 4065 4066 if (typeof z.image.touchesStart.x === 'undefined' && e) { 4067 touchX = e.type === 'touchend' ? e.changedTouches[0].pageX : e.pageX; 4068 touchY = e.type === 'touchend' ? e.changedTouches[0].pageY : e.pageY; 4069 } 4070 else { 4071 touchX = z.image.touchesStart.x; 4072 touchY = z.image.touchesStart.y; 4073 } 4074 4075 if (z.scale && z.scale !== 1) { 4076 // Zoom Out 4077 z.scale = z.currentScale = 1; 4078 z.gesture.imageWrap.transition(300).transform('translate3d(0,0,0)'); 4079 z.gesture.image.transition(300).transform('translate3d(0,0,0) scale(1)'); 4080 z.gesture.slide = undefined; 4081 } 4082 else { 4083 // Zoom In 4084 z.scale = z.currentScale = z.gesture.imageWrap.attr('data-swiper-zoom') || s.params.zoomMax; 4085 if (e) { 4086 slideWidth = z.gesture.slide[0].offsetWidth; 4087 slideHeight = z.gesture.slide[0].offsetHeight; 4088 offsetX = z.gesture.slide.offset().left; 4089 offsetY = z.gesture.slide.offset().top; 4090 diffX = offsetX + slideWidth/2 - touchX; 4091 diffY = offsetY + slideHeight/2 - touchY; 4092 4093 imageWidth = z.gesture.image[0].offsetWidth; 4094 imageHeight = z.gesture.image[0].offsetHeight; 4095 scaledWidth = imageWidth * z.scale; 4096 scaledHeight = imageHeight * z.scale; 4097 4098 translateMinX = Math.min((slideWidth / 2 - scaledWidth / 2), 0); 4099 translateMinY = Math.min((slideHeight / 2 - scaledHeight / 2), 0); 4100 translateMaxX = -translateMinX; 4101 translateMaxY = -translateMinY; 4102 4103 translateX = diffX * z.scale; 4104 translateY = diffY * z.scale; 4105 4106 if (translateX < translateMinX) { 4107 translateX = translateMinX; 4108 } 4109 if (translateX > translateMaxX) { 4110 translateX = translateMaxX; 4111 } 4112 4113 if (translateY < translateMinY) { 4114 translateY = translateMinY; 4115 } 4116 if (translateY > translateMaxY) { 4117 translateY = translateMaxY; 4118 } 4119 } 4120 else { 4121 translateX = 0; 4122 translateY = 0; 4123 } 4124 z.gesture.imageWrap.transition(300).transform('translate3d(' + translateX + 'px, ' + translateY + 'px,0)'); 4125 z.gesture.image.transition(300).transform('translate3d(0,0,0) scale(' + z.scale + ')'); 4126 } 4127 }, 4128 // Attach/Detach Events 4129 attachEvents: function (detach) { 4130 var action = detach ? 'off' : 'on'; 4131 4132 if (s.params.zoom) { 4133 var target = s.slides; 4134 var passiveListener = s.touchEvents.start === 'touchstart' && s.support.passiveListener && s.params.passiveListeners ? {passive: true, capture: false} : false; 4135 // Scale image 4136 if (s.support.gestures) { 4137 s.slides[action]('gesturestart', s.zoom.onGestureStart, passiveListener); 4138 s.slides[action]('gesturechange', s.zoom.onGestureChange, passiveListener); 4139 s.slides[action]('gestureend', s.zoom.onGestureEnd, passiveListener); 4140 } 4141 else if (s.touchEvents.start === 'touchstart') { 4142 s.slides[action](s.touchEvents.start, s.zoom.onGestureStart, passiveListener); 4143 s.slides[action](s.touchEvents.move, s.zoom.onGestureChange, passiveListener); 4144 s.slides[action](s.touchEvents.end, s.zoom.onGestureEnd, passiveListener); 4145 } 4146 4147 // Move image 4148 s[action]('touchStart', s.zoom.onTouchStart); 4149 s.slides.each(function (index, slide){ 4150 if ($(slide).find('.' + s.params.zoomContainerClass).length > 0) { 4151 $(slide)[action](s.touchEvents.move, s.zoom.onTouchMove); 4152 } 4153 }); 4154 s[action]('touchEnd', s.zoom.onTouchEnd); 4155 4156 // Scale Out 4157 s[action]('transitionEnd', s.zoom.onTransitionEnd); 4158 if (s.params.zoomToggle) { 4159 s.on('doubleTap', s.zoom.toggleZoom); 4160 } 4161 } 4162 }, 4163 init: function () { 4164 s.zoom.attachEvents(); 4165 }, 4166 destroy: function () { 4167 s.zoom.attachEvents(true); 4168 } 4169 }; 4170 4171 4172 /*========================= 4173 Plugins API. Collect all and init all plugins 4174 ===========================*/ 4175 s._plugins = []; 4176 for (var plugin in s.plugins) { 4177 var p = s.plugins[plugin](s, s.params[plugin]); 4178 if (p) s._plugins.push(p); 4179 } 4180 // Method to call all plugins event/method 4181 s.callPlugins = function (eventName) { 4182 for (var i = 0; i < s._plugins.length; i++) { 4183 if (eventName in s._plugins[i]) { 4184 s._plugins[i][eventName](arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]); 4185 } 4186 } 4187 }; 4188 4189 4190 /*========================= 4191 Events/Callbacks/Plugins Emitter 4192 ===========================*/ 4193 function normalizeEventName (eventName) { 4194 if (eventName.indexOf('on') !== 0) { 4195 if (eventName[0] !== eventName[0].toUpperCase()) { 4196 eventName = 'on' + eventName[0].toUpperCase() + eventName.substring(1); 4197 } 4198 else { 4199 eventName = 'on' + eventName; 4200 } 4201 } 4202 return eventName; 4203 } 4204 s.emitterEventListeners = { 4205 4206 }; 4207 s.emit = function (eventName) { 4208 // Trigger callbacks 4209 if (s.params[eventName]) { 4210 s.params[eventName](arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]); 4211 } 4212 var i; 4213 // Trigger events 4214 if (s.emitterEventListeners[eventName]) { 4215 for (i = 0; i < s.emitterEventListeners[eventName].length; i++) { 4216 s.emitterEventListeners[eventName][i](arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]); 4217 } 4218 } 4219 // Trigger plugins 4220 if (s.callPlugins) s.callPlugins(eventName, arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]); 4221 }; 4222 s.on = function (eventName, handler) { 4223 eventName = normalizeEventName(eventName); 4224 if (!s.emitterEventListeners[eventName]) s.emitterEventListeners[eventName] = []; 4225 s.emitterEventListeners[eventName].push(handler); 4226 return s; 4227 }; 4228 s.off = function (eventName, handler) { 4229 var i; 4230 eventName = normalizeEventName(eventName); 4231 if (typeof handler === 'undefined') { 4232 // Remove all handlers for such event 4233 s.emitterEventListeners[eventName] = []; 4234 return s; 4235 } 4236 if (!s.emitterEventListeners[eventName] || s.emitterEventListeners[eventName].length === 0) return; 4237 for (i = 0; i < s.emitterEventListeners[eventName].length; i++) { 4238 if(s.emitterEventListeners[eventName][i] === handler) s.emitterEventListeners[eventName].splice(i, 1); 4239 } 4240 return s; 4241 }; 4242 s.once = function (eventName, handler) { 4243 eventName = normalizeEventName(eventName); 4244 var _handler = function () { 4245 handler(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]); 4246 s.off(eventName, _handler); 4247 }; 4248 s.on(eventName, _handler); 4249 return s; 4250 }; 4251 4252 4253 // Accessibility tools 4254 s.a11y = { 4255 makeFocusable: function ($el) { 4256 $el.attr('tabIndex', '0'); 4257 return $el; 4258 }, 4259 addRole: function ($el, role) { 4260 $el.attr('role', role); 4261 return $el; 4262 }, 4263 4264 addLabel: function ($el, label) { 4265 $el.attr('aria-label', label); 4266 return $el; 4267 }, 4268 4269 disable: function ($el) { 4270 $el.attr('aria-disabled', true); 4271 return $el; 4272 }, 4273 4274 enable: function ($el) { 4275 $el.attr('aria-disabled', false); 4276 return $el; 4277 }, 4278 4279 onEnterKey: function (event) { 4280 if (event.keyCode !== 13) return; 4281 if ($(event.target).is(s.params.nextButton)) { 4282 s.onClickNext(event); 4283 if (s.isEnd) { 4284 s.a11y.notify(s.params.lastSlideMessage); 4285 } 4286 else { 4287 s.a11y.notify(s.params.nextSlideMessage); 4288 } 4289 } 4290 else if ($(event.target).is(s.params.prevButton)) { 4291 s.onClickPrev(event); 4292 if (s.isBeginning) { 4293 s.a11y.notify(s.params.firstSlideMessage); 4294 } 4295 else { 4296 s.a11y.notify(s.params.prevSlideMessage); 4297 } 4298 } 4299 if ($(event.target).is('.' + s.params.bulletClass)) { 4300 $(event.target)[0].click(); 4301 } 4302 }, 4303 4304 liveRegion: $('<span class="' + s.params.notificationClass + '" aria-live="assertive" aria-atomic="true"></span>'), 4305 4306 notify: function (message) { 4307 var notification = s.a11y.liveRegion; 4308 if (notification.length === 0) return; 4309 notification.html(''); 4310 notification.html(message); 4311 }, 4312 init: function () { 4313 // Setup accessibility 4314 if (s.params.nextButton && s.nextButton && s.nextButton.length > 0) { 4315 s.a11y.makeFocusable(s.nextButton); 4316 s.a11y.addRole(s.nextButton, 'button'); 4317 s.a11y.addLabel(s.nextButton, s.params.nextSlideMessage); 4318 } 4319 if (s.params.prevButton && s.prevButton && s.prevButton.length > 0) { 4320 s.a11y.makeFocusable(s.prevButton); 4321 s.a11y.addRole(s.prevButton, 'button'); 4322 s.a11y.addLabel(s.prevButton, s.params.prevSlideMessage); 4323 } 4324 4325 $(s.container).append(s.a11y.liveRegion); 4326 }, 4327 initPagination: function () { 4328 if (s.params.pagination && s.params.paginationClickable && s.bullets && s.bullets.length) { 4329 s.bullets.each(function () { 4330 var bullet = $(this); 4331 s.a11y.makeFocusable(bullet); 4332 s.a11y.addRole(bullet, 'button'); 4333 s.a11y.addLabel(bullet, s.params.paginationBulletMessage.replace(/{{index}}/, bullet.index() + 1)); 4334 }); 4335 } 4336 }, 4337 destroy: function () { 4338 if (s.a11y.liveRegion && s.a11y.liveRegion.length > 0) s.a11y.liveRegion.remove(); 4339 } 4340 }; 4341 4342 4343 /*========================= 4344 Init/Destroy 4345 ===========================*/ 4346 s.init = function () { 4347 if (s.params.loop) s.createLoop(); 4348 s.updateContainerSize(); 4349 s.updateSlidesSize(); 4350 s.updatePagination(); 4351 if (s.params.scrollbar && s.scrollbar) { 4352 s.scrollbar.set(); 4353 if (s.params.scrollbarDraggable) { 4354 s.scrollbar.enableDraggable(); 4355 } 4356 } 4357 if (s.params.effect !== 'slide' && s.effects[s.params.effect]) { 4358 if (!s.params.loop) s.updateProgress(); 4359 s.effects[s.params.effect].setTranslate(); 4360 } 4361 if (s.params.loop) { 4362 s.slideTo(s.params.initialSlide + s.loopedSlides, 0, s.params.runCallbacksOnInit); 4363 } 4364 else { 4365 s.slideTo(s.params.initialSlide, 0, s.params.runCallbacksOnInit); 4366 if (s.params.initialSlide === 0) { 4367 if (s.parallax && s.params.parallax) s.parallax.setTranslate(); 4368 if (s.lazy && s.params.lazyLoading) { 4369 s.lazy.load(); 4370 s.lazy.initialImageLoaded = true; 4371 } 4372 } 4373 } 4374 s.attachEvents(); 4375 if (s.params.observer && s.support.observer) { 4376 s.initObservers(); 4377 } 4378 if (s.params.preloadImages && !s.params.lazyLoading) { 4379 s.preloadImages(); 4380 } 4381 if (s.params.zoom && s.zoom) { 4382 s.zoom.init(); 4383 } 4384 if (s.params.autoplay) { 4385 s.startAutoplay(); 4386 } 4387 if (s.params.keyboardControl) { 4388 if (s.enableKeyboardControl) s.enableKeyboardControl(); 4389 } 4390 if (s.params.mousewheelControl) { 4391 if (s.enableMousewheelControl) s.enableMousewheelControl(); 4392 } 4393 // Deprecated hashnavReplaceState changed to replaceState for use in hashnav and history 4394 if (s.params.hashnavReplaceState) { 4395 s.params.replaceState = s.params.hashnavReplaceState; 4396 } 4397 if (s.params.history) { 4398 if (s.history) s.history.init(); 4399 } 4400 if (s.params.hashnav) { 4401 if (s.hashnav) s.hashnav.init(); 4402 } 4403 if (s.params.a11y && s.a11y) s.a11y.init(); 4404 s.emit('onInit', s); 4405 }; 4406 4407 // Cleanup dynamic styles 4408 s.cleanupStyles = function () { 4409 // Container 4410 s.container.removeClass(s.classNames.join(' ')).removeAttr('style'); 4411 4412 // Wrapper 4413 s.wrapper.removeAttr('style'); 4414 4415 // Slides 4416 if (s.slides && s.slides.length) { 4417 s.slides 4418 .removeClass([ 4419 s.params.slideVisibleClass, 4420 s.params.slideActiveClass, 4421 s.params.slideNextClass, 4422 s.params.slidePrevClass 4423 ].join(' ')) 4424 .removeAttr('style') 4425 .removeAttr('data-swiper-column') 4426 .removeAttr('data-swiper-row'); 4427 } 4428 4429 // Pagination/Bullets 4430 if (s.paginationContainer && s.paginationContainer.length) { 4431 s.paginationContainer.removeClass(s.params.paginationHiddenClass); 4432 } 4433 if (s.bullets && s.bullets.length) { 4434 s.bullets.removeClass(s.params.bulletActiveClass); 4435 } 4436 4437 // Buttons 4438 if (s.params.prevButton) $(s.params.prevButton).removeClass(s.params.buttonDisabledClass); 4439 if (s.params.nextButton) $(s.params.nextButton).removeClass(s.params.buttonDisabledClass); 4440 4441 // Scrollbar 4442 if (s.params.scrollbar && s.scrollbar) { 4443 if (s.scrollbar.track && s.scrollbar.track.length) s.scrollbar.track.removeAttr('style'); 4444 if (s.scrollbar.drag && s.scrollbar.drag.length) s.scrollbar.drag.removeAttr('style'); 4445 } 4446 }; 4447 4448 // Destroy 4449 s.destroy = function (deleteInstance, cleanupStyles) { 4450 // Detach evebts 4451 s.detachEvents(); 4452 // Stop autoplay 4453 s.stopAutoplay(); 4454 // Disable draggable 4455 if (s.params.scrollbar && s.scrollbar) { 4456 if (s.params.scrollbarDraggable) { 4457 s.scrollbar.disableDraggable(); 4458 } 4459 } 4460 // Destroy loop 4461 if (s.params.loop) { 4462 s.destroyLoop(); 4463 } 4464 // Cleanup styles 4465 if (cleanupStyles) { 4466 s.cleanupStyles(); 4467 } 4468 // Disconnect observer 4469 s.disconnectObservers(); 4470 4471 // Destroy zoom 4472 if (s.params.zoom && s.zoom) { 4473 s.zoom.destroy(); 4474 } 4475 // Disable keyboard/mousewheel 4476 if (s.params.keyboardControl) { 4477 if (s.disableKeyboardControl) s.disableKeyboardControl(); 4478 } 4479 if (s.params.mousewheelControl) { 4480 if (s.disableMousewheelControl) s.disableMousewheelControl(); 4481 } 4482 // Disable a11y 4483 if (s.params.a11y && s.a11y) s.a11y.destroy(); 4484 // Delete history popstate 4485 if (s.params.history && !s.params.replaceState) { 4486 window.removeEventListener('popstate', s.history.setHistoryPopState); 4487 } 4488 if (s.params.hashnav && s.hashnav) { 4489 s.hashnav.destroy(); 4490 } 4491 // Destroy callback 4492 s.emit('onDestroy'); 4493 // Delete instance 4494 if (deleteInstance !== false) s = null; 4495 }; 4496 4497 s.init(); 4498 4499 4500 4501 // Return swiper instance 4502 return s; 4503 }; 4504 4505 4506 /*================================================== 4507 Prototype 4508 ====================================================*/ 4509 Swiper.prototype = { 4510 isSafari: (function () { 4511 var ua = window.navigator.userAgent.toLowerCase(); 4512 return (ua.indexOf('safari') >= 0 && ua.indexOf('chrome') < 0 && ua.indexOf('android') < 0); 4513 })(), 4514 isUiWebView: /(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(window.navigator.userAgent), 4515 isArray: function (arr) { 4516 return Object.prototype.toString.apply(arr) === '[object Array]'; 4517 }, 4518 /*================================================== 4519 Browser 4520 ====================================================*/ 4521 browser: { 4522 ie: window.navigator.pointerEnabled || window.navigator.msPointerEnabled, 4523 ieTouch: (window.navigator.msPointerEnabled && window.navigator.msMaxTouchPoints > 1) || (window.navigator.pointerEnabled && window.navigator.maxTouchPoints > 1), 4524 lteIE9: (function() { 4525 // create temporary DIV 4526 var div = document.createElement('div'); 4527 // add content to tmp DIV which is wrapped into the IE HTML conditional statement 4528 div.innerHTML = '<!--[if lte IE 9]><i></i><![endif]-->'; 4529 // return true / false value based on what will browser render 4530 return div.getElementsByTagName('i').length === 1; 4531 })() 4532 }, 4533 /*================================================== 4534 Devices 4535 ====================================================*/ 4536 device: (function () { 4537 var ua = window.navigator.userAgent; 4538 var android = ua.match(/(Android);?[\s\/]+([\d.]+)?/); 4539 var ipad = ua.match(/(iPad).*OS\s([\d_]+)/); 4540 var ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/); 4541 var iphone = !ipad && ua.match(/(iPhone\sOS|iOS)\s([\d_]+)/); 4542 return { 4543 ios: ipad || iphone || ipod, 4544 android: android 4545 }; 4546 })(), 4547 /*================================================== 4548 Feature Detection 4549 ====================================================*/ 4550 support: { 4551 touch : (window.Modernizr && Modernizr.touch === true) || (function () { 4552 return !!(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch); 4553 })(), 4554 4555 transforms3d : (window.Modernizr && Modernizr.csstransforms3d === true) || (function () { 4556 var div = document.createElement('div').style; 4557 return ('webkitPerspective' in div || 'MozPerspective' in div || 'OPerspective' in div || 'MsPerspective' in div || 'perspective' in div); 4558 })(), 4559 4560 flexbox: (function () { 4561 var div = document.createElement('div').style; 4562 var styles = ('alignItems webkitAlignItems webkitBoxAlign msFlexAlign mozBoxAlign webkitFlexDirection msFlexDirection mozBoxDirection mozBoxOrient webkitBoxDirection webkitBoxOrient').split(' '); 4563 for (var i = 0; i < styles.length; i++) { 4564 if (styles[i] in div) return true; 4565 } 4566 })(), 4567 4568 observer: (function () { 4569 return ('MutationObserver' in window || 'WebkitMutationObserver' in window); 4570 })(), 4571 4572 passiveListener: (function () { 4573 var supportsPassive = false; 4574 try { 4575 var opts = Object.defineProperty({}, 'passive', { 4576 get: function() { 4577 supportsPassive = true; 4578 } 4579 }); 4580 window.addEventListener('testPassiveListener', null, opts); 4581 } catch (e) {} 4582 return supportsPassive; 4583 })(), 4584 4585 gestures: (function () { 4586 return 'ongesturestart' in window; 4587 })() 4588 }, 4589 /*================================================== 4590 Plugins 4591 ====================================================*/ 4592 plugins: {} 4593 }; 4594 4595 4596 /*=========================== 4597 Get jQuery 4598 ===========================*/ 4599 addLibraryPlugin($); 4600 4601 var domLib = $; 4602 4603 4604 /*=========================== 4605 Add .swiper plugin from Dom libraries 4606 ===========================*/ 4607 function addLibraryPlugin(lib) { 4608 lib.fn.swiper = function (params) { 4609 var firstInstance; 4610 lib(this).each(function () { 4611 var s = new Swiper(this, params); 4612 if (!firstInstance) firstInstance = s; 4613 }); 4614 return firstInstance; 4615 }; 4616 } 4617 4618 if (domLib) { 4619 if (!('transitionEnd' in domLib.fn)) { 4620 domLib.fn.transitionEnd = function (callback) { 4621 var events = ['webkitTransitionEnd', 'transitionend', 'oTransitionEnd', 'MSTransitionEnd', 'msTransitionEnd'], 4622 i, j, dom = this; 4623 function fireCallBack(e) { 4624 /*jshint validthis:true */ 4625 if (e.target !== this) return; 4626 callback.call(this, e); 4627 for (i = 0; i < events.length; i++) { 4628 dom.off(events[i], fireCallBack); 4629 } 4630 } 4631 if (callback) { 4632 for (i = 0; i < events.length; i++) { 4633 dom.on(events[i], fireCallBack); 4634 } 4635 } 4636 return this; 4637 }; 4638 } 4639 if (!('transform' in domLib.fn)) { 4640 domLib.fn.transform = function (transform) { 4641 for (var i = 0; i < this.length; i++) { 4642 var elStyle = this[i].style; 4643 elStyle.webkitTransform = elStyle.MsTransform = elStyle.msTransform = elStyle.MozTransform = elStyle.OTransform = elStyle.transform = transform; 4644 } 4645 return this; 4646 }; 4647 } 4648 if (!('transition' in domLib.fn)) { 4649 domLib.fn.transition = function (duration) { 4650 if (typeof duration !== 'string') { 4651 duration = duration + 'ms'; 4652 } 4653 for (var i = 0; i < this.length; i++) { 4654 var elStyle = this[i].style; 4655 elStyle.webkitTransitionDuration = elStyle.MsTransitionDuration = elStyle.msTransitionDuration = elStyle.MozTransitionDuration = elStyle.OTransitionDuration = elStyle.transitionDuration = duration; 4656 } 4657 return this; 4658 }; 4659 } 4660 if (!('outerWidth' in domLib.fn)) { 4661 domLib.fn.outerWidth = function (includeMargins) { 4662 if (this.length > 0) { 4663 if (includeMargins) 4664 return this[0].offsetWidth + parseFloat(this.css('margin-right')) + parseFloat(this.css('margin-left')); 4665 else 4666 return this[0].offsetWidth; 4667 } 4668 else return null; 4669 }; 4670 } 4671 } 4672 4673 4674 return Swiper; 4675 })); 4676 4677 //# sourceMappingURL=maps/swiper.jquery.umd.js.map