bootstrap 5.1.1 → 5.2.0

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