carousel.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  1. /*!
  2. * Bootstrap carousel.js v4.5.2 (https://getbootstrap.com/)
  3. * Copyright 2011-2020 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
  4. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
  5. */
  6. (function (global, factory) {
  7. typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('./util.js')) :
  8. typeof define === 'function' && define.amd ? define(['jquery', './util.js'], factory) :
  9. (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Carousel = factory(global.jQuery, global.Util));
  10. }(this, (function ($, Util) { 'use strict';
  11. $ = $ && Object.prototype.hasOwnProperty.call($, 'default') ? $['default'] : $;
  12. Util = Util && Object.prototype.hasOwnProperty.call(Util, 'default') ? Util['default'] : Util;
  13. function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
  14. function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
  15. function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
  16. /**
  17. * ------------------------------------------------------------------------
  18. * Constants
  19. * ------------------------------------------------------------------------
  20. */
  21. var NAME = 'carousel';
  22. var VERSION = '4.5.2';
  23. var DATA_KEY = 'bs.carousel';
  24. var EVENT_KEY = "." + DATA_KEY;
  25. var DATA_API_KEY = '.data-api';
  26. var JQUERY_NO_CONFLICT = $.fn[NAME];
  27. var ARROW_LEFT_KEYCODE = 37; // KeyboardEvent.which value for left arrow key
  28. var ARROW_RIGHT_KEYCODE = 39; // KeyboardEvent.which value for right arrow key
  29. var TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch
  30. var SWIPE_THRESHOLD = 40;
  31. var Default = {
  32. interval: 5000,
  33. keyboard: true,
  34. slide: false,
  35. pause: 'hover',
  36. wrap: true,
  37. touch: true
  38. };
  39. var DefaultType = {
  40. interval: '(number|boolean)',
  41. keyboard: 'boolean',
  42. slide: '(boolean|string)',
  43. pause: '(string|boolean)',
  44. wrap: 'boolean',
  45. touch: 'boolean'
  46. };
  47. var DIRECTION_NEXT = 'next';
  48. var DIRECTION_PREV = 'prev';
  49. var DIRECTION_LEFT = 'left';
  50. var DIRECTION_RIGHT = 'right';
  51. var EVENT_SLIDE = "slide" + EVENT_KEY;
  52. var EVENT_SLID = "slid" + EVENT_KEY;
  53. var EVENT_KEYDOWN = "keydown" + EVENT_KEY;
  54. var EVENT_MOUSEENTER = "mouseenter" + EVENT_KEY;
  55. var EVENT_MOUSELEAVE = "mouseleave" + EVENT_KEY;
  56. var EVENT_TOUCHSTART = "touchstart" + EVENT_KEY;
  57. var EVENT_TOUCHMOVE = "touchmove" + EVENT_KEY;
  58. var EVENT_TOUCHEND = "touchend" + EVENT_KEY;
  59. var EVENT_POINTERDOWN = "pointerdown" + EVENT_KEY;
  60. var EVENT_POINTERUP = "pointerup" + EVENT_KEY;
  61. var EVENT_DRAG_START = "dragstart" + EVENT_KEY;
  62. var EVENT_LOAD_DATA_API = "load" + EVENT_KEY + DATA_API_KEY;
  63. var EVENT_CLICK_DATA_API = "click" + EVENT_KEY + DATA_API_KEY;
  64. var CLASS_NAME_CAROUSEL = 'carousel';
  65. var CLASS_NAME_ACTIVE = 'active';
  66. var CLASS_NAME_SLIDE = 'slide';
  67. var CLASS_NAME_RIGHT = 'carousel-item-right';
  68. var CLASS_NAME_LEFT = 'carousel-item-left';
  69. var CLASS_NAME_NEXT = 'carousel-item-next';
  70. var CLASS_NAME_PREV = 'carousel-item-prev';
  71. var CLASS_NAME_POINTER_EVENT = 'pointer-event';
  72. var SELECTOR_ACTIVE = '.active';
  73. var SELECTOR_ACTIVE_ITEM = '.active.carousel-item';
  74. var SELECTOR_ITEM = '.carousel-item';
  75. var SELECTOR_ITEM_IMG = '.carousel-item img';
  76. var SELECTOR_NEXT_PREV = '.carousel-item-next, .carousel-item-prev';
  77. var SELECTOR_INDICATORS = '.carousel-indicators';
  78. var SELECTOR_DATA_SLIDE = '[data-slide], [data-slide-to]';
  79. var SELECTOR_DATA_RIDE = '[data-ride="carousel"]';
  80. var PointerType = {
  81. TOUCH: 'touch',
  82. PEN: 'pen'
  83. };
  84. /**
  85. * ------------------------------------------------------------------------
  86. * Class Definition
  87. * ------------------------------------------------------------------------
  88. */
  89. var Carousel = /*#__PURE__*/function () {
  90. function Carousel(element, config) {
  91. this._items = null;
  92. this._interval = null;
  93. this._activeElement = null;
  94. this._isPaused = false;
  95. this._isSliding = false;
  96. this.touchTimeout = null;
  97. this.touchStartX = 0;
  98. this.touchDeltaX = 0;
  99. this._config = this._getConfig(config);
  100. this._element = element;
  101. this._indicatorsElement = this._element.querySelector(SELECTOR_INDICATORS);
  102. this._touchSupported = 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0;
  103. this._pointerEvent = Boolean(window.PointerEvent || window.MSPointerEvent);
  104. this._addEventListeners();
  105. } // Getters
  106. var _proto = Carousel.prototype;
  107. // Public
  108. _proto.next = function next() {
  109. if (!this._isSliding) {
  110. this._slide(DIRECTION_NEXT);
  111. }
  112. };
  113. _proto.nextWhenVisible = function nextWhenVisible() {
  114. // Don't call next when the page isn't visible
  115. // or the carousel or its parent isn't visible
  116. if (!document.hidden && $(this._element).is(':visible') && $(this._element).css('visibility') !== 'hidden') {
  117. this.next();
  118. }
  119. };
  120. _proto.prev = function prev() {
  121. if (!this._isSliding) {
  122. this._slide(DIRECTION_PREV);
  123. }
  124. };
  125. _proto.pause = function pause(event) {
  126. if (!event) {
  127. this._isPaused = true;
  128. }
  129. if (this._element.querySelector(SELECTOR_NEXT_PREV)) {
  130. Util.triggerTransitionEnd(this._element);
  131. this.cycle(true);
  132. }
  133. clearInterval(this._interval);
  134. this._interval = null;
  135. };
  136. _proto.cycle = function cycle(event) {
  137. if (!event) {
  138. this._isPaused = false;
  139. }
  140. if (this._interval) {
  141. clearInterval(this._interval);
  142. this._interval = null;
  143. }
  144. if (this._config.interval && !this._isPaused) {
  145. this._interval = setInterval((document.visibilityState ? this.nextWhenVisible : this.next).bind(this), this._config.interval);
  146. }
  147. };
  148. _proto.to = function to(index) {
  149. var _this = this;
  150. this._activeElement = this._element.querySelector(SELECTOR_ACTIVE_ITEM);
  151. var activeIndex = this._getItemIndex(this._activeElement);
  152. if (index > this._items.length - 1 || index < 0) {
  153. return;
  154. }
  155. if (this._isSliding) {
  156. $(this._element).one(EVENT_SLID, function () {
  157. return _this.to(index);
  158. });
  159. return;
  160. }
  161. if (activeIndex === index) {
  162. this.pause();
  163. this.cycle();
  164. return;
  165. }
  166. var direction = index > activeIndex ? DIRECTION_NEXT : DIRECTION_PREV;
  167. this._slide(direction, this._items[index]);
  168. };
  169. _proto.dispose = function dispose() {
  170. $(this._element).off(EVENT_KEY);
  171. $.removeData(this._element, DATA_KEY);
  172. this._items = null;
  173. this._config = null;
  174. this._element = null;
  175. this._interval = null;
  176. this._isPaused = null;
  177. this._isSliding = null;
  178. this._activeElement = null;
  179. this._indicatorsElement = null;
  180. } // Private
  181. ;
  182. _proto._getConfig = function _getConfig(config) {
  183. config = _extends({}, Default, config);
  184. Util.typeCheckConfig(NAME, config, DefaultType);
  185. return config;
  186. };
  187. _proto._handleSwipe = function _handleSwipe() {
  188. var absDeltax = Math.abs(this.touchDeltaX);
  189. if (absDeltax <= SWIPE_THRESHOLD) {
  190. return;
  191. }
  192. var direction = absDeltax / this.touchDeltaX;
  193. this.touchDeltaX = 0; // swipe left
  194. if (direction > 0) {
  195. this.prev();
  196. } // swipe right
  197. if (direction < 0) {
  198. this.next();
  199. }
  200. };
  201. _proto._addEventListeners = function _addEventListeners() {
  202. var _this2 = this;
  203. if (this._config.keyboard) {
  204. $(this._element).on(EVENT_KEYDOWN, function (event) {
  205. return _this2._keydown(event);
  206. });
  207. }
  208. if (this._config.pause === 'hover') {
  209. $(this._element).on(EVENT_MOUSEENTER, function (event) {
  210. return _this2.pause(event);
  211. }).on(EVENT_MOUSELEAVE, function (event) {
  212. return _this2.cycle(event);
  213. });
  214. }
  215. if (this._config.touch) {
  216. this._addTouchEventListeners();
  217. }
  218. };
  219. _proto._addTouchEventListeners = function _addTouchEventListeners() {
  220. var _this3 = this;
  221. if (!this._touchSupported) {
  222. return;
  223. }
  224. var start = function start(event) {
  225. if (_this3._pointerEvent && PointerType[event.originalEvent.pointerType.toUpperCase()]) {
  226. _this3.touchStartX = event.originalEvent.clientX;
  227. } else if (!_this3._pointerEvent) {
  228. _this3.touchStartX = event.originalEvent.touches[0].clientX;
  229. }
  230. };
  231. var move = function move(event) {
  232. // ensure swiping with one touch and not pinching
  233. if (event.originalEvent.touches && event.originalEvent.touches.length > 1) {
  234. _this3.touchDeltaX = 0;
  235. } else {
  236. _this3.touchDeltaX = event.originalEvent.touches[0].clientX - _this3.touchStartX;
  237. }
  238. };
  239. var end = function end(event) {
  240. if (_this3._pointerEvent && PointerType[event.originalEvent.pointerType.toUpperCase()]) {
  241. _this3.touchDeltaX = event.originalEvent.clientX - _this3.touchStartX;
  242. }
  243. _this3._handleSwipe();
  244. if (_this3._config.pause === 'hover') {
  245. // If it's a touch-enabled device, mouseenter/leave are fired as
  246. // part of the mouse compatibility events on first tap - the carousel
  247. // would stop cycling until user tapped out of it;
  248. // here, we listen for touchend, explicitly pause the carousel
  249. // (as if it's the second time we tap on it, mouseenter compat event
  250. // is NOT fired) and after a timeout (to allow for mouse compatibility
  251. // events to fire) we explicitly restart cycling
  252. _this3.pause();
  253. if (_this3.touchTimeout) {
  254. clearTimeout(_this3.touchTimeout);
  255. }
  256. _this3.touchTimeout = setTimeout(function (event) {
  257. return _this3.cycle(event);
  258. }, TOUCHEVENT_COMPAT_WAIT + _this3._config.interval);
  259. }
  260. };
  261. $(this._element.querySelectorAll(SELECTOR_ITEM_IMG)).on(EVENT_DRAG_START, function (e) {
  262. return e.preventDefault();
  263. });
  264. if (this._pointerEvent) {
  265. $(this._element).on(EVENT_POINTERDOWN, function (event) {
  266. return start(event);
  267. });
  268. $(this._element).on(EVENT_POINTERUP, function (event) {
  269. return end(event);
  270. });
  271. this._element.classList.add(CLASS_NAME_POINTER_EVENT);
  272. } else {
  273. $(this._element).on(EVENT_TOUCHSTART, function (event) {
  274. return start(event);
  275. });
  276. $(this._element).on(EVENT_TOUCHMOVE, function (event) {
  277. return move(event);
  278. });
  279. $(this._element).on(EVENT_TOUCHEND, function (event) {
  280. return end(event);
  281. });
  282. }
  283. };
  284. _proto._keydown = function _keydown(event) {
  285. if (/input|textarea/i.test(event.target.tagName)) {
  286. return;
  287. }
  288. switch (event.which) {
  289. case ARROW_LEFT_KEYCODE:
  290. event.preventDefault();
  291. this.prev();
  292. break;
  293. case ARROW_RIGHT_KEYCODE:
  294. event.preventDefault();
  295. this.next();
  296. break;
  297. }
  298. };
  299. _proto._getItemIndex = function _getItemIndex(element) {
  300. this._items = element && element.parentNode ? [].slice.call(element.parentNode.querySelectorAll(SELECTOR_ITEM)) : [];
  301. return this._items.indexOf(element);
  302. };
  303. _proto._getItemByDirection = function _getItemByDirection(direction, activeElement) {
  304. var isNextDirection = direction === DIRECTION_NEXT;
  305. var isPrevDirection = direction === DIRECTION_PREV;
  306. var activeIndex = this._getItemIndex(activeElement);
  307. var lastItemIndex = this._items.length - 1;
  308. var isGoingToWrap = isPrevDirection && activeIndex === 0 || isNextDirection && activeIndex === lastItemIndex;
  309. if (isGoingToWrap && !this._config.wrap) {
  310. return activeElement;
  311. }
  312. var delta = direction === DIRECTION_PREV ? -1 : 1;
  313. var itemIndex = (activeIndex + delta) % this._items.length;
  314. return itemIndex === -1 ? this._items[this._items.length - 1] : this._items[itemIndex];
  315. };
  316. _proto._triggerSlideEvent = function _triggerSlideEvent(relatedTarget, eventDirectionName) {
  317. var targetIndex = this._getItemIndex(relatedTarget);
  318. var fromIndex = this._getItemIndex(this._element.querySelector(SELECTOR_ACTIVE_ITEM));
  319. var slideEvent = $.Event(EVENT_SLIDE, {
  320. relatedTarget: relatedTarget,
  321. direction: eventDirectionName,
  322. from: fromIndex,
  323. to: targetIndex
  324. });
  325. $(this._element).trigger(slideEvent);
  326. return slideEvent;
  327. };
  328. _proto._setActiveIndicatorElement = function _setActiveIndicatorElement(element) {
  329. if (this._indicatorsElement) {
  330. var indicators = [].slice.call(this._indicatorsElement.querySelectorAll(SELECTOR_ACTIVE));
  331. $(indicators).removeClass(CLASS_NAME_ACTIVE);
  332. var nextIndicator = this._indicatorsElement.children[this._getItemIndex(element)];
  333. if (nextIndicator) {
  334. $(nextIndicator).addClass(CLASS_NAME_ACTIVE);
  335. }
  336. }
  337. };
  338. _proto._slide = function _slide(direction, element) {
  339. var _this4 = this;
  340. var activeElement = this._element.querySelector(SELECTOR_ACTIVE_ITEM);
  341. var activeElementIndex = this._getItemIndex(activeElement);
  342. var nextElement = element || activeElement && this._getItemByDirection(direction, activeElement);
  343. var nextElementIndex = this._getItemIndex(nextElement);
  344. var isCycling = Boolean(this._interval);
  345. var directionalClassName;
  346. var orderClassName;
  347. var eventDirectionName;
  348. if (direction === DIRECTION_NEXT) {
  349. directionalClassName = CLASS_NAME_LEFT;
  350. orderClassName = CLASS_NAME_NEXT;
  351. eventDirectionName = DIRECTION_LEFT;
  352. } else {
  353. directionalClassName = CLASS_NAME_RIGHT;
  354. orderClassName = CLASS_NAME_PREV;
  355. eventDirectionName = DIRECTION_RIGHT;
  356. }
  357. if (nextElement && $(nextElement).hasClass(CLASS_NAME_ACTIVE)) {
  358. this._isSliding = false;
  359. return;
  360. }
  361. var slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName);
  362. if (slideEvent.isDefaultPrevented()) {
  363. return;
  364. }
  365. if (!activeElement || !nextElement) {
  366. // Some weirdness is happening, so we bail
  367. return;
  368. }
  369. this._isSliding = true;
  370. if (isCycling) {
  371. this.pause();
  372. }
  373. this._setActiveIndicatorElement(nextElement);
  374. var slidEvent = $.Event(EVENT_SLID, {
  375. relatedTarget: nextElement,
  376. direction: eventDirectionName,
  377. from: activeElementIndex,
  378. to: nextElementIndex
  379. });
  380. if ($(this._element).hasClass(CLASS_NAME_SLIDE)) {
  381. $(nextElement).addClass(orderClassName);
  382. Util.reflow(nextElement);
  383. $(activeElement).addClass(directionalClassName);
  384. $(nextElement).addClass(directionalClassName);
  385. var nextElementInterval = parseInt(nextElement.getAttribute('data-interval'), 10);
  386. if (nextElementInterval) {
  387. this._config.defaultInterval = this._config.defaultInterval || this._config.interval;
  388. this._config.interval = nextElementInterval;
  389. } else {
  390. this._config.interval = this._config.defaultInterval || this._config.interval;
  391. }
  392. var transitionDuration = Util.getTransitionDurationFromElement(activeElement);
  393. $(activeElement).one(Util.TRANSITION_END, function () {
  394. $(nextElement).removeClass(directionalClassName + " " + orderClassName).addClass(CLASS_NAME_ACTIVE);
  395. $(activeElement).removeClass(CLASS_NAME_ACTIVE + " " + orderClassName + " " + directionalClassName);
  396. _this4._isSliding = false;
  397. setTimeout(function () {
  398. return $(_this4._element).trigger(slidEvent);
  399. }, 0);
  400. }).emulateTransitionEnd(transitionDuration);
  401. } else {
  402. $(activeElement).removeClass(CLASS_NAME_ACTIVE);
  403. $(nextElement).addClass(CLASS_NAME_ACTIVE);
  404. this._isSliding = false;
  405. $(this._element).trigger(slidEvent);
  406. }
  407. if (isCycling) {
  408. this.cycle();
  409. }
  410. } // Static
  411. ;
  412. Carousel._jQueryInterface = function _jQueryInterface(config) {
  413. return this.each(function () {
  414. var data = $(this).data(DATA_KEY);
  415. var _config = _extends({}, Default, $(this).data());
  416. if (typeof config === 'object') {
  417. _config = _extends({}, _config, config);
  418. }
  419. var action = typeof config === 'string' ? config : _config.slide;
  420. if (!data) {
  421. data = new Carousel(this, _config);
  422. $(this).data(DATA_KEY, data);
  423. }
  424. if (typeof config === 'number') {
  425. data.to(config);
  426. } else if (typeof action === 'string') {
  427. if (typeof data[action] === 'undefined') {
  428. throw new TypeError("No method named \"" + action + "\"");
  429. }
  430. data[action]();
  431. } else if (_config.interval && _config.ride) {
  432. data.pause();
  433. data.cycle();
  434. }
  435. });
  436. };
  437. Carousel._dataApiClickHandler = function _dataApiClickHandler(event) {
  438. var selector = Util.getSelectorFromElement(this);
  439. if (!selector) {
  440. return;
  441. }
  442. var target = $(selector)[0];
  443. if (!target || !$(target).hasClass(CLASS_NAME_CAROUSEL)) {
  444. return;
  445. }
  446. var config = _extends({}, $(target).data(), $(this).data());
  447. var slideIndex = this.getAttribute('data-slide-to');
  448. if (slideIndex) {
  449. config.interval = false;
  450. }
  451. Carousel._jQueryInterface.call($(target), config);
  452. if (slideIndex) {
  453. $(target).data(DATA_KEY).to(slideIndex);
  454. }
  455. event.preventDefault();
  456. };
  457. _createClass(Carousel, null, [{
  458. key: "VERSION",
  459. get: function get() {
  460. return VERSION;
  461. }
  462. }, {
  463. key: "Default",
  464. get: function get() {
  465. return Default;
  466. }
  467. }]);
  468. return Carousel;
  469. }();
  470. /**
  471. * ------------------------------------------------------------------------
  472. * Data Api implementation
  473. * ------------------------------------------------------------------------
  474. */
  475. $(document).on(EVENT_CLICK_DATA_API, SELECTOR_DATA_SLIDE, Carousel._dataApiClickHandler);
  476. $(window).on(EVENT_LOAD_DATA_API, function () {
  477. var carousels = [].slice.call(document.querySelectorAll(SELECTOR_DATA_RIDE));
  478. for (var i = 0, len = carousels.length; i < len; i++) {
  479. var $carousel = $(carousels[i]);
  480. Carousel._jQueryInterface.call($carousel, $carousel.data());
  481. }
  482. });
  483. /**
  484. * ------------------------------------------------------------------------
  485. * jQuery
  486. * ------------------------------------------------------------------------
  487. */
  488. $.fn[NAME] = Carousel._jQueryInterface;
  489. $.fn[NAME].Constructor = Carousel;
  490. $.fn[NAME].noConflict = function () {
  491. $.fn[NAME] = JQUERY_NO_CONFLICT;
  492. return Carousel._jQueryInterface;
  493. };
  494. return Carousel;
  495. })));
  496. //# sourceMappingURL=carousel.js.map