slide.js 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949
  1. /*!
  2. * better-scroll / slide
  3. * (c) 2016-2021 ustbhuangyi
  4. * Released under the MIT License.
  5. */
  6. (function (global, factory) {
  7. typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
  8. typeof define === 'function' && define.amd ? define(factory) :
  9. (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Slide = factory());
  10. }(this, (function () { 'use strict';
  11. function warn(msg) {
  12. console.error("[BScroll warn]: " + msg);
  13. }
  14. // ssr support
  15. var inBrowser = typeof window !== 'undefined';
  16. var ua = inBrowser && navigator.userAgent.toLowerCase();
  17. !!(ua && /wechatdevtools/.test(ua));
  18. ua && ua.indexOf('android') > 0;
  19. /* istanbul ignore next */
  20. ((function () {
  21. if (typeof ua === 'string') {
  22. var regex = /os (\d\d?_\d(_\d)?)/;
  23. var matches = regex.exec(ua);
  24. if (!matches)
  25. return false;
  26. var parts = matches[1].split('_').map(function (item) {
  27. return parseInt(item, 10);
  28. });
  29. // ios version >= 13.4 issue 982
  30. return !!(parts[0] === 13 && parts[1] >= 4);
  31. }
  32. return false;
  33. }))();
  34. /* istanbul ignore next */
  35. var supportsPassive = false;
  36. /* istanbul ignore next */
  37. if (inBrowser) {
  38. var EventName = 'test-passive';
  39. try {
  40. var opts = {};
  41. Object.defineProperty(opts, 'passive', {
  42. get: function () {
  43. supportsPassive = true;
  44. },
  45. }); // https://github.com/facebook/flow/issues/285
  46. window.addEventListener(EventName, function () { }, opts);
  47. }
  48. catch (e) { }
  49. }
  50. var extend = function (target, source) {
  51. for (var key in source) {
  52. target[key] = source[key];
  53. }
  54. return target;
  55. };
  56. function between(x, min, max) {
  57. if (x < min) {
  58. return min;
  59. }
  60. if (x > max) {
  61. return max;
  62. }
  63. return x;
  64. }
  65. var elementStyle = (inBrowser &&
  66. document.createElement('div').style);
  67. var vendor = (function () {
  68. /* istanbul ignore if */
  69. if (!inBrowser) {
  70. return false;
  71. }
  72. var transformNames = [
  73. {
  74. key: 'standard',
  75. value: 'transform',
  76. },
  77. {
  78. key: 'webkit',
  79. value: 'webkitTransform',
  80. },
  81. {
  82. key: 'Moz',
  83. value: 'MozTransform',
  84. },
  85. {
  86. key: 'O',
  87. value: 'OTransform',
  88. },
  89. {
  90. key: 'ms',
  91. value: 'msTransform',
  92. },
  93. ];
  94. for (var _i = 0, transformNames_1 = transformNames; _i < transformNames_1.length; _i++) {
  95. var obj = transformNames_1[_i];
  96. if (elementStyle[obj.value] !== undefined) {
  97. return obj.key;
  98. }
  99. }
  100. /* istanbul ignore next */
  101. return false;
  102. })();
  103. /* istanbul ignore next */
  104. function prefixStyle(style) {
  105. if (vendor === false) {
  106. return style;
  107. }
  108. if (vendor === 'standard') {
  109. if (style === 'transitionEnd') {
  110. return 'transitionend';
  111. }
  112. return style;
  113. }
  114. return vendor + style.charAt(0).toUpperCase() + style.substr(1);
  115. }
  116. vendor && vendor !== 'standard' ? '-' + vendor.toLowerCase() + '-' : '';
  117. var transform = prefixStyle('transform');
  118. var transition = prefixStyle('transition');
  119. inBrowser && prefixStyle('perspective') in elementStyle;
  120. ({
  121. transform: transform,
  122. transition: transition,
  123. transitionTimingFunction: prefixStyle('transitionTimingFunction'),
  124. transitionDuration: prefixStyle('transitionDuration'),
  125. transitionDelay: prefixStyle('transitionDelay'),
  126. transformOrigin: prefixStyle('transformOrigin'),
  127. transitionEnd: prefixStyle('transitionEnd'),
  128. transitionProperty: prefixStyle('transitionProperty'),
  129. });
  130. function prepend(el, target) {
  131. var firstChild = target.firstChild;
  132. if (firstChild) {
  133. before(el, firstChild);
  134. }
  135. else {
  136. target.appendChild(el);
  137. }
  138. }
  139. function before(el, target) {
  140. var parentNode = target.parentNode;
  141. parentNode.insertBefore(el, target);
  142. }
  143. function removeChild(el, child) {
  144. el.removeChild(child);
  145. }
  146. var ease = {
  147. // easeOutQuint
  148. swipe: {
  149. style: 'cubic-bezier(0.23, 1, 0.32, 1)',
  150. fn: function (t) {
  151. return 1 + --t * t * t * t * t;
  152. }
  153. },
  154. // easeOutQuard
  155. swipeBounce: {
  156. style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
  157. fn: function (t) {
  158. return t * (2 - t);
  159. }
  160. },
  161. // easeOutQuart
  162. bounce: {
  163. style: 'cubic-bezier(0.165, 0.84, 0.44, 1)',
  164. fn: function (t) {
  165. return 1 - --t * t * t * t;
  166. }
  167. }
  168. };
  169. var PagesMatrix = /** @class */ (function () {
  170. function PagesMatrix(scroll) {
  171. this.scroll = scroll;
  172. this.init();
  173. }
  174. PagesMatrix.prototype.init = function () {
  175. var scroller = this.scroll.scroller;
  176. var scrollBehaviorX = scroller.scrollBehaviorX, scrollBehaviorY = scroller.scrollBehaviorY;
  177. this.wrapperWidth = scrollBehaviorX.wrapperSize;
  178. this.wrapperHeight = scrollBehaviorY.wrapperSize;
  179. this.scrollerHeight = scrollBehaviorY.contentSize;
  180. this.scrollerWidth = scrollBehaviorX.contentSize;
  181. this.pages = this.buildPagesMatrix(this.wrapperWidth, this.wrapperHeight);
  182. this.pageLengthOfX = this.pages ? this.pages.length : 0;
  183. this.pageLengthOfY = this.pages && this.pages[0] ? this.pages[0].length : 0;
  184. };
  185. PagesMatrix.prototype.getPageStats = function (pageX, pageY) {
  186. return this.pages[pageX][pageY];
  187. };
  188. PagesMatrix.prototype.getNearestPageIndex = function (x, y) {
  189. var pageX = 0;
  190. var pageY = 0;
  191. var l = this.pages.length;
  192. for (; pageX < l - 1; pageX++) {
  193. if (x >= this.pages[pageX][0].cx) {
  194. break;
  195. }
  196. }
  197. l = this.pages[pageX].length;
  198. for (; pageY < l - 1; pageY++) {
  199. if (y >= this.pages[0][pageY].cy) {
  200. break;
  201. }
  202. }
  203. return {
  204. pageX: pageX,
  205. pageY: pageY,
  206. };
  207. };
  208. // (n x 1) matrix for horizontal scroll or
  209. // (1 * n) matrix for vertical scroll
  210. PagesMatrix.prototype.buildPagesMatrix = function (stepX, stepY) {
  211. var pages = [];
  212. var x = 0;
  213. var y;
  214. var cx;
  215. var cy;
  216. var i = 0;
  217. var l;
  218. var maxScrollPosX = this.scroll.scroller.scrollBehaviorX.maxScrollPos;
  219. var maxScrollPosY = this.scroll.scroller.scrollBehaviorY.maxScrollPos;
  220. cx = Math.round(stepX / 2);
  221. cy = Math.round(stepY / 2);
  222. while (x > -this.scrollerWidth) {
  223. pages[i] = [];
  224. l = 0;
  225. y = 0;
  226. while (y > -this.scrollerHeight) {
  227. pages[i][l] = {
  228. x: Math.max(x, maxScrollPosX),
  229. y: Math.max(y, maxScrollPosY),
  230. width: stepX,
  231. height: stepY,
  232. cx: x - cx,
  233. cy: y - cy,
  234. };
  235. y -= stepY;
  236. l++;
  237. }
  238. x -= stepX;
  239. i++;
  240. }
  241. return pages;
  242. };
  243. return PagesMatrix;
  244. }());
  245. var BASE_PAGE = {
  246. pageX: 0,
  247. pageY: 0,
  248. x: 0,
  249. y: 0,
  250. };
  251. var SlidePages = /** @class */ (function () {
  252. function SlidePages(scroll, slideOptions) {
  253. this.scroll = scroll;
  254. this.slideOptions = slideOptions;
  255. this.slideX = false;
  256. this.slideY = false;
  257. this.currentPage = extend({}, BASE_PAGE);
  258. }
  259. SlidePages.prototype.refresh = function () {
  260. this.pagesMatrix = new PagesMatrix(this.scroll);
  261. this.checkSlideLoop();
  262. this.currentPage = this.getAdjustedCurrentPage();
  263. };
  264. SlidePages.prototype.getAdjustedCurrentPage = function () {
  265. var _a = this.currentPage, pageX = _a.pageX, pageY = _a.pageY;
  266. // page index should be handled
  267. // because page counts may reduce
  268. pageX = Math.min(pageX, this.pagesMatrix.pageLengthOfX - 1);
  269. pageY = Math.min(pageY, this.pagesMatrix.pageLengthOfY - 1);
  270. // loop scene should also be respected
  271. // because clonedNode will cause pageLength increasing
  272. if (this.loopX) {
  273. pageX = Math.min(pageX, this.pagesMatrix.pageLengthOfX - 2);
  274. }
  275. if (this.loopY) {
  276. pageY = Math.min(pageY, this.pagesMatrix.pageLengthOfY - 2);
  277. }
  278. var _b = this.pagesMatrix.getPageStats(pageX, pageY), x = _b.x, y = _b.y;
  279. return { pageX: pageX, pageY: pageY, x: x, y: y };
  280. };
  281. SlidePages.prototype.setCurrentPage = function (newPage) {
  282. this.currentPage = newPage;
  283. };
  284. SlidePages.prototype.getInternalPage = function (pageX, pageY) {
  285. if (pageX >= this.pagesMatrix.pageLengthOfX) {
  286. pageX = this.pagesMatrix.pageLengthOfX - 1;
  287. }
  288. else if (pageX < 0) {
  289. pageX = 0;
  290. }
  291. if (pageY >= this.pagesMatrix.pageLengthOfY) {
  292. pageY = this.pagesMatrix.pageLengthOfY - 1;
  293. }
  294. else if (pageY < 0) {
  295. pageY = 0;
  296. }
  297. var _a = this.pagesMatrix.getPageStats(pageX, pageY), x = _a.x, y = _a.y;
  298. return {
  299. pageX: pageX,
  300. pageY: pageY,
  301. x: x,
  302. y: y,
  303. };
  304. };
  305. SlidePages.prototype.getInitialPage = function (showFirstPage, firstInitialised) {
  306. if (showFirstPage === void 0) { showFirstPage = false; }
  307. if (firstInitialised === void 0) { firstInitialised = false; }
  308. var _a = this.slideOptions, startPageXIndex = _a.startPageXIndex, startPageYIndex = _a.startPageYIndex;
  309. var firstPageX = this.loopX ? 1 : 0;
  310. var firstPageY = this.loopY ? 1 : 0;
  311. var pageX = showFirstPage ? firstPageX : this.currentPage.pageX;
  312. var pageY = showFirstPage ? firstPageY : this.currentPage.pageY;
  313. if (firstInitialised) {
  314. pageX = this.loopX ? startPageXIndex + 1 : startPageXIndex;
  315. pageY = this.loopY ? startPageYIndex + 1 : startPageYIndex;
  316. }
  317. else {
  318. pageX = showFirstPage ? firstPageX : this.currentPage.pageX;
  319. pageY = showFirstPage ? firstPageY : this.currentPage.pageY;
  320. }
  321. var _b = this.pagesMatrix.getPageStats(pageX, pageY), x = _b.x, y = _b.y;
  322. return {
  323. pageX: pageX,
  324. pageY: pageY,
  325. x: x,
  326. y: y,
  327. };
  328. };
  329. SlidePages.prototype.getExposedPage = function (page) {
  330. var exposedPage = extend({}, page);
  331. // only pageX or pageY need fix
  332. if (this.loopX) {
  333. exposedPage.pageX = this.fixedPage(exposedPage.pageX, this.pagesMatrix.pageLengthOfX - 2);
  334. }
  335. if (this.loopY) {
  336. exposedPage.pageY = this.fixedPage(exposedPage.pageY, this.pagesMatrix.pageLengthOfY - 2);
  337. }
  338. return exposedPage;
  339. };
  340. SlidePages.prototype.getExposedPageByPageIndex = function (pageIndexX, pageIndexY) {
  341. var page = {
  342. pageX: pageIndexX,
  343. pageY: pageIndexY,
  344. };
  345. if (this.loopX) {
  346. page.pageX = pageIndexX + 1;
  347. }
  348. if (this.loopY) {
  349. page.pageY = pageIndexY + 1;
  350. }
  351. var _a = this.pagesMatrix.getPageStats(page.pageX, page.pageY), x = _a.x, y = _a.y;
  352. return {
  353. x: x,
  354. y: y,
  355. pageX: pageIndexX,
  356. pageY: pageIndexY,
  357. };
  358. };
  359. SlidePages.prototype.getWillChangedPage = function (page) {
  360. page = extend({}, page);
  361. // Page need fix
  362. if (this.loopX) {
  363. page.pageX = this.fixedPage(page.pageX, this.pagesMatrix.pageLengthOfX - 2);
  364. page.x = this.pagesMatrix.getPageStats(page.pageX + 1, 0).x;
  365. }
  366. if (this.loopY) {
  367. page.pageY = this.fixedPage(page.pageY, this.pagesMatrix.pageLengthOfY - 2);
  368. page.y = this.pagesMatrix.getPageStats(0, page.pageY + 1).y;
  369. }
  370. return page;
  371. };
  372. SlidePages.prototype.fixedPage = function (page, realPageLen) {
  373. var pageIndex = [];
  374. for (var i = 0; i < realPageLen; i++) {
  375. pageIndex.push(i);
  376. }
  377. pageIndex.unshift(realPageLen - 1);
  378. pageIndex.push(0);
  379. return pageIndex[page];
  380. };
  381. SlidePages.prototype.getPageStats = function () {
  382. return this.pagesMatrix.getPageStats(this.currentPage.pageX, this.currentPage.pageY);
  383. };
  384. SlidePages.prototype.getValidPageIndex = function (x, y) {
  385. var lastX = this.pagesMatrix.pageLengthOfX - 1;
  386. var lastY = this.pagesMatrix.pageLengthOfY - 1;
  387. var firstX = 0;
  388. var firstY = 0;
  389. if (this.loopX) {
  390. x += 1;
  391. firstX = firstX + 1;
  392. lastX = lastX - 1;
  393. }
  394. if (this.loopY) {
  395. y += 1;
  396. firstY = firstY + 1;
  397. lastY = lastY - 1;
  398. }
  399. x = between(x, firstX, lastX);
  400. y = between(y, firstY, lastY);
  401. return {
  402. pageX: x,
  403. pageY: y,
  404. };
  405. };
  406. SlidePages.prototype.nextPageIndex = function () {
  407. return this.getPageIndexByDirection("positive" /* Positive */);
  408. };
  409. SlidePages.prototype.prevPageIndex = function () {
  410. return this.getPageIndexByDirection("negative" /* Negative */);
  411. };
  412. SlidePages.prototype.getNearestPage = function (x, y) {
  413. var pageIndex = this.pagesMatrix.getNearestPageIndex(x, y);
  414. var pageX = pageIndex.pageX, pageY = pageIndex.pageY;
  415. var newX = this.pagesMatrix.getPageStats(pageX, 0).x;
  416. var newY = this.pagesMatrix.getPageStats(0, pageY).y;
  417. return {
  418. x: newX,
  419. y: newY,
  420. pageX: pageX,
  421. pageY: pageY,
  422. };
  423. };
  424. SlidePages.prototype.getPageByDirection = function (page, directionX, directionY) {
  425. var pageX = page.pageX, pageY = page.pageY;
  426. if (pageX === this.currentPage.pageX) {
  427. pageX = between(pageX + directionX, 0, this.pagesMatrix.pageLengthOfX - 1);
  428. }
  429. if (pageY === this.currentPage.pageY) {
  430. pageY = between(pageY + directionY, 0, this.pagesMatrix.pageLengthOfY - 1);
  431. }
  432. var x = this.pagesMatrix.getPageStats(pageX, 0).x;
  433. var y = this.pagesMatrix.getPageStats(0, pageY).y;
  434. return {
  435. x: x,
  436. y: y,
  437. pageX: pageX,
  438. pageY: pageY,
  439. };
  440. };
  441. SlidePages.prototype.resetLoopPage = function () {
  442. if (this.loopX) {
  443. if (this.currentPage.pageX === 0) {
  444. return {
  445. pageX: this.pagesMatrix.pageLengthOfX - 2,
  446. pageY: this.currentPage.pageY,
  447. };
  448. }
  449. if (this.currentPage.pageX === this.pagesMatrix.pageLengthOfX - 1) {
  450. return {
  451. pageX: 1,
  452. pageY: this.currentPage.pageY,
  453. };
  454. }
  455. }
  456. if (this.loopY) {
  457. if (this.currentPage.pageY === 0) {
  458. return {
  459. pageX: this.currentPage.pageX,
  460. pageY: this.pagesMatrix.pageLengthOfY - 2,
  461. };
  462. }
  463. if (this.currentPage.pageY === this.pagesMatrix.pageLengthOfY - 1) {
  464. return {
  465. pageX: this.currentPage.pageX,
  466. pageY: 1,
  467. };
  468. }
  469. }
  470. };
  471. SlidePages.prototype.getPageIndexByDirection = function (direction) {
  472. var x = this.currentPage.pageX;
  473. var y = this.currentPage.pageY;
  474. if (this.slideX) {
  475. x = direction === "negative" /* Negative */ ? x - 1 : x + 1;
  476. }
  477. if (this.slideY) {
  478. y = direction === "negative" /* Negative */ ? y - 1 : y + 1;
  479. }
  480. return {
  481. pageX: x,
  482. pageY: y,
  483. };
  484. };
  485. SlidePages.prototype.checkSlideLoop = function () {
  486. this.wannaLoop = this.slideOptions.loop;
  487. if (this.pagesMatrix.pageLengthOfX > 1) {
  488. this.slideX = true;
  489. }
  490. else {
  491. this.slideX = false;
  492. }
  493. if (this.pagesMatrix.pages[0] && this.pagesMatrix.pageLengthOfY > 1) {
  494. this.slideY = true;
  495. }
  496. else {
  497. this.slideY = false;
  498. }
  499. this.loopX = this.wannaLoop && this.slideX;
  500. this.loopY = this.wannaLoop && this.slideY;
  501. if (this.slideX && this.slideY) {
  502. warn('slide does not support two direction at the same time.');
  503. }
  504. };
  505. return SlidePages;
  506. }());
  507. var sourcePrefix = 'plugins.slide';
  508. var propertiesMap = [
  509. {
  510. key: 'next',
  511. name: 'next',
  512. },
  513. {
  514. key: 'prev',
  515. name: 'prev',
  516. },
  517. {
  518. key: 'goToPage',
  519. name: 'goToPage',
  520. },
  521. {
  522. key: 'getCurrentPage',
  523. name: 'getCurrentPage',
  524. },
  525. {
  526. key: 'startPlay',
  527. name: 'startPlay',
  528. },
  529. {
  530. key: 'pausePlay',
  531. name: 'pausePlay',
  532. },
  533. ];
  534. var propertiesConfig = propertiesMap.map(function (item) {
  535. return {
  536. key: item.key,
  537. sourceKey: sourcePrefix + "." + item.name,
  538. };
  539. });
  540. var samePage = function (p1, p2) {
  541. return p1.pageX === p2.pageX && p1.pageY === p2.pageY;
  542. };
  543. var Slide = /** @class */ (function () {
  544. function Slide(scroll) {
  545. this.scroll = scroll;
  546. this.cachedClonedPageDOM = [];
  547. this.resetLooping = false;
  548. this.autoplayTimer = 0;
  549. if (!this.satisfyInitialization()) {
  550. return;
  551. }
  552. this.init();
  553. }
  554. Slide.prototype.satisfyInitialization = function () {
  555. if (this.scroll.scroller.content.children.length <= 0) {
  556. warn("slide need at least one slide page to be initialised." +
  557. "please check your DOM layout.");
  558. return false;
  559. }
  560. return true;
  561. };
  562. Slide.prototype.init = function () {
  563. this.willChangeToPage = extend({}, BASE_PAGE);
  564. this.handleBScroll();
  565. this.handleOptions();
  566. this.handleHooks();
  567. this.createPages();
  568. };
  569. Slide.prototype.createPages = function () {
  570. this.pages = new SlidePages(this.scroll, this.options);
  571. };
  572. Slide.prototype.handleBScroll = function () {
  573. this.scroll.registerType(['slideWillChange', 'slidePageChanged']);
  574. this.scroll.proxy(propertiesConfig);
  575. };
  576. Slide.prototype.handleOptions = function () {
  577. var userOptions = (this.scroll.options.slide === true
  578. ? {}
  579. : this.scroll.options.slide);
  580. var defaultOptions = {
  581. loop: true,
  582. threshold: 0.1,
  583. speed: 400,
  584. easing: ease.bounce,
  585. listenFlick: true,
  586. autoplay: true,
  587. interval: 3000,
  588. startPageXIndex: 0,
  589. startPageYIndex: 0,
  590. };
  591. this.options = extend(defaultOptions, userOptions);
  592. };
  593. Slide.prototype.handleLoop = function (prevSlideContent) {
  594. var loop = this.options.loop;
  595. var slideContent = this.scroll.scroller.content;
  596. var currentSlidePagesLength = slideContent.children.length;
  597. // only should respect loop scene
  598. if (loop) {
  599. if (slideContent !== prevSlideContent) {
  600. this.resetLoopChangedStatus();
  601. this.removeClonedSlidePage(prevSlideContent);
  602. currentSlidePagesLength > 1 &&
  603. this.cloneFirstAndLastSlidePage(slideContent);
  604. }
  605. else {
  606. // many pages reduce to one page
  607. if (currentSlidePagesLength === 3 && this.initialised) {
  608. this.removeClonedSlidePage(slideContent);
  609. this.moreToOnePageInLoop = true;
  610. this.oneToMorePagesInLoop = false;
  611. }
  612. else if (currentSlidePagesLength > 1) {
  613. // one page increases to many page
  614. if (this.initialised && this.cachedClonedPageDOM.length === 0) {
  615. this.oneToMorePagesInLoop = true;
  616. this.moreToOnePageInLoop = false;
  617. }
  618. else {
  619. this.removeClonedSlidePage(slideContent);
  620. this.resetLoopChangedStatus();
  621. }
  622. this.cloneFirstAndLastSlidePage(slideContent);
  623. }
  624. else {
  625. this.resetLoopChangedStatus();
  626. }
  627. }
  628. }
  629. };
  630. Slide.prototype.resetLoopChangedStatus = function () {
  631. this.moreToOnePageInLoop = false;
  632. this.oneToMorePagesInLoop = false;
  633. };
  634. Slide.prototype.handleHooks = function () {
  635. var _this = this;
  636. var scrollHooks = this.scroll.hooks;
  637. var scrollerHooks = this.scroll.scroller.hooks;
  638. var listenFlick = this.options.listenFlick;
  639. this.prevContent = this.scroll.scroller.content;
  640. this.hooksFn = [];
  641. // scroll
  642. this.registerHooks(this.scroll, this.scroll.eventTypes.beforeScrollStart, this.pausePlay);
  643. this.registerHooks(this.scroll, this.scroll.eventTypes.scrollEnd, this.modifyCurrentPage);
  644. this.registerHooks(this.scroll, this.scroll.eventTypes.scrollEnd, this.startPlay);
  645. // for mousewheel event
  646. if (this.scroll.eventTypes.mousewheelMove) {
  647. this.registerHooks(this.scroll, this.scroll.eventTypes.mousewheelMove, function () {
  648. // prevent default action of mousewheelMove
  649. return true;
  650. });
  651. this.registerHooks(this.scroll, this.scroll.eventTypes.mousewheelEnd, function (delta) {
  652. if (delta.directionX === 1 /* Positive */ ||
  653. delta.directionY === 1 /* Positive */) {
  654. _this.next();
  655. }
  656. if (delta.directionX === -1 /* Negative */ ||
  657. delta.directionY === -1 /* Negative */) {
  658. _this.prev();
  659. }
  660. });
  661. }
  662. // scrollHooks
  663. this.registerHooks(scrollHooks, scrollHooks.eventTypes.refresh, this.refreshHandler);
  664. this.registerHooks(scrollHooks, scrollHooks.eventTypes.destroy, this.destroy);
  665. // scroller
  666. this.registerHooks(scrollerHooks, scrollerHooks.eventTypes.beforeRefresh, function () {
  667. _this.handleLoop(_this.prevContent);
  668. _this.setSlideInlineStyle();
  669. });
  670. this.registerHooks(scrollerHooks, scrollerHooks.eventTypes.momentum, this.modifyScrollMetaHandler);
  671. this.registerHooks(scrollerHooks, scrollerHooks.eventTypes.scroll, this.scrollHandler);
  672. // a click operation will clearTimer, so restart a new one
  673. this.registerHooks(scrollerHooks, scrollerHooks.eventTypes.checkClick, this.startPlay);
  674. if (listenFlick) {
  675. this.registerHooks(scrollerHooks, scrollerHooks.eventTypes.flick, this.flickHandler);
  676. }
  677. };
  678. Slide.prototype.startPlay = function () {
  679. var _this = this;
  680. var _a = this.options, interval = _a.interval, autoplay = _a.autoplay;
  681. if (autoplay) {
  682. clearTimeout(this.autoplayTimer);
  683. this.autoplayTimer = window.setTimeout(function () {
  684. _this.next();
  685. }, interval);
  686. }
  687. };
  688. Slide.prototype.pausePlay = function () {
  689. if (this.options.autoplay) {
  690. clearTimeout(this.autoplayTimer);
  691. }
  692. };
  693. Slide.prototype.setSlideInlineStyle = function () {
  694. var styleConfigurations = [
  695. {
  696. direction: 'scrollX',
  697. sizeType: 'offsetWidth',
  698. styleType: 'width',
  699. },
  700. {
  701. direction: 'scrollY',
  702. sizeType: 'offsetHeight',
  703. styleType: 'height',
  704. },
  705. ];
  706. var _a = this.scroll.scroller, slideContent = _a.content, slideWrapper = _a.wrapper;
  707. var scrollOptions = this.scroll.options;
  708. styleConfigurations.forEach(function (_a) {
  709. var direction = _a.direction, sizeType = _a.sizeType, styleType = _a.styleType;
  710. // wanna scroll in this direction
  711. if (scrollOptions[direction]) {
  712. var size = slideWrapper[sizeType];
  713. var children = slideContent.children;
  714. var length_1 = children.length;
  715. for (var i = 0; i < length_1; i++) {
  716. var slidePageDOM = children[i];
  717. slidePageDOM.style[styleType] = size + 'px';
  718. }
  719. slideContent.style[styleType] = size * length_1 + 'px';
  720. }
  721. });
  722. };
  723. Slide.prototype.next = function (time, easing) {
  724. var _a = this.pages.nextPageIndex(), pageX = _a.pageX, pageY = _a.pageY;
  725. this.goTo(pageX, pageY, time, easing);
  726. };
  727. Slide.prototype.prev = function (time, easing) {
  728. var _a = this.pages.prevPageIndex(), pageX = _a.pageX, pageY = _a.pageY;
  729. this.goTo(pageX, pageY, time, easing);
  730. };
  731. Slide.prototype.goToPage = function (pageX, pageY, time, easing) {
  732. var pageIndex = this.pages.getValidPageIndex(pageX, pageY);
  733. this.goTo(pageIndex.pageX, pageIndex.pageY, time, easing);
  734. };
  735. Slide.prototype.getCurrentPage = function () {
  736. return this.exposedPage || this.pages.getInitialPage(false, true);
  737. };
  738. Slide.prototype.setCurrentPage = function (page) {
  739. this.pages.setCurrentPage(page);
  740. this.exposedPage = this.pages.getExposedPage(page);
  741. };
  742. Slide.prototype.nearestPage = function (x, y) {
  743. var _a = this.scroll.scroller, scrollBehaviorX = _a.scrollBehaviorX, scrollBehaviorY = _a.scrollBehaviorY;
  744. var maxScrollPosX = scrollBehaviorX.maxScrollPos, minScrollPosX = scrollBehaviorX.minScrollPos;
  745. var maxScrollPosY = scrollBehaviorY.maxScrollPos, minScrollPosY = scrollBehaviorY.minScrollPos;
  746. return this.pages.getNearestPage(between(x, maxScrollPosX, minScrollPosX), between(y, maxScrollPosY, minScrollPosY));
  747. };
  748. Slide.prototype.satisfyThreshold = function (x, y) {
  749. var _a = this.scroll.scroller, scrollBehaviorX = _a.scrollBehaviorX, scrollBehaviorY = _a.scrollBehaviorY;
  750. var satisfied = true;
  751. if (Math.abs(x - scrollBehaviorX.absStartPos) <= this.thresholdX &&
  752. Math.abs(y - scrollBehaviorY.absStartPos) <= this.thresholdY) {
  753. satisfied = false;
  754. }
  755. return satisfied;
  756. };
  757. Slide.prototype.refreshHandler = function (content) {
  758. var _this = this;
  759. if (!this.satisfyInitialization()) {
  760. return;
  761. }
  762. this.pages.refresh();
  763. this.computeThreshold();
  764. var contentChanged = (this.contentChanged = this.prevContent !== content);
  765. if (contentChanged) {
  766. this.prevContent = content;
  767. }
  768. var initPage = this.pages.getInitialPage(this.oneToMorePagesInLoop || this.moreToOnePageInLoop, contentChanged || !this.initialised);
  769. if (this.initialised) {
  770. this.goTo(initPage.pageX, initPage.pageY, 0);
  771. }
  772. else {
  773. this.registerHooks(this.scroll.hooks, this.scroll.hooks.eventTypes.beforeInitialScrollTo, function (position) {
  774. _this.initialised = true;
  775. position.x = initPage.x;
  776. position.y = initPage.y;
  777. });
  778. }
  779. this.startPlay();
  780. };
  781. Slide.prototype.computeThreshold = function () {
  782. var threshold = this.options.threshold;
  783. // Integer
  784. if (threshold % 1 === 0) {
  785. this.thresholdX = threshold;
  786. this.thresholdY = threshold;
  787. }
  788. else {
  789. // decimal
  790. var _a = this.pages.getPageStats(), width = _a.width, height = _a.height;
  791. this.thresholdX = Math.round(width * threshold);
  792. this.thresholdY = Math.round(height * threshold);
  793. }
  794. };
  795. Slide.prototype.cloneFirstAndLastSlidePage = function (slideContent) {
  796. var children = slideContent.children;
  797. var preprendDOM = children[children.length - 1].cloneNode(true);
  798. var appendDOM = children[0].cloneNode(true);
  799. prepend(preprendDOM, slideContent);
  800. slideContent.appendChild(appendDOM);
  801. this.cachedClonedPageDOM = [preprendDOM, appendDOM];
  802. };
  803. Slide.prototype.removeClonedSlidePage = function (slideContent) {
  804. // maybe slideContent has removed from DOM Tree
  805. var slidePages = (slideContent && slideContent.children) || [];
  806. if (slidePages.length) {
  807. this.cachedClonedPageDOM.forEach(function (el) {
  808. removeChild(slideContent, el);
  809. });
  810. }
  811. this.cachedClonedPageDOM = [];
  812. };
  813. Slide.prototype.modifyCurrentPage = function (point) {
  814. var _a = this.getCurrentPage(), prevExposedPageX = _a.pageX, prevExposedPageY = _a.pageY;
  815. var newPage = this.nearestPage(point.x, point.y);
  816. this.setCurrentPage(newPage);
  817. /* istanbul ignore if */
  818. if (this.contentChanged) {
  819. this.contentChanged = false;
  820. return true;
  821. }
  822. var _b = this.getCurrentPage(), currentExposedPageX = _b.pageX, currentExposedPageY = _b.pageY;
  823. this.pageWillChangeTo(newPage);
  824. // loop is true, and one page becomes many pages when call bs.refresh
  825. if (this.oneToMorePagesInLoop) {
  826. this.oneToMorePagesInLoop = false;
  827. return true;
  828. }
  829. // loop is true, and many page becomes one page when call bs.refresh
  830. // if prevPage > 0, dispatch slidePageChanged and scrollEnd events
  831. /* istanbul ignore if */
  832. if (this.moreToOnePageInLoop &&
  833. prevExposedPageX === 0 &&
  834. prevExposedPageY === 0) {
  835. this.moreToOnePageInLoop = false;
  836. return true;
  837. }
  838. if (prevExposedPageX !== currentExposedPageX ||
  839. prevExposedPageY !== currentExposedPageY) {
  840. // only trust pageX & pageY when loop is true
  841. var page = this.pages.getExposedPageByPageIndex(currentExposedPageX, currentExposedPageY);
  842. this.scroll.trigger(this.scroll.eventTypes.slidePageChanged, page);
  843. }
  844. // triggered by resetLoop
  845. if (this.resetLooping) {
  846. this.resetLooping = false;
  847. return;
  848. }
  849. var changePage = this.pages.resetLoopPage();
  850. if (changePage) {
  851. this.resetLooping = true;
  852. this.goTo(changePage.pageX, changePage.pageY, 0);
  853. // stop user's scrollEnd
  854. // since it is a seamless scroll
  855. return true;
  856. }
  857. };
  858. Slide.prototype.goTo = function (pageX, pageY, time, easing) {
  859. var newPage = this.pages.getInternalPage(pageX, pageY);
  860. var scrollEasing = easing || this.options.easing || ease.bounce;
  861. var x = newPage.x, y = newPage.y;
  862. var deltaX = x - this.scroll.scroller.scrollBehaviorX.currentPos;
  863. var deltaY = y - this.scroll.scroller.scrollBehaviorY.currentPos;
  864. /* istanbul ignore if */
  865. if (!deltaX && !deltaY) {
  866. this.scroll.scroller.togglePointerEvents(true);
  867. return;
  868. }
  869. time = time === undefined ? this.getEaseTime(deltaX, deltaY) : time;
  870. this.scroll.scroller.scrollTo(x, y, time, scrollEasing);
  871. };
  872. Slide.prototype.flickHandler = function () {
  873. var _a = this.scroll.scroller, scrollBehaviorX = _a.scrollBehaviorX, scrollBehaviorY = _a.scrollBehaviorY;
  874. var currentPosX = scrollBehaviorX.currentPos, startPosX = scrollBehaviorX.startPos, directionX = scrollBehaviorX.direction;
  875. var currentPosY = scrollBehaviorY.currentPos, startPosY = scrollBehaviorY.startPos, directionY = scrollBehaviorY.direction;
  876. var _b = this.pages.currentPage, pageX = _b.pageX, pageY = _b.pageY;
  877. var time = this.getEaseTime(currentPosX - startPosX, currentPosY - startPosY);
  878. this.goTo(pageX + directionX, pageY + directionY, time);
  879. };
  880. Slide.prototype.getEaseTime = function (deltaX, deltaY) {
  881. return (this.options.speed ||
  882. Math.max(Math.max(Math.min(Math.abs(deltaX), 1000), Math.min(Math.abs(deltaY), 1000)), 300));
  883. };
  884. Slide.prototype.modifyScrollMetaHandler = function (scrollMeta) {
  885. var _a = this.scroll.scroller, scrollBehaviorX = _a.scrollBehaviorX, scrollBehaviorY = _a.scrollBehaviorY, animater = _a.animater;
  886. var newX = scrollMeta.newX;
  887. var newY = scrollMeta.newY;
  888. var newPage = this.satisfyThreshold(newX, newY) || animater.forceStopped
  889. ? this.pages.getPageByDirection(this.nearestPage(newX, newY), scrollBehaviorX.direction, scrollBehaviorY.direction)
  890. : this.pages.currentPage;
  891. scrollMeta.time = this.getEaseTime(scrollMeta.newX - newPage.x, scrollMeta.newY - newPage.y);
  892. scrollMeta.newX = newPage.x;
  893. scrollMeta.newY = newPage.y;
  894. scrollMeta.easing = this.options.easing || ease.bounce;
  895. };
  896. Slide.prototype.scrollHandler = function (_a) {
  897. var x = _a.x, y = _a.y;
  898. if (this.satisfyThreshold(x, y)) {
  899. var newPage = this.nearestPage(x, y);
  900. this.pageWillChangeTo(newPage);
  901. }
  902. };
  903. Slide.prototype.pageWillChangeTo = function (newPage) {
  904. var changeToPage = this.pages.getWillChangedPage(newPage);
  905. if (!samePage(this.willChangeToPage, changeToPage)) {
  906. this.willChangeToPage = changeToPage;
  907. this.scroll.trigger(this.scroll.eventTypes.slideWillChange, this.willChangeToPage);
  908. }
  909. };
  910. Slide.prototype.registerHooks = function (hooks, name, handler) {
  911. hooks.on(name, handler, this);
  912. this.hooksFn.push([hooks, name, handler]);
  913. };
  914. Slide.prototype.destroy = function () {
  915. var slideContent = this.scroll.scroller.content;
  916. var _a = this.options, loop = _a.loop, autoplay = _a.autoplay;
  917. if (loop) {
  918. this.removeClonedSlidePage(slideContent);
  919. }
  920. if (autoplay) {
  921. clearTimeout(this.autoplayTimer);
  922. }
  923. this.hooksFn.forEach(function (item) {
  924. var hooks = item[0];
  925. var hooksName = item[1];
  926. var handlerFn = item[2];
  927. if (hooks.eventTypes[hooksName]) {
  928. hooks.off(hooksName, handlerFn);
  929. }
  930. });
  931. this.hooksFn.length = 0;
  932. };
  933. Slide.pluginName = 'slide';
  934. return Slide;
  935. }());
  936. return Slide;
  937. })));