PageSourceSearch

https://vegda.ru/catalog/view/javascript/jquery/swiper/js/swiper.jquery.js

js vegda.ru collected 2026-10-09 23:10:09 UTC 208,639 bytes, 4,688 lines download raw bytes

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) * slidesNumber
876EvenToRows;
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 || force
1288UpdatePagination) 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;
vendor: 6,131 bytes, lines 3999-4111
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,
41110,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/*===========================
4675Swiper AMD Export
4676===========================*/
4677if (typeof(module) !== 'undefined')
4678{
4679    module.exports = window.Swiper;
4680}
4681else 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

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.