You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

743 lines
24 KiB

  1. /*!
  2. * Bootstrap carousel.js v5.1.3 (https://getbootstrap.com/)
  3. * Copyright 2011-2021 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('./dom/event-handler.js'), require('./dom/manipulator.js'), require('./dom/selector-engine.js'), require('./base-component.js')) :
  8. typeof define === 'function' && define.amd ? define(['./dom/event-handler', './dom/manipulator', './dom/selector-engine', './base-component'], factory) :
  9. (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Carousel = factory(global.EventHandler, global.Manipulator, global.SelectorEngine, global.Base));
  10. })(this, (function (EventHandler, Manipulator, SelectorEngine, BaseComponent) { 'use strict';
  11. const _interopDefaultLegacy = e => e && typeof e === 'object' && 'default' in e ? e : { default: e };
  12. const EventHandler__default = /*#__PURE__*/_interopDefaultLegacy(EventHandler);
  13. const Manipulator__default = /*#__PURE__*/_interopDefaultLegacy(Manipulator);
  14. const SelectorEngine__default = /*#__PURE__*/_interopDefaultLegacy(SelectorEngine);
  15. const BaseComponent__default = /*#__PURE__*/_interopDefaultLegacy(BaseComponent);
  16. /**
  17. * --------------------------------------------------------------------------
  18. * Bootstrap (v5.1.3): util/index.js
  19. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
  20. * --------------------------------------------------------------------------
  21. */
  22. const TRANSITION_END = 'transitionend'; // Shoutout AngusCroll (https://goo.gl/pxwQGp)
  23. const toType = obj => {
  24. if (obj === null || obj === undefined) {
  25. return `${obj}`;
  26. }
  27. return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase();
  28. };
  29. const getSelector = element => {
  30. let selector = element.getAttribute('data-bs-target');
  31. if (!selector || selector === '#') {
  32. let hrefAttr = element.getAttribute('href'); // The only valid content that could double as a selector are IDs or classes,
  33. // so everything starting with `#` or `.`. If a "real" URL is used as the selector,
  34. // `document.querySelector` will rightfully complain it is invalid.
  35. // See https://github.com/twbs/bootstrap/issues/32273
  36. if (!hrefAttr || !hrefAttr.includes('#') && !hrefAttr.startsWith('.')) {
  37. return null;
  38. } // Just in case some CMS puts out a full URL with the anchor appended
  39. if (hrefAttr.includes('#') && !hrefAttr.startsWith('#')) {
  40. hrefAttr = `#${hrefAttr.split('#')[1]}`;
  41. }
  42. selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : null;
  43. }
  44. return selector;
  45. };
  46. const getElementFromSelector = element => {
  47. const selector = getSelector(element);
  48. return selector ? document.querySelector(selector) : null;
  49. };
  50. const triggerTransitionEnd = element => {
  51. element.dispatchEvent(new Event(TRANSITION_END));
  52. };
  53. const isElement = obj => {
  54. if (!obj || typeof obj !== 'object') {
  55. return false;
  56. }
  57. if (typeof obj.jquery !== 'undefined') {
  58. obj = obj[0];
  59. }
  60. return typeof obj.nodeType !== 'undefined';
  61. };
  62. const typeCheckConfig = (componentName, config, configTypes) => {
  63. Object.keys(configTypes).forEach(property => {
  64. const expectedTypes = configTypes[property];
  65. const value = config[property];
  66. const valueType = value && isElement(value) ? 'element' : toType(value);
  67. if (!new RegExp(expectedTypes).test(valueType)) {
  68. throw new TypeError(`${componentName.toUpperCase()}: Option "${property}" provided type "${valueType}" but expected type "${expectedTypes}".`);
  69. }
  70. });
  71. };
  72. const isVisible = element => {
  73. if (!isElement(element) || element.getClientRects().length === 0) {
  74. return false;
  75. }
  76. return getComputedStyle(element).getPropertyValue('visibility') === 'visible';
  77. };
  78. /**
  79. * Trick to restart an element's animation
  80. *
  81. * @param {HTMLElement} element
  82. * @return void
  83. *
  84. * @see https://www.charistheo.io/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
  85. */
  86. const reflow = element => {
  87. // eslint-disable-next-line no-unused-expressions
  88. element.offsetHeight;
  89. };
  90. const getjQuery = () => {
  91. const {
  92. jQuery
  93. } = window;
  94. if (jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {
  95. return jQuery;
  96. }
  97. return null;
  98. };
  99. const DOMContentLoadedCallbacks = [];
  100. const onDOMContentLoaded = callback => {
  101. if (document.readyState === 'loading') {
  102. // add listener on the first call when the document is in loading state
  103. if (!DOMContentLoadedCallbacks.length) {
  104. document.addEventListener('DOMContentLoaded', () => {
  105. DOMContentLoadedCallbacks.forEach(callback => callback());
  106. });
  107. }
  108. DOMContentLoadedCallbacks.push(callback);
  109. } else {
  110. callback();
  111. }
  112. };
  113. const isRTL = () => document.documentElement.dir === 'rtl';
  114. const defineJQueryPlugin = plugin => {
  115. onDOMContentLoaded(() => {
  116. const $ = getjQuery();
  117. /* istanbul ignore if */
  118. if ($) {
  119. const name = plugin.NAME;
  120. const JQUERY_NO_CONFLICT = $.fn[name];
  121. $.fn[name] = plugin.jQueryInterface;
  122. $.fn[name].Constructor = plugin;
  123. $.fn[name].noConflict = () => {
  124. $.fn[name] = JQUERY_NO_CONFLICT;
  125. return plugin.jQueryInterface;
  126. };
  127. }
  128. });
  129. };
  130. /**
  131. * Return the previous/next element of a list.
  132. *
  133. * @param {array} list The list of elements
  134. * @param activeElement The active element
  135. * @param shouldGetNext Choose to get next or previous element
  136. * @param isCycleAllowed
  137. * @return {Element|elem} The proper element
  138. */
  139. const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {
  140. let index = list.indexOf(activeElement); // if the element does not exist in the list return an element depending on the direction and if cycle is allowed
  141. if (index === -1) {
  142. return list[!shouldGetNext && isCycleAllowed ? list.length - 1 : 0];
  143. }
  144. const listLength = list.length;
  145. index += shouldGetNext ? 1 : -1;
  146. if (isCycleAllowed) {
  147. index = (index + listLength) % listLength;
  148. }
  149. return list[Math.max(0, Math.min(index, listLength - 1))];
  150. };
  151. /**
  152. * --------------------------------------------------------------------------
  153. * Bootstrap (v5.1.3): carousel.js
  154. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
  155. * --------------------------------------------------------------------------
  156. */
  157. /**
  158. * ------------------------------------------------------------------------
  159. * Constants
  160. * ------------------------------------------------------------------------
  161. */
  162. const NAME = 'carousel';
  163. const DATA_KEY = 'bs.carousel';
  164. const EVENT_KEY = `.${DATA_KEY}`;
  165. const DATA_API_KEY = '.data-api';
  166. const ARROW_LEFT_KEY = 'ArrowLeft';
  167. const ARROW_RIGHT_KEY = 'ArrowRight';
  168. const TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch
  169. const SWIPE_THRESHOLD = 40;
  170. const Default = {
  171. interval: 5000,
  172. keyboard: true,
  173. slide: false,
  174. pause: 'hover',
  175. wrap: true,
  176. touch: true
  177. };
  178. const DefaultType = {
  179. interval: '(number|boolean)',
  180. keyboard: 'boolean',
  181. slide: '(boolean|string)',
  182. pause: '(string|boolean)',
  183. wrap: 'boolean',
  184. touch: 'boolean'
  185. };
  186. const ORDER_NEXT = 'next';
  187. const ORDER_PREV = 'prev';
  188. const DIRECTION_LEFT = 'left';
  189. const DIRECTION_RIGHT = 'right';
  190. const KEY_TO_DIRECTION = {
  191. [ARROW_LEFT_KEY]: DIRECTION_RIGHT,
  192. [ARROW_RIGHT_KEY]: DIRECTION_LEFT
  193. };
  194. const EVENT_SLIDE = `slide${EVENT_KEY}`;
  195. const EVENT_SLID = `slid${EVENT_KEY}`;
  196. const EVENT_KEYDOWN = `keydown${EVENT_KEY}`;
  197. const EVENT_MOUSEENTER = `mouseenter${EVENT_KEY}`;
  198. const EVENT_MOUSELEAVE = `mouseleave${EVENT_KEY}`;
  199. const EVENT_TOUCHSTART = `touchstart${EVENT_KEY}`;
  200. const EVENT_TOUCHMOVE = `touchmove${EVENT_KEY}`;
  201. const EVENT_TOUCHEND = `touchend${EVENT_KEY}`;
  202. const EVENT_POINTERDOWN = `pointerdown${EVENT_KEY}`;
  203. const EVENT_POINTERUP = `pointerup${EVENT_KEY}`;
  204. const EVENT_DRAG_START = `dragstart${EVENT_KEY}`;
  205. const EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}`;
  206. const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`;
  207. const CLASS_NAME_CAROUSEL = 'carousel';
  208. const CLASS_NAME_ACTIVE = 'active';
  209. const CLASS_NAME_SLIDE = 'slide';
  210. const CLASS_NAME_END = 'carousel-item-end';
  211. const CLASS_NAME_START = 'carousel-item-start';
  212. const CLASS_NAME_NEXT = 'carousel-item-next';
  213. const CLASS_NAME_PREV = 'carousel-item-prev';
  214. const CLASS_NAME_POINTER_EVENT = 'pointer-event';
  215. const SELECTOR_ACTIVE = '.active';
  216. const SELECTOR_ACTIVE_ITEM = '.active.carousel-item';
  217. const SELECTOR_ITEM = '.carousel-item';
  218. const SELECTOR_ITEM_IMG = '.carousel-item img';
  219. const SELECTOR_NEXT_PREV = '.carousel-item-next, .carousel-item-prev';
  220. const SELECTOR_INDICATORS = '.carousel-indicators';
  221. const SELECTOR_INDICATOR = '[data-bs-target]';
  222. const SELECTOR_DATA_SLIDE = '[data-bs-slide], [data-bs-slide-to]';
  223. const SELECTOR_DATA_RIDE = '[data-bs-ride="carousel"]';
  224. const POINTER_TYPE_TOUCH = 'touch';
  225. const POINTER_TYPE_PEN = 'pen';
  226. /**
  227. * ------------------------------------------------------------------------
  228. * Class Definition
  229. * ------------------------------------------------------------------------
  230. */
  231. class Carousel extends BaseComponent__default.default {
  232. constructor(element, config) {
  233. super(element);
  234. this._items = null;
  235. this._interval = null;
  236. this._activeElement = null;
  237. this._isPaused = false;
  238. this._isSliding = false;
  239. this.touchTimeout = null;
  240. this.touchStartX = 0;
  241. this.touchDeltaX = 0;
  242. this._config = this._getConfig(config);
  243. this._indicatorsElement = SelectorEngine__default.default.findOne(SELECTOR_INDICATORS, this._element);
  244. this._touchSupported = 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0;
  245. this._pointerEvent = Boolean(window.PointerEvent);
  246. this._addEventListeners();
  247. } // Getters
  248. static get Default() {
  249. return Default;
  250. }
  251. static get NAME() {
  252. return NAME;
  253. } // Public
  254. next() {
  255. this._slide(ORDER_NEXT);
  256. }
  257. nextWhenVisible() {
  258. // Don't call next when the page isn't visible
  259. // or the carousel or its parent isn't visible
  260. if (!document.hidden && isVisible(this._element)) {
  261. this.next();
  262. }
  263. }
  264. prev() {
  265. this._slide(ORDER_PREV);
  266. }
  267. pause(event) {
  268. if (!event) {
  269. this._isPaused = true;
  270. }
  271. if (SelectorEngine__default.default.findOne(SELECTOR_NEXT_PREV, this._element)) {
  272. triggerTransitionEnd(this._element);
  273. this.cycle(true);
  274. }
  275. clearInterval(this._interval);
  276. this._interval = null;
  277. }
  278. cycle(event) {
  279. if (!event) {
  280. this._isPaused = false;
  281. }
  282. if (this._interval) {
  283. clearInterval(this._interval);
  284. this._interval = null;
  285. }
  286. if (this._config && this._config.interval && !this._isPaused) {
  287. this._updateInterval();
  288. this._interval = setInterval((document.visibilityState ? this.nextWhenVisible : this.next).bind(this), this._config.interval);
  289. }
  290. }
  291. to(index) {
  292. this._activeElement = SelectorEngine__default.default.findOne(SELECTOR_ACTIVE_ITEM, this._element);
  293. const activeIndex = this._getItemIndex(this._activeElement);
  294. if (index > this._items.length - 1 || index < 0) {
  295. return;
  296. }
  297. if (this._isSliding) {
  298. EventHandler__default.default.one(this._element, EVENT_SLID, () => this.to(index));
  299. return;
  300. }
  301. if (activeIndex === index) {
  302. this.pause();
  303. this.cycle();
  304. return;
  305. }
  306. const order = index > activeIndex ? ORDER_NEXT : ORDER_PREV;
  307. this._slide(order, this._items[index]);
  308. } // Private
  309. _getConfig(config) {
  310. config = { ...Default,
  311. ...Manipulator__default.default.getDataAttributes(this._element),
  312. ...(typeof config === 'object' ? config : {})
  313. };
  314. typeCheckConfig(NAME, config, DefaultType);
  315. return config;
  316. }
  317. _handleSwipe() {
  318. const absDeltax = Math.abs(this.touchDeltaX);
  319. if (absDeltax <= SWIPE_THRESHOLD) {
  320. return;
  321. }
  322. const direction = absDeltax / this.touchDeltaX;
  323. this.touchDeltaX = 0;
  324. if (!direction) {
  325. return;
  326. }
  327. this._slide(direction > 0 ? DIRECTION_RIGHT : DIRECTION_LEFT);
  328. }
  329. _addEventListeners() {
  330. if (this._config.keyboard) {
  331. EventHandler__default.default.on(this._element, EVENT_KEYDOWN, event => this._keydown(event));
  332. }
  333. if (this._config.pause === 'hover') {
  334. EventHandler__default.default.on(this._element, EVENT_MOUSEENTER, event => this.pause(event));
  335. EventHandler__default.default.on(this._element, EVENT_MOUSELEAVE, event => this.cycle(event));
  336. }
  337. if (this._config.touch && this._touchSupported) {
  338. this._addTouchEventListeners();
  339. }
  340. }
  341. _addTouchEventListeners() {
  342. const hasPointerPenTouch = event => {
  343. return this._pointerEvent && (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH);
  344. };
  345. const start = event => {
  346. if (hasPointerPenTouch(event)) {
  347. this.touchStartX = event.clientX;
  348. } else if (!this._pointerEvent) {
  349. this.touchStartX = event.touches[0].clientX;
  350. }
  351. };
  352. const move = event => {
  353. // ensure swiping with one touch and not pinching
  354. this.touchDeltaX = event.touches && event.touches.length > 1 ? 0 : event.touches[0].clientX - this.touchStartX;
  355. };
  356. const end = event => {
  357. if (hasPointerPenTouch(event)) {
  358. this.touchDeltaX = event.clientX - this.touchStartX;
  359. }
  360. this._handleSwipe();
  361. if (this._config.pause === 'hover') {
  362. // If it's a touch-enabled device, mouseenter/leave are fired as
  363. // part of the mouse compatibility events on first tap - the carousel
  364. // would stop cycling until user tapped out of it;
  365. // here, we listen for touchend, explicitly pause the carousel
  366. // (as if it's the second time we tap on it, mouseenter compat event
  367. // is NOT fired) and after a timeout (to allow for mouse compatibility
  368. // events to fire) we explicitly restart cycling
  369. this.pause();
  370. if (this.touchTimeout) {
  371. clearTimeout(this.touchTimeout);
  372. }
  373. this.touchTimeout = setTimeout(event => this.cycle(event), TOUCHEVENT_COMPAT_WAIT + this._config.interval);
  374. }
  375. };
  376. SelectorEngine__default.default.find(SELECTOR_ITEM_IMG, this._element).forEach(itemImg => {
  377. EventHandler__default.default.on(itemImg, EVENT_DRAG_START, event => event.preventDefault());
  378. });
  379. if (this._pointerEvent) {
  380. EventHandler__default.default.on(this._element, EVENT_POINTERDOWN, event => start(event));
  381. EventHandler__default.default.on(this._element, EVENT_POINTERUP, event => end(event));
  382. this._element.classList.add(CLASS_NAME_POINTER_EVENT);
  383. } else {
  384. EventHandler__default.default.on(this._element, EVENT_TOUCHSTART, event => start(event));
  385. EventHandler__default.default.on(this._element, EVENT_TOUCHMOVE, event => move(event));
  386. EventHandler__default.default.on(this._element, EVENT_TOUCHEND, event => end(event));
  387. }
  388. }
  389. _keydown(event) {
  390. if (/input|textarea/i.test(event.target.tagName)) {
  391. return;
  392. }
  393. const direction = KEY_TO_DIRECTION[event.key];
  394. if (direction) {
  395. event.preventDefault();
  396. this._slide(direction);
  397. }
  398. }
  399. _getItemIndex(element) {
  400. this._items = element && element.parentNode ? SelectorEngine__default.default.find(SELECTOR_ITEM, element.parentNode) : [];
  401. return this._items.indexOf(element);
  402. }
  403. _getItemByOrder(order, activeElement) {
  404. const isNext = order === ORDER_NEXT;
  405. return getNextActiveElement(this._items, activeElement, isNext, this._config.wrap);
  406. }
  407. _triggerSlideEvent(relatedTarget, eventDirectionName) {
  408. const targetIndex = this._getItemIndex(relatedTarget);
  409. const fromIndex = this._getItemIndex(SelectorEngine__default.default.findOne(SELECTOR_ACTIVE_ITEM, this._element));
  410. return EventHandler__default.default.trigger(this._element, EVENT_SLIDE, {
  411. relatedTarget,
  412. direction: eventDirectionName,
  413. from: fromIndex,
  414. to: targetIndex
  415. });
  416. }
  417. _setActiveIndicatorElement(element) {
  418. if (this._indicatorsElement) {
  419. const activeIndicator = SelectorEngine__default.default.findOne(SELECTOR_ACTIVE, this._indicatorsElement);
  420. activeIndicator.classList.remove(CLASS_NAME_ACTIVE);
  421. activeIndicator.removeAttribute('aria-current');
  422. const indicators = SelectorEngine__default.default.find(SELECTOR_INDICATOR, this._indicatorsElement);
  423. for (let i = 0; i < indicators.length; i++) {
  424. if (Number.parseInt(indicators[i].getAttribute('data-bs-slide-to'), 10) === this._getItemIndex(element)) {
  425. indicators[i].classList.add(CLASS_NAME_ACTIVE);
  426. indicators[i].setAttribute('aria-current', 'true');
  427. break;
  428. }
  429. }
  430. }
  431. }
  432. _updateInterval() {
  433. const element = this._activeElement || SelectorEngine__default.default.findOne(SELECTOR_ACTIVE_ITEM, this._element);
  434. if (!element) {
  435. return;
  436. }
  437. const elementInterval = Number.parseInt(element.getAttribute('data-bs-interval'), 10);
  438. if (elementInterval) {
  439. this._config.defaultInterval = this._config.defaultInterval || this._config.interval;
  440. this._config.interval = elementInterval;
  441. } else {
  442. this._config.interval = this._config.defaultInterval || this._config.interval;
  443. }
  444. }
  445. _slide(directionOrOrder, element) {
  446. const order = this._directionToOrder(directionOrOrder);
  447. const activeElement = SelectorEngine__default.default.findOne(SELECTOR_ACTIVE_ITEM, this._element);
  448. const activeElementIndex = this._getItemIndex(activeElement);
  449. const nextElement = element || this._getItemByOrder(order, activeElement);
  450. const nextElementIndex = this._getItemIndex(nextElement);
  451. const isCycling = Boolean(this._interval);
  452. const isNext = order === ORDER_NEXT;
  453. const directionalClassName = isNext ? CLASS_NAME_START : CLASS_NAME_END;
  454. const orderClassName = isNext ? CLASS_NAME_NEXT : CLASS_NAME_PREV;
  455. const eventDirectionName = this._orderToDirection(order);
  456. if (nextElement && nextElement.classList.contains(CLASS_NAME_ACTIVE)) {
  457. this._isSliding = false;
  458. return;
  459. }
  460. if (this._isSliding) {
  461. return;
  462. }
  463. const slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName);
  464. if (slideEvent.defaultPrevented) {
  465. return;
  466. }
  467. if (!activeElement || !nextElement) {
  468. // Some weirdness is happening, so we bail
  469. return;
  470. }
  471. this._isSliding = true;
  472. if (isCycling) {
  473. this.pause();
  474. }
  475. this._setActiveIndicatorElement(nextElement);
  476. this._activeElement = nextElement;
  477. const triggerSlidEvent = () => {
  478. EventHandler__default.default.trigger(this._element, EVENT_SLID, {
  479. relatedTarget: nextElement,
  480. direction: eventDirectionName,
  481. from: activeElementIndex,
  482. to: nextElementIndex
  483. });
  484. };
  485. if (this._element.classList.contains(CLASS_NAME_SLIDE)) {
  486. nextElement.classList.add(orderClassName);
  487. reflow(nextElement);
  488. activeElement.classList.add(directionalClassName);
  489. nextElement.classList.add(directionalClassName);
  490. const completeCallBack = () => {
  491. nextElement.classList.remove(directionalClassName, orderClassName);
  492. nextElement.classList.add(CLASS_NAME_ACTIVE);
  493. activeElement.classList.remove(CLASS_NAME_ACTIVE, orderClassName, directionalClassName);
  494. this._isSliding = false;
  495. setTimeout(triggerSlidEvent, 0);
  496. };
  497. this._queueCallback(completeCallBack, activeElement, true);
  498. } else {
  499. activeElement.classList.remove(CLASS_NAME_ACTIVE);
  500. nextElement.classList.add(CLASS_NAME_ACTIVE);
  501. this._isSliding = false;
  502. triggerSlidEvent();
  503. }
  504. if (isCycling) {
  505. this.cycle();
  506. }
  507. }
  508. _directionToOrder(direction) {
  509. if (![DIRECTION_RIGHT, DIRECTION_LEFT].includes(direction)) {
  510. return direction;
  511. }
  512. if (isRTL()) {
  513. return direction === DIRECTION_LEFT ? ORDER_PREV : ORDER_NEXT;
  514. }
  515. return direction === DIRECTION_LEFT ? ORDER_NEXT : ORDER_PREV;
  516. }
  517. _orderToDirection(order) {
  518. if (![ORDER_NEXT, ORDER_PREV].includes(order)) {
  519. return order;
  520. }
  521. if (isRTL()) {
  522. return order === ORDER_PREV ? DIRECTION_LEFT : DIRECTION_RIGHT;
  523. }
  524. return order === ORDER_PREV ? DIRECTION_RIGHT : DIRECTION_LEFT;
  525. } // Static
  526. static carouselInterface(element, config) {
  527. const data = Carousel.getOrCreateInstance(element, config);
  528. let {
  529. _config
  530. } = data;
  531. if (typeof config === 'object') {
  532. _config = { ..._config,
  533. ...config
  534. };
  535. }
  536. const action = typeof config === 'string' ? config : _config.slide;
  537. if (typeof config === 'number') {
  538. data.to(config);
  539. } else if (typeof action === 'string') {
  540. if (typeof data[action] === 'undefined') {
  541. throw new TypeError(`No method named "${action}"`);
  542. }
  543. data[action]();
  544. } else if (_config.interval && _config.ride) {
  545. data.pause();
  546. data.cycle();
  547. }
  548. }
  549. static jQueryInterface(config) {
  550. return this.each(function () {
  551. Carousel.carouselInterface(this, config);
  552. });
  553. }
  554. static dataApiClickHandler(event) {
  555. const target = getElementFromSelector(this);
  556. if (!target || !target.classList.contains(CLASS_NAME_CAROUSEL)) {
  557. return;
  558. }
  559. const config = { ...Manipulator__default.default.getDataAttributes(target),
  560. ...Manipulator__default.default.getDataAttributes(this)
  561. };
  562. const slideIndex = this.getAttribute('data-bs-slide-to');
  563. if (slideIndex) {
  564. config.interval = false;
  565. }
  566. Carousel.carouselInterface(target, config);
  567. if (slideIndex) {
  568. Carousel.getInstance(target).to(slideIndex);
  569. }
  570. event.preventDefault();
  571. }
  572. }
  573. /**
  574. * ------------------------------------------------------------------------
  575. * Data Api implementation
  576. * ------------------------------------------------------------------------
  577. */
  578. EventHandler__default.default.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_SLIDE, Carousel.dataApiClickHandler);
  579. EventHandler__default.default.on(window, EVENT_LOAD_DATA_API, () => {
  580. const carousels = SelectorEngine__default.default.find(SELECTOR_DATA_RIDE);
  581. for (let i = 0, len = carousels.length; i < len; i++) {
  582. Carousel.carouselInterface(carousels[i], Carousel.getInstance(carousels[i]));
  583. }
  584. });
  585. /**
  586. * ------------------------------------------------------------------------
  587. * jQuery
  588. * ------------------------------------------------------------------------
  589. * add .Carousel to jQuery only if jQuery is present
  590. */
  591. defineJQueryPlugin(Carousel);
  592. return Carousel;
  593. }));
  594. //# sourceMappingURL=carousel.js.map