github.com/jincm/wesharechain@v0.0.0-20210122032815-1537409ce26a/app/script/idangerous.swiper.js (about)

     1  var Swiper = function (selector, params) {
     2      'use strict';
     3  
     4      /*=========================
     5        A little bit dirty but required part for IE8 and old FF support
     6        ===========================*/
     7      if (!document.body.outerHTML && document.body.__defineGetter__) {
     8          if (HTMLElement) {
     9              var element = HTMLElement.prototype;
    10              if (element.__defineGetter__) {
    11                  element.__defineGetter__('outerHTML', function () { return new XMLSerializer().serializeToString(this); });
    12              }
    13          }
    14      }
    15  
    16      if (!window.getComputedStyle) {
    17          window.getComputedStyle = function (el, pseudo) {
    18              this.el = el;
    19              this.getPropertyValue = function (prop) {
    20                  var re = /(\-([a-z]){1})/g;
    21                  if (prop === 'float') prop = 'styleFloat';
    22                  if (re.test(prop)) {
    23                      prop = prop.replace(re, function () {
    24                          return arguments[2].toUpperCase();
    25                      });
    26                  }
    27                  return el.currentStyle[prop] ? el.currentStyle[prop] : null;
    28              };
    29              return this;
    30          };
    31      }
    32      if (!Array.prototype.indexOf) {
    33          Array.prototype.indexOf = function (obj, start) {
    34              for (var i = (start || 0), j = this.length; i < j; i++) {
    35                  if (this[i] === obj) { return i; }
    36              }
    37              return -1;
    38          };
    39      }
    40      if (!document.querySelectorAll) {
    41          if (!window.jQuery) return;
    42      }
    43      function $$(selector, context) {
    44          if (document.querySelectorAll)
    45              return (context || document).querySelectorAll(selector);
    46          else
    47              return jQuery(selector, context);
    48      }
    49  
    50      /*=========================
    51        Check for correct selector
    52        ===========================*/
    53      if (typeof selector === 'undefined') return;
    54  
    55      if (!(selector.nodeType)) {
    56          if ($$(selector).length === 0) return;
    57      }
    58  
    59       /*=========================
    60        _this
    61        ===========================*/
    62      var _this = this;
    63  
    64       /*=========================
    65        Default Flags and vars
    66        ===========================*/
    67      _this.touches = {
    68          start: 0,
    69          startX: 0,
    70          startY: 0,
    71          current: 0,
    72          currentX: 0,
    73          currentY: 0,
    74          diff: 0,
    75          abs: 0
    76      };
    77      _this.positions = {
    78          start: 0,
    79          abs: 0,
    80          diff: 0,
    81          current: 0
    82      };
    83      _this.times = {
    84          start: 0,
    85          end: 0
    86      };
    87  
    88      _this.id = (new Date()).getTime();
    89      _this.container = (selector.nodeType) ? selector : $$(selector)[0];
    90      _this.isTouched = false;
    91      _this.isMoved = false;
    92      _this.activeIndex = 0;
    93      _this.centerIndex = 0;
    94      _this.activeLoaderIndex = 0;
    95      _this.activeLoopIndex = 0;
    96      _this.previousIndex = null;
    97      _this.velocity = 0;
    98      _this.snapGrid = [];
    99      _this.slidesGrid = [];
   100      _this.imagesToLoad = [];
   101      _this.imagesLoaded = 0;
   102      _this.wrapperLeft = 0;
   103      _this.wrapperRight = 0;
   104      _this.wrapperTop = 0;
   105      _this.wrapperBottom = 0;
   106      _this.isAndroid = navigator.userAgent.toLowerCase().indexOf('android') >= 0;
   107      var wrapper, slideSize, wrapperSize, direction, isScrolling, containerSize;
   108  
   109      /*=========================
   110        Default Parameters
   111        ===========================*/
   112      var defaults = {
   113          eventTarget: 'wrapper', // or 'container'
   114          mode : 'horizontal', // or 'vertical'
   115          touchRatio : 1,
   116          speed : 300,
   117          freeMode : false,
   118          freeModeFluid : false,
   119          momentumRatio: 1,
   120          momentumBounce: true,
   121          momentumBounceRatio: 1,
   122          slidesPerView : 1,
   123          slidesPerGroup : 1,
   124          slidesPerViewFit: true, //Fit to slide when spv "auto" and slides larger than container
   125          simulateTouch : true,
   126          followFinger : true,
   127          shortSwipes : true,
   128          longSwipesRatio: 0.5,
   129          moveStartThreshold: false,
   130          onlyExternal : false,
   131          createPagination : true,
   132          pagination : false,
   133          paginationElement: 'span',
   134          paginationClickable: false,
   135          paginationAsRange: true,
   136          resistance : true, // or false or 100%
   137          scrollContainer : false,
   138          preventLinks : true,
   139          preventLinksPropagation: false,
   140          noSwiping : false, // or class
   141          noSwipingClass : 'swiper-no-swiping', //:)
   142          initialSlide: 0,
   143          keyboardControl: false,
   144          mousewheelControl : false,
   145          mousewheelControlForceToAxis : false,
   146          useCSS3Transforms : true,
   147          // Autoplay
   148          autoplay: false,
   149          autoplayDisableOnInteraction: true,
   150          autoplayStopOnLast: false,
   151          //Loop mode
   152          loop: false,
   153          loopAdditionalSlides: 0,
   154          // Round length values
   155          roundLengths: false,
   156          //Auto Height
   157          calculateHeight: false,
   158          //Apply CSS for width and/or height
   159          cssWidthAndHeight: false, // or true or 'width' or 'height'
   160          //Images Preloader
   161          updateOnImagesReady : true,
   162          //Form elements
   163          releaseFormElements : true,
   164          //Watch for active slide, useful when use effects on different slide states
   165          watchActiveIndex: false,
   166          //Slides Visibility Fit
   167          visibilityFullFit : false,
   168          //Slides Offset
   169          offsetPxBefore : 0,
   170          offsetPxAfter : 0,
   171          offsetSlidesBefore : 0,
   172          offsetSlidesAfter : 0,
   173          centeredSlides: false,
   174          //Queue callbacks
   175          queueStartCallbacks : false,
   176          queueEndCallbacks : false,
   177          //Auto Resize
   178          autoResize : true,
   179          resizeReInit : false,
   180          //DOMAnimation
   181          DOMAnimation : true,
   182          //Slides Loader
   183          loader: {
   184              slides: [], //array with slides
   185              slidesHTMLType: 'inner', // or 'outer'
   186              surroundGroups: 1, //keep preloaded slides groups around view
   187              logic: 'reload', //or 'change'
   188              loadAllSlides: false
   189          },
   190          // One way swipes
   191          swipeToPrev: true,
   192          swipeToNext: true,
   193          //Namespace
   194          slideElement: 'div',
   195          slideClass: 'swiper-slide',
   196          slideActiveClass: 'swiper-slide-active',
   197          slideVisibleClass: 'swiper-slide-visible',
   198          slideDuplicateClass: 'swiper-slide-duplicate',
   199          wrapperClass: 'swiper-wrapper',
   200          paginationElementClass: 'swiper-pagination-switch',
   201          paginationActiveClass: 'swiper-active-switch',
   202          paginationVisibleClass: 'swiper-visible-switch'
   203      };
   204      params = params || {};
   205      for (var prop in defaults) {
   206          if (prop in params && typeof params[prop] === 'object') {
   207              for (var subProp in defaults[prop]) {
   208                  if (! (subProp in params[prop])) {
   209                      params[prop][subProp] = defaults[prop][subProp];
   210                  }
   211              }
   212          }
   213          else if (! (prop in params)) {
   214              params[prop] = defaults[prop];
   215          }
   216      }
   217      _this.params = params;
   218      if (params.scrollContainer) {
   219          params.freeMode = true;
   220          params.freeModeFluid = true;
   221      }
   222      if (params.loop) {
   223          params.resistance = '100%';
   224      }
   225      var isH = params.mode === 'horizontal';
   226  
   227      /*=========================
   228        Define Touch Events
   229        ===========================*/
   230      var desktopEvents = ['mousedown', 'mousemove', 'mouseup'];
   231      if (_this.browser.ie10) desktopEvents = ['MSPointerDown', 'MSPointerMove', 'MSPointerUp'];
   232      if (_this.browser.ie11) desktopEvents = ['pointerdown', 'pointermove', 'pointerup'];
   233  
   234      _this.touchEvents = {
   235          touchStart : _this.support.touch || !params.simulateTouch  ? 'touchstart' : desktopEvents[0],
   236          touchMove : _this.support.touch || !params.simulateTouch ? 'touchmove' : desktopEvents[1],
   237          touchEnd : _this.support.touch || !params.simulateTouch ? 'touchend' : desktopEvents[2]
   238      };
   239  
   240      /*=========================
   241        Wrapper
   242        ===========================*/
   243      for (var i = _this.container.childNodes.length - 1; i >= 0; i--) {
   244          if (_this.container.childNodes[i].className) {
   245              var _wrapperClasses = _this.container.childNodes[i].className.split(/\s+/);
   246              for (var j = 0; j < _wrapperClasses.length; j++) {
   247                  if (_wrapperClasses[j] === params.wrapperClass) {
   248                      wrapper = _this.container.childNodes[i];
   249                  }
   250              }
   251          }
   252      }
   253  
   254      _this.wrapper = wrapper;
   255      /*=========================
   256        Slide API
   257        ===========================*/
   258      _this._extendSwiperSlide = function  (el) {
   259          el.append = function () {
   260              if (params.loop) {
   261                  el.insertAfter(_this.slides.length - _this.loopedSlides);
   262              }
   263              else {
   264                  _this.wrapper.appendChild(el);
   265                  _this.reInit();
   266              }
   267  
   268              return el;
   269          };
   270          el.prepend = function () {
   271              if (params.loop) {
   272                  _this.wrapper.insertBefore(el, _this.slides[_this.loopedSlides]);
   273                  _this.removeLoopedSlides();
   274                  _this.calcSlides();
   275                  _this.createLoop();
   276              }
   277              else {
   278                  _this.wrapper.insertBefore(el, _this.wrapper.firstChild);
   279              }
   280              _this.reInit();
   281              return el;
   282          };
   283          el.insertAfter = function (index) {
   284              if (typeof index === 'undefined') return false;
   285              var beforeSlide;
   286  
   287              if (params.loop) {
   288                  beforeSlide = _this.slides[index + 1 + _this.loopedSlides];
   289                  if (beforeSlide) {
   290                      _this.wrapper.insertBefore(el, beforeSlide);
   291                  }
   292                  else {
   293                      _this.wrapper.appendChild(el);
   294                  }
   295                  _this.removeLoopedSlides();
   296                  _this.calcSlides();
   297                  _this.createLoop();
   298              }
   299              else {
   300                  beforeSlide = _this.slides[index + 1];
   301                  _this.wrapper.insertBefore(el, beforeSlide);
   302              }
   303              _this.reInit();
   304              return el;
   305          };
   306          el.clone = function () {
   307              return _this._extendSwiperSlide(el.cloneNode(true));
   308          };
   309          el.remove = function () {
   310              _this.wrapper.removeChild(el);
   311              _this.reInit();
   312          };
   313          el.html = function (html) {
   314              if (typeof html === 'undefined') {
   315                  return el.innerHTML;
   316              }
   317              else {
   318                  el.innerHTML = html;
   319                  return el;
   320              }
   321          };
   322          el.index = function () {
   323              var index;
   324              for (var i = _this.slides.length - 1; i >= 0; i--) {
   325                  if (el === _this.slides[i]) index = i;
   326              }
   327              return index;
   328          };
   329          el.isActive = function () {
   330              if (el.index() === _this.activeIndex) return true;
   331              else return false;
   332          };
   333          if (!el.swiperSlideDataStorage) el.swiperSlideDataStorage = {};
   334          el.getData = function (name) {
   335              return el.swiperSlideDataStorage[name];
   336          };
   337          el.setData = function (name, value) {
   338              el.swiperSlideDataStorage[name] = value;
   339              return el;
   340          };
   341          el.data = function (name, value) {
   342              if (typeof value === 'undefined') {
   343                  return el.getAttribute('data-' + name);
   344              }
   345              else {
   346                  el.setAttribute('data-' + name, value);
   347                  return el;
   348              }
   349          };
   350          el.getWidth = function (outer, round) {
   351              return _this.h.getWidth(el, outer, round);
   352          };
   353          el.getHeight = function (outer, round) {
   354              return _this.h.getHeight(el, outer, round);
   355          };
   356          el.getOffset = function () {
   357              return _this.h.getOffset(el);
   358          };
   359          return el;
   360      };
   361  
   362      //Calculate information about number of slides
   363      _this.calcSlides = function (forceCalcSlides) {
   364          var oldNumber = _this.slides ? _this.slides.length : false;
   365          _this.slides = [];
   366          _this.displaySlides = [];
   367          for (var i = 0; i < _this.wrapper.childNodes.length; i++) {
   368              if (_this.wrapper.childNodes[i].className) {
   369                  var _className = _this.wrapper.childNodes[i].className;
   370                  var _slideClasses = _className.split(/\s+/);
   371                  for (var j = 0; j < _slideClasses.length; j++) {
   372                      if (_slideClasses[j] === params.slideClass) {
   373                          _this.slides.push(_this.wrapper.childNodes[i]);
   374                      }
   375                  }
   376              }
   377          }
   378          for (i = _this.slides.length - 1; i >= 0; i--) {
   379              _this._extendSwiperSlide(_this.slides[i]);
   380          }
   381          if (oldNumber === false) return;
   382          if (oldNumber !== _this.slides.length || forceCalcSlides) {
   383  
   384              // Number of slides has been changed
   385              removeSlideEvents();
   386              addSlideEvents();
   387              _this.updateActiveSlide();
   388              if (_this.params.pagination) _this.createPagination();
   389              _this.callPlugins('numberOfSlidesChanged');
   390          }
   391      };
   392  
   393      //Create Slide
   394      _this.createSlide = function (html, slideClassList, el) {
   395          slideClassList = slideClassList || _this.params.slideClass;
   396          el = el || params.slideElement;
   397          var newSlide = document.createElement(el);
   398          newSlide.innerHTML = html || '';
   399          newSlide.className = slideClassList;
   400          return _this._extendSwiperSlide(newSlide);
   401      };
   402  
   403      //Append Slide
   404      _this.appendSlide = function (html, slideClassList, el) {
   405          if (!html) return;
   406          if (html.nodeType) {
   407              return _this._extendSwiperSlide(html).append();
   408          }
   409          else {
   410              return _this.createSlide(html, slideClassList, el).append();
   411          }
   412      };
   413      _this.prependSlide = function (html, slideClassList, el) {
   414          if (!html) return;
   415          if (html.nodeType) {
   416              return _this._extendSwiperSlide(html).prepend();
   417          }
   418          else {
   419              return _this.createSlide(html, slideClassList, el).prepend();
   420          }
   421      };
   422      _this.insertSlideAfter = function (index, html, slideClassList, el) {
   423          if (typeof index === 'undefined') return false;
   424          if (html.nodeType) {
   425              return _this._extendSwiperSlide(html).insertAfter(index);
   426          }
   427          else {
   428              return _this.createSlide(html, slideClassList, el).insertAfter(index);
   429          }
   430      };
   431      _this.removeSlide = function (index) {
   432          if (_this.slides[index]) {
   433              if (params.loop) {
   434                  if (!_this.slides[index + _this.loopedSlides]) return false;
   435                  _this.slides[index + _this.loopedSlides].remove();
   436                  _this.removeLoopedSlides();
   437                  _this.calcSlides();
   438                  _this.createLoop();
   439              }
   440              else _this.slides[index].remove();
   441              return true;
   442          }
   443          else return false;
   444      };
   445      _this.removeLastSlide = function () {
   446          if (_this.slides.length > 0) {
   447              if (params.loop) {
   448                  _this.slides[_this.slides.length - 1 - _this.loopedSlides].remove();
   449                  _this.removeLoopedSlides();
   450                  _this.calcSlides();
   451                  _this.createLoop();
   452              }
   453              else _this.slides[_this.slides.length - 1].remove();
   454              return true;
   455          }
   456          else {
   457              return false;
   458          }
   459      };
   460      _this.removeAllSlides = function () {
   461          var num = _this.slides.length;
   462          for (var i = _this.slides.length - 1; i >= 0; i--) {
   463              _this.slides[i].remove();
   464              if (i === num - 1) {
   465                  _this.setWrapperTranslate(0);
   466              }
   467          }
   468      };
   469      _this.getSlide = function (index) {
   470          return _this.slides[index];
   471      };
   472      _this.getLastSlide = function () {
   473          return _this.slides[_this.slides.length - 1];
   474      };
   475      _this.getFirstSlide = function () {
   476          return _this.slides[0];
   477      };
   478  
   479      //Currently Active Slide
   480      _this.activeSlide = function () {
   481          return _this.slides[_this.activeIndex];
   482      };
   483  
   484      /*=========================
   485       Wrapper for Callbacks : Allows additive callbacks via function arrays
   486       ===========================*/
   487      _this.fireCallback = function () {
   488          var callback = arguments[0];
   489          if (Object.prototype.toString.call(callback) === '[object Array]') {
   490              for (var i = 0; i < callback.length; i++) {
   491                  if (typeof callback[i] === 'function') {
   492                      callback[i](arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]);
   493                  }
   494              }
   495          } else if (Object.prototype.toString.call(callback) === '[object String]') {
   496              if (params['on' + callback]) _this.fireCallback(params['on' + callback], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]);
   497          } else {
   498              callback(arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]);
   499          }
   500      };
   501      function isArray(obj) {
   502          if (Object.prototype.toString.apply(obj) === '[object Array]') return true;
   503          return false;
   504      }
   505  
   506      /**
   507       * Allows user to add callbacks, rather than replace them
   508       * @param callback
   509       * @param func
   510       * @return {*}
   511       */
   512      _this.addCallback = function (callback, func) {
   513          var _this = this, tempFunc;
   514          if (_this.params['on' + callback]) {
   515              if (isArray(this.params['on' + callback])) {
   516                  return this.params['on' + callback].push(func);
   517              } else if (typeof this.params['on' + callback] === 'function') {
   518                  tempFunc = this.params['on' + callback];
   519                  this.params['on' + callback] = [];
   520                  this.params['on' + callback].push(tempFunc);
   521                  return this.params['on' + callback].push(func);
   522              }
   523          } else {
   524              this.params['on' + callback] = [];
   525              return this.params['on' + callback].push(func);
   526          }
   527      };
   528      _this.removeCallbacks = function (callback) {
   529          if (_this.params['on' + callback]) {
   530              _this.params['on' + callback] = null;
   531          }
   532      };
   533  
   534      /*=========================
   535        Plugins API
   536        ===========================*/
   537      var _plugins = [];
   538      for (var plugin in _this.plugins) {
   539          if (params[plugin]) {
   540              var p = _this.plugins[plugin](_this, params[plugin]);
   541              if (p) _plugins.push(p);
   542          }
   543      }
   544      _this.callPlugins = function (method, args) {
   545          if (!args) args = {};
   546          for (var i = 0; i < _plugins.length; i++) {
   547              if (method in _plugins[i]) {
   548                  _plugins[i][method](args);
   549              }
   550          }
   551      };
   552  
   553      /*=========================
   554        Windows Phone 8 Fix
   555        ===========================*/
   556      if ((_this.browser.ie10 || _this.browser.ie11) && !params.onlyExternal) {
   557          _this.wrapper.classList.add('swiper-wp8-' + (isH ? 'horizontal' : 'vertical'));
   558      }
   559  
   560      /*=========================
   561        Free Mode Class
   562        ===========================*/
   563      if (params.freeMode) {
   564          _this.container.className += ' swiper-free-mode';
   565      }
   566  
   567      /*==================================================
   568          Init/Re-init/Resize Fix
   569      ====================================================*/
   570      _this.initialized = false;
   571      _this.init = function (force, forceCalcSlides) {
   572          var _width = _this.h.getWidth(_this.container, false, params.roundLengths);
   573          var _height = _this.h.getHeight(_this.container, false, params.roundLengths);
   574          if (_width === _this.width && _height === _this.height && !force) return;
   575  
   576          _this.width = _width;
   577          _this.height = _height;
   578  
   579          var slideWidth, slideHeight, slideMaxHeight, wrapperWidth, wrapperHeight, slideLeft;
   580          var i; // loop index variable to avoid JSHint W004 / W038
   581          containerSize = isH ? _width : _height;
   582          var wrapper = _this.wrapper;
   583  
   584          if (force) {
   585              _this.calcSlides(forceCalcSlides);
   586          }
   587  
   588          if (params.slidesPerView === 'auto') {
   589              //Auto mode
   590              var slidesWidth = 0;
   591              var slidesHeight = 0;
   592  
   593              //Unset Styles
   594              if (params.slidesOffset > 0) {
   595                  wrapper.style.paddingLeft = '';
   596                  wrapper.style.paddingRight = '';
   597                  wrapper.style.paddingTop = '';
   598                  wrapper.style.paddingBottom = '';
   599              }
   600              wrapper.style.width = '';
   601              wrapper.style.height = '';
   602              if (params.offsetPxBefore > 0) {
   603                  if (isH) _this.wrapperLeft = params.offsetPxBefore;
   604                  else _this.wrapperTop = params.offsetPxBefore;
   605              }
   606              if (params.offsetPxAfter > 0) {
   607                  if (isH) _this.wrapperRight = params.offsetPxAfter;
   608                  else _this.wrapperBottom = params.offsetPxAfter;
   609              }
   610  
   611              if (params.centeredSlides) {
   612                  if (isH) {
   613                      _this.wrapperLeft = (containerSize - this.slides[0].getWidth(true, params.roundLengths)) / 2;
   614                      _this.wrapperRight = (containerSize - _this.slides[_this.slides.length - 1].getWidth(true, params.roundLengths)) / 2;
   615                  }
   616                  else {
   617                      _this.wrapperTop = (containerSize - _this.slides[0].getHeight(true, params.roundLengths)) / 2;
   618                      _this.wrapperBottom = (containerSize - _this.slides[_this.slides.length - 1].getHeight(true, params.roundLengths)) / 2;
   619                  }
   620              }
   621  
   622              if (isH) {
   623                  if (_this.wrapperLeft >= 0) wrapper.style.paddingLeft = _this.wrapperLeft + 'px';
   624                  if (_this.wrapperRight >= 0) wrapper.style.paddingRight = _this.wrapperRight + 'px';
   625              }
   626              else {
   627                  if (_this.wrapperTop >= 0) wrapper.style.paddingTop = _this.wrapperTop + 'px';
   628                  if (_this.wrapperBottom >= 0) wrapper.style.paddingBottom = _this.wrapperBottom + 'px';
   629              }
   630              slideLeft = 0;
   631              var centeredSlideLeft = 0;
   632              _this.snapGrid = [];
   633              _this.slidesGrid = [];
   634  
   635              slideMaxHeight = 0;
   636              for (i = 0; i < _this.slides.length; i++) {
   637                  slideWidth = _this.slides[i].getWidth(true, params.roundLengths);
   638                  slideHeight = _this.slides[i].getHeight(true, params.roundLengths);
   639                  if (params.calculateHeight) {
   640                      slideMaxHeight = Math.max(slideMaxHeight, slideHeight);
   641                  }
   642                  var _slideSize = isH ? slideWidth : slideHeight;
   643                  if (params.centeredSlides) {
   644                      var nextSlideWidth = i === _this.slides.length - 1 ? 0 : _this.slides[i + 1].getWidth(true, params.roundLengths);
   645                      var nextSlideHeight = i === _this.slides.length - 1 ? 0 : _this.slides[i + 1].getHeight(true, params.roundLengths);
   646                      var nextSlideSize = isH ? nextSlideWidth : nextSlideHeight;
   647                      if (_slideSize > containerSize) {
   648                          if (params.slidesPerViewFit) {
   649                              _this.snapGrid.push(slideLeft + _this.wrapperLeft);
   650                              _this.snapGrid.push(slideLeft + _slideSize - containerSize + _this.wrapperLeft);
   651                          }
   652                          else {
   653                              for (var j = 0; j <= Math.floor(_slideSize / (containerSize + _this.wrapperLeft)); j++) {
   654                                  if (j === 0) _this.snapGrid.push(slideLeft + _this.wrapperLeft);
   655                                  else _this.snapGrid.push(slideLeft + _this.wrapperLeft + containerSize * j);
   656                              }
   657                          }
   658                          _this.slidesGrid.push(slideLeft + _this.wrapperLeft);
   659                      }
   660                      else {
   661                          _this.snapGrid.push(centeredSlideLeft);
   662                          _this.slidesGrid.push(centeredSlideLeft);
   663                      }
   664                      centeredSlideLeft += _slideSize / 2 + nextSlideSize / 2;
   665                  }
   666                  else {
   667                      if (_slideSize > containerSize) {
   668                          if (params.slidesPerViewFit) {
   669                              _this.snapGrid.push(slideLeft);
   670                              _this.snapGrid.push(slideLeft + _slideSize - containerSize);
   671                          }
   672                          else {
   673                              if (containerSize !== 0) {
   674                                  for (var k = 0; k <= Math.floor(_slideSize / containerSize); k++) {
   675                                      _this.snapGrid.push(slideLeft + containerSize * k);
   676                                  }
   677                              }
   678                              else {
   679                                  _this.snapGrid.push(slideLeft);
   680                              }
   681                          }
   682  
   683                      }
   684                      else {
   685                          _this.snapGrid.push(slideLeft);
   686                      }
   687                      _this.slidesGrid.push(slideLeft);
   688                  }
   689  
   690                  slideLeft += _slideSize;
   691  
   692                  slidesWidth += slideWidth;
   693                  slidesHeight += slideHeight;
   694              }
   695              if (params.calculateHeight) _this.height = slideMaxHeight;
   696              if (isH) {
   697                  wrapperSize = slidesWidth + _this.wrapperRight + _this.wrapperLeft;
   698                  if(!params.cssWidthAndHeight || params.cssWidthAndHeight === 'height') {
   699                      wrapper.style.width = (slidesWidth) + 'px';
   700                  }
   701                  if(!params.cssWidthAndHeight || params.cssWidthAndHeight === 'width') {
   702                      wrapper.style.height = (_this.height) + 'px';
   703                  }
   704              }
   705              else {
   706                  if(!params.cssWidthAndHeight || params.cssWidthAndHeight === 'height') {
   707                      wrapper.style.width = (_this.width) + 'px';
   708                  }
   709                  if(!params.cssWidthAndHeight || params.cssWidthAndHeight === 'width') {
   710                      wrapper.style.height = (slidesHeight) + 'px';
   711                  }
   712                  wrapperSize = slidesHeight + _this.wrapperTop + _this.wrapperBottom;
   713              }
   714  
   715          }
   716          else if (params.scrollContainer) {
   717              //Scroll Container
   718              wrapper.style.width = '';
   719              wrapper.style.height = '';
   720              wrapperWidth = _this.slides[0].getWidth(true, params.roundLengths);
   721              wrapperHeight = _this.slides[0].getHeight(true, params.roundLengths);
   722              wrapperSize = isH ? wrapperWidth : wrapperHeight;
   723              wrapper.style.width = wrapperWidth + 'px';
   724              wrapper.style.height = wrapperHeight + 'px';
   725              slideSize = isH ? wrapperWidth : wrapperHeight;
   726  
   727          }
   728          else {
   729              //For usual slides
   730              if (params.calculateHeight) {
   731                  slideMaxHeight = 0;
   732                  wrapperHeight = 0;
   733                  //ResetWrapperSize
   734                  if (!isH) _this.container.style.height = '';
   735                  wrapper.style.height = '';
   736  
   737                  for (i = 0; i < _this.slides.length; i++) {
   738                      //ResetSlideSize
   739                      _this.slides[i].style.height = '';
   740                      slideMaxHeight = Math.max(_this.slides[i].getHeight(true), slideMaxHeight);
   741                      if (!isH) wrapperHeight += _this.slides[i].getHeight(true);
   742                  }
   743                  slideHeight = slideMaxHeight;
   744                  _this.height = slideHeight;
   745  
   746                  if (isH) wrapperHeight = slideHeight;
   747                  else {
   748                      containerSize = slideHeight;
   749                      _this.container.style.height = containerSize + 'px';
   750                  }
   751              }
   752              else {
   753                  slideHeight = isH ? _this.height : _this.height / params.slidesPerView;
   754                  if (params.roundLengths) slideHeight = Math.ceil(slideHeight);
   755                  wrapperHeight = isH ? _this.height : _this.slides.length * slideHeight;
   756              }
   757              slideWidth = isH ? _this.width / params.slidesPerView : _this.width;
   758              if (params.roundLengths) slideWidth = Math.ceil(slideWidth);
   759              wrapperWidth = isH ? _this.slides.length * slideWidth : _this.width;
   760              slideSize = isH ? slideWidth : slideHeight;
   761  
   762              if (params.offsetSlidesBefore > 0) {
   763                  if (isH) _this.wrapperLeft = slideSize * params.offsetSlidesBefore;
   764                  else _this.wrapperTop = slideSize * params.offsetSlidesBefore;
   765              }
   766              if (params.offsetSlidesAfter > 0) {
   767                  if (isH) _this.wrapperRight = slideSize * params.offsetSlidesAfter;
   768                  else _this.wrapperBottom = slideSize * params.offsetSlidesAfter;
   769              }
   770              if (params.offsetPxBefore > 0) {
   771                  if (isH) _this.wrapperLeft = params.offsetPxBefore;
   772                  else _this.wrapperTop = params.offsetPxBefore;
   773              }
   774              if (params.offsetPxAfter > 0) {
   775                  if (isH) _this.wrapperRight = params.offsetPxAfter;
   776                  else _this.wrapperBottom = params.offsetPxAfter;
   777              }
   778              if (params.centeredSlides) {
   779                  if (isH) {
   780                      _this.wrapperLeft = (containerSize - slideSize) / 2;
   781                      _this.wrapperRight = (containerSize - slideSize) / 2;
   782                  }
   783                  else {
   784                      _this.wrapperTop = (containerSize - slideSize) / 2;
   785                      _this.wrapperBottom = (containerSize - slideSize) / 2;
   786                  }
   787              }
   788              if (isH) {
   789                  if (_this.wrapperLeft > 0) wrapper.style.paddingLeft = _this.wrapperLeft + 'px';
   790                  if (_this.wrapperRight > 0) wrapper.style.paddingRight = _this.wrapperRight + 'px';
   791              }
   792              else {
   793                  if (_this.wrapperTop > 0) wrapper.style.paddingTop = _this.wrapperTop + 'px';
   794                  if (_this.wrapperBottom > 0) wrapper.style.paddingBottom = _this.wrapperBottom + 'px';
   795              }
   796  
   797              wrapperSize = isH ? wrapperWidth + _this.wrapperRight + _this.wrapperLeft : wrapperHeight + _this.wrapperTop + _this.wrapperBottom;
   798              if (parseFloat(wrapperWidth) > 0 && (!params.cssWidthAndHeight || params.cssWidthAndHeight === 'height')) {
   799                  wrapper.style.width = wrapperWidth + 'px';
   800              }
   801              if (parseFloat(wrapperHeight) > 0 && (!params.cssWidthAndHeight || params.cssWidthAndHeight === 'width')) {
   802                  wrapper.style.height = wrapperHeight + 'px';
   803              }
   804              slideLeft = 0;
   805              _this.snapGrid = [];
   806              _this.slidesGrid = [];
   807              for (i = 0; i < _this.slides.length; i++) {
   808                  _this.snapGrid.push(slideLeft);
   809                  _this.slidesGrid.push(slideLeft);
   810                  slideLeft += slideSize;
   811                  if (parseFloat(slideWidth) > 0 && (!params.cssWidthAndHeight || params.cssWidthAndHeight === 'height')) {
   812                      _this.slides[i].style.width = slideWidth + 'px';
   813                  }
   814                  if (parseFloat(slideHeight) > 0 && (!params.cssWidthAndHeight || params.cssWidthAndHeight === 'width')) {
   815                      _this.slides[i].style.height = slideHeight + 'px';
   816                  }
   817              }
   818  
   819          }
   820  
   821          if (!_this.initialized) {
   822              _this.callPlugins('onFirstInit');
   823              if (params.onFirstInit) _this.fireCallback(params.onFirstInit, _this);
   824          }
   825          else {
   826              _this.callPlugins('onInit');
   827              if (params.onInit) _this.fireCallback(params.onInit, _this);
   828          }
   829          _this.initialized = true;
   830      };
   831  
   832      _this.reInit = function (forceCalcSlides) {
   833          _this.init(true, forceCalcSlides);
   834      };
   835  
   836      _this.resizeFix = function (reInit) {
   837          _this.callPlugins('beforeResizeFix');
   838  
   839          _this.init(params.resizeReInit || reInit);
   840  
   841          // swipe to active slide in fixed mode
   842          if (!params.freeMode) {
   843              _this.swipeTo((params.loop ? _this.activeLoopIndex : _this.activeIndex), 0, false);
   844              // Fix autoplay
   845              if (params.autoplay) {
   846                  if (_this.support.transitions && typeof autoplayTimeoutId !== 'undefined') {
   847                      if (typeof autoplayTimeoutId !== 'undefined') {
   848                          clearTimeout(autoplayTimeoutId);
   849                          autoplayTimeoutId = undefined;
   850                          _this.startAutoplay();
   851                      }
   852                  }
   853                  else {
   854                      if (typeof autoplayIntervalId !== 'undefined') {
   855                          clearInterval(autoplayIntervalId);
   856                          autoplayIntervalId = undefined;
   857                          _this.startAutoplay();
   858                      }
   859                  }
   860              }
   861          }
   862          // move wrapper to the beginning in free mode
   863          else if (_this.getWrapperTranslate() < -maxWrapperPosition()) {
   864              _this.setWrapperTransition(0);
   865              _this.setWrapperTranslate(-maxWrapperPosition());
   866          }
   867  
   868          _this.callPlugins('afterResizeFix');
   869      };
   870  
   871      /*==========================================
   872          Max and Min Positions
   873      ============================================*/
   874      function maxWrapperPosition() {
   875          var a = (wrapperSize - containerSize);
   876          if (params.freeMode) {
   877              a = wrapperSize - containerSize;
   878          }
   879          // if (params.loop) a -= containerSize;
   880          if (params.slidesPerView > _this.slides.length && !params.centeredSlides) {
   881              a = 0;
   882          }
   883          if (a < 0) a = 0;
   884          return a;
   885      }
   886  
   887      /*==========================================
   888          Event Listeners
   889      ============================================*/
   890      function initEvents() {
   891          var bind = _this.h.addEventListener;
   892          var eventTarget = params.eventTarget === 'wrapper' ? _this.wrapper : _this.container;
   893          //Touch Events
   894          if (! (_this.browser.ie10 || _this.browser.ie11)) {
   895              if (_this.support.touch) {
   896                  bind(eventTarget, 'touchstart', onTouchStart);
   897                  bind(eventTarget, 'touchmove', onTouchMove);
   898                  bind(eventTarget, 'touchend', onTouchEnd);
   899              }
   900              if (params.simulateTouch) {
   901                  bind(eventTarget, 'mousedown', onTouchStart);
   902                  bind(document, 'mousemove', onTouchMove);
   903                  bind(document, 'mouseup', onTouchEnd);
   904              }
   905          }
   906          else {
   907              bind(eventTarget, _this.touchEvents.touchStart, onTouchStart);
   908              bind(document, _this.touchEvents.touchMove, onTouchMove);
   909              bind(document, _this.touchEvents.touchEnd, onTouchEnd);
   910          }
   911  
   912          //Resize Event
   913          if (params.autoResize) {
   914              bind(window, 'resize', _this.resizeFix);
   915          }
   916          //Slide Events
   917          addSlideEvents();
   918          //Mousewheel
   919          _this._wheelEvent = false;
   920          if (params.mousewheelControl) {
   921              if (document.onmousewheel !== undefined) {
   922                  _this._wheelEvent = 'mousewheel';
   923              }
   924              if (!_this._wheelEvent) {
   925                  try {
   926                      new WheelEvent('wheel');
   927                      _this._wheelEvent = 'wheel';
   928                  } catch (e) {}
   929              }
   930              if (!_this._wheelEvent) {
   931                  _this._wheelEvent = 'DOMMouseScroll';
   932              }
   933              if (_this._wheelEvent) {
   934                  bind(_this.container, _this._wheelEvent, handleMousewheel);
   935              }
   936          }
   937  
   938          //Keyboard
   939          function _loadImage(src) {
   940              var image = new Image();
   941              image.onload = function () {
   942                  if (typeof _this === 'undefined' || _this === null) return;
   943                  if (_this.imagesLoaded !== undefined) _this.imagesLoaded++;
   944                  if (_this.imagesLoaded === _this.imagesToLoad.length) {
   945                      _this.reInit();
   946                      if (params.onImagesReady) _this.fireCallback(params.onImagesReady, _this);
   947                  }
   948              };
   949              image.src = src;
   950          }
   951  
   952          if (params.keyboardControl) {
   953              bind(document, 'keydown', handleKeyboardKeys);
   954          }
   955          if (params.updateOnImagesReady) {
   956              _this.imagesToLoad = $$('img', _this.container);
   957  
   958              for (var i = 0; i < _this.imagesToLoad.length; i++) {
   959                  _loadImage(_this.imagesToLoad[i].getAttribute('src'));
   960              }
   961          }
   962      }
   963  
   964      //Remove Event Listeners
   965      _this.destroy = function (removeStyles) {
   966          var unbind = _this.h.removeEventListener;
   967          var eventTarget = params.eventTarget === 'wrapper' ? _this.wrapper : _this.container;
   968          //Touch Events
   969          if (! (_this.browser.ie10 || _this.browser.ie11)) {
   970              if (_this.support.touch) {
   971                  unbind(eventTarget, 'touchstart', onTouchStart);
   972                  unbind(eventTarget, 'touchmove', onTouchMove);
   973                  unbind(eventTarget, 'touchend', onTouchEnd);
   974              }
   975              if (params.simulateTouch) {
   976                  unbind(eventTarget, 'mousedown', onTouchStart);
   977                  unbind(document, 'mousemove', onTouchMove);
   978                  unbind(document, 'mouseup', onTouchEnd);
   979              }
   980          }
   981          else {
   982              unbind(eventTarget, _this.touchEvents.touchStart, onTouchStart);
   983              unbind(document, _this.touchEvents.touchMove, onTouchMove);
   984              unbind(document, _this.touchEvents.touchEnd, onTouchEnd);
   985          }
   986  
   987          //Resize Event
   988          if (params.autoResize) {
   989              unbind(window, 'resize', _this.resizeFix);
   990          }
   991  
   992          //Init Slide Events
   993          removeSlideEvents();
   994  
   995          //Pagination
   996          if (params.paginationClickable) {
   997              removePaginationEvents();
   998          }
   999  
  1000          //Mousewheel
  1001          if (params.mousewheelControl && _this._wheelEvent) {
  1002              unbind(_this.container, _this._wheelEvent, handleMousewheel);
  1003          }
  1004  
  1005          //Keyboard
  1006          if (params.keyboardControl) {
  1007              unbind(document, 'keydown', handleKeyboardKeys);
  1008          }
  1009  
  1010          //Stop autoplay
  1011          if (params.autoplay) {
  1012              _this.stopAutoplay();
  1013          }
  1014          // Remove styles
  1015          if (removeStyles) {
  1016              _this.wrapper.removeAttribute('style');
  1017              for (var i = 0; i < _this.slides.length; i++) {
  1018                  _this.slides[i].removeAttribute('style');
  1019              }
  1020          }
  1021          // Plugins
  1022          _this.callPlugins('onDestroy');
  1023  
  1024          // Check jQuery/Zepto data
  1025          if (window.jQuery && window.jQuery(_this.container).data('swiper')) {
  1026              window.jQuery(_this.container).removeData('swiper');
  1027          }
  1028          if (window.Zepto && window.Zepto(_this.container).data('swiper')) {
  1029              window.Zepto(_this.container).removeData('swiper');
  1030          }
  1031  
  1032          //Destroy variable
  1033          _this = null;
  1034      };
  1035  
  1036      function addSlideEvents() {
  1037          var bind = _this.h.addEventListener,
  1038              i;
  1039  
  1040          //Prevent Links Events
  1041          if (params.preventLinks) {
  1042              var links = $$('a', _this.container);
  1043              for (i = 0; i < links.length; i++) {
  1044                  bind(links[i], 'click', preventClick);
  1045              }
  1046          }
  1047          //Release Form Elements
  1048          if (params.releaseFormElements) {
  1049              var formElements = $$('input, textarea, select', _this.container);
  1050              for (i = 0; i < formElements.length; i++) {
  1051                  bind(formElements[i], _this.touchEvents.touchStart, releaseForms, true);
  1052                  if (_this.support.touch && params.simulateTouch) {
  1053                      bind(formElements[i], 'mousedown', releaseForms, true);
  1054                  }
  1055              }
  1056          }
  1057  
  1058          //Slide Clicks & Touches
  1059          if (params.onSlideClick) {
  1060              for (i = 0; i < _this.slides.length; i++) {
  1061                  bind(_this.slides[i], 'click', slideClick);
  1062              }
  1063          }
  1064          if (params.onSlideTouch) {
  1065              for (i = 0; i < _this.slides.length; i++) {
  1066                  bind(_this.slides[i], _this.touchEvents.touchStart, slideTouch);
  1067              }
  1068          }
  1069      }
  1070      function removeSlideEvents() {
  1071          var unbind = _this.h.removeEventListener,
  1072              i;
  1073  
  1074          //Slide Clicks & Touches
  1075          if (params.onSlideClick) {
  1076              for (i = 0; i < _this.slides.length; i++) {
  1077                  unbind(_this.slides[i], 'click', slideClick);
  1078              }
  1079          }
  1080          if (params.onSlideTouch) {
  1081              for (i = 0; i < _this.slides.length; i++) {
  1082                  unbind(_this.slides[i], _this.touchEvents.touchStart, slideTouch);
  1083              }
  1084          }
  1085          //Release Form Elements
  1086          if (params.releaseFormElements) {
  1087              var formElements = $$('input, textarea, select', _this.container);
  1088              for (i = 0; i < formElements.length; i++) {
  1089                  unbind(formElements[i], _this.touchEvents.touchStart, releaseForms, true);
  1090                  if (_this.support.touch && params.simulateTouch) {
  1091                      unbind(formElements[i], 'mousedown', releaseForms, true);
  1092                  }
  1093              }
  1094          }
  1095          //Prevent Links Events
  1096          if (params.preventLinks) {
  1097              var links = $$('a', _this.container);
  1098              for (i = 0; i < links.length; i++) {
  1099                  unbind(links[i], 'click', preventClick);
  1100              }
  1101          }
  1102      }
  1103      /*==========================================
  1104          Keyboard Control
  1105      ============================================*/
  1106      function handleKeyboardKeys(e) {
  1107          var kc = e.keyCode || e.charCode;
  1108          if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) return;
  1109          if (kc === 37 || kc === 39 || kc === 38 || kc === 40) {
  1110              var inView = false;
  1111              //Check that swiper should be inside of visible area of window
  1112              var swiperOffset = _this.h.getOffset(_this.container);
  1113              var scrollLeft = _this.h.windowScroll().left;
  1114              var scrollTop = _this.h.windowScroll().top;
  1115              var windowWidth = _this.h.windowWidth();
  1116              var windowHeight = _this.h.windowHeight();
  1117              var swiperCoord = [
  1118                  [swiperOffset.left, swiperOffset.top],
  1119                  [swiperOffset.left + _this.width, swiperOffset.top],
  1120                  [swiperOffset.left, swiperOffset.top + _this.height],
  1121                  [swiperOffset.left + _this.width, swiperOffset.top + _this.height]
  1122              ];
  1123              for (var i = 0; i < swiperCoord.length; i++) {
  1124                  var point = swiperCoord[i];
  1125                  if (
  1126                      point[0] >= scrollLeft && point[0] <= scrollLeft + windowWidth &&
  1127                      point[1] >= scrollTop && point[1] <= scrollTop + windowHeight
  1128                  ) {
  1129                      inView = true;
  1130                  }
  1131  
  1132              }
  1133              if (!inView) return;
  1134          }
  1135          if (isH) {
  1136              if (kc === 37 || kc === 39) {
  1137                  if (e.preventDefault) e.preventDefault();
  1138                  else e.returnValue = false;
  1139              }
  1140              if (kc === 39) _this.swipeNext();
  1141              if (kc === 37) _this.swipePrev();
  1142          }
  1143          else {
  1144              if (kc === 38 || kc === 40) {
  1145                  if (e.preventDefault) e.preventDefault();
  1146                  else e.returnValue = false;
  1147              }
  1148              if (kc === 40) _this.swipeNext();
  1149              if (kc === 38) _this.swipePrev();
  1150          }
  1151      }
  1152  
  1153      _this.disableKeyboardControl = function () {
  1154          params.keyboardControl = false;
  1155          _this.h.removeEventListener(document, 'keydown', handleKeyboardKeys);
  1156      };
  1157  
  1158      _this.enableKeyboardControl = function () {
  1159          params.keyboardControl = true;
  1160          _this.h.addEventListener(document, 'keydown', handleKeyboardKeys);
  1161      };
  1162  
  1163      /*==========================================
  1164          Mousewheel Control
  1165      ============================================*/
  1166      var lastScrollTime = (new Date()).getTime();
  1167      function handleMousewheel(e) {
  1168          var we = _this._wheelEvent;
  1169          var delta = 0;
  1170  
  1171          //Opera & IE
  1172          if (e.detail) delta = -e.detail;
  1173          //WebKits
  1174          else if (we === 'mousewheel') {
  1175              if (params.mousewheelControlForceToAxis) {
  1176                  if (isH) {
  1177                      if (Math.abs(e.wheelDeltaX) > Math.abs(e.wheelDeltaY)) delta = e.wheelDeltaX;
  1178                      else return;
  1179                  }
  1180                  else {
  1181                      if (Math.abs(e.wheelDeltaY) > Math.abs(e.wheelDeltaX)) delta = e.wheelDeltaY;
  1182                      else return;
  1183                  }
  1184              }
  1185              else {
  1186                  delta = e.wheelDelta;
  1187              }
  1188          }
  1189          //Old FireFox
  1190          else if (we === 'DOMMouseScroll') delta = -e.detail;
  1191          //New FireFox
  1192          else if (we === 'wheel') {
  1193              if (params.mousewheelControlForceToAxis) {
  1194                  if (isH) {
  1195                      if (Math.abs(e.deltaX) > Math.abs(e.deltaY)) delta = -e.deltaX;
  1196                      else return;
  1197                  }
  1198                  else {
  1199                      if (Math.abs(e.deltaY) > Math.abs(e.deltaX)) delta = -e.deltaY;
  1200                      else return;
  1201                  }
  1202              }
  1203              else {
  1204                  delta = Math.abs(e.deltaX) > Math.abs(e.deltaY) ? - e.deltaX : - e.deltaY;
  1205              }
  1206          }
  1207  
  1208          if (!params.freeMode) {
  1209              if ((new Date()).getTime() - lastScrollTime > 60) {
  1210                  if (delta < 0) _this.swipeNext();
  1211                  else _this.swipePrev();
  1212              }
  1213              lastScrollTime = (new Date()).getTime();
  1214  
  1215          }
  1216          else {
  1217              //Freemode or scrollContainer:
  1218              var position = _this.getWrapperTranslate() + delta;
  1219  
  1220              if (position > 0) position = 0;
  1221              if (position < -maxWrapperPosition()) position = -maxWrapperPosition();
  1222  
  1223              _this.setWrapperTransition(0);
  1224              _this.setWrapperTranslate(position);
  1225              _this.updateActiveSlide(position);
  1226  
  1227              // Return page scroll on edge positions
  1228              if (position === 0 || position === -maxWrapperPosition()) return;
  1229          }
  1230          if (params.autoplay) _this.stopAutoplay(true);
  1231  
  1232          if (e.preventDefault) e.preventDefault();
  1233          else e.returnValue = false;
  1234          return false;
  1235      }
  1236      _this.disableMousewheelControl = function () {
  1237          if (!_this._wheelEvent) return false;
  1238          params.mousewheelControl = false;
  1239          _this.h.removeEventListener(_this.container, _this._wheelEvent, handleMousewheel);
  1240          return true;
  1241      };
  1242  
  1243      _this.enableMousewheelControl = function () {
  1244          if (!_this._wheelEvent) return false;
  1245          params.mousewheelControl = true;
  1246          _this.h.addEventListener(_this.container, _this._wheelEvent, handleMousewheel);
  1247          return true;
  1248      };
  1249  
  1250      /*=========================
  1251        Grab Cursor
  1252        ===========================*/
  1253      if (params.grabCursor) {
  1254          var containerStyle = _this.container.style;
  1255          containerStyle.cursor = 'move';
  1256          containerStyle.cursor = 'grab';
  1257          containerStyle.cursor = '-moz-grab';
  1258          containerStyle.cursor = '-webkit-grab';
  1259      }
  1260  
  1261      /*=========================
  1262        Slides Events Handlers
  1263        ===========================*/
  1264  
  1265      _this.allowSlideClick = true;
  1266      function slideClick(event) {
  1267          if (_this.allowSlideClick) {
  1268              setClickedSlide(event);
  1269              _this.fireCallback(params.onSlideClick, _this, event);
  1270          }
  1271      }
  1272  
  1273      function slideTouch(event) {
  1274          setClickedSlide(event);
  1275          _this.fireCallback(params.onSlideTouch, _this, event);
  1276      }
  1277  
  1278      function setClickedSlide(event) {
  1279  
  1280          // IE 6-8 support
  1281          if (!event.currentTarget) {
  1282              var element = event.srcElement;
  1283              do {
  1284                  if (element.className.indexOf(params.slideClass) > -1) {
  1285                      break;
  1286                  }
  1287                  element = element.parentNode;
  1288              } while (element);
  1289              _this.clickedSlide = element;
  1290          }
  1291          else {
  1292              _this.clickedSlide = event.currentTarget;
  1293          }
  1294  
  1295          _this.clickedSlideIndex     = _this.slides.indexOf(_this.clickedSlide);
  1296          _this.clickedSlideLoopIndex = _this.clickedSlideIndex - (_this.loopedSlides || 0);
  1297      }
  1298  
  1299      _this.allowLinks = true;
  1300      function preventClick(e) {
  1301          if (!_this.allowLinks) {
  1302              if (e.preventDefault) e.preventDefault();
  1303              else e.returnValue = false;
  1304              if (params.preventLinksPropagation && 'stopPropagation' in e) {
  1305                  e.stopPropagation();
  1306              }
  1307              return false;
  1308          }
  1309      }
  1310      function releaseForms(e) {
  1311          if (e.stopPropagation) e.stopPropagation();
  1312          else e.returnValue = false;
  1313          return false;
  1314  
  1315      }
  1316  
  1317      /*==================================================
  1318          Event Handlers
  1319      ====================================================*/
  1320      var isTouchEvent = false;
  1321      var allowThresholdMove;
  1322      var allowMomentumBounce = true;
  1323      function onTouchStart(event) {
  1324          if (params.preventLinks) _this.allowLinks = true;
  1325          //Exit if slider is already was touched
  1326          if (_this.isTouched || params.onlyExternal) {
  1327              return false;
  1328          }
  1329  
  1330          // Blur active elements
  1331          var eventTarget = event.target || event.srcElement;
  1332          if (document.activeElement) {
  1333              if (document.activeElement !== eventTarget) document.activeElement.blur();
  1334          }
  1335  
  1336          // Form tag names
  1337          var formTagNames = ('input select textarea').split(' ');
  1338  
  1339          // Check for no swiping
  1340          if (params.noSwiping && (eventTarget) && noSwipingSlide(eventTarget)) return false;
  1341          allowMomentumBounce = false;
  1342          //Check For Nested Swipers
  1343          _this.isTouched = true;
  1344          isTouchEvent = event.type === 'touchstart';
  1345  
  1346          // prevent user enter with right and the swiper move (needs isTouchEvent)
  1347          if (!isTouchEvent && 'which' in event && event.which === 3) {
  1348              _this.isTouched = false;
  1349              return false;
  1350          }
  1351  
  1352          if (!isTouchEvent || event.targetTouches.length === 1) {
  1353              _this.callPlugins('onTouchStartBegin');
  1354              if (!isTouchEvent && !_this.isAndroid && formTagNames.indexOf(eventTarget.tagName.toLowerCase()) < 0) {
  1355  
  1356                  if (event.preventDefault) event.preventDefault();
  1357                  else event.returnValue = false;
  1358              }
  1359  
  1360              var pageX = isTouchEvent ? event.targetTouches[0].pageX : (event.pageX || event.clientX);
  1361              var pageY = isTouchEvent ? event.targetTouches[0].pageY : (event.pageY || event.clientY);
  1362  
  1363              //Start Touches to check the scrolling
  1364              _this.touches.startX = _this.touches.currentX = pageX;
  1365              _this.touches.startY = _this.touches.currentY = pageY;
  1366  
  1367              _this.touches.start = _this.touches.current = isH ? pageX : pageY;
  1368  
  1369              //Set Transition Time to 0
  1370              _this.setWrapperTransition(0);
  1371  
  1372              //Get Start Translate Position
  1373              _this.positions.start = _this.positions.current = _this.getWrapperTranslate();
  1374  
  1375              //Set Transform
  1376              _this.setWrapperTranslate(_this.positions.start);
  1377  
  1378              //TouchStartTime
  1379              _this.times.start = (new Date()).getTime();
  1380  
  1381              //Unset Scrolling
  1382              isScrolling = undefined;
  1383  
  1384              //Set Treshold
  1385              if (params.moveStartThreshold > 0) {
  1386                  allowThresholdMove = false;
  1387              }
  1388  
  1389              //CallBack
  1390              if (params.onTouchStart) _this.fireCallback(params.onTouchStart, _this, event);
  1391              _this.callPlugins('onTouchStartEnd');
  1392  
  1393          }
  1394      }
  1395      var velocityPrevPosition, velocityPrevTime;
  1396      function onTouchMove(event) {
  1397          // If slider is not touched - exit
  1398          if (!_this.isTouched || params.onlyExternal) return;
  1399          if (isTouchEvent && event.type === 'mousemove') return;
  1400  
  1401          var pageX = isTouchEvent ? event.targetTouches[0].pageX : (event.pageX || event.clientX);
  1402          var pageY = isTouchEvent ? event.targetTouches[0].pageY : (event.pageY || event.clientY);
  1403  
  1404          //check for scrolling
  1405          if (typeof isScrolling === 'undefined' && isH) {
  1406              isScrolling = !!(isScrolling || Math.abs(pageY - _this.touches.startY) > Math.abs(pageX - _this.touches.startX));
  1407          }
  1408          if (typeof isScrolling === 'undefined' && !isH) {
  1409              isScrolling = !!(isScrolling || Math.abs(pageY - _this.touches.startY) < Math.abs(pageX - _this.touches.startX));
  1410          }
  1411          if (isScrolling) {
  1412              _this.isTouched = false;
  1413              return;
  1414          }
  1415  
  1416          // One way swipes
  1417          if (isH) {
  1418              if ((!params.swipeToNext && pageX < _this.touches.startX) || ((!params.swipeToPrev && pageX > _this.touches.startX))) {
  1419                  return;
  1420              }
  1421          }
  1422          else {
  1423              if ((!params.swipeToNext && pageY < _this.touches.startY) || ((!params.swipeToPrev && pageY > _this.touches.startY))) {
  1424                  return;
  1425              }
  1426          }
  1427  
  1428          //Check For Nested Swipers
  1429          if (event.assignedToSwiper) {
  1430              _this.isTouched = false;
  1431              return;
  1432          }
  1433          event.assignedToSwiper = true;
  1434  
  1435          //Block inner links
  1436          if (params.preventLinks) {
  1437              _this.allowLinks = false;
  1438          }
  1439          if (params.onSlideClick) {
  1440              _this.allowSlideClick = false;
  1441          }
  1442  
  1443          //Stop AutoPlay if exist
  1444          if (params.autoplay) {
  1445              _this.stopAutoplay(true);
  1446          }
  1447          if (!isTouchEvent || event.touches.length === 1) {
  1448  
  1449              //Moved Flag
  1450              if (!_this.isMoved) {
  1451                  _this.callPlugins('onTouchMoveStart');
  1452  
  1453                  if (params.loop) {
  1454                      _this.fixLoop();
  1455                      _this.positions.start = _this.getWrapperTranslate();
  1456                  }
  1457                  if (params.onTouchMoveStart) _this.fireCallback(params.onTouchMoveStart, _this);
  1458              }
  1459              _this.isMoved = true;
  1460  
  1461              // cancel event
  1462              if (event.preventDefault) event.preventDefault();
  1463              else event.returnValue = false;
  1464  
  1465              _this.touches.current = isH ? pageX : pageY;
  1466  
  1467              _this.positions.current = (_this.touches.current - _this.touches.start) * params.touchRatio + _this.positions.start;
  1468  
  1469              //Resistance Callbacks
  1470              if (_this.positions.current > 0 && params.onResistanceBefore) {
  1471                  _this.fireCallback(params.onResistanceBefore, _this, _this.positions.current);
  1472              }
  1473              if (_this.positions.current < -maxWrapperPosition() && params.onResistanceAfter) {
  1474                  _this.fireCallback(params.onResistanceAfter, _this, Math.abs(_this.positions.current + maxWrapperPosition()));
  1475              }
  1476              //Resistance
  1477              if (params.resistance && params.resistance !== '100%') {
  1478                  var resistance;
  1479                  //Resistance for Negative-Back sliding
  1480                  if (_this.positions.current > 0) {
  1481                      resistance = 1 - _this.positions.current / containerSize / 2;
  1482                      if (resistance < 0.5)
  1483                          _this.positions.current = (containerSize / 2);
  1484                      else
  1485                          _this.positions.current = _this.positions.current * resistance;
  1486                  }
  1487                  //Resistance for After-End Sliding
  1488                  if (_this.positions.current < -maxWrapperPosition()) {
  1489  
  1490                      var diff = (_this.touches.current - _this.touches.start) * params.touchRatio + (maxWrapperPosition() + _this.positions.start);
  1491                      resistance = (containerSize + diff) / (containerSize);
  1492                      var newPos = _this.positions.current - diff * (1 - resistance) / 2;
  1493                      var stopPos = -maxWrapperPosition() - containerSize / 2;
  1494  
  1495                      if (newPos < stopPos || resistance <= 0)
  1496                          _this.positions.current = stopPos;
  1497                      else
  1498                          _this.positions.current = newPos;
  1499                  }
  1500              }
  1501              if (params.resistance && params.resistance === '100%') {
  1502                  //Resistance for Negative-Back sliding
  1503                  if (_this.positions.current > 0 && !(params.freeMode && !params.freeModeFluid)) {
  1504                      _this.positions.current = 0;
  1505                  }
  1506                  //Resistance for After-End Sliding
  1507                  if (_this.positions.current < -maxWrapperPosition() && !(params.freeMode && !params.freeModeFluid)) {
  1508                      _this.positions.current = -maxWrapperPosition();
  1509                  }
  1510              }
  1511              //Move Slides
  1512              if (!params.followFinger) return;
  1513  
  1514              if (!params.moveStartThreshold) {
  1515                  _this.setWrapperTranslate(_this.positions.current);
  1516              }
  1517              else {
  1518                  if (Math.abs(_this.touches.current - _this.touches.start) > params.moveStartThreshold || allowThresholdMove) {
  1519                      if (!allowThresholdMove) {
  1520                          allowThresholdMove = true;
  1521                          _this.touches.start = _this.touches.current;
  1522                          return;
  1523                      }
  1524                      _this.setWrapperTranslate(_this.positions.current);
  1525                  }
  1526                  else {
  1527                      _this.positions.current = _this.positions.start;
  1528                  }
  1529              }
  1530  
  1531              if (params.freeMode || params.watchActiveIndex) {
  1532                  _this.updateActiveSlide(_this.positions.current);
  1533              }
  1534  
  1535              //Grab Cursor
  1536              if (params.grabCursor) {
  1537                  _this.container.style.cursor = 'move';
  1538                  _this.container.style.cursor = 'grabbing';
  1539                  _this.container.style.cursor = '-moz-grabbin';
  1540                  _this.container.style.cursor = '-webkit-grabbing';
  1541              }
  1542              //Velocity
  1543              if (!velocityPrevPosition) velocityPrevPosition = _this.touches.current;
  1544              if (!velocityPrevTime) velocityPrevTime = (new Date()).getTime();
  1545              _this.velocity = (_this.touches.current - velocityPrevPosition) / ((new Date()).getTime() - velocityPrevTime) / 2;
  1546              if (Math.abs(_this.touches.current - velocityPrevPosition) < 2) _this.velocity = 0;
  1547              velocityPrevPosition = _this.touches.current;
  1548              velocityPrevTime = (new Date()).getTime();
  1549              //Callbacks
  1550              _this.callPlugins('onTouchMoveEnd');
  1551              if (params.onTouchMove) _this.fireCallback(params.onTouchMove, _this, event);
  1552  
  1553              return false;
  1554          }
  1555      }
  1556      function onTouchEnd(event) {
  1557          //Check For scrolling
  1558          if (isScrolling) {
  1559              _this.swipeReset();
  1560          }
  1561          // If slider is not touched exit
  1562          if (params.onlyExternal || !_this.isTouched) return;
  1563          _this.isTouched = false;
  1564  
  1565          //Return Grab Cursor
  1566          if (params.grabCursor) {
  1567              _this.container.style.cursor = 'move';
  1568              _this.container.style.cursor = 'grab';
  1569              _this.container.style.cursor = '-moz-grab';
  1570              _this.container.style.cursor = '-webkit-grab';
  1571          }
  1572  
  1573          //Check for Current Position
  1574          if (!_this.positions.current && _this.positions.current !== 0) {
  1575              _this.positions.current = _this.positions.start;
  1576          }
  1577  
  1578          //For case if slider touched but not moved
  1579          if (params.followFinger) {
  1580              _this.setWrapperTranslate(_this.positions.current);
  1581          }
  1582  
  1583          // TouchEndTime
  1584          _this.times.end = (new Date()).getTime();
  1585  
  1586          //Difference
  1587          _this.touches.diff = _this.touches.current - _this.touches.start;
  1588          _this.touches.abs = Math.abs(_this.touches.diff);
  1589  
  1590          _this.positions.diff = _this.positions.current - _this.positions.start;
  1591          _this.positions.abs = Math.abs(_this.positions.diff);
  1592  
  1593          var diff = _this.positions.diff;
  1594          var diffAbs = _this.positions.abs;
  1595          var timeDiff = _this.times.end - _this.times.start;
  1596  
  1597          if (diffAbs < 5 && (timeDiff) < 300 && _this.allowLinks === false) {
  1598              if (!params.freeMode && diffAbs !== 0) _this.swipeReset();
  1599              //Release inner links
  1600              if (params.preventLinks) {
  1601                  _this.allowLinks = true;
  1602              }
  1603              if (params.onSlideClick) {
  1604                  _this.allowSlideClick = true;
  1605              }
  1606          }
  1607  
  1608          setTimeout(function () {
  1609              //Release inner links
  1610              if (typeof _this === 'undefined' || _this === null) return;
  1611              if (params.preventLinks) {
  1612                  _this.allowLinks = true;
  1613              }
  1614              if (params.onSlideClick) {
  1615                  _this.allowSlideClick = true;
  1616              }
  1617          }, 100);
  1618  
  1619          var maxPosition = maxWrapperPosition();
  1620  
  1621          //Not moved or Prevent Negative Back Sliding/After-End Sliding
  1622          if (!_this.isMoved && params.freeMode) {
  1623              _this.isMoved = false;
  1624              if (params.onTouchEnd) _this.fireCallback(params.onTouchEnd, _this, event);
  1625              _this.callPlugins('onTouchEnd');
  1626              return;
  1627          }
  1628          if (!_this.isMoved || _this.positions.current > 0 || _this.positions.current < -maxPosition) {
  1629              _this.swipeReset();
  1630              if (params.onTouchEnd) _this.fireCallback(params.onTouchEnd, _this, event);
  1631              _this.callPlugins('onTouchEnd');
  1632              return;
  1633          }
  1634  
  1635          _this.isMoved = false;
  1636  
  1637          //Free Mode
  1638          if (params.freeMode) {
  1639              if (params.freeModeFluid) {
  1640                  var momentumDuration = 1000 * params.momentumRatio;
  1641                  var momentumDistance = _this.velocity * momentumDuration;
  1642                  var newPosition = _this.positions.current + momentumDistance;
  1643                  var doBounce = false;
  1644                  var afterBouncePosition;
  1645                  var bounceAmount = Math.abs(_this.velocity) * 20 * params.momentumBounceRatio;
  1646                  if (newPosition < -maxPosition) {
  1647                      if (params.momentumBounce && _this.support.transitions) {
  1648                          if (newPosition + maxPosition < -bounceAmount) newPosition = -maxPosition - bounceAmount;
  1649                          afterBouncePosition = -maxPosition;
  1650                          doBounce = true;
  1651                          allowMomentumBounce = true;
  1652                      }
  1653                      else newPosition = -maxPosition;
  1654                  }
  1655                  if (newPosition > 0) {
  1656                      if (params.momentumBounce && _this.support.transitions) {
  1657                          if (newPosition > bounceAmount) newPosition = bounceAmount;
  1658                          afterBouncePosition = 0;
  1659                          doBounce = true;
  1660                          allowMomentumBounce = true;
  1661                      }
  1662                      else newPosition = 0;
  1663                  }
  1664                  //Fix duration
  1665                  if (_this.velocity !== 0) momentumDuration = Math.abs((newPosition - _this.positions.current) / _this.velocity);
  1666  
  1667                  _this.setWrapperTranslate(newPosition);
  1668  
  1669                  _this.setWrapperTransition(momentumDuration);
  1670  
  1671                  if (params.momentumBounce && doBounce) {
  1672                      _this.wrapperTransitionEnd(function () {
  1673                          if (!allowMomentumBounce) return;
  1674                          if (params.onMomentumBounce) _this.fireCallback(params.onMomentumBounce, _this);
  1675                          _this.callPlugins('onMomentumBounce');
  1676  
  1677                          _this.setWrapperTranslate(afterBouncePosition);
  1678                          _this.setWrapperTransition(300);
  1679                      });
  1680                  }
  1681  
  1682                  _this.updateActiveSlide(newPosition);
  1683              }
  1684              if (!params.freeModeFluid || timeDiff >= 300) _this.updateActiveSlide(_this.positions.current);
  1685  
  1686              if (params.onTouchEnd) _this.fireCallback(params.onTouchEnd, _this, event);
  1687              _this.callPlugins('onTouchEnd');
  1688              return;
  1689          }
  1690  
  1691          //Direction
  1692          direction = diff < 0 ? 'toNext' : 'toPrev';
  1693  
  1694          //Short Touches
  1695          if (direction === 'toNext' && (timeDiff <= 300)) {
  1696              if (diffAbs < 30 || !params.shortSwipes) _this.swipeReset();
  1697              else _this.swipeNext(true, true);
  1698          }
  1699  
  1700          if (direction === 'toPrev' && (timeDiff <= 300)) {
  1701              if (diffAbs < 30 || !params.shortSwipes) _this.swipeReset();
  1702              else _this.swipePrev(true, true);
  1703          }
  1704  
  1705          //Long Touches
  1706          var targetSlideSize = 0;
  1707          if (params.slidesPerView === 'auto') {
  1708              //Define current slide's width
  1709              var currentPosition = Math.abs(_this.getWrapperTranslate());
  1710              var slidesOffset = 0;
  1711              var _slideSize;
  1712              for (var i = 0; i < _this.slides.length; i++) {
  1713                  _slideSize = isH ? _this.slides[i].getWidth(true, params.roundLengths) : _this.slides[i].getHeight(true, params.roundLengths);
  1714                  slidesOffset += _slideSize;
  1715                  if (slidesOffset > currentPosition) {
  1716                      targetSlideSize = _slideSize;
  1717                      break;
  1718                  }
  1719              }
  1720              if (targetSlideSize > containerSize) targetSlideSize = containerSize;
  1721          }
  1722          else {
  1723              targetSlideSize = slideSize * params.slidesPerView;
  1724          }
  1725          if (direction === 'toNext' && (timeDiff > 300)) {
  1726              if (diffAbs >= targetSlideSize * params.longSwipesRatio) {
  1727                  _this.swipeNext(true, true);
  1728              }
  1729              else {
  1730                  _this.swipeReset();
  1731              }
  1732          }
  1733          if (direction === 'toPrev' && (timeDiff > 300)) {
  1734              if (diffAbs >= targetSlideSize * params.longSwipesRatio) {
  1735                  _this.swipePrev(true, true);
  1736              }
  1737              else {
  1738                  _this.swipeReset();
  1739              }
  1740          }
  1741          if (params.onTouchEnd) _this.fireCallback(params.onTouchEnd, _this, event);
  1742          _this.callPlugins('onTouchEnd');
  1743      }
  1744  
  1745  
  1746      /*==================================================
  1747          noSwiping Bubble Check by Isaac Strack
  1748      ====================================================*/
  1749      function noSwipingSlide(el) {
  1750          /*This function is specifically designed to check the parent elements for the noSwiping class, up to the wrapper.
  1751          We need to check parents because while onTouchStart bubbles, _this.isTouched is checked in onTouchStart, which stops the bubbling.
  1752          So, if a text box, for example, is the initial target, and the parent slide container has the noSwiping class, the _this.isTouched
  1753          check will never find it, and what was supposed to be noSwiping is able to be swiped.
  1754          This function will iterate up and check for the noSwiping class in parents, up through the wrapperClass.*/
  1755  
  1756          // First we create a truthy variable, which is that swiping is allowd (noSwiping = false)
  1757          var noSwiping = false;
  1758  
  1759          // Now we iterate up (parentElements) until we reach the node with the wrapperClass.
  1760          do {
  1761  
  1762              // Each time, we check to see if there's a 'swiper-no-swiping' class (noSwipingClass).
  1763              if (el.className.indexOf(params.noSwipingClass) > -1)
  1764              {
  1765                  noSwiping = true; // If there is, we set noSwiping = true;
  1766              }
  1767  
  1768              el = el.parentElement;  // now we iterate up (parent node)
  1769  
  1770          } while (!noSwiping && el.parentElement && el.className.indexOf(params.wrapperClass) === -1); // also include el.parentElement truthy, just in case.
  1771  
  1772          // because we didn't check the wrapper itself, we do so now, if noSwiping is false:
  1773          if (!noSwiping && el.className.indexOf(params.wrapperClass) > -1 && el.className.indexOf(params.noSwipingClass) > -1)
  1774              noSwiping = true; // if the wrapper has the noSwipingClass, we set noSwiping = true;
  1775  
  1776          return noSwiping;
  1777      }
  1778  
  1779      function addClassToHtmlString(klass, outerHtml) {
  1780          var par = document.createElement('div');
  1781          var child;
  1782  
  1783          par.innerHTML = outerHtml;
  1784          child = par.firstChild;
  1785          child.className += ' ' + klass;
  1786  
  1787          return child.outerHTML;
  1788      }
  1789  
  1790  
  1791      /*==================================================
  1792          Swipe Functions
  1793      ====================================================*/
  1794      _this.swipeNext = function (runCallbacks, internal) {
  1795          if (typeof runCallbacks === 'undefined') runCallbacks = true;
  1796          if (!internal && params.loop) _this.fixLoop();
  1797          if (!internal && params.autoplay) _this.stopAutoplay(true);
  1798          _this.callPlugins('onSwipeNext');
  1799          var currentPosition = _this.getWrapperTranslate().toFixed(2);
  1800          var newPosition = currentPosition;
  1801          if (params.slidesPerView === 'auto') {
  1802              for (var i = 0; i < _this.snapGrid.length; i++) {
  1803                  if (-currentPosition >= _this.snapGrid[i].toFixed(2) && -currentPosition < _this.snapGrid[i + 1].toFixed(2)) {
  1804                      newPosition = -_this.snapGrid[i + 1];
  1805                      break;
  1806                  }
  1807              }
  1808          }
  1809          else {
  1810              var groupSize = slideSize * params.slidesPerGroup;
  1811              newPosition = -(Math.floor(Math.abs(currentPosition) / Math.floor(groupSize)) * groupSize + groupSize);
  1812          }
  1813          if (newPosition < -maxWrapperPosition()) {
  1814              newPosition = -maxWrapperPosition();
  1815          }
  1816          if (newPosition === currentPosition) return false;
  1817          swipeToPosition(newPosition, 'next', {runCallbacks: runCallbacks});
  1818          return true;
  1819      };
  1820      _this.swipePrev = function (runCallbacks, internal) {
  1821          if (typeof runCallbacks === 'undefined') runCallbacks = true;
  1822          if (!internal && params.loop) _this.fixLoop();
  1823          if (!internal && params.autoplay) _this.stopAutoplay(true);
  1824          _this.callPlugins('onSwipePrev');
  1825  
  1826          var currentPosition = Math.ceil(_this.getWrapperTranslate());
  1827          var newPosition;
  1828          if (params.slidesPerView === 'auto') {
  1829              newPosition = 0;
  1830              for (var i = 1; i < _this.snapGrid.length; i++) {
  1831                  if (-currentPosition === _this.snapGrid[i]) {
  1832                      newPosition = -_this.snapGrid[i - 1];
  1833                      break;
  1834                  }
  1835                  if (-currentPosition > _this.snapGrid[i] && -currentPosition < _this.snapGrid[i + 1]) {
  1836                      newPosition = -_this.snapGrid[i];
  1837                      break;
  1838                  }
  1839              }
  1840          }
  1841          else {
  1842              var groupSize = slideSize * params.slidesPerGroup;
  1843              newPosition = -(Math.ceil(-currentPosition / groupSize) - 1) * groupSize;
  1844          }
  1845  
  1846          if (newPosition > 0) newPosition = 0;
  1847  
  1848          if (newPosition === currentPosition) return false;
  1849          swipeToPosition(newPosition, 'prev', {runCallbacks: runCallbacks});
  1850          return true;
  1851  
  1852      };
  1853      _this.swipeReset = function (runCallbacks) {
  1854          if (typeof runCallbacks === 'undefined') runCallbacks = true;
  1855          _this.callPlugins('onSwipeReset');
  1856          var currentPosition = _this.getWrapperTranslate();
  1857          var groupSize = slideSize * params.slidesPerGroup;
  1858          var newPosition;
  1859          var maxPosition = -maxWrapperPosition();
  1860          if (params.slidesPerView === 'auto') {
  1861              newPosition = 0;
  1862              for (var i = 0; i < _this.snapGrid.length; i++) {
  1863                  if (-currentPosition === _this.snapGrid[i]) return;
  1864                  if (-currentPosition >= _this.snapGrid[i] && -currentPosition < _this.snapGrid[i + 1]) {
  1865                      if (_this.positions.diff > 0) newPosition = -_this.snapGrid[i + 1];
  1866                      else newPosition = -_this.snapGrid[i];
  1867                      break;
  1868                  }
  1869              }
  1870              if (-currentPosition >= _this.snapGrid[_this.snapGrid.length - 1]) newPosition = -_this.snapGrid[_this.snapGrid.length - 1];
  1871              if (currentPosition <= -maxWrapperPosition()) newPosition = -maxWrapperPosition();
  1872          }
  1873          else {
  1874              newPosition = currentPosition < 0 ? Math.round(currentPosition / groupSize) * groupSize : 0;
  1875              if (currentPosition <= -maxWrapperPosition()) newPosition = -maxWrapperPosition();
  1876          }
  1877          if (params.scrollContainer)  {
  1878              newPosition = currentPosition < 0 ? currentPosition : 0;
  1879          }
  1880          if (newPosition < -maxWrapperPosition()) {
  1881              newPosition = -maxWrapperPosition();
  1882          }
  1883          if (params.scrollContainer && (containerSize > slideSize)) {
  1884              newPosition = 0;
  1885          }
  1886  
  1887          if (newPosition === currentPosition) return false;
  1888  
  1889          swipeToPosition(newPosition, 'reset', {runCallbacks: runCallbacks});
  1890          return true;
  1891      };
  1892  
  1893      _this.swipeTo = function (index, speed, runCallbacks) {
  1894          index = parseInt(index, 10);
  1895          _this.callPlugins('onSwipeTo', {index: index, speed: speed});
  1896          if (params.loop) index = index + _this.loopedSlides;
  1897          var currentPosition = _this.getWrapperTranslate();
  1898          if (index > (_this.slides.length - 1) || index < 0) return;
  1899          var newPosition;
  1900          if (params.slidesPerView === 'auto') {
  1901              newPosition = -_this.slidesGrid[index];
  1902          }
  1903          else {
  1904              newPosition = -index * slideSize;
  1905          }
  1906          if (newPosition < - maxWrapperPosition()) {
  1907              newPosition = - maxWrapperPosition();
  1908          }
  1909  
  1910          if (newPosition === currentPosition) return false;
  1911  
  1912          if (typeof runCallbacks === 'undefined') runCallbacks = true;
  1913          swipeToPosition(newPosition, 'to', {index: index, speed: speed, runCallbacks: runCallbacks});
  1914          return true;
  1915      };
  1916  
  1917      function swipeToPosition(newPosition, action, toOptions) {
  1918          var speed = (action === 'to' && toOptions.speed >= 0) ? toOptions.speed : params.speed;
  1919          var timeOld = + new Date();
  1920  
  1921          function anim() {
  1922              var timeNew = + new Date();
  1923              var time = timeNew - timeOld;
  1924              currentPosition += animationStep * time / (1000 / 60);
  1925              condition = direction === 'toNext' ? currentPosition > newPosition : currentPosition < newPosition;
  1926              if (condition) {
  1927                  _this.setWrapperTranslate(Math.ceil(currentPosition));
  1928                  _this._DOMAnimating = true;
  1929                  window.setTimeout(function () {
  1930                      anim();
  1931                  }, 1000 / 60);
  1932              }
  1933              else {
  1934                  if (params.onSlideChangeEnd) {
  1935                      if (action === 'to') {
  1936                          if (toOptions.runCallbacks === true) _this.fireCallback(params.onSlideChangeEnd, _this, direction);
  1937                      }
  1938                      else {
  1939                          _this.fireCallback(params.onSlideChangeEnd, _this, direction);
  1940                      }
  1941  
  1942                  }
  1943                  _this.setWrapperTranslate(newPosition);
  1944                  _this._DOMAnimating = false;
  1945              }
  1946          }
  1947  
  1948          if (_this.support.transitions || !params.DOMAnimation) {
  1949              _this.setWrapperTranslate(newPosition);
  1950              _this.setWrapperTransition(speed);
  1951          }
  1952          else {
  1953              //Try the DOM animation
  1954              var currentPosition = _this.getWrapperTranslate();
  1955              var animationStep = Math.ceil((newPosition - currentPosition) / speed * (1000 / 60));
  1956              var direction = currentPosition > newPosition ? 'toNext' : 'toPrev';
  1957              var condition = direction === 'toNext' ? currentPosition > newPosition : currentPosition < newPosition;
  1958              if (_this._DOMAnimating) return;
  1959  
  1960              anim();
  1961          }
  1962  
  1963          //Update Active Slide Index
  1964          _this.updateActiveSlide(newPosition);
  1965  
  1966          //Callbacks
  1967          if (params.onSlideNext && action === 'next' && toOptions.runCallbacks === true) {
  1968              _this.fireCallback(params.onSlideNext, _this, newPosition);
  1969          }
  1970          if (params.onSlidePrev && action === 'prev' && toOptions.runCallbacks === true) {
  1971              _this.fireCallback(params.onSlidePrev, _this, newPosition);
  1972          }
  1973          //'Reset' Callback
  1974          if (params.onSlideReset && action === 'reset' && toOptions.runCallbacks === true) {
  1975              _this.fireCallback(params.onSlideReset, _this, newPosition);
  1976          }
  1977  
  1978          //'Next', 'Prev' and 'To' Callbacks
  1979          if ((action === 'next' || action === 'prev' || action === 'to') && toOptions.runCallbacks === true)
  1980              slideChangeCallbacks(action);
  1981      }
  1982      /*==================================================
  1983          Transition Callbacks
  1984      ====================================================*/
  1985      //Prevent Multiple Callbacks
  1986      _this._queueStartCallbacks = false;
  1987      _this._queueEndCallbacks = false;
  1988      function slideChangeCallbacks(direction) {
  1989          //Transition Start Callback
  1990          _this.callPlugins('onSlideChangeStart');
  1991          if (params.onSlideChangeStart) {
  1992              if (params.queueStartCallbacks && _this.support.transitions) {
  1993                  if (_this._queueStartCallbacks) return;
  1994                  _this._queueStartCallbacks = true;
  1995                  _this.fireCallback(params.onSlideChangeStart, _this, direction);
  1996                  _this.wrapperTransitionEnd(function () {
  1997                      _this._queueStartCallbacks = false;
  1998                  });
  1999              }
  2000              else _this.fireCallback(params.onSlideChangeStart, _this, direction);
  2001          }
  2002          //Transition End Callback
  2003          if (params.onSlideChangeEnd) {
  2004              if (_this.support.transitions) {
  2005                  if (params.queueEndCallbacks) {
  2006                      if (_this._queueEndCallbacks) return;
  2007                      _this._queueEndCallbacks = true;
  2008                      _this.wrapperTransitionEnd(function (swiper) {
  2009                          _this.fireCallback(params.onSlideChangeEnd, swiper, direction);
  2010                      });
  2011                  }
  2012                  else {
  2013                      _this.wrapperTransitionEnd(function (swiper) {
  2014                          _this.fireCallback(params.onSlideChangeEnd, swiper, direction);
  2015                      });
  2016                  }
  2017              }
  2018              else {
  2019                  if (!params.DOMAnimation) {
  2020                      setTimeout(function () {
  2021                          _this.fireCallback(params.onSlideChangeEnd, _this, direction);
  2022                      }, 10);
  2023                  }
  2024              }
  2025          }
  2026      }
  2027  
  2028      /*==================================================
  2029          Update Active Slide Index
  2030      ====================================================*/
  2031      _this.updateActiveSlide = function (position) {
  2032          if (!_this.initialized) return;
  2033          if (_this.slides.length === 0) return;
  2034          _this.previousIndex = _this.activeIndex;
  2035          if (typeof position === 'undefined') position = _this.getWrapperTranslate();
  2036          if (position > 0) position = 0;
  2037          var i;
  2038          if (params.slidesPerView === 'auto') {
  2039              var slidesOffset = 0;
  2040              _this.activeIndex = _this.slidesGrid.indexOf(-position);
  2041              if (_this.activeIndex < 0) {
  2042                  for (i = 0; i < _this.slidesGrid.length - 1; i++) {
  2043                      if (-position > _this.slidesGrid[i] && -position < _this.slidesGrid[i + 1]) {
  2044                          break;
  2045                      }
  2046                  }
  2047                  var leftDistance = Math.abs(_this.slidesGrid[i] + position);
  2048                  var rightDistance = Math.abs(_this.slidesGrid[i + 1] + position);
  2049                  if (leftDistance <= rightDistance) _this.activeIndex = i;
  2050                  else _this.activeIndex = i + 1;
  2051              }
  2052          }
  2053          else {
  2054              _this.activeIndex = Math[params.visibilityFullFit ? 'ceil' : 'round'](-position / slideSize);
  2055          }
  2056  
  2057          if (_this.activeIndex === _this.slides.length) _this.activeIndex = _this.slides.length - 1;
  2058          if (_this.activeIndex < 0) _this.activeIndex = 0;
  2059  
  2060          // Check for slide
  2061          if (!_this.slides[_this.activeIndex]) return;
  2062  
  2063          // Calc Visible slides
  2064          _this.calcVisibleSlides(position);
  2065  
  2066          // Mark visible and active slides with additonal classes
  2067          if (_this.support.classList) {
  2068              var slide;
  2069              for (i = 0; i < _this.slides.length; i++) {
  2070                  slide = _this.slides[i];
  2071                  slide.classList.remove(params.slideActiveClass);
  2072                  if (_this.visibleSlides.indexOf(slide) >= 0) {
  2073                      slide.classList.add(params.slideVisibleClass);
  2074                  } else {
  2075                      slide.classList.remove(params.slideVisibleClass);
  2076                  }
  2077              }
  2078              _this.slides[_this.activeIndex].classList.add(params.slideActiveClass);
  2079          } else {
  2080              var activeClassRegexp = new RegExp('\\s*' + params.slideActiveClass);
  2081              var inViewClassRegexp = new RegExp('\\s*' + params.slideVisibleClass);
  2082  
  2083              for (i = 0; i < _this.slides.length; i++) {
  2084                  _this.slides[i].className = _this.slides[i].className.replace(activeClassRegexp, '').replace(inViewClassRegexp, '');
  2085                  if (_this.visibleSlides.indexOf(_this.slides[i]) >= 0) {
  2086                      _this.slides[i].className += ' ' + params.slideVisibleClass;
  2087                  }
  2088              }
  2089              _this.slides[_this.activeIndex].className += ' ' + params.slideActiveClass;
  2090          }
  2091  
  2092          //Update loop index
  2093          if (params.loop) {
  2094              var ls = _this.loopedSlides;
  2095              _this.activeLoopIndex = _this.activeIndex - ls;
  2096              if (_this.activeLoopIndex >= _this.slides.length - ls * 2) {
  2097                  _this.activeLoopIndex = _this.slides.length - ls * 2 - _this.activeLoopIndex;
  2098              }
  2099              if (_this.activeLoopIndex < 0) {
  2100                  _this.activeLoopIndex = _this.slides.length - ls * 2 + _this.activeLoopIndex;
  2101              }
  2102              if (_this.activeLoopIndex < 0) _this.activeLoopIndex = 0;
  2103          }
  2104          else {
  2105              _this.activeLoopIndex = _this.activeIndex;
  2106          }
  2107          //Update Pagination
  2108          if (params.pagination) {
  2109              _this.updatePagination(position);
  2110          }
  2111      };
  2112      /*==================================================
  2113          Pagination
  2114      ====================================================*/
  2115      _this.createPagination = function (firstInit) {
  2116          if (params.paginationClickable && _this.paginationButtons) {
  2117              removePaginationEvents();
  2118          }
  2119          _this.paginationContainer = params.pagination.nodeType ? params.pagination : $$(params.pagination)[0];
  2120          if (params.createPagination) {
  2121              var paginationHTML = '';
  2122              var numOfSlides = _this.slides.length;
  2123              var numOfButtons = numOfSlides;
  2124              if (params.loop) numOfButtons -= _this.loopedSlides * 2;
  2125              for (var i = 0; i < numOfButtons; i++) {
  2126                  paginationHTML += '<' + params.paginationElement + ' class="' + params.paginationElementClass + '"></' + params.paginationElement + '>';
  2127              }
  2128              _this.paginationContainer.innerHTML = paginationHTML;
  2129          }
  2130          _this.paginationButtons = $$('.' + params.paginationElementClass, _this.paginationContainer);
  2131          if (!firstInit) _this.updatePagination();
  2132          _this.callPlugins('onCreatePagination');
  2133          if (params.paginationClickable) {
  2134              addPaginationEvents();
  2135          }
  2136      };
  2137      function removePaginationEvents() {
  2138          var pagers = _this.paginationButtons;
  2139          if (pagers) {
  2140              for (var i = 0; i < pagers.length; i++) {
  2141                  _this.h.removeEventListener(pagers[i], 'click', paginationClick);
  2142              }
  2143          }
  2144      }
  2145      function addPaginationEvents() {
  2146          var pagers = _this.paginationButtons;
  2147          if (pagers) {
  2148              for (var i = 0; i < pagers.length; i++) {
  2149                  _this.h.addEventListener(pagers[i], 'click', paginationClick);
  2150              }
  2151          }
  2152      }
  2153      function paginationClick(e) {
  2154          var index;
  2155          var target = e.target || e.srcElement;
  2156          var pagers = _this.paginationButtons;
  2157          for (var i = 0; i < pagers.length; i++) {
  2158              if (target === pagers[i]) index = i;
  2159          }
  2160          if (params.autoplay) _this.stopAutoplay(true);
  2161          _this.swipeTo(index);
  2162      }
  2163      _this.updatePagination = function (position) {
  2164          if (!params.pagination) return;
  2165          if (_this.slides.length < 1) return;
  2166          var activePagers = $$('.' + params.paginationActiveClass, _this.paginationContainer);
  2167          if (!activePagers) return;
  2168  
  2169          //Reset all Buttons' class to not active
  2170          var pagers = _this.paginationButtons;
  2171          if (pagers.length === 0) return;
  2172          for (var i = 0; i < pagers.length; i++) {
  2173              pagers[i].className = params.paginationElementClass;
  2174          }
  2175  
  2176          var indexOffset = params.loop ? _this.loopedSlides : 0;
  2177          if (params.paginationAsRange) {
  2178              if (!_this.visibleSlides) _this.calcVisibleSlides(position);
  2179              //Get Visible Indexes
  2180              var visibleIndexes = [];
  2181              var j; // lopp index - avoid JSHint W004 / W038
  2182              for (j = 0; j < _this.visibleSlides.length; j++) {
  2183                  var visIndex = _this.slides.indexOf(_this.visibleSlides[j]) - indexOffset;
  2184  
  2185                  if (params.loop && visIndex < 0) {
  2186                      visIndex = _this.slides.length - _this.loopedSlides * 2 + visIndex;
  2187                  }
  2188                  if (params.loop && visIndex >= _this.slides.length - _this.loopedSlides * 2) {
  2189                      visIndex = _this.slides.length - _this.loopedSlides * 2 - visIndex;
  2190                      visIndex = Math.abs(visIndex);
  2191                  }
  2192                  visibleIndexes.push(visIndex);
  2193              }
  2194  
  2195              for (j = 0; j < visibleIndexes.length; j++) {
  2196                  if (pagers[visibleIndexes[j]]) pagers[visibleIndexes[j]].className += ' ' + params.paginationVisibleClass;
  2197              }
  2198  
  2199              if (params.loop) {
  2200                  if (pagers[_this.activeLoopIndex] !== undefined) {
  2201                      pagers[_this.activeLoopIndex].className += ' ' + params.paginationActiveClass;
  2202                  }
  2203              }
  2204              else {
  2205                  if (pagers[_this.activeIndex]) pagers[_this.activeIndex].className += ' ' + params.paginationActiveClass;
  2206              }
  2207          }
  2208          else {
  2209              if (params.loop) {
  2210                  if (pagers[_this.activeLoopIndex]) pagers[_this.activeLoopIndex].className += ' ' + params.paginationActiveClass + ' ' + params.paginationVisibleClass;
  2211              }
  2212              else {
  2213                  if (pagers[_this.activeIndex]) pagers[_this.activeIndex].className += ' ' + params.paginationActiveClass + ' ' + params.paginationVisibleClass;
  2214              }
  2215          }
  2216      };
  2217      _this.calcVisibleSlides = function (position) {
  2218          var visibleSlides = [];
  2219          var _slideLeft = 0, _slideSize = 0, _slideRight = 0;
  2220          if (isH && _this.wrapperLeft > 0) position = position + _this.wrapperLeft;
  2221          if (!isH && _this.wrapperTop > 0) position = position + _this.wrapperTop;
  2222  
  2223          for (var i = 0; i < _this.slides.length; i++) {
  2224              _slideLeft += _slideSize;
  2225              if (params.slidesPerView === 'auto')
  2226                  _slideSize  = isH ? _this.h.getWidth(_this.slides[i], true, params.roundLengths) : _this.h.getHeight(_this.slides[i], true, params.roundLengths);
  2227              else _slideSize = slideSize;
  2228  
  2229              _slideRight = _slideLeft + _slideSize;
  2230              var isVisibile = false;
  2231              if (params.visibilityFullFit) {
  2232                  if (_slideLeft >= -position && _slideRight <= -position + containerSize) isVisibile = true;
  2233                  if (_slideLeft <= -position && _slideRight >= -position + containerSize) isVisibile = true;
  2234              }
  2235              else {
  2236                  if (_slideRight > -position && _slideRight <= ((-position + containerSize))) isVisibile = true;
  2237                  if (_slideLeft >= -position && _slideLeft < ((-position + containerSize))) isVisibile = true;
  2238                  if (_slideLeft < -position && _slideRight > ((-position + containerSize))) isVisibile = true;
  2239              }
  2240  
  2241              if (isVisibile) visibleSlides.push(_this.slides[i]);
  2242  
  2243          }
  2244          if (visibleSlides.length === 0) visibleSlides = [_this.slides[_this.activeIndex]];
  2245  
  2246          _this.visibleSlides = visibleSlides;
  2247      };
  2248  
  2249      /*==========================================
  2250          Autoplay
  2251      ============================================*/
  2252      var autoplayTimeoutId, autoplayIntervalId;
  2253      _this.startAutoplay = function () {
  2254          if (_this.support.transitions) {
  2255              if (typeof autoplayTimeoutId !== 'undefined') return false;
  2256              if (!params.autoplay) return;
  2257              _this.callPlugins('onAutoplayStart');
  2258              if (params.onAutoplayStart) _this.fireCallback(params.onAutoplayStart, _this);
  2259              autoplay();
  2260          }
  2261          else {
  2262              if (typeof autoplayIntervalId !== 'undefined') return false;
  2263              if (!params.autoplay) return;
  2264              _this.callPlugins('onAutoplayStart');
  2265              if (params.onAutoplayStart) _this.fireCallback(params.onAutoplayStart, _this);
  2266              autoplayIntervalId = setInterval(function () {
  2267                  if (params.loop) {
  2268                      _this.fixLoop();
  2269                      _this.swipeNext(true, true);
  2270                  }
  2271                  else if (!_this.swipeNext(true, true)) {
  2272                      if (!params.autoplayStopOnLast) _this.swipeTo(0);
  2273                      else {
  2274                          clearInterval(autoplayIntervalId);
  2275                          autoplayIntervalId = undefined;
  2276                      }
  2277                  }
  2278              }, params.autoplay);
  2279          }
  2280      };
  2281      _this.stopAutoplay = function (internal) {
  2282          if (_this.support.transitions) {
  2283              if (!autoplayTimeoutId) return;
  2284              if (autoplayTimeoutId) clearTimeout(autoplayTimeoutId);
  2285              autoplayTimeoutId = undefined;
  2286              if (internal && !params.autoplayDisableOnInteraction) {
  2287                  _this.wrapperTransitionEnd(function () {
  2288                      autoplay();
  2289                  });
  2290              }
  2291              _this.callPlugins('onAutoplayStop');
  2292              if (params.onAutoplayStop) _this.fireCallback(params.onAutoplayStop, _this);
  2293          }
  2294          else {
  2295              if (autoplayIntervalId) clearInterval(autoplayIntervalId);
  2296              autoplayIntervalId = undefined;
  2297              _this.callPlugins('onAutoplayStop');
  2298              if (params.onAutoplayStop) _this.fireCallback(params.onAutoplayStop, _this);
  2299          }
  2300      };
  2301      function autoplay() {
  2302          autoplayTimeoutId = setTimeout(function () {
  2303              if (params.loop) {
  2304                  _this.fixLoop();
  2305                  _this.swipeNext(true, true);
  2306              }
  2307              else if (!_this.swipeNext(true, true)) {
  2308                  if (!params.autoplayStopOnLast) _this.swipeTo(0);
  2309                  else {
  2310                      clearTimeout(autoplayTimeoutId);
  2311                      autoplayTimeoutId = undefined;
  2312                  }
  2313              }
  2314              _this.wrapperTransitionEnd(function () {
  2315                  if (typeof autoplayTimeoutId !== 'undefined') autoplay();
  2316              });
  2317          }, params.autoplay);
  2318      }
  2319      /*==================================================
  2320          Loop
  2321      ====================================================*/
  2322      _this.loopCreated = false;
  2323      _this.removeLoopedSlides = function () {
  2324          if (_this.loopCreated) {
  2325              for (var i = 0; i < _this.slides.length; i++) {
  2326                  if (_this.slides[i].getData('looped') === true) _this.wrapper.removeChild(_this.slides[i]);
  2327              }
  2328          }
  2329      };
  2330  
  2331      _this.createLoop = function () {
  2332          if (_this.slides.length === 0) return;
  2333          if (params.slidesPerView === 'auto') {
  2334              _this.loopedSlides = params.loopedSlides || 1;
  2335          }
  2336          else {
  2337              _this.loopedSlides = params.slidesPerView + params.loopAdditionalSlides;
  2338          }
  2339  
  2340          if (_this.loopedSlides > _this.slides.length) {
  2341              _this.loopedSlides = _this.slides.length;
  2342          }
  2343  
  2344          var slideFirstHTML = '',
  2345              slideLastHTML = '',
  2346              i;
  2347          var slidesSetFullHTML = '';
  2348          /**
  2349                  loopedSlides is too large if loopAdditionalSlides are set.
  2350                  Need to divide the slides by maximum number of slides existing.
  2351  
  2352                  @author        Tomaz Lovrec <tomaz.lovrec@blanc-noir.at>
  2353          */
  2354          var numSlides = _this.slides.length;
  2355          var fullSlideSets = Math.floor(_this.loopedSlides / numSlides);
  2356          var remainderSlides = _this.loopedSlides % numSlides;
  2357          // assemble full sets of slides
  2358          for (i = 0; i < (fullSlideSets * numSlides); i++) {
  2359              var j = i;
  2360              if (i >= numSlides) {
  2361                  var over = Math.floor(i / numSlides);
  2362                  j = i - (numSlides * over);
  2363              }
  2364              slidesSetFullHTML += _this.slides[j].outerHTML;
  2365          }
  2366          // assemble remainder slides
  2367          // assemble remainder appended to existing slides
  2368          for (i = 0; i < remainderSlides;i++) {
  2369              slideLastHTML += addClassToHtmlString(params.slideDuplicateClass, _this.slides[i].outerHTML);
  2370          }
  2371          // assemble slides that get preppended to existing slides
  2372          for (i = numSlides - remainderSlides; i < numSlides;i++) {
  2373              slideFirstHTML += addClassToHtmlString(params.slideDuplicateClass, _this.slides[i].outerHTML);
  2374          }
  2375          // assemble all slides
  2376          var slides = slideFirstHTML + slidesSetFullHTML + wrapper.innerHTML + slidesSetFullHTML + slideLastHTML;
  2377          // set the slides
  2378          wrapper.innerHTML = slides;
  2379  
  2380          _this.loopCreated = true;
  2381          _this.calcSlides();
  2382  
  2383          //Update Looped Slides with special class
  2384          for (i = 0; i < _this.slides.length; i++) {
  2385              if (i < _this.loopedSlides || i >= _this.slides.length - _this.loopedSlides) _this.slides[i].setData('looped', true);
  2386          }
  2387          _this.callPlugins('onCreateLoop');
  2388  
  2389      };
  2390  
  2391      _this.fixLoop = function () {
  2392          var newIndex;
  2393          //Fix For Negative Oversliding
  2394          if (_this.activeIndex < _this.loopedSlides) {
  2395              newIndex = _this.slides.length - _this.loopedSlides * 3 + _this.activeIndex;
  2396              _this.swipeTo(newIndex, 0, false);
  2397          }
  2398          //Fix For Positive Oversliding
  2399          else if ((params.slidesPerView === 'auto' && _this.activeIndex >= _this.loopedSlides * 2) || (_this.activeIndex > _this.slides.length - params.slidesPerView * 2)) {
  2400              newIndex = -_this.slides.length + _this.activeIndex + _this.loopedSlides;
  2401              _this.swipeTo(newIndex, 0, false);
  2402          }
  2403      };
  2404  
  2405      /*==================================================
  2406          Slides Loader
  2407      ====================================================*/
  2408      _this.loadSlides = function () {
  2409          var slidesHTML = '';
  2410          _this.activeLoaderIndex = 0;
  2411          var slides = params.loader.slides;
  2412          var slidesToLoad = params.loader.loadAllSlides ? slides.length : params.slidesPerView * (1 + params.loader.surroundGroups);
  2413          for (var i = 0; i < slidesToLoad; i++) {
  2414              if (params.loader.slidesHTMLType === 'outer') slidesHTML += slides[i];
  2415              else {
  2416                  slidesHTML += '<' + params.slideElement + ' class="' + params.slideClass + '" data-swiperindex="' + i + '">' + slides[i] + '</' + params.slideElement + '>';
  2417              }
  2418          }
  2419          _this.wrapper.innerHTML = slidesHTML;
  2420          _this.calcSlides(true);
  2421          //Add permanent transitionEnd callback
  2422          if (!params.loader.loadAllSlides) {
  2423              _this.wrapperTransitionEnd(_this.reloadSlides, true);
  2424          }
  2425      };
  2426  
  2427      _this.reloadSlides = function () {
  2428          var slides = params.loader.slides;
  2429          var newActiveIndex = parseInt(_this.activeSlide().data('swiperindex'), 10);
  2430          if (newActiveIndex < 0 || newActiveIndex > slides.length - 1) return; //<-- Exit
  2431          _this.activeLoaderIndex = newActiveIndex;
  2432          var firstIndex = Math.max(0, newActiveIndex - params.slidesPerView * params.loader.surroundGroups);
  2433          var lastIndex = Math.min(newActiveIndex + params.slidesPerView * (1 + params.loader.surroundGroups) - 1, slides.length - 1);
  2434          //Update Transforms
  2435          if (newActiveIndex > 0) {
  2436              var newTransform = -slideSize * (newActiveIndex - firstIndex);
  2437              _this.setWrapperTranslate(newTransform);
  2438              _this.setWrapperTransition(0);
  2439          }
  2440          var i; // loop index
  2441          //New Slides
  2442          if (params.loader.logic === 'reload') {
  2443              _this.wrapper.innerHTML = '';
  2444              var slidesHTML = '';
  2445              for (i = firstIndex; i <= lastIndex; i++) {
  2446                  slidesHTML += params.loader.slidesHTMLType === 'outer' ? slides[i] : '<' + params.slideElement + ' class="' + params.slideClass + '" data-swiperindex="' + i + '">' + slides[i] + '</' + params.slideElement + '>';
  2447              }
  2448              _this.wrapper.innerHTML = slidesHTML;
  2449          }
  2450          else {
  2451              var minExistIndex = 1000;
  2452              var maxExistIndex = 0;
  2453  
  2454              for (i = 0; i < _this.slides.length; i++) {
  2455                  var index = _this.slides[i].data('swiperindex');
  2456                  if (index < firstIndex || index > lastIndex) {
  2457                      _this.wrapper.removeChild(_this.slides[i]);
  2458                  }
  2459                  else {
  2460                      minExistIndex = Math.min(index, minExistIndex);
  2461                      maxExistIndex = Math.max(index, maxExistIndex);
  2462                  }
  2463              }
  2464              for (i = firstIndex; i <= lastIndex; i++) {
  2465                  var newSlide;
  2466                  if (i < minExistIndex) {
  2467                      newSlide = document.createElement(params.slideElement);
  2468                      newSlide.className = params.slideClass;
  2469                      newSlide.setAttribute('data-swiperindex', i);
  2470                      newSlide.innerHTML = slides[i];
  2471                      _this.wrapper.insertBefore(newSlide, _this.wrapper.firstChild);
  2472                  }
  2473                  if (i > maxExistIndex) {
  2474                      newSlide = document.createElement(params.slideElement);
  2475                      newSlide.className = params.slideClass;
  2476                      newSlide.setAttribute('data-swiperindex', i);
  2477                      newSlide.innerHTML = slides[i];
  2478                      _this.wrapper.appendChild(newSlide);
  2479                  }
  2480              }
  2481          }
  2482          //reInit
  2483          _this.reInit(true);
  2484      };
  2485  
  2486      /*==================================================
  2487          Make Swiper
  2488      ====================================================*/
  2489      function makeSwiper() {
  2490          _this.calcSlides();
  2491          if (params.loader.slides.length > 0 && _this.slides.length === 0) {
  2492              _this.loadSlides();
  2493          }
  2494          if (params.loop) {
  2495              _this.createLoop();
  2496          }
  2497          _this.init();
  2498          initEvents();
  2499          if (params.pagination) {
  2500              _this.createPagination(true);
  2501          }
  2502  
  2503          if (params.loop || params.initialSlide > 0) {
  2504              _this.swipeTo(params.initialSlide, 0, false);
  2505          }
  2506          else {
  2507              _this.updateActiveSlide(0);
  2508          }
  2509          if (params.autoplay) {
  2510              _this.startAutoplay();
  2511          }
  2512          /**
  2513           * Set center slide index.
  2514           *
  2515           * @author        Tomaz Lovrec <tomaz.lovrec@gmail.com>
  2516           */
  2517          _this.centerIndex = _this.activeIndex;
  2518  
  2519          // Callbacks
  2520          if (params.onSwiperCreated) _this.fireCallback(params.onSwiperCreated, _this);
  2521          _this.callPlugins('onSwiperCreated');
  2522      }
  2523  
  2524      makeSwiper();
  2525  };
  2526  
  2527  Swiper.prototype = {
  2528      plugins : {},
  2529  
  2530      /*==================================================
  2531          Wrapper Operations
  2532      ====================================================*/
  2533      wrapperTransitionEnd : function (callback, permanent) {
  2534          'use strict';
  2535          var a = this,
  2536              el = a.wrapper,
  2537              events = ['webkitTransitionEnd', 'transitionend', 'oTransitionEnd', 'MSTransitionEnd', 'msTransitionEnd'],
  2538              i;
  2539  
  2540          function fireCallBack(e) {
  2541              if (e.target !== el) return;
  2542              callback(a);
  2543              if (a.params.queueEndCallbacks) a._queueEndCallbacks = false;
  2544              if (!permanent) {
  2545                  for (i = 0; i < events.length; i++) {
  2546                      a.h.removeEventListener(el, events[i], fireCallBack);
  2547                  }
  2548              }
  2549          }
  2550  
  2551          if (callback) {
  2552              for (i = 0; i < events.length; i++) {
  2553                  a.h.addEventListener(el, events[i], fireCallBack);
  2554              }
  2555          }
  2556      },
  2557  
  2558      getWrapperTranslate : function (axis) {
  2559          'use strict';
  2560          var el = this.wrapper,
  2561              matrix, curTransform, curStyle, transformMatrix;
  2562  
  2563          // automatic axis detection
  2564          if (typeof axis === 'undefined') {
  2565              axis = this.params.mode === 'horizontal' ? 'x' : 'y';
  2566          }
  2567  
  2568          if (this.support.transforms && this.params.useCSS3Transforms) {
  2569              curStyle = window.getComputedStyle(el, null);
  2570              if (window.WebKitCSSMatrix) {
  2571                  // Some old versions of Webkit choke when 'none' is passed; pass
  2572                  // empty string instead in this case
  2573                  transformMatrix = new WebKitCSSMatrix(curStyle.webkitTransform === 'none' ? '' : curStyle.webkitTransform);
  2574              }
  2575              else {
  2576                  transformMatrix = curStyle.MozTransform || curStyle.OTransform || curStyle.MsTransform || curStyle.msTransform  || curStyle.transform || curStyle.getPropertyValue('transform').replace('translate(', 'matrix(1, 0, 0, 1,');
  2577                  matrix = transformMatrix.toString().split(',');
  2578              }
  2579  
  2580              if (axis === 'x') {
  2581                  //Latest Chrome and webkits Fix
  2582                  if (window.WebKitCSSMatrix)
  2583                      curTransform = transformMatrix.m41;
  2584                  //Crazy IE10 Matrix
  2585                  else if (matrix.length === 16)
  2586                      curTransform = parseFloat(matrix[12]);
  2587                  //Normal Browsers
  2588                  else
  2589                      curTransform = parseFloat(matrix[4]);
  2590              }
  2591              if (axis === 'y') {
  2592                  //Latest Chrome and webkits Fix
  2593                  if (window.WebKitCSSMatrix)
  2594                      curTransform = transformMatrix.m42;
  2595                  //Crazy IE10 Matrix
  2596                  else if (matrix.length === 16)
  2597                      curTransform = parseFloat(matrix[13]);
  2598                  //Normal Browsers
  2599                  else
  2600                      curTransform = parseFloat(matrix[5]);
  2601              }
  2602          }
  2603          else {
  2604              if (axis === 'x') curTransform = parseFloat(el.style.left, 10) || 0;
  2605              if (axis === 'y') curTransform = parseFloat(el.style.top, 10) || 0;
  2606          }
  2607          return curTransform || 0;
  2608      },
  2609  
  2610      setWrapperTranslate : function (x, y, z) {
  2611          'use strict';
  2612          var es = this.wrapper.style,
  2613              coords = {x: 0, y: 0, z: 0},
  2614              translate;
  2615  
  2616          // passed all coordinates
  2617          if (arguments.length === 3) {
  2618              coords.x = x;
  2619              coords.y = y;
  2620              coords.z = z;
  2621          }
  2622  
  2623          // passed one coordinate and optional axis
  2624          else {
  2625              if (typeof y === 'undefined') {
  2626                  y = this.params.mode === 'horizontal' ? 'x' : 'y';
  2627              }
  2628              coords[y] = x;
  2629          }
  2630  
  2631          if (this.support.transforms && this.params.useCSS3Transforms) {
  2632              translate = this.support.transforms3d ? 'translate3d(' + coords.x + 'px, ' + coords.y + 'px, ' + coords.z + 'px)' : 'translate(' + coords.x + 'px, ' + coords.y + 'px)';
  2633              es.webkitTransform = es.MsTransform = es.msTransform = es.MozTransform = es.OTransform = es.transform = translate;
  2634          }
  2635          else {
  2636              es.left = coords.x + 'px';
  2637              es.top  = coords.y + 'px';
  2638          }
  2639          this.callPlugins('onSetWrapperTransform', coords);
  2640          if (this.params.onSetWrapperTransform) this.fireCallback(this.params.onSetWrapperTransform, this, coords);
  2641      },
  2642  
  2643      setWrapperTransition : function (duration) {
  2644          'use strict';
  2645          var es = this.wrapper.style;
  2646          es.webkitTransitionDuration = es.MsTransitionDuration = es.msTransitionDuration = es.MozTransitionDuration = es.OTransitionDuration = es.transitionDuration = (duration / 1000) + 's';
  2647          this.callPlugins('onSetWrapperTransition', {duration: duration});
  2648          if (this.params.onSetWrapperTransition) this.fireCallback(this.params.onSetWrapperTransition, this, duration);
  2649  
  2650      },
  2651  
  2652      /*==================================================
  2653          Helpers
  2654      ====================================================*/
  2655      h : {
  2656          getWidth: function (el, outer, round) {
  2657              'use strict';
  2658              var width = window.getComputedStyle(el, null).getPropertyValue('width');
  2659              var returnWidth = parseFloat(width);
  2660              //IE Fixes
  2661              if (isNaN(returnWidth) || width.indexOf('%') > 0 || returnWidth < 0) {
  2662                  returnWidth = el.offsetWidth - parseFloat(window.getComputedStyle(el, null).getPropertyValue('padding-left')) - parseFloat(window.getComputedStyle(el, null).getPropertyValue('padding-right'));
  2663              }
  2664              if (outer) returnWidth += parseFloat(window.getComputedStyle(el, null).getPropertyValue('padding-left')) + parseFloat(window.getComputedStyle(el, null).getPropertyValue('padding-right'));
  2665              if (round) return Math.ceil(returnWidth);
  2666              else return returnWidth;
  2667          },
  2668          getHeight: function (el, outer, round) {
  2669              'use strict';
  2670              if (outer) return el.offsetHeight;
  2671  
  2672              var height = window.getComputedStyle(el, null).getPropertyValue('height');
  2673              var returnHeight = parseFloat(height);
  2674              //IE Fixes
  2675              if (isNaN(returnHeight) || height.indexOf('%') > 0 || returnHeight < 0) {
  2676                  returnHeight = el.offsetHeight - parseFloat(window.getComputedStyle(el, null).getPropertyValue('padding-top')) - parseFloat(window.getComputedStyle(el, null).getPropertyValue('padding-bottom'));
  2677              }
  2678              if (outer) returnHeight += parseFloat(window.getComputedStyle(el, null).getPropertyValue('padding-top')) + parseFloat(window.getComputedStyle(el, null).getPropertyValue('padding-bottom'));
  2679              if (round) return Math.ceil(returnHeight);
  2680              else return returnHeight;
  2681          },
  2682          getOffset: function (el) {
  2683              'use strict';
  2684              var box = el.getBoundingClientRect();
  2685              var body = document.body;
  2686              var clientTop  = el.clientTop  || body.clientTop  || 0;
  2687              var clientLeft = el.clientLeft || body.clientLeft || 0;
  2688              var scrollTop  = window.pageYOffset || el.scrollTop;
  2689              var scrollLeft = window.pageXOffset || el.scrollLeft;
  2690              if (document.documentElement && !window.pageYOffset) {
  2691                  //IE7-8
  2692                  scrollTop  = document.documentElement.scrollTop;
  2693                  scrollLeft = document.documentElement.scrollLeft;
  2694              }
  2695              return {
  2696                  top: box.top  + scrollTop  - clientTop,
  2697                  left: box.left + scrollLeft - clientLeft
  2698              };
  2699          },
  2700          windowWidth : function () {
  2701              'use strict';
  2702              if (window.innerWidth) return window.innerWidth;
  2703              else if (document.documentElement && document.documentElement.clientWidth) return document.documentElement.clientWidth;
  2704          },
  2705          windowHeight : function () {
  2706              'use strict';
  2707              if (window.innerHeight) return window.innerHeight;
  2708              else if (document.documentElement && document.documentElement.clientHeight) return document.documentElement.clientHeight;
  2709          },
  2710          windowScroll : function () {
  2711              'use strict';
  2712              if (typeof pageYOffset !== 'undefined') {
  2713                  return {
  2714                      left: window.pageXOffset,
  2715                      top: window.pageYOffset
  2716                  };
  2717              }
  2718              else if (document.documentElement) {
  2719                  return {
  2720                      left: document.documentElement.scrollLeft,
  2721                      top: document.documentElement.scrollTop
  2722                  };
  2723              }
  2724          },
  2725  
  2726          addEventListener : function (el, event, listener, useCapture) {
  2727              'use strict';
  2728              if (typeof useCapture === 'undefined') {
  2729                  useCapture = false;
  2730              }
  2731  
  2732              if (el.addEventListener) {
  2733                  el.addEventListener(event, listener, useCapture);
  2734              }
  2735              else if (el.attachEvent) {
  2736                  el.attachEvent('on' + event, listener);
  2737              }
  2738          },
  2739  
  2740          removeEventListener : function (el, event, listener, useCapture) {
  2741              'use strict';
  2742              if (typeof useCapture === 'undefined') {
  2743                  useCapture = false;
  2744              }
  2745  
  2746              if (el.removeEventListener) {
  2747                  el.removeEventListener(event, listener, useCapture);
  2748              }
  2749              else if (el.detachEvent) {
  2750                  el.detachEvent('on' + event, listener);
  2751              }
  2752          }
  2753      },
  2754      setTransform : function (el, transform) {
  2755          'use strict';
  2756          var es = el.style;
  2757          es.webkitTransform = es.MsTransform = es.msTransform = es.MozTransform = es.OTransform = es.transform = transform;
  2758      },
  2759      setTranslate : function (el, translate) {
  2760          'use strict';
  2761          var es = el.style;
  2762          var pos = {
  2763              x : translate.x || 0,
  2764              y : translate.y || 0,
  2765              z : translate.z || 0
  2766          };
  2767          var transformString = this.support.transforms3d ? 'translate3d(' + (pos.x) + 'px,' + (pos.y) + 'px,' + (pos.z) + 'px)' : 'translate(' + (pos.x) + 'px,' + (pos.y) + 'px)';
  2768          es.webkitTransform = es.MsTransform = es.msTransform = es.MozTransform = es.OTransform = es.transform = transformString;
  2769          if (!this.support.transforms) {
  2770              es.left = pos.x + 'px';
  2771              es.top = pos.y + 'px';
  2772          }
  2773      },
  2774      setTransition : function (el, duration) {
  2775          'use strict';
  2776          var es = el.style;
  2777          es.webkitTransitionDuration = es.MsTransitionDuration = es.msTransitionDuration = es.MozTransitionDuration = es.OTransitionDuration = es.transitionDuration = duration + 'ms';
  2778      },
  2779      /*==================================================
  2780          Feature Detection
  2781      ====================================================*/
  2782      support: {
  2783  
  2784          touch : (window.Modernizr && Modernizr.touch === true) || (function () {
  2785              'use strict';
  2786              return !!(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch);
  2787          })(),
  2788  
  2789          transforms3d : (window.Modernizr && Modernizr.csstransforms3d === true) || (function () {
  2790              'use strict';
  2791              var div = document.createElement('div').style;
  2792              return ('webkitPerspective' in div || 'MozPerspective' in div || 'OPerspective' in div || 'MsPerspective' in div || 'perspective' in div);
  2793          })(),
  2794  
  2795          transforms : (window.Modernizr && Modernizr.csstransforms === true) || (function () {
  2796              'use strict';
  2797              var div = document.createElement('div').style;
  2798              return ('transform' in div || 'WebkitTransform' in div || 'MozTransform' in div || 'msTransform' in div || 'MsTransform' in div || 'OTransform' in div);
  2799          })(),
  2800  
  2801          transitions : (window.Modernizr && Modernizr.csstransitions === true) || (function () {
  2802              'use strict';
  2803              var div = document.createElement('div').style;
  2804              return ('transition' in div || 'WebkitTransition' in div || 'MozTransition' in div || 'msTransition' in div || 'MsTransition' in div || 'OTransition' in div);
  2805          })(),
  2806  
  2807          classList : (function () {
  2808              'use strict';
  2809              var div = document.createElement('div');
  2810              return 'classList' in div;
  2811          })()
  2812      },
  2813  
  2814      browser : {
  2815  
  2816          ie8 : (function () {
  2817              'use strict';
  2818              var rv = -1; // Return value assumes failure.
  2819              if (navigator.appName === 'Microsoft Internet Explorer') {
  2820                  var ua = navigator.userAgent;
  2821                  var re = new RegExp(/MSIE ([0-9]{1,}[\.0-9]{0,})/);
  2822                  if (re.exec(ua) !== null)
  2823                      rv = parseFloat(RegExp.$1);
  2824              }
  2825              return rv !== -1 && rv < 9;
  2826          })(),
  2827  
  2828          ie10 : window.navigator.msPointerEnabled,
  2829          ie11 : window.navigator.pointerEnabled
  2830      }
  2831  };
  2832  
  2833  /*=========================
  2834    jQuery & Zepto Plugins
  2835    ===========================*/
  2836  if (window.jQuery || window.Zepto) {
  2837      (function ($) {
  2838          'use strict';
  2839          $.fn.swiper = function (params) {
  2840              var firstInstance;
  2841              this.each(function (i) {
  2842                  var that = $(this);
  2843                  var s = new Swiper(that[0], params);
  2844                  if (!i) firstInstance = s;
  2845                  that.data('swiper', s);
  2846              });
  2847              return firstInstance;
  2848          };
  2849      })(window.jQuery || window.Zepto);
  2850  }
  2851  
  2852  // component
  2853  if (typeof(module) !== 'undefined')
  2854  {
  2855      module.exports = Swiper;
  2856  }
  2857  
  2858  // requirejs support
  2859  if (typeof define === 'function' && define.amd) {
  2860      define([], function () {
  2861          'use strict';
  2862          return Swiper;
  2863      });
  2864  }