shop.balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

swiper.jquery.js (213327B)


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