bootstrap 5.1.3 → 5.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +24 -4
  3. data/assets/javascripts/bootstrap/alert.js +11 -146
  4. data/assets/javascripts/bootstrap/base-component.js +37 -120
  5. data/assets/javascripts/bootstrap/button.js +10 -74
  6. data/assets/javascripts/bootstrap/carousel.js +213 -485
  7. data/assets/javascripts/bootstrap/collapse.js +65 -249
  8. data/assets/javascripts/bootstrap/dom/data.js +3 -5
  9. data/assets/javascripts/bootstrap/dom/event-handler.js +94 -132
  10. data/assets/javascripts/bootstrap/dom/manipulator.js +23 -27
  11. data/assets/javascripts/bootstrap/dom/selector-engine.js +16 -58
  12. data/assets/javascripts/bootstrap/dropdown.js +103 -317
  13. data/assets/javascripts/bootstrap/modal.js +107 -749
  14. data/assets/javascripts/bootstrap/offcanvas.js +90 -659
  15. data/assets/javascripts/bootstrap/popover.js +36 -118
  16. data/assets/javascripts/bootstrap/scrollspy.js +183 -262
  17. data/assets/javascripts/bootstrap/tab.js +215 -214
  18. data/assets/javascripts/bootstrap/toast.js +28 -214
  19. data/assets/javascripts/bootstrap/tooltip.js +272 -611
  20. data/assets/javascripts/bootstrap/util/backdrop.js +165 -0
  21. data/assets/javascripts/bootstrap/util/component-functions.js +46 -0
  22. data/assets/javascripts/bootstrap/util/config.js +79 -0
  23. data/assets/javascripts/bootstrap/util/focustrap.js +129 -0
  24. data/assets/javascripts/bootstrap/util/index.js +350 -0
  25. data/assets/javascripts/bootstrap/util/sanitizer.js +122 -0
  26. data/assets/javascripts/bootstrap/util/scrollbar.js +138 -0
  27. data/assets/javascripts/bootstrap/util/swipe.js +155 -0
  28. data/assets/javascripts/bootstrap/util/template-factory.js +177 -0
  29. data/assets/javascripts/bootstrap-global-this-define.js +1 -1
  30. data/assets/javascripts/bootstrap-sprockets.js +10 -1
  31. data/assets/javascripts/bootstrap.js +2077 -1859
  32. data/assets/javascripts/bootstrap.min.js +3 -3
  33. data/assets/stylesheets/_bootstrap-grid.scss +3 -6
  34. data/assets/stylesheets/_bootstrap-reboot.scss +3 -7
  35. data/assets/stylesheets/_bootstrap.scss +4 -6
  36. data/assets/stylesheets/bootstrap/_accordion.scss +56 -25
  37. data/assets/stylesheets/bootstrap/_alert.scss +18 -4
  38. data/assets/stylesheets/bootstrap/_badge.scss +14 -5
  39. data/assets/stylesheets/bootstrap/_breadcrumb.scss +22 -10
  40. data/assets/stylesheets/bootstrap/_button-group.scss +4 -1
  41. data/assets/stylesheets/bootstrap/_buttons.scss +120 -30
  42. data/assets/stylesheets/bootstrap/_card.scss +55 -37
  43. data/assets/stylesheets/bootstrap/_close.scss +1 -1
  44. data/assets/stylesheets/bootstrap/_containers.scss +1 -1
  45. data/assets/stylesheets/bootstrap/_dropdown.scss +85 -76
  46. data/assets/stylesheets/bootstrap/_functions.scss +8 -8
  47. data/assets/stylesheets/bootstrap/_grid.scss +3 -3
  48. data/assets/stylesheets/bootstrap/_helpers.scss +1 -0
  49. data/assets/stylesheets/bootstrap/_list-group.scss +48 -30
  50. data/assets/stylesheets/bootstrap/_maps.scss +54 -0
  51. data/assets/stylesheets/bootstrap/_modal.scss +71 -43
  52. data/assets/stylesheets/bootstrap/_nav.scss +53 -20
  53. data/assets/stylesheets/bootstrap/_navbar.scss +93 -150
  54. data/assets/stylesheets/bootstrap/_offcanvas.scss +120 -59
  55. data/assets/stylesheets/bootstrap/_pagination.scss +66 -21
  56. data/assets/stylesheets/bootstrap/_placeholders.scss +1 -1
  57. data/assets/stylesheets/bootstrap/_popover.scss +90 -52
  58. data/assets/stylesheets/bootstrap/_progress.scss +20 -9
  59. data/assets/stylesheets/bootstrap/_reboot.scss +25 -40
  60. data/assets/stylesheets/bootstrap/_root.scss +40 -21
  61. data/assets/stylesheets/bootstrap/_spinners.scss +38 -22
  62. data/assets/stylesheets/bootstrap/_tables.scss +32 -23
  63. data/assets/stylesheets/bootstrap/_toasts.scss +36 -16
  64. data/assets/stylesheets/bootstrap/_tooltip.scss +61 -56
  65. data/assets/stylesheets/bootstrap/_type.scss +2 -0
  66. data/assets/stylesheets/bootstrap/_utilities.scss +43 -26
  67. data/assets/stylesheets/bootstrap/_variables.scss +128 -135
  68. data/assets/stylesheets/bootstrap/bootstrap-utilities.scss +3 -6
  69. data/assets/stylesheets/bootstrap/forms/_floating-labels.scss +15 -3
  70. data/assets/stylesheets/bootstrap/forms/_form-check.scss +28 -5
  71. data/assets/stylesheets/bootstrap/forms/_form-control.scss +12 -37
  72. data/assets/stylesheets/bootstrap/forms/_form-select.scss +0 -1
  73. data/assets/stylesheets/bootstrap/forms/_input-group.scss +19 -8
  74. data/assets/stylesheets/bootstrap/helpers/_color-bg.scss +10 -0
  75. data/assets/stylesheets/bootstrap/helpers/_colored-links.scss +2 -2
  76. data/assets/stylesheets/bootstrap/helpers/_position.scss +7 -1
  77. data/assets/stylesheets/bootstrap/helpers/_ratio.scss +2 -2
  78. data/assets/stylesheets/bootstrap/helpers/_vr.scss +1 -1
  79. data/assets/stylesheets/bootstrap/mixins/_alert.scss +7 -3
  80. data/assets/stylesheets/bootstrap/mixins/_banner.scss +9 -0
  81. data/assets/stylesheets/bootstrap/mixins/_breakpoints.scss +8 -8
  82. data/assets/stylesheets/bootstrap/mixins/_buttons.scss +32 -95
  83. data/assets/stylesheets/bootstrap/mixins/_container.scss +4 -2
  84. data/assets/stylesheets/bootstrap/mixins/_forms.scss +18 -10
  85. data/assets/stylesheets/bootstrap/mixins/_gradients.scss +1 -1
  86. data/assets/stylesheets/bootstrap/mixins/_grid.scss +12 -12
  87. data/assets/stylesheets/bootstrap/mixins/_pagination.scss +4 -25
  88. data/assets/stylesheets/bootstrap/mixins/_reset-text.scss +1 -1
  89. data/assets/stylesheets/bootstrap/mixins/_table-variants.scss +12 -9
  90. data/assets/stylesheets/bootstrap/mixins/_utilities.scss +13 -5
  91. data/bootstrap.gemspec +1 -1
  92. data/lib/bootstrap/version.rb +2 -2
  93. data/tasks/updater/js.rb +10 -5
  94. metadata +16 -4
@@ -1,19 +1,19 @@
1
1
  /*!
2
- * Bootstrap tooltip.js v5.1.3 (https://getbootstrap.com/)
3
- * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
2
+ * Bootstrap tooltip.js v5.2.1 (https://getbootstrap.com/)
3
+ * Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
4
4
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
5
5
  */
6
6
  (function (global, factory) {
7
- typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('@popperjs/core'), require('./dom/data.js'), 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(['@popperjs/core', './dom/data', './dom/event-handler', './dom/manipulator', './dom/selector-engine', './base-component'], factory) :
9
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Tooltip = factory(global.Popper, global.Data, global.EventHandler, global.Manipulator, global.SelectorEngine, global.Base));
10
- })(this, (function (Popper, Data, EventHandler, Manipulator, SelectorEngine, BaseComponent) { 'use strict';
7
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('@popperjs/core'), require('./util/index'), require('./util/sanitizer'), require('./dom/event-handler'), require('./dom/manipulator'), require('./base-component'), require('./util/template-factory')) :
8
+ typeof define === 'function' && define.amd ? define(['@popperjs/core', './util/index', './util/sanitizer', './dom/event-handler', './dom/manipulator', './base-component', './util/template-factory'], factory) :
9
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Tooltip = factory(global["@popperjs/core"], global.Index, global.Sanitizer, global.EventHandler, global.Manipulator, global.BaseComponent, global.TemplateFactory));
10
+ })(this, (function (Popper, index, sanitizer, EventHandler, Manipulator, BaseComponent, TemplateFactory) { 'use strict';
11
11
 
12
12
  const _interopDefaultLegacy = e => e && typeof e === 'object' && 'default' in e ? e : { default: e };
13
13
 
14
14
  function _interopNamespace(e) {
15
15
  if (e && e.__esModule) return e;
16
- const n = Object.create(null);
16
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: 'Module' } });
17
17
  if (e) {
18
18
  for (const k in e) {
19
19
  if (k !== 'default') {
@@ -30,356 +30,90 @@
30
30
  }
31
31
 
32
32
  const Popper__namespace = /*#__PURE__*/_interopNamespace(Popper);
33
- const Data__default = /*#__PURE__*/_interopDefaultLegacy(Data);
34
33
  const EventHandler__default = /*#__PURE__*/_interopDefaultLegacy(EventHandler);
35
34
  const Manipulator__default = /*#__PURE__*/_interopDefaultLegacy(Manipulator);
36
- const SelectorEngine__default = /*#__PURE__*/_interopDefaultLegacy(SelectorEngine);
37
35
  const BaseComponent__default = /*#__PURE__*/_interopDefaultLegacy(BaseComponent);
36
+ const TemplateFactory__default = /*#__PURE__*/_interopDefaultLegacy(TemplateFactory);
38
37
 
39
38
  /**
40
39
  * --------------------------------------------------------------------------
41
- * Bootstrap (v5.1.3): util/index.js
40
+ * Bootstrap (v5.2.1): tooltip.js
42
41
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
43
42
  * --------------------------------------------------------------------------
44
43
  */
45
- const MAX_UID = 1000000;
46
-
47
- const toType = obj => {
48
- if (obj === null || obj === undefined) {
49
- return `${obj}`;
50
- }
51
-
52
- return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase();
53
- };
54
44
  /**
55
- * --------------------------------------------------------------------------
56
- * Public Util Api
57
- * --------------------------------------------------------------------------
58
- */
59
-
60
-
61
- const getUID = prefix => {
62
- do {
63
- prefix += Math.floor(Math.random() * MAX_UID);
64
- } while (document.getElementById(prefix));
65
-
66
- return prefix;
67
- };
68
-
69
- const isElement = obj => {
70
- if (!obj || typeof obj !== 'object') {
71
- return false;
72
- }
73
-
74
- if (typeof obj.jquery !== 'undefined') {
75
- obj = obj[0];
76
- }
77
-
78
- return typeof obj.nodeType !== 'undefined';
79
- };
80
-
81
- const getElement = obj => {
82
- if (isElement(obj)) {
83
- // it's a jQuery object or a node element
84
- return obj.jquery ? obj[0] : obj;
85
- }
86
-
87
- if (typeof obj === 'string' && obj.length > 0) {
88
- return document.querySelector(obj);
89
- }
90
-
91
- return null;
92
- };
93
-
94
- const typeCheckConfig = (componentName, config, configTypes) => {
95
- Object.keys(configTypes).forEach(property => {
96
- const expectedTypes = configTypes[property];
97
- const value = config[property];
98
- const valueType = value && isElement(value) ? 'element' : toType(value);
99
-
100
- if (!new RegExp(expectedTypes).test(valueType)) {
101
- throw new TypeError(`${componentName.toUpperCase()}: Option "${property}" provided type "${valueType}" but expected type "${expectedTypes}".`);
102
- }
103
- });
104
- };
105
-
106
- const findShadowRoot = element => {
107
- if (!document.documentElement.attachShadow) {
108
- return null;
109
- } // Can find the shadow root otherwise it'll return the document
110
-
111
-
112
- if (typeof element.getRootNode === 'function') {
113
- const root = element.getRootNode();
114
- return root instanceof ShadowRoot ? root : null;
115
- }
116
-
117
- if (element instanceof ShadowRoot) {
118
- return element;
119
- } // when we don't find a shadow root
120
-
121
-
122
- if (!element.parentNode) {
123
- return null;
124
- }
125
-
126
- return findShadowRoot(element.parentNode);
127
- };
128
-
129
- const noop = () => {};
130
-
131
- const getjQuery = () => {
132
- const {
133
- jQuery
134
- } = window;
135
-
136
- if (jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {
137
- return jQuery;
138
- }
139
-
140
- return null;
141
- };
142
-
143
- const DOMContentLoadedCallbacks = [];
144
-
145
- const onDOMContentLoaded = callback => {
146
- if (document.readyState === 'loading') {
147
- // add listener on the first call when the document is in loading state
148
- if (!DOMContentLoadedCallbacks.length) {
149
- document.addEventListener('DOMContentLoaded', () => {
150
- DOMContentLoadedCallbacks.forEach(callback => callback());
151
- });
152
- }
153
-
154
- DOMContentLoadedCallbacks.push(callback);
155
- } else {
156
- callback();
157
- }
158
- };
159
-
160
- const isRTL = () => document.documentElement.dir === 'rtl';
161
-
162
- const defineJQueryPlugin = plugin => {
163
- onDOMContentLoaded(() => {
164
- const $ = getjQuery();
165
- /* istanbul ignore if */
166
-
167
- if ($) {
168
- const name = plugin.NAME;
169
- const JQUERY_NO_CONFLICT = $.fn[name];
170
- $.fn[name] = plugin.jQueryInterface;
171
- $.fn[name].Constructor = plugin;
172
-
173
- $.fn[name].noConflict = () => {
174
- $.fn[name] = JQUERY_NO_CONFLICT;
175
- return plugin.jQueryInterface;
176
- };
177
- }
178
- });
179
- };
180
-
181
- /**
182
- * --------------------------------------------------------------------------
183
- * Bootstrap (v5.1.3): util/sanitizer.js
184
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
185
- * --------------------------------------------------------------------------
186
- */
187
- const uriAttributes = new Set(['background', 'cite', 'href', 'itemtype', 'longdesc', 'poster', 'src', 'xlink:href']);
188
- const ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i;
189
- /**
190
- * A pattern that recognizes a commonly useful subset of URLs that are safe.
191
- *
192
- * Shoutout to Angular https://github.com/angular/angular/blob/12.2.x/packages/core/src/sanitization/url_sanitizer.ts
193
- */
194
-
195
- const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file|sms):|[^#&/:?]*(?:[#/?]|$))/i;
196
- /**
197
- * A pattern that matches safe data URLs. Only matches image, video and audio types.
198
- *
199
- * Shoutout to Angular https://github.com/angular/angular/blob/12.2.x/packages/core/src/sanitization/url_sanitizer.ts
200
- */
201
-
202
- const DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i;
203
-
204
- const allowedAttribute = (attribute, allowedAttributeList) => {
205
- const attributeName = attribute.nodeName.toLowerCase();
206
-
207
- if (allowedAttributeList.includes(attributeName)) {
208
- if (uriAttributes.has(attributeName)) {
209
- return Boolean(SAFE_URL_PATTERN.test(attribute.nodeValue) || DATA_URL_PATTERN.test(attribute.nodeValue));
210
- }
211
-
212
- return true;
213
- }
214
-
215
- const regExp = allowedAttributeList.filter(attributeRegex => attributeRegex instanceof RegExp); // Check if a regular expression validates the attribute.
216
-
217
- for (let i = 0, len = regExp.length; i < len; i++) {
218
- if (regExp[i].test(attributeName)) {
219
- return true;
220
- }
221
- }
222
-
223
- return false;
224
- };
225
-
226
- const DefaultAllowlist = {
227
- // Global attributes allowed on any supplied element below.
228
- '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],
229
- a: ['target', 'href', 'title', 'rel'],
230
- area: [],
231
- b: [],
232
- br: [],
233
- col: [],
234
- code: [],
235
- div: [],
236
- em: [],
237
- hr: [],
238
- h1: [],
239
- h2: [],
240
- h3: [],
241
- h4: [],
242
- h5: [],
243
- h6: [],
244
- i: [],
245
- img: ['src', 'srcset', 'alt', 'title', 'width', 'height'],
246
- li: [],
247
- ol: [],
248
- p: [],
249
- pre: [],
250
- s: [],
251
- small: [],
252
- span: [],
253
- sub: [],
254
- sup: [],
255
- strong: [],
256
- u: [],
257
- ul: []
258
- };
259
- function sanitizeHtml(unsafeHtml, allowList, sanitizeFn) {
260
- if (!unsafeHtml.length) {
261
- return unsafeHtml;
262
- }
263
-
264
- if (sanitizeFn && typeof sanitizeFn === 'function') {
265
- return sanitizeFn(unsafeHtml);
266
- }
267
-
268
- const domParser = new window.DOMParser();
269
- const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html');
270
- const elements = [].concat(...createdDocument.body.querySelectorAll('*'));
271
-
272
- for (let i = 0, len = elements.length; i < len; i++) {
273
- const element = elements[i];
274
- const elementName = element.nodeName.toLowerCase();
275
-
276
- if (!Object.keys(allowList).includes(elementName)) {
277
- element.remove();
278
- continue;
279
- }
280
-
281
- const attributeList = [].concat(...element.attributes);
282
- const allowedAttributes = [].concat(allowList['*'] || [], allowList[elementName] || []);
283
- attributeList.forEach(attribute => {
284
- if (!allowedAttribute(attribute, allowedAttributes)) {
285
- element.removeAttribute(attribute.nodeName);
286
- }
287
- });
288
- }
289
-
290
- return createdDocument.body.innerHTML;
291
- }
292
-
293
- /**
294
- * --------------------------------------------------------------------------
295
- * Bootstrap (v5.1.3): tooltip.js
296
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
297
- * --------------------------------------------------------------------------
298
- */
299
- /**
300
- * ------------------------------------------------------------------------
301
45
  * Constants
302
- * ------------------------------------------------------------------------
303
46
  */
304
47
 
305
48
  const NAME = 'tooltip';
306
- const DATA_KEY = 'bs.tooltip';
307
- const EVENT_KEY = `.${DATA_KEY}`;
308
- const CLASS_PREFIX = 'bs-tooltip';
309
49
  const DISALLOWED_ATTRIBUTES = new Set(['sanitize', 'allowList', 'sanitizeFn']);
310
- const DefaultType = {
311
- animation: 'boolean',
312
- template: 'string',
313
- title: '(string|element|function)',
314
- trigger: 'string',
315
- delay: '(number|object)',
316
- html: 'boolean',
317
- selector: '(string|boolean)',
318
- placement: '(string|function)',
319
- offset: '(array|string|function)',
320
- container: '(string|element|boolean)',
321
- fallbackPlacements: 'array',
322
- boundary: '(string|element)',
323
- customClass: '(string|function)',
324
- sanitize: 'boolean',
325
- sanitizeFn: '(null|function)',
326
- allowList: 'object',
327
- popperConfig: '(null|object|function)'
328
- };
50
+ const CLASS_NAME_FADE = 'fade';
51
+ const CLASS_NAME_MODAL = 'modal';
52
+ const CLASS_NAME_SHOW = 'show';
53
+ const SELECTOR_TOOLTIP_INNER = '.tooltip-inner';
54
+ const SELECTOR_MODAL = `.${CLASS_NAME_MODAL}`;
55
+ const EVENT_MODAL_HIDE = 'hide.bs.modal';
56
+ const TRIGGER_HOVER = 'hover';
57
+ const TRIGGER_FOCUS = 'focus';
58
+ const TRIGGER_CLICK = 'click';
59
+ const TRIGGER_MANUAL = 'manual';
60
+ const EVENT_HIDE = 'hide';
61
+ const EVENT_HIDDEN = 'hidden';
62
+ const EVENT_SHOW = 'show';
63
+ const EVENT_SHOWN = 'shown';
64
+ const EVENT_INSERTED = 'inserted';
65
+ const EVENT_CLICK = 'click';
66
+ const EVENT_FOCUSIN = 'focusin';
67
+ const EVENT_FOCUSOUT = 'focusout';
68
+ const EVENT_MOUSEENTER = 'mouseenter';
69
+ const EVENT_MOUSELEAVE = 'mouseleave';
329
70
  const AttachmentMap = {
330
71
  AUTO: 'auto',
331
72
  TOP: 'top',
332
- RIGHT: isRTL() ? 'left' : 'right',
73
+ RIGHT: index.isRTL() ? 'left' : 'right',
333
74
  BOTTOM: 'bottom',
334
- LEFT: isRTL() ? 'right' : 'left'
75
+ LEFT: index.isRTL() ? 'right' : 'left'
335
76
  };
336
77
  const Default = {
78
+ allowList: sanitizer.DefaultAllowlist,
337
79
  animation: true,
338
- template: '<div class="tooltip" role="tooltip">' + '<div class="tooltip-arrow"></div>' + '<div class="tooltip-inner"></div>' + '</div>',
339
- trigger: 'hover focus',
340
- title: '',
80
+ boundary: 'clippingParents',
81
+ container: false,
82
+ customClass: '',
341
83
  delay: 0,
84
+ fallbackPlacements: ['top', 'right', 'bottom', 'left'],
342
85
  html: false,
343
- selector: false,
344
- placement: 'top',
345
86
  offset: [0, 0],
346
- container: false,
347
- fallbackPlacements: ['top', 'right', 'bottom', 'left'],
348
- boundary: 'clippingParents',
349
- customClass: '',
87
+ placement: 'top',
88
+ popperConfig: null,
350
89
  sanitize: true,
351
90
  sanitizeFn: null,
352
- allowList: DefaultAllowlist,
353
- popperConfig: null
91
+ selector: false,
92
+ template: '<div class="tooltip" role="tooltip">' + '<div class="tooltip-arrow"></div>' + '<div class="tooltip-inner"></div>' + '</div>',
93
+ title: '',
94
+ trigger: 'hover focus'
354
95
  };
355
- const Event = {
356
- HIDE: `hide${EVENT_KEY}`,
357
- HIDDEN: `hidden${EVENT_KEY}`,
358
- SHOW: `show${EVENT_KEY}`,
359
- SHOWN: `shown${EVENT_KEY}`,
360
- INSERTED: `inserted${EVENT_KEY}`,
361
- CLICK: `click${EVENT_KEY}`,
362
- FOCUSIN: `focusin${EVENT_KEY}`,
363
- FOCUSOUT: `focusout${EVENT_KEY}`,
364
- MOUSEENTER: `mouseenter${EVENT_KEY}`,
365
- MOUSELEAVE: `mouseleave${EVENT_KEY}`
96
+ const DefaultType = {
97
+ allowList: 'object',
98
+ animation: 'boolean',
99
+ boundary: '(string|element)',
100
+ container: '(string|element|boolean)',
101
+ customClass: '(string|function)',
102
+ delay: '(number|object)',
103
+ fallbackPlacements: 'array',
104
+ html: 'boolean',
105
+ offset: '(array|string|function)',
106
+ placement: '(string|function)',
107
+ popperConfig: '(null|object|function)',
108
+ sanitize: 'boolean',
109
+ sanitizeFn: '(null|function)',
110
+ selector: '(string|boolean)',
111
+ template: 'string',
112
+ title: '(string|element|function)',
113
+ trigger: 'string'
366
114
  };
367
- const CLASS_NAME_FADE = 'fade';
368
- const CLASS_NAME_MODAL = 'modal';
369
- const CLASS_NAME_SHOW = 'show';
370
- const HOVER_STATE_SHOW = 'show';
371
- const HOVER_STATE_OUT = 'out';
372
- const SELECTOR_TOOLTIP_INNER = '.tooltip-inner';
373
- const SELECTOR_MODAL = `.${CLASS_NAME_MODAL}`;
374
- const EVENT_MODAL_HIDE = 'hide.bs.modal';
375
- const TRIGGER_HOVER = 'hover';
376
- const TRIGGER_FOCUS = 'focus';
377
- const TRIGGER_CLICK = 'click';
378
- const TRIGGER_MANUAL = 'manual';
379
115
  /**
380
- * ------------------------------------------------------------------------
381
- * Class Definition
382
- * ------------------------------------------------------------------------
116
+ * Class definition
383
117
  */
384
118
 
385
119
  class Tooltip extends BaseComponent__default.default {
@@ -388,15 +122,16 @@
388
122
  throw new TypeError('Bootstrap\'s tooltips require Popper (https://popper.js.org)');
389
123
  }
390
124
 
391
- super(element); // private
125
+ super(element, config); // Private
392
126
 
393
127
  this._isEnabled = true;
394
128
  this._timeout = 0;
395
- this._hoverState = '';
129
+ this._isHovered = null;
396
130
  this._activeTrigger = {};
397
- this._popper = null; // Protected
131
+ this._popper = null;
132
+ this._templateFactory = null;
133
+ this._newContent = null; // Protected
398
134
 
399
- this._config = this._getConfig(config);
400
135
  this.tip = null;
401
136
 
402
137
  this._setListeners();
@@ -407,16 +142,12 @@
407
142
  return Default;
408
143
  }
409
144
 
410
- static get NAME() {
411
- return NAME;
412
- }
413
-
414
- static get Event() {
415
- return Event;
416
- }
417
-
418
145
  static get DefaultType() {
419
146
  return DefaultType;
147
+ }
148
+
149
+ static get NAME() {
150
+ return NAME;
420
151
  } // Public
421
152
 
422
153
 
@@ -443,19 +174,21 @@
443
174
  context._activeTrigger.click = !context._activeTrigger.click;
444
175
 
445
176
  if (context._isWithActiveTrigger()) {
446
- context._enter(null, context);
177
+ context._enter();
447
178
  } else {
448
- context._leave(null, context);
179
+ context._leave();
449
180
  }
450
- } else {
451
- if (this.getTipElement().classList.contains(CLASS_NAME_SHOW)) {
452
- this._leave(null, this);
453
181
 
454
- return;
455
- }
182
+ return;
183
+ }
184
+
185
+ if (this._isShown()) {
186
+ this._leave();
456
187
 
457
- this._enter(null, this);
188
+ return;
458
189
  }
190
+
191
+ this._enter();
459
192
  }
460
193
 
461
194
  dispose() {
@@ -466,6 +199,10 @@
466
199
  this.tip.remove();
467
200
  }
468
201
 
202
+ if (this._config.originalTitle) {
203
+ this._element.setAttribute('title', this._config.originalTitle);
204
+ }
205
+
469
206
  this._disposePopper();
470
207
 
471
208
  super.dispose();
@@ -476,233 +213,206 @@
476
213
  throw new Error('Please use show on visible elements');
477
214
  }
478
215
 
479
- if (!(this.isWithContent() && this._isEnabled)) {
216
+ if (!(this._isWithContent() && this._isEnabled)) {
480
217
  return;
481
218
  }
482
219
 
483
- const showEvent = EventHandler__default.default.trigger(this._element, this.constructor.Event.SHOW);
484
- const shadowRoot = findShadowRoot(this._element);
485
- const isInTheDom = shadowRoot === null ? this._element.ownerDocument.documentElement.contains(this._element) : shadowRoot.contains(this._element);
220
+ const showEvent = EventHandler__default.default.trigger(this._element, this.constructor.eventName(EVENT_SHOW));
221
+ const shadowRoot = index.findShadowRoot(this._element);
222
+
223
+ const isInTheDom = (shadowRoot || this._element.ownerDocument.documentElement).contains(this._element);
486
224
 
487
225
  if (showEvent.defaultPrevented || !isInTheDom) {
488
226
  return;
489
- } // A trick to recreate a tooltip in case a new title is given by using the NOT documented `data-bs-original-title`
490
- // This will be removed later in favor of a `setContent` method
227
+ } // todo v6 remove this OR make it optional
491
228
 
492
229
 
493
- if (this.constructor.NAME === 'tooltip' && this.tip && this.getTitle() !== this.tip.querySelector(SELECTOR_TOOLTIP_INNER).innerHTML) {
494
- this._disposePopper();
495
-
230
+ if (this.tip) {
496
231
  this.tip.remove();
497
232
  this.tip = null;
498
233
  }
499
234
 
500
- const tip = this.getTipElement();
501
- const tipId = getUID(this.constructor.NAME);
502
- tip.setAttribute('id', tipId);
503
-
504
- this._element.setAttribute('aria-describedby', tipId);
505
-
506
- if (this._config.animation) {
507
- tip.classList.add(CLASS_NAME_FADE);
508
- }
235
+ const tip = this._getTipElement();
509
236
 
510
- const placement = typeof this._config.placement === 'function' ? this._config.placement.call(this, tip, this._element) : this._config.placement;
511
-
512
- const attachment = this._getAttachment(placement);
513
-
514
- this._addAttachmentClass(attachment);
237
+ this._element.setAttribute('aria-describedby', tip.getAttribute('id'));
515
238
 
516
239
  const {
517
240
  container
518
241
  } = this._config;
519
- Data__default.default.set(tip, this.constructor.DATA_KEY, this);
520
242
 
521
243
  if (!this._element.ownerDocument.documentElement.contains(this.tip)) {
522
244
  container.append(tip);
523
- EventHandler__default.default.trigger(this._element, this.constructor.Event.INSERTED);
245
+ EventHandler__default.default.trigger(this._element, this.constructor.eventName(EVENT_INSERTED));
524
246
  }
525
247
 
526
248
  if (this._popper) {
527
249
  this._popper.update();
528
250
  } else {
529
- this._popper = Popper__namespace.createPopper(this._element, tip, this._getPopperConfig(attachment));
251
+ this._popper = this._createPopper(tip);
530
252
  }
531
253
 
532
- tip.classList.add(CLASS_NAME_SHOW);
533
-
534
- const customClass = this._resolvePossibleFunction(this._config.customClass);
535
-
536
- if (customClass) {
537
- tip.classList.add(...customClass.split(' '));
538
- } // If this is a touch-enabled device we add extra
254
+ tip.classList.add(CLASS_NAME_SHOW); // If this is a touch-enabled device we add extra
539
255
  // empty mouseover listeners to the body's immediate children;
540
256
  // only needed because of broken event delegation on iOS
541
257
  // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
542
258
 
543
-
544
259
  if ('ontouchstart' in document.documentElement) {
545
- [].concat(...document.body.children).forEach(element => {
546
- EventHandler__default.default.on(element, 'mouseover', noop);
547
- });
260
+ for (const element of [].concat(...document.body.children)) {
261
+ EventHandler__default.default.on(element, 'mouseover', index.noop);
262
+ }
548
263
  }
549
264
 
550
265
  const complete = () => {
551
- const prevHoverState = this._hoverState;
552
- this._hoverState = null;
553
- EventHandler__default.default.trigger(this._element, this.constructor.Event.SHOWN);
266
+ EventHandler__default.default.trigger(this._element, this.constructor.eventName(EVENT_SHOWN));
554
267
 
555
- if (prevHoverState === HOVER_STATE_OUT) {
556
- this._leave(null, this);
268
+ if (this._isHovered === false) {
269
+ this._leave();
557
270
  }
558
- };
559
271
 
560
- const isAnimated = this.tip.classList.contains(CLASS_NAME_FADE);
272
+ this._isHovered = false;
273
+ };
561
274
 
562
- this._queueCallback(complete, this.tip, isAnimated);
275
+ this._queueCallback(complete, this.tip, this._isAnimated());
563
276
  }
564
277
 
565
278
  hide() {
566
- if (!this._popper) {
279
+ if (!this._isShown()) {
567
280
  return;
568
281
  }
569
282
 
570
- const tip = this.getTipElement();
571
-
572
- const complete = () => {
573
- if (this._isWithActiveTrigger()) {
574
- return;
575
- }
576
-
577
- if (this._hoverState !== HOVER_STATE_SHOW) {
578
- tip.remove();
579
- }
580
-
581
- this._cleanTipClass();
582
-
583
- this._element.removeAttribute('aria-describedby');
584
-
585
- EventHandler__default.default.trigger(this._element, this.constructor.Event.HIDDEN);
586
-
587
- this._disposePopper();
588
- };
589
-
590
- const hideEvent = EventHandler__default.default.trigger(this._element, this.constructor.Event.HIDE);
283
+ const hideEvent = EventHandler__default.default.trigger(this._element, this.constructor.eventName(EVENT_HIDE));
591
284
 
592
285
  if (hideEvent.defaultPrevented) {
593
286
  return;
594
287
  }
595
288
 
289
+ const tip = this._getTipElement();
290
+
596
291
  tip.classList.remove(CLASS_NAME_SHOW); // If this is a touch-enabled device we remove the extra
597
292
  // empty mouseover listeners we added for iOS support
598
293
 
599
294
  if ('ontouchstart' in document.documentElement) {
600
- [].concat(...document.body.children).forEach(element => EventHandler__default.default.off(element, 'mouseover', noop));
295
+ for (const element of [].concat(...document.body.children)) {
296
+ EventHandler__default.default.off(element, 'mouseover', index.noop);
297
+ }
601
298
  }
602
299
 
603
300
  this._activeTrigger[TRIGGER_CLICK] = false;
604
301
  this._activeTrigger[TRIGGER_FOCUS] = false;
605
302
  this._activeTrigger[TRIGGER_HOVER] = false;
606
- const isAnimated = this.tip.classList.contains(CLASS_NAME_FADE);
303
+ this._isHovered = null; // it is a trick to support manual triggering
304
+
305
+ const complete = () => {
306
+ if (this._isWithActiveTrigger()) {
307
+ return;
308
+ }
309
+
310
+ if (!this._isHovered) {
311
+ tip.remove();
312
+ }
313
+
314
+ this._element.removeAttribute('aria-describedby');
607
315
 
608
- this._queueCallback(complete, this.tip, isAnimated);
316
+ EventHandler__default.default.trigger(this._element, this.constructor.eventName(EVENT_HIDDEN));
609
317
 
610
- this._hoverState = '';
318
+ this._disposePopper();
319
+ };
320
+
321
+ this._queueCallback(complete, this.tip, this._isAnimated());
611
322
  }
612
323
 
613
324
  update() {
614
- if (this._popper !== null) {
325
+ if (this._popper) {
615
326
  this._popper.update();
616
327
  }
617
328
  } // Protected
618
329
 
619
330
 
620
- isWithContent() {
621
- return Boolean(this.getTitle());
331
+ _isWithContent() {
332
+ return Boolean(this._getTitle());
622
333
  }
623
334
 
624
- getTipElement() {
625
- if (this.tip) {
626
- return this.tip;
335
+ _getTipElement() {
336
+ if (!this.tip) {
337
+ this.tip = this._createTipElement(this._newContent || this._getContentForTemplate());
627
338
  }
628
339
 
629
- const element = document.createElement('div');
630
- element.innerHTML = this._config.template;
631
- const tip = element.children[0];
632
- this.setContent(tip);
633
- tip.classList.remove(CLASS_NAME_FADE, CLASS_NAME_SHOW);
634
- this.tip = tip;
635
340
  return this.tip;
636
341
  }
637
342
 
638
- setContent(tip) {
639
- this._sanitizeAndSetContent(tip, this.getTitle(), SELECTOR_TOOLTIP_INNER);
640
- }
343
+ _createTipElement(content) {
344
+ const tip = this._getTemplateFactory(content).toHtml(); // todo: remove this check on v6
641
345
 
642
- _sanitizeAndSetContent(template, content, selector) {
643
- const templateElement = SelectorEngine__default.default.findOne(selector, template);
644
346
 
645
- if (!content && templateElement) {
646
- templateElement.remove();
647
- return;
648
- } // we use append for html objects to maintain js events
347
+ if (!tip) {
348
+ return null;
349
+ }
649
350
 
351
+ tip.classList.remove(CLASS_NAME_FADE, CLASS_NAME_SHOW); // todo: on v6 the following can be achieved with CSS only
650
352
 
651
- this.setElementContent(templateElement, content);
652
- }
353
+ tip.classList.add(`bs-${this.constructor.NAME}-auto`);
354
+ const tipId = index.getUID(this.constructor.NAME).toString();
355
+ tip.setAttribute('id', tipId);
653
356
 
654
- setElementContent(element, content) {
655
- if (element === null) {
656
- return;
357
+ if (this._isAnimated()) {
358
+ tip.classList.add(CLASS_NAME_FADE);
657
359
  }
658
360
 
659
- if (isElement(content)) {
660
- content = getElement(content); // content is a DOM node or a jQuery
361
+ return tip;
362
+ }
661
363
 
662
- if (this._config.html) {
663
- if (content.parentNode !== element) {
664
- element.innerHTML = '';
665
- element.append(content);
666
- }
667
- } else {
668
- element.textContent = content.textContent;
669
- }
364
+ setContent(content) {
365
+ this._newContent = content;
670
366
 
671
- return;
672
- }
367
+ if (this._isShown()) {
368
+ this._disposePopper();
673
369
 
674
- if (this._config.html) {
675
- if (this._config.sanitize) {
676
- content = sanitizeHtml(content, this._config.allowList, this._config.sanitizeFn);
677
- }
370
+ this.show();
371
+ }
372
+ }
678
373
 
679
- element.innerHTML = content;
374
+ _getTemplateFactory(content) {
375
+ if (this._templateFactory) {
376
+ this._templateFactory.changeContent(content);
680
377
  } else {
681
- element.textContent = content;
378
+ this._templateFactory = new TemplateFactory__default.default({ ...this._config,
379
+ // the `content` var has to be after `this._config`
380
+ // to override config.content in case of popover
381
+ content,
382
+ extraClass: this._resolvePossibleFunction(this._config.customClass)
383
+ });
682
384
  }
683
- }
684
385
 
685
- getTitle() {
686
- const title = this._element.getAttribute('data-bs-original-title') || this._config.title;
386
+ return this._templateFactory;
387
+ }
687
388
 
688
- return this._resolvePossibleFunction(title);
389
+ _getContentForTemplate() {
390
+ return {
391
+ [SELECTOR_TOOLTIP_INNER]: this._getTitle()
392
+ };
689
393
  }
690
394
 
691
- updateAttachment(attachment) {
692
- if (attachment === 'right') {
693
- return 'end';
694
- }
395
+ _getTitle() {
396
+ return this._resolvePossibleFunction(this._config.title) || this._config.originalTitle;
397
+ } // Private
695
398
 
696
- if (attachment === 'left') {
697
- return 'start';
698
- }
699
399
 
700
- return attachment;
701
- } // Private
400
+ _initializeOnDelegatedTarget(event) {
401
+ return this.constructor.getOrCreateInstance(event.delegateTarget, this._getDelegateConfig());
402
+ }
403
+
404
+ _isAnimated() {
405
+ return this._config.animation || this.tip && this.tip.classList.contains(CLASS_NAME_FADE);
406
+ }
702
407
 
408
+ _isShown() {
409
+ return this.tip && this.tip.classList.contains(CLASS_NAME_SHOW);
410
+ }
703
411
 
704
- _initializeOnDelegatedTarget(event, context) {
705
- return context || this.constructor.getOrCreateInstance(event.delegateTarget, this._getDelegateConfig());
412
+ _createPopper(tip) {
413
+ const placement = typeof this._config.placement === 'function' ? this._config.placement.call(this, tip, this._element) : this._config.placement;
414
+ const attachment = AttachmentMap[placement.toUpperCase()];
415
+ return Popper__namespace.createPopper(this._element, tip, this._getPopperConfig(attachment));
706
416
  }
707
417
 
708
418
  _getOffset() {
@@ -711,7 +421,7 @@
711
421
  } = this._config;
712
422
 
713
423
  if (typeof offset === 'string') {
714
- return offset.split(',').map(val => Number.parseInt(val, 10));
424
+ return offset.split(',').map(value => Number.parseInt(value, 10));
715
425
  }
716
426
 
717
427
  if (typeof offset === 'function') {
@@ -721,8 +431,8 @@
721
431
  return offset;
722
432
  }
723
433
 
724
- _resolvePossibleFunction(content) {
725
- return typeof content === 'function' ? content.call(this._element) : content;
434
+ _resolvePossibleFunction(arg) {
435
+ return typeof arg === 'function' ? arg.call(this._element) : arg;
726
436
  }
727
437
 
728
438
  _getPopperConfig(attachment) {
@@ -749,43 +459,46 @@
749
459
  element: `.${this.constructor.NAME}-arrow`
750
460
  }
751
461
  }, {
752
- name: 'onChange',
462
+ name: 'preSetPlacement',
753
463
  enabled: true,
754
- phase: 'afterWrite',
755
- fn: data => this._handlePopperPlacementChange(data)
756
- }],
757
- onFirstUpdate: data => {
758
- if (data.options.placement !== data.placement) {
759
- this._handlePopperPlacementChange(data);
464
+ phase: 'beforeMain',
465
+ fn: data => {
466
+ // Pre-set Popper's placement attribute in order to read the arrow sizes properly.
467
+ // Otherwise, Popper mixes up the width and height dimensions since the initial arrow style is for top placement
468
+ this._getTipElement().setAttribute('data-popper-placement', data.state.placement);
760
469
  }
761
- }
470
+ }]
762
471
  };
763
472
  return { ...defaultBsPopperConfig,
764
473
  ...(typeof this._config.popperConfig === 'function' ? this._config.popperConfig(defaultBsPopperConfig) : this._config.popperConfig)
765
474
  };
766
475
  }
767
476
 
768
- _addAttachmentClass(attachment) {
769
- this.getTipElement().classList.add(`${this._getBasicClassPrefix()}-${this.updateAttachment(attachment)}`);
770
- }
771
-
772
- _getAttachment(placement) {
773
- return AttachmentMap[placement.toUpperCase()];
774
- }
775
-
776
477
  _setListeners() {
777
478
  const triggers = this._config.trigger.split(' ');
778
479
 
779
- triggers.forEach(trigger => {
480
+ for (const trigger of triggers) {
780
481
  if (trigger === 'click') {
781
- EventHandler__default.default.on(this._element, this.constructor.Event.CLICK, this._config.selector, event => this.toggle(event));
482
+ EventHandler__default.default.on(this._element, this.constructor.eventName(EVENT_CLICK), this._config.selector, event => this.toggle(event));
782
483
  } else if (trigger !== TRIGGER_MANUAL) {
783
- const eventIn = trigger === TRIGGER_HOVER ? this.constructor.Event.MOUSEENTER : this.constructor.Event.FOCUSIN;
784
- const eventOut = trigger === TRIGGER_HOVER ? this.constructor.Event.MOUSELEAVE : this.constructor.Event.FOCUSOUT;
785
- EventHandler__default.default.on(this._element, eventIn, this._config.selector, event => this._enter(event));
786
- EventHandler__default.default.on(this._element, eventOut, this._config.selector, event => this._leave(event));
484
+ const eventIn = trigger === TRIGGER_HOVER ? this.constructor.eventName(EVENT_MOUSEENTER) : this.constructor.eventName(EVENT_FOCUSIN);
485
+ const eventOut = trigger === TRIGGER_HOVER ? this.constructor.eventName(EVENT_MOUSELEAVE) : this.constructor.eventName(EVENT_FOCUSOUT);
486
+ EventHandler__default.default.on(this._element, eventIn, this._config.selector, event => {
487
+ const context = this._initializeOnDelegatedTarget(event);
488
+
489
+ context._activeTrigger[event.type === 'focusin' ? TRIGGER_FOCUS : TRIGGER_HOVER] = true;
490
+
491
+ context._enter();
492
+ });
493
+ EventHandler__default.default.on(this._element, eventOut, this._config.selector, event => {
494
+ const context = this._initializeOnDelegatedTarget(event);
495
+
496
+ context._activeTrigger[event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER] = context._element.contains(event.relatedTarget);
497
+
498
+ context._leave();
499
+ });
787
500
  }
788
- });
501
+ }
789
502
 
790
503
  this._hideModalHandler = () => {
791
504
  if (this._element) {
@@ -806,96 +519,79 @@
806
519
  }
807
520
 
808
521
  _fixTitle() {
809
- const title = this._element.getAttribute('title');
810
-
811
- const originalTitleType = typeof this._element.getAttribute('data-bs-original-title');
522
+ const title = this._config.originalTitle;
812
523
 
813
- if (title || originalTitleType !== 'string') {
814
- this._element.setAttribute('data-bs-original-title', title || '');
815
-
816
- if (title && !this._element.getAttribute('aria-label') && !this._element.textContent) {
817
- this._element.setAttribute('aria-label', title);
818
- }
819
-
820
- this._element.setAttribute('title', '');
821
- }
822
- }
823
-
824
- _enter(event, context) {
825
- context = this._initializeOnDelegatedTarget(event, context);
826
-
827
- if (event) {
828
- context._activeTrigger[event.type === 'focusin' ? TRIGGER_FOCUS : TRIGGER_HOVER] = true;
524
+ if (!title) {
525
+ return;
829
526
  }
830
527
 
831
- if (context.getTipElement().classList.contains(CLASS_NAME_SHOW) || context._hoverState === HOVER_STATE_SHOW) {
832
- context._hoverState = HOVER_STATE_SHOW;
833
- return;
528
+ if (!this._element.getAttribute('aria-label') && !this._element.textContent.trim()) {
529
+ this._element.setAttribute('aria-label', title);
834
530
  }
835
531
 
836
- clearTimeout(context._timeout);
837
- context._hoverState = HOVER_STATE_SHOW;
532
+ this._element.removeAttribute('title');
533
+ }
838
534
 
839
- if (!context._config.delay || !context._config.delay.show) {
840
- context.show();
535
+ _enter() {
536
+ if (this._isShown() || this._isHovered) {
537
+ this._isHovered = true;
841
538
  return;
842
539
  }
843
540
 
844
- context._timeout = setTimeout(() => {
845
- if (context._hoverState === HOVER_STATE_SHOW) {
846
- context.show();
541
+ this._isHovered = true;
542
+
543
+ this._setTimeout(() => {
544
+ if (this._isHovered) {
545
+ this.show();
847
546
  }
848
- }, context._config.delay.show);
547
+ }, this._config.delay.show);
849
548
  }
850
549
 
851
- _leave(event, context) {
852
- context = this._initializeOnDelegatedTarget(event, context);
853
-
854
- if (event) {
855
- context._activeTrigger[event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER] = context._element.contains(event.relatedTarget);
856
- }
857
-
858
- if (context._isWithActiveTrigger()) {
550
+ _leave() {
551
+ if (this._isWithActiveTrigger()) {
859
552
  return;
860
553
  }
861
554
 
862
- clearTimeout(context._timeout);
863
- context._hoverState = HOVER_STATE_OUT;
864
-
865
- if (!context._config.delay || !context._config.delay.hide) {
866
- context.hide();
867
- return;
868
- }
555
+ this._isHovered = false;
869
556
 
870
- context._timeout = setTimeout(() => {
871
- if (context._hoverState === HOVER_STATE_OUT) {
872
- context.hide();
557
+ this._setTimeout(() => {
558
+ if (!this._isHovered) {
559
+ this.hide();
873
560
  }
874
- }, context._config.delay.hide);
561
+ }, this._config.delay.hide);
875
562
  }
876
563
 
877
- _isWithActiveTrigger() {
878
- for (const trigger in this._activeTrigger) {
879
- if (this._activeTrigger[trigger]) {
880
- return true;
881
- }
882
- }
564
+ _setTimeout(handler, timeout) {
565
+ clearTimeout(this._timeout);
566
+ this._timeout = setTimeout(handler, timeout);
567
+ }
883
568
 
884
- return false;
569
+ _isWithActiveTrigger() {
570
+ return Object.values(this._activeTrigger).includes(true);
885
571
  }
886
572
 
887
573
  _getConfig(config) {
888
574
  const dataAttributes = Manipulator__default.default.getDataAttributes(this._element);
889
- Object.keys(dataAttributes).forEach(dataAttr => {
890
- if (DISALLOWED_ATTRIBUTES.has(dataAttr)) {
891
- delete dataAttributes[dataAttr];
575
+
576
+ for (const dataAttribute of Object.keys(dataAttributes)) {
577
+ if (DISALLOWED_ATTRIBUTES.has(dataAttribute)) {
578
+ delete dataAttributes[dataAttribute];
892
579
  }
893
- });
894
- config = { ...this.constructor.Default,
895
- ...dataAttributes,
580
+ }
581
+
582
+ config = { ...dataAttributes,
896
583
  ...(typeof config === 'object' && config ? config : {})
897
584
  };
898
- config.container = config.container === false ? document.body : getElement(config.container);
585
+ config = this._mergeConfigObj(config);
586
+ config = this._configAfterMerge(config);
587
+
588
+ this._typeCheckConfig(config);
589
+
590
+ return config;
591
+ }
592
+
593
+ _configAfterMerge(config) {
594
+ config.container = config.container === false ? document.body : index.getElement(config.container);
899
595
 
900
596
  if (typeof config.delay === 'number') {
901
597
  config.delay = {
@@ -904,6 +600,8 @@
904
600
  };
905
601
  }
906
602
 
603
+ config.originalTitle = this._element.getAttribute('title') || '';
604
+
907
605
  if (typeof config.title === 'number') {
908
606
  config.title = config.title.toString();
909
607
  }
@@ -912,12 +610,6 @@
912
610
  config.content = config.content.toString();
913
611
  }
914
612
 
915
- typeCheckConfig(NAME, config, this.constructor.DefaultType);
916
-
917
- if (config.sanitize) {
918
- config.template = sanitizeHtml(config.template, config.allowList, config.sanitizeFn);
919
- }
920
-
921
613
  return config;
922
614
  }
923
615
 
@@ -936,36 +628,6 @@
936
628
  return config;
937
629
  }
938
630
 
939
- _cleanTipClass() {
940
- const tip = this.getTipElement();
941
- const basicClassPrefixRegex = new RegExp(`(^|\\s)${this._getBasicClassPrefix()}\\S+`, 'g');
942
- const tabClass = tip.getAttribute('class').match(basicClassPrefixRegex);
943
-
944
- if (tabClass !== null && tabClass.length > 0) {
945
- tabClass.map(token => token.trim()).forEach(tClass => tip.classList.remove(tClass));
946
- }
947
- }
948
-
949
- _getBasicClassPrefix() {
950
- return CLASS_PREFIX;
951
- }
952
-
953
- _handlePopperPlacementChange(popperData) {
954
- const {
955
- state
956
- } = popperData;
957
-
958
- if (!state) {
959
- return;
960
- }
961
-
962
- this.tip = state.elements.popper;
963
-
964
- this._cleanTipClass();
965
-
966
- this._addAttachmentClass(this._getAttachment(state.placement));
967
- }
968
-
969
631
  _disposePopper() {
970
632
  if (this._popper) {
971
633
  this._popper.destroy();
@@ -979,26 +641,25 @@
979
641
  return this.each(function () {
980
642
  const data = Tooltip.getOrCreateInstance(this, config);
981
643
 
982
- if (typeof config === 'string') {
983
- if (typeof data[config] === 'undefined') {
984
- throw new TypeError(`No method named "${config}"`);
985
- }
644
+ if (typeof config !== 'string') {
645
+ return;
646
+ }
986
647
 
987
- data[config]();
648
+ if (typeof data[config] === 'undefined') {
649
+ throw new TypeError(`No method named "${config}"`);
988
650
  }
651
+
652
+ data[config]();
989
653
  });
990
654
  }
991
655
 
992
656
  }
993
657
  /**
994
- * ------------------------------------------------------------------------
995
658
  * jQuery
996
- * ------------------------------------------------------------------------
997
- * add .Tooltip to jQuery only if jQuery is present
998
659
  */
999
660
 
1000
661
 
1001
- defineJQueryPlugin(Tooltip);
662
+ index.defineJQueryPlugin(Tooltip);
1002
663
 
1003
664
  return Tooltip;
1004
665