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