idangerous.swiper.js 111 KB

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