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.

423 lines
12 KiB

  1. /*!
  2. * Bootstrap toast.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('./base-component.js')) :
  8. typeof define === 'function' && define.amd ? define(['./dom/event-handler', './dom/manipulator', './base-component'], factory) :
  9. (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Toast = factory(global.EventHandler, global.Manipulator, global.Base));
  10. })(this, (function (EventHandler, Manipulator, 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 BaseComponent__default = /*#__PURE__*/_interopDefaultLegacy(BaseComponent);
  15. /**
  16. * --------------------------------------------------------------------------
  17. * Bootstrap (v5.1.3): util/index.js
  18. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
  19. * --------------------------------------------------------------------------
  20. */
  21. const toType = obj => {
  22. if (obj === null || obj === undefined) {
  23. return `${obj}`;
  24. }
  25. return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase();
  26. };
  27. const getSelector = element => {
  28. let selector = element.getAttribute('data-bs-target');
  29. if (!selector || selector === '#') {
  30. let hrefAttr = element.getAttribute('href'); // The only valid content that could double as a selector are IDs or classes,
  31. // so everything starting with `#` or `.`. If a "real" URL is used as the selector,
  32. // `document.querySelector` will rightfully complain it is invalid.
  33. // See https://github.com/twbs/bootstrap/issues/32273
  34. if (!hrefAttr || !hrefAttr.includes('#') && !hrefAttr.startsWith('.')) {
  35. return null;
  36. } // Just in case some CMS puts out a full URL with the anchor appended
  37. if (hrefAttr.includes('#') && !hrefAttr.startsWith('#')) {
  38. hrefAttr = `#${hrefAttr.split('#')[1]}`;
  39. }
  40. selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : null;
  41. }
  42. return selector;
  43. };
  44. const getElementFromSelector = element => {
  45. const selector = getSelector(element);
  46. return selector ? document.querySelector(selector) : null;
  47. };
  48. const isElement = obj => {
  49. if (!obj || typeof obj !== 'object') {
  50. return false;
  51. }
  52. if (typeof obj.jquery !== 'undefined') {
  53. obj = obj[0];
  54. }
  55. return typeof obj.nodeType !== 'undefined';
  56. };
  57. const typeCheckConfig = (componentName, config, configTypes) => {
  58. Object.keys(configTypes).forEach(property => {
  59. const expectedTypes = configTypes[property];
  60. const value = config[property];
  61. const valueType = value && isElement(value) ? 'element' : toType(value);
  62. if (!new RegExp(expectedTypes).test(valueType)) {
  63. throw new TypeError(`${componentName.toUpperCase()}: Option "${property}" provided type "${valueType}" but expected type "${expectedTypes}".`);
  64. }
  65. });
  66. };
  67. const isDisabled = element => {
  68. if (!element || element.nodeType !== Node.ELEMENT_NODE) {
  69. return true;
  70. }
  71. if (element.classList.contains('disabled')) {
  72. return true;
  73. }
  74. if (typeof element.disabled !== 'undefined') {
  75. return element.disabled;
  76. }
  77. return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false';
  78. };
  79. /**
  80. * Trick to restart an element's animation
  81. *
  82. * @param {HTMLElement} element
  83. * @return void
  84. *
  85. * @see https://www.charistheo.io/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
  86. */
  87. const reflow = element => {
  88. // eslint-disable-next-line no-unused-expressions
  89. element.offsetHeight;
  90. };
  91. const getjQuery = () => {
  92. const {
  93. jQuery
  94. } = window;
  95. if (jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {
  96. return jQuery;
  97. }
  98. return null;
  99. };
  100. const DOMContentLoadedCallbacks = [];
  101. const onDOMContentLoaded = callback => {
  102. if (document.readyState === 'loading') {
  103. // add listener on the first call when the document is in loading state
  104. if (!DOMContentLoadedCallbacks.length) {
  105. document.addEventListener('DOMContentLoaded', () => {
  106. DOMContentLoadedCallbacks.forEach(callback => callback());
  107. });
  108. }
  109. DOMContentLoadedCallbacks.push(callback);
  110. } else {
  111. callback();
  112. }
  113. };
  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. * --------------------------------------------------------------------------
  132. * Bootstrap (v5.1.3): util/component-functions.js
  133. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
  134. * --------------------------------------------------------------------------
  135. */
  136. const enableDismissTrigger = (component, method = 'hide') => {
  137. const clickEvent = `click.dismiss${component.EVENT_KEY}`;
  138. const name = component.NAME;
  139. EventHandler__default.default.on(document, clickEvent, `[data-bs-dismiss="${name}"]`, function (event) {
  140. if (['A', 'AREA'].includes(this.tagName)) {
  141. event.preventDefault();
  142. }
  143. if (isDisabled(this)) {
  144. return;
  145. }
  146. const target = getElementFromSelector(this) || this.closest(`.${name}`);
  147. const instance = component.getOrCreateInstance(target); // Method argument is left, for Alert and only, as it doesn't implement the 'hide' method
  148. instance[method]();
  149. });
  150. };
  151. /**
  152. * --------------------------------------------------------------------------
  153. * Bootstrap (v5.1.3): toast.js
  154. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
  155. * --------------------------------------------------------------------------
  156. */
  157. /**
  158. * ------------------------------------------------------------------------
  159. * Constants
  160. * ------------------------------------------------------------------------
  161. */
  162. const NAME = 'toast';
  163. const DATA_KEY = 'bs.toast';
  164. const EVENT_KEY = `.${DATA_KEY}`;
  165. const EVENT_MOUSEOVER = `mouseover${EVENT_KEY}`;
  166. const EVENT_MOUSEOUT = `mouseout${EVENT_KEY}`;
  167. const EVENT_FOCUSIN = `focusin${EVENT_KEY}`;
  168. const EVENT_FOCUSOUT = `focusout${EVENT_KEY}`;
  169. const EVENT_HIDE = `hide${EVENT_KEY}`;
  170. const EVENT_HIDDEN = `hidden${EVENT_KEY}`;
  171. const EVENT_SHOW = `show${EVENT_KEY}`;
  172. const EVENT_SHOWN = `shown${EVENT_KEY}`;
  173. const CLASS_NAME_FADE = 'fade';
  174. const CLASS_NAME_HIDE = 'hide'; // @deprecated - kept here only for backwards compatibility
  175. const CLASS_NAME_SHOW = 'show';
  176. const CLASS_NAME_SHOWING = 'showing';
  177. const DefaultType = {
  178. animation: 'boolean',
  179. autohide: 'boolean',
  180. delay: 'number'
  181. };
  182. const Default = {
  183. animation: true,
  184. autohide: true,
  185. delay: 5000
  186. };
  187. /**
  188. * ------------------------------------------------------------------------
  189. * Class Definition
  190. * ------------------------------------------------------------------------
  191. */
  192. class Toast extends BaseComponent__default.default {
  193. constructor(element, config) {
  194. super(element);
  195. this._config = this._getConfig(config);
  196. this._timeout = null;
  197. this._hasMouseInteraction = false;
  198. this._hasKeyboardInteraction = false;
  199. this._setListeners();
  200. } // Getters
  201. static get DefaultType() {
  202. return DefaultType;
  203. }
  204. static get Default() {
  205. return Default;
  206. }
  207. static get NAME() {
  208. return NAME;
  209. } // Public
  210. show() {
  211. const showEvent = EventHandler__default.default.trigger(this._element, EVENT_SHOW);
  212. if (showEvent.defaultPrevented) {
  213. return;
  214. }
  215. this._clearTimeout();
  216. if (this._config.animation) {
  217. this._element.classList.add(CLASS_NAME_FADE);
  218. }
  219. const complete = () => {
  220. this._element.classList.remove(CLASS_NAME_SHOWING);
  221. EventHandler__default.default.trigger(this._element, EVENT_SHOWN);
  222. this._maybeScheduleHide();
  223. };
  224. this._element.classList.remove(CLASS_NAME_HIDE); // @deprecated
  225. reflow(this._element);
  226. this._element.classList.add(CLASS_NAME_SHOW);
  227. this._element.classList.add(CLASS_NAME_SHOWING);
  228. this._queueCallback(complete, this._element, this._config.animation);
  229. }
  230. hide() {
  231. if (!this._element.classList.contains(CLASS_NAME_SHOW)) {
  232. return;
  233. }
  234. const hideEvent = EventHandler__default.default.trigger(this._element, EVENT_HIDE);
  235. if (hideEvent.defaultPrevented) {
  236. return;
  237. }
  238. const complete = () => {
  239. this._element.classList.add(CLASS_NAME_HIDE); // @deprecated
  240. this._element.classList.remove(CLASS_NAME_SHOWING);
  241. this._element.classList.remove(CLASS_NAME_SHOW);
  242. EventHandler__default.default.trigger(this._element, EVENT_HIDDEN);
  243. };
  244. this._element.classList.add(CLASS_NAME_SHOWING);
  245. this._queueCallback(complete, this._element, this._config.animation);
  246. }
  247. dispose() {
  248. this._clearTimeout();
  249. if (this._element.classList.contains(CLASS_NAME_SHOW)) {
  250. this._element.classList.remove(CLASS_NAME_SHOW);
  251. }
  252. super.dispose();
  253. } // Private
  254. _getConfig(config) {
  255. config = { ...Default,
  256. ...Manipulator__default.default.getDataAttributes(this._element),
  257. ...(typeof config === 'object' && config ? config : {})
  258. };
  259. typeCheckConfig(NAME, config, this.constructor.DefaultType);
  260. return config;
  261. }
  262. _maybeScheduleHide() {
  263. if (!this._config.autohide) {
  264. return;
  265. }
  266. if (this._hasMouseInteraction || this._hasKeyboardInteraction) {
  267. return;
  268. }
  269. this._timeout = setTimeout(() => {
  270. this.hide();
  271. }, this._config.delay);
  272. }
  273. _onInteraction(event, isInteracting) {
  274. switch (event.type) {
  275. case 'mouseover':
  276. case 'mouseout':
  277. this._hasMouseInteraction = isInteracting;
  278. break;
  279. case 'focusin':
  280. case 'focusout':
  281. this._hasKeyboardInteraction = isInteracting;
  282. break;
  283. }
  284. if (isInteracting) {
  285. this._clearTimeout();
  286. return;
  287. }
  288. const nextElement = event.relatedTarget;
  289. if (this._element === nextElement || this._element.contains(nextElement)) {
  290. return;
  291. }
  292. this._maybeScheduleHide();
  293. }
  294. _setListeners() {
  295. EventHandler__default.default.on(this._element, EVENT_MOUSEOVER, event => this._onInteraction(event, true));
  296. EventHandler__default.default.on(this._element, EVENT_MOUSEOUT, event => this._onInteraction(event, false));
  297. EventHandler__default.default.on(this._element, EVENT_FOCUSIN, event => this._onInteraction(event, true));
  298. EventHandler__default.default.on(this._element, EVENT_FOCUSOUT, event => this._onInteraction(event, false));
  299. }
  300. _clearTimeout() {
  301. clearTimeout(this._timeout);
  302. this._timeout = null;
  303. } // Static
  304. static jQueryInterface(config) {
  305. return this.each(function () {
  306. const data = Toast.getOrCreateInstance(this, config);
  307. if (typeof config === 'string') {
  308. if (typeof data[config] === 'undefined') {
  309. throw new TypeError(`No method named "${config}"`);
  310. }
  311. data[config](this);
  312. }
  313. });
  314. }
  315. }
  316. enableDismissTrigger(Toast);
  317. /**
  318. * ------------------------------------------------------------------------
  319. * jQuery
  320. * ------------------------------------------------------------------------
  321. * add .Toast to jQuery only if jQuery is present
  322. */
  323. defineJQueryPlugin(Toast);
  324. return Toast;
  325. }));
  326. //# sourceMappingURL=toast.js.map