bootstrap 5.1.3 → 5.3.5
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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +61 -0
- data/CHANGELOG.md +9 -0
- data/Gemfile +1 -0
- data/README.md +35 -14
- data/Rakefile +16 -5
- data/assets/javascripts/bootstrap/alert.js +22 -167
- data/assets/javascripts/bootstrap/base-component.js +34 -133
- data/assets/javascripts/bootstrap/button.js +19 -86
- data/assets/javascripts/bootstrap/carousel.js +209 -564
- data/assets/javascripts/bootstrap/collapse.js +78 -324
- data/assets/javascripts/bootstrap/dom/data.js +8 -14
- data/assets/javascripts/bootstrap/dom/event-handler.js +89 -174
- data/assets/javascripts/bootstrap/dom/manipulator.js +22 -39
- data/assets/javascripts/bootstrap/dom/selector-engine.js +47 -71
- data/assets/javascripts/bootstrap/dropdown.js +135 -420
- data/assets/javascripts/bootstrap/modal.js +115 -837
- data/assets/javascripts/bootstrap/offcanvas.js +93 -714
- data/assets/javascripts/bootstrap/popover.js +42 -130
- data/assets/javascripts/bootstrap/scrollspy.js +180 -296
- data/assets/javascripts/bootstrap/tab.js +197 -245
- data/assets/javascripts/bootstrap/toast.js +52 -276
- data/assets/javascripts/bootstrap/tooltip.js +283 -744
- data/assets/javascripts/bootstrap/util/backdrop.js +138 -0
- data/assets/javascripts/bootstrap/util/component-functions.js +41 -0
- data/assets/javascripts/bootstrap/util/config.js +67 -0
- data/assets/javascripts/bootstrap/util/focustrap.js +112 -0
- data/assets/javascripts/bootstrap/util/index.js +280 -0
- data/assets/javascripts/bootstrap/util/sanitizer.js +113 -0
- data/assets/javascripts/bootstrap/util/scrollbar.js +112 -0
- data/assets/javascripts/bootstrap/util/swipe.js +134 -0
- data/assets/javascripts/bootstrap/util/template-factory.js +150 -0
- data/assets/javascripts/bootstrap-global-this-define.js +1 -1
- data/assets/javascripts/bootstrap-sprockets.js +15 -6
- data/assets/javascripts/bootstrap.js +2278 -2831
- data/assets/javascripts/bootstrap.min.js +3 -3
- data/assets/stylesheets/_bootstrap-grid.scss +4 -9
- data/assets/stylesheets/_bootstrap-reboot.scss +4 -7
- data/assets/stylesheets/_bootstrap-utilities.scss +19 -0
- data/assets/stylesheets/_bootstrap.scss +5 -6
- data/assets/stylesheets/bootstrap/_accordion.scss +68 -33
- data/assets/stylesheets/bootstrap/_alert.scss +25 -14
- data/assets/stylesheets/bootstrap/_badge.scss +14 -5
- data/assets/stylesheets/bootstrap/_breadcrumb.scss +22 -10
- data/assets/stylesheets/bootstrap/_button-group.scss +12 -4
- data/assets/stylesheets/bootstrap/_buttons.scss +133 -28
- data/assets/stylesheets/bootstrap/_card.scss +61 -39
- data/assets/stylesheets/bootstrap/_carousel.scss +22 -25
- data/assets/stylesheets/bootstrap/_close.scss +36 -10
- data/assets/stylesheets/bootstrap/_containers.scss +1 -1
- data/assets/stylesheets/bootstrap/_dropdown.scss +86 -76
- data/assets/stylesheets/bootstrap/_functions.scss +10 -10
- data/assets/stylesheets/bootstrap/_grid.scss +9 -3
- data/assets/stylesheets/bootstrap/_helpers.scss +3 -0
- data/assets/stylesheets/bootstrap/_list-group.scss +81 -56
- data/assets/stylesheets/bootstrap/_maps.scss +174 -0
- data/assets/stylesheets/bootstrap/_mixins.scss +1 -2
- data/assets/stylesheets/bootstrap/_modal.scss +76 -45
- data/assets/stylesheets/bootstrap/_nav.scss +87 -29
- data/assets/stylesheets/bootstrap/_navbar.scss +102 -148
- data/assets/stylesheets/bootstrap/_offcanvas.scss +125 -61
- data/assets/stylesheets/bootstrap/_pagination.scss +66 -21
- data/assets/stylesheets/bootstrap/_placeholders.scss +1 -1
- data/assets/stylesheets/bootstrap/_popover.scss +90 -52
- data/assets/stylesheets/bootstrap/_progress.scss +31 -11
- data/assets/stylesheets/bootstrap/_reboot.scss +32 -46
- data/assets/stylesheets/bootstrap/_root.scss +155 -22
- data/assets/stylesheets/bootstrap/_spinners.scss +38 -22
- data/assets/stylesheets/bootstrap/_tables.scss +40 -24
- data/assets/stylesheets/bootstrap/_toasts.scss +38 -16
- data/assets/stylesheets/bootstrap/_tooltip.scss +60 -56
- data/assets/stylesheets/bootstrap/_type.scss +3 -1
- data/assets/stylesheets/bootstrap/_utilities.scss +209 -33
- data/assets/stylesheets/bootstrap/_variables-dark.scss +102 -0
- data/assets/stylesheets/bootstrap/_variables.scss +415 -303
- data/assets/stylesheets/bootstrap/forms/_floating-labels.scss +39 -5
- data/assets/stylesheets/bootstrap/forms/_form-check.scss +51 -14
- data/assets/stylesheets/bootstrap/forms/_form-control.scss +36 -41
- data/assets/stylesheets/bootstrap/forms/_form-range.scss +3 -3
- data/assets/stylesheets/bootstrap/forms/_form-select.scss +12 -4
- data/assets/stylesheets/bootstrap/forms/_input-group.scss +20 -9
- data/assets/stylesheets/bootstrap/helpers/_color-bg.scss +7 -0
- data/assets/stylesheets/bootstrap/helpers/_colored-links.scss +20 -2
- data/assets/stylesheets/bootstrap/helpers/_focus-ring.scss +5 -0
- data/assets/stylesheets/bootstrap/helpers/_icon-link.scss +25 -0
- data/assets/stylesheets/bootstrap/helpers/_position.scss +7 -1
- data/assets/stylesheets/bootstrap/helpers/_ratio.scss +2 -2
- data/assets/stylesheets/bootstrap/helpers/_vr.scss +2 -2
- data/assets/stylesheets/bootstrap/mixins/_alert.scss +11 -4
- data/assets/stylesheets/bootstrap/mixins/_banner.scss +7 -0
- data/assets/stylesheets/bootstrap/mixins/_breakpoints.scss +8 -8
- data/assets/stylesheets/bootstrap/mixins/_buttons.scss +32 -95
- data/assets/stylesheets/bootstrap/mixins/_caret.scss +30 -25
- data/assets/stylesheets/bootstrap/mixins/_color-mode.scss +21 -0
- data/assets/stylesheets/bootstrap/mixins/_container.scss +4 -2
- data/assets/stylesheets/bootstrap/mixins/_forms.scss +38 -19
- data/assets/stylesheets/bootstrap/mixins/_gradients.scss +1 -1
- data/assets/stylesheets/bootstrap/mixins/_grid.scss +15 -15
- data/assets/stylesheets/bootstrap/mixins/_list-group.scss +2 -0
- data/assets/stylesheets/bootstrap/mixins/_pagination.scss +4 -25
- data/assets/stylesheets/bootstrap/mixins/_reset-text.scss +1 -1
- data/assets/stylesheets/bootstrap/mixins/_table-variants.scss +12 -9
- data/assets/stylesheets/bootstrap/mixins/_utilities.scss +14 -6
- data/assets/stylesheets/bootstrap/mixins/_visually-hidden.scss +6 -2
- data/assets/stylesheets/bootstrap/vendor/_rfs.scss +23 -29
- data/bootstrap.gemspec +3 -3
- data/lib/bootstrap/engine.rb +17 -2
- data/lib/bootstrap/version.rb +2 -2
- data/tasks/updater/js.rb +10 -5
- data/tasks/updater/network.rb +2 -2
- data/tasks/updater/scss.rb +2 -2
- data/tasks/updater.rb +2 -2
- data/test/dummy_rails/config/application.rb +0 -2
- data/test/dummy_rails/public/favicon.ico +0 -0
- data/test/gemfiles/rails_4_2.gemfile +2 -1
- data/test/gemfiles/rails_5_0.gemfile +1 -2
- data/test/gemfiles/rails_5_1.gemfile +1 -2
- data/test/gemfiles/rails_5_2.gemfile +7 -0
- data/test/gemfiles/rails_6_0.gemfile +1 -1
- data/test/gemfiles/rails_6_1.gemfile +1 -1
- data/test/gemfiles/rails_7_0_dartsass.gemfile +7 -0
- data/test/gemfiles/rails_7_0_sassc.gemfile +7 -0
- data/test/rails_test.rb +0 -5
- data/test/test_helper.rb +3 -2
- metadata +49 -29
- data/.travis.yml +0 -32
- data/assets/stylesheets/bootstrap/bootstrap-utilities.scss +0 -18
|
@@ -1,19 +1,16 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Bootstrap tooltip.js v5.
|
|
3
|
-
* Copyright 2011-
|
|
2
|
+
* Bootstrap tooltip.js v5.3.5 (https://getbootstrap.com/)
|
|
3
|
+
* Copyright 2011-2025 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('./
|
|
8
|
-
typeof define === 'function' && define.amd ? define(['@popperjs/core', './
|
|
9
|
-
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Tooltip = factory(global
|
|
10
|
-
})(this, (function (Popper,
|
|
7
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('@popperjs/core'), require('./base-component.js'), require('./dom/event-handler.js'), require('./dom/manipulator.js'), require('./util/index.js'), require('./util/sanitizer.js'), require('./util/template-factory.js')) :
|
|
8
|
+
typeof define === 'function' && define.amd ? define(['@popperjs/core', './base-component', './dom/event-handler', './dom/manipulator', './util/index', './util/sanitizer', './util/template-factory'], factory) :
|
|
9
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Tooltip = factory(global["@popperjs/core"], global.BaseComponent, global.EventHandler, global.Manipulator, global.Index, global.Sanitizer, global.TemplateFactory));
|
|
10
|
+
})(this, (function (Popper, BaseComponent, EventHandler, Manipulator, index_js, sanitizer_js, TemplateFactory) { 'use strict';
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
function _interopNamespace(e) {
|
|
15
|
-
if (e && e.__esModule) return e;
|
|
16
|
-
const n = Object.create(null);
|
|
12
|
+
function _interopNamespaceDefault(e) {
|
|
13
|
+
const n = Object.create(null, { [Symbol.toStringTag]: { value: 'Module' } });
|
|
17
14
|
if (e) {
|
|
18
15
|
for (const k in e) {
|
|
19
16
|
if (k !== 'default') {
|
|
@@ -29,702 +26,330 @@
|
|
|
29
26
|
return Object.freeze(n);
|
|
30
27
|
}
|
|
31
28
|
|
|
32
|
-
const Popper__namespace = /*#__PURE__*/
|
|
33
|
-
const Data__default = /*#__PURE__*/_interopDefaultLegacy(Data);
|
|
34
|
-
const EventHandler__default = /*#__PURE__*/_interopDefaultLegacy(EventHandler);
|
|
35
|
-
const Manipulator__default = /*#__PURE__*/_interopDefaultLegacy(Manipulator);
|
|
36
|
-
const SelectorEngine__default = /*#__PURE__*/_interopDefaultLegacy(SelectorEngine);
|
|
37
|
-
const BaseComponent__default = /*#__PURE__*/_interopDefaultLegacy(BaseComponent);
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* --------------------------------------------------------------------------
|
|
41
|
-
* Bootstrap (v5.1.3): util/index.js
|
|
42
|
-
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
|
43
|
-
* --------------------------------------------------------------------------
|
|
44
|
-
*/
|
|
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
|
-
/**
|
|
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
|
-
};
|
|
29
|
+
const Popper__namespace = /*#__PURE__*/_interopNamespaceDefault(Popper);
|
|
180
30
|
|
|
181
31
|
/**
|
|
182
32
|
* --------------------------------------------------------------------------
|
|
183
|
-
* Bootstrap
|
|
33
|
+
* Bootstrap tooltip.js
|
|
184
34
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
|
185
35
|
* --------------------------------------------------------------------------
|
|
186
36
|
*/
|
|
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
37
|
|
|
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
38
|
|
|
293
39
|
/**
|
|
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
40
|
* Constants
|
|
302
|
-
* ------------------------------------------------------------------------
|
|
303
41
|
*/
|
|
304
42
|
|
|
305
43
|
const NAME = 'tooltip';
|
|
306
|
-
const DATA_KEY = 'bs.tooltip';
|
|
307
|
-
const EVENT_KEY = `.${DATA_KEY}`;
|
|
308
|
-
const CLASS_PREFIX = 'bs-tooltip';
|
|
309
44
|
const DISALLOWED_ATTRIBUTES = new Set(['sanitize', 'allowList', 'sanitizeFn']);
|
|
310
|
-
const
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
45
|
+
const CLASS_NAME_FADE = 'fade';
|
|
46
|
+
const CLASS_NAME_MODAL = 'modal';
|
|
47
|
+
const CLASS_NAME_SHOW = 'show';
|
|
48
|
+
const SELECTOR_TOOLTIP_INNER = '.tooltip-inner';
|
|
49
|
+
const SELECTOR_MODAL = `.${CLASS_NAME_MODAL}`;
|
|
50
|
+
const EVENT_MODAL_HIDE = 'hide.bs.modal';
|
|
51
|
+
const TRIGGER_HOVER = 'hover';
|
|
52
|
+
const TRIGGER_FOCUS = 'focus';
|
|
53
|
+
const TRIGGER_CLICK = 'click';
|
|
54
|
+
const TRIGGER_MANUAL = 'manual';
|
|
55
|
+
const EVENT_HIDE = 'hide';
|
|
56
|
+
const EVENT_HIDDEN = 'hidden';
|
|
57
|
+
const EVENT_SHOW = 'show';
|
|
58
|
+
const EVENT_SHOWN = 'shown';
|
|
59
|
+
const EVENT_INSERTED = 'inserted';
|
|
60
|
+
const EVENT_CLICK = 'click';
|
|
61
|
+
const EVENT_FOCUSIN = 'focusin';
|
|
62
|
+
const EVENT_FOCUSOUT = 'focusout';
|
|
63
|
+
const EVENT_MOUSEENTER = 'mouseenter';
|
|
64
|
+
const EVENT_MOUSELEAVE = 'mouseleave';
|
|
329
65
|
const AttachmentMap = {
|
|
330
66
|
AUTO: 'auto',
|
|
331
67
|
TOP: 'top',
|
|
332
|
-
RIGHT: isRTL() ? 'left' : 'right',
|
|
68
|
+
RIGHT: index_js.isRTL() ? 'left' : 'right',
|
|
333
69
|
BOTTOM: 'bottom',
|
|
334
|
-
LEFT: isRTL() ? 'right' : 'left'
|
|
70
|
+
LEFT: index_js.isRTL() ? 'right' : 'left'
|
|
335
71
|
};
|
|
336
72
|
const Default = {
|
|
73
|
+
allowList: sanitizer_js.DefaultAllowlist,
|
|
337
74
|
animation: true,
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
75
|
+
boundary: 'clippingParents',
|
|
76
|
+
container: false,
|
|
77
|
+
customClass: '',
|
|
341
78
|
delay: 0,
|
|
79
|
+
fallbackPlacements: ['top', 'right', 'bottom', 'left'],
|
|
342
80
|
html: false,
|
|
343
|
-
|
|
81
|
+
offset: [0, 6],
|
|
344
82
|
placement: 'top',
|
|
345
|
-
|
|
346
|
-
container: false,
|
|
347
|
-
fallbackPlacements: ['top', 'right', 'bottom', 'left'],
|
|
348
|
-
boundary: 'clippingParents',
|
|
349
|
-
customClass: '',
|
|
83
|
+
popperConfig: null,
|
|
350
84
|
sanitize: true,
|
|
351
85
|
sanitizeFn: null,
|
|
352
|
-
|
|
353
|
-
|
|
86
|
+
selector: false,
|
|
87
|
+
template: '<div class="tooltip" role="tooltip">' + '<div class="tooltip-arrow"></div>' + '<div class="tooltip-inner"></div>' + '</div>',
|
|
88
|
+
title: '',
|
|
89
|
+
trigger: 'hover focus'
|
|
354
90
|
};
|
|
355
|
-
const
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
91
|
+
const DefaultType = {
|
|
92
|
+
allowList: 'object',
|
|
93
|
+
animation: 'boolean',
|
|
94
|
+
boundary: '(string|element)',
|
|
95
|
+
container: '(string|element|boolean)',
|
|
96
|
+
customClass: '(string|function)',
|
|
97
|
+
delay: '(number|object)',
|
|
98
|
+
fallbackPlacements: 'array',
|
|
99
|
+
html: 'boolean',
|
|
100
|
+
offset: '(array|string|function)',
|
|
101
|
+
placement: '(string|function)',
|
|
102
|
+
popperConfig: '(null|object|function)',
|
|
103
|
+
sanitize: 'boolean',
|
|
104
|
+
sanitizeFn: '(null|function)',
|
|
105
|
+
selector: '(string|boolean)',
|
|
106
|
+
template: 'string',
|
|
107
|
+
title: '(string|element|function)',
|
|
108
|
+
trigger: 'string'
|
|
366
109
|
};
|
|
367
|
-
|
|
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';
|
|
110
|
+
|
|
379
111
|
/**
|
|
380
|
-
*
|
|
381
|
-
* Class Definition
|
|
382
|
-
* ------------------------------------------------------------------------
|
|
112
|
+
* Class definition
|
|
383
113
|
*/
|
|
384
114
|
|
|
385
|
-
class Tooltip extends
|
|
115
|
+
class Tooltip extends BaseComponent {
|
|
386
116
|
constructor(element, config) {
|
|
387
117
|
if (typeof Popper__namespace === 'undefined') {
|
|
388
|
-
throw new TypeError('Bootstrap\'s tooltips require Popper (https://popper.js.org)');
|
|
118
|
+
throw new TypeError('Bootstrap\'s tooltips require Popper (https://popper.js.org/docs/v2/)');
|
|
389
119
|
}
|
|
120
|
+
super(element, config);
|
|
390
121
|
|
|
391
|
-
|
|
392
|
-
|
|
122
|
+
// Private
|
|
393
123
|
this._isEnabled = true;
|
|
394
124
|
this._timeout = 0;
|
|
395
|
-
this.
|
|
125
|
+
this._isHovered = null;
|
|
396
126
|
this._activeTrigger = {};
|
|
397
|
-
this._popper = null;
|
|
127
|
+
this._popper = null;
|
|
128
|
+
this._templateFactory = null;
|
|
129
|
+
this._newContent = null;
|
|
398
130
|
|
|
399
|
-
|
|
131
|
+
// Protected
|
|
400
132
|
this.tip = null;
|
|
401
|
-
|
|
402
133
|
this._setListeners();
|
|
403
|
-
|
|
404
|
-
|
|
134
|
+
if (!this._config.selector) {
|
|
135
|
+
this._fixTitle();
|
|
136
|
+
}
|
|
137
|
+
}
|
|
405
138
|
|
|
139
|
+
// Getters
|
|
406
140
|
static get Default() {
|
|
407
141
|
return Default;
|
|
408
142
|
}
|
|
409
|
-
|
|
143
|
+
static get DefaultType() {
|
|
144
|
+
return DefaultType;
|
|
145
|
+
}
|
|
410
146
|
static get NAME() {
|
|
411
147
|
return NAME;
|
|
412
148
|
}
|
|
413
149
|
|
|
414
|
-
|
|
415
|
-
return Event;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
static get DefaultType() {
|
|
419
|
-
return DefaultType;
|
|
420
|
-
} // Public
|
|
421
|
-
|
|
422
|
-
|
|
150
|
+
// Public
|
|
423
151
|
enable() {
|
|
424
152
|
this._isEnabled = true;
|
|
425
153
|
}
|
|
426
|
-
|
|
427
154
|
disable() {
|
|
428
155
|
this._isEnabled = false;
|
|
429
156
|
}
|
|
430
|
-
|
|
431
157
|
toggleEnabled() {
|
|
432
158
|
this._isEnabled = !this._isEnabled;
|
|
433
159
|
}
|
|
434
|
-
|
|
435
|
-
toggle(event) {
|
|
160
|
+
toggle() {
|
|
436
161
|
if (!this._isEnabled) {
|
|
437
162
|
return;
|
|
438
163
|
}
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
context._activeTrigger.click = !context._activeTrigger.click;
|
|
444
|
-
|
|
445
|
-
if (context._isWithActiveTrigger()) {
|
|
446
|
-
context._enter(null, context);
|
|
447
|
-
} else {
|
|
448
|
-
context._leave(null, context);
|
|
449
|
-
}
|
|
450
|
-
} else {
|
|
451
|
-
if (this.getTipElement().classList.contains(CLASS_NAME_SHOW)) {
|
|
452
|
-
this._leave(null, this);
|
|
453
|
-
|
|
454
|
-
return;
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
this._enter(null, this);
|
|
164
|
+
if (this._isShown()) {
|
|
165
|
+
this._leave();
|
|
166
|
+
return;
|
|
458
167
|
}
|
|
168
|
+
this._enter();
|
|
459
169
|
}
|
|
460
|
-
|
|
461
170
|
dispose() {
|
|
462
171
|
clearTimeout(this._timeout);
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
this.tip.remove();
|
|
172
|
+
EventHandler.off(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler);
|
|
173
|
+
if (this._element.getAttribute('data-bs-original-title')) {
|
|
174
|
+
this._element.setAttribute('title', this._element.getAttribute('data-bs-original-title'));
|
|
467
175
|
}
|
|
468
|
-
|
|
469
176
|
this._disposePopper();
|
|
470
|
-
|
|
471
177
|
super.dispose();
|
|
472
178
|
}
|
|
473
|
-
|
|
474
179
|
show() {
|
|
475
180
|
if (this._element.style.display === 'none') {
|
|
476
181
|
throw new Error('Please use show on visible elements');
|
|
477
182
|
}
|
|
478
|
-
|
|
479
|
-
if (!(this.isWithContent() && this._isEnabled)) {
|
|
183
|
+
if (!(this._isWithContent() && this._isEnabled)) {
|
|
480
184
|
return;
|
|
481
185
|
}
|
|
482
|
-
|
|
483
|
-
const
|
|
484
|
-
const
|
|
485
|
-
const isInTheDom = shadowRoot === null ? this._element.ownerDocument.documentElement.contains(this._element) : shadowRoot.contains(this._element);
|
|
486
|
-
|
|
186
|
+
const showEvent = EventHandler.trigger(this._element, this.constructor.eventName(EVENT_SHOW));
|
|
187
|
+
const shadowRoot = index_js.findShadowRoot(this._element);
|
|
188
|
+
const isInTheDom = (shadowRoot || this._element.ownerDocument.documentElement).contains(this._element);
|
|
487
189
|
if (showEvent.defaultPrevented || !isInTheDom) {
|
|
488
190
|
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
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
if (this.constructor.NAME === 'tooltip' && this.tip && this.getTitle() !== this.tip.querySelector(SELECTOR_TOOLTIP_INNER).innerHTML) {
|
|
494
|
-
this._disposePopper();
|
|
495
|
-
|
|
496
|
-
this.tip.remove();
|
|
497
|
-
this.tip = null;
|
|
498
|
-
}
|
|
499
|
-
|
|
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
191
|
}
|
|
509
192
|
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
const
|
|
513
|
-
|
|
514
|
-
this._addAttachmentClass(attachment);
|
|
515
|
-
|
|
193
|
+
// TODO: v6 remove this or make it optional
|
|
194
|
+
this._disposePopper();
|
|
195
|
+
const tip = this._getTipElement();
|
|
196
|
+
this._element.setAttribute('aria-describedby', tip.getAttribute('id'));
|
|
516
197
|
const {
|
|
517
198
|
container
|
|
518
199
|
} = this._config;
|
|
519
|
-
Data__default.default.set(tip, this.constructor.DATA_KEY, this);
|
|
520
|
-
|
|
521
200
|
if (!this._element.ownerDocument.documentElement.contains(this.tip)) {
|
|
522
201
|
container.append(tip);
|
|
523
|
-
|
|
202
|
+
EventHandler.trigger(this._element, this.constructor.eventName(EVENT_INSERTED));
|
|
524
203
|
}
|
|
525
|
-
|
|
526
|
-
if (this._popper) {
|
|
527
|
-
this._popper.update();
|
|
528
|
-
} else {
|
|
529
|
-
this._popper = Popper__namespace.createPopper(this._element, tip, this._getPopperConfig(attachment));
|
|
530
|
-
}
|
|
531
|
-
|
|
204
|
+
this._popper = this._createPopper(tip);
|
|
532
205
|
tip.classList.add(CLASS_NAME_SHOW);
|
|
533
206
|
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
if (customClass) {
|
|
537
|
-
tip.classList.add(...customClass.split(' '));
|
|
538
|
-
} // If this is a touch-enabled device we add extra
|
|
207
|
+
// If this is a touch-enabled device we add extra
|
|
539
208
|
// empty mouseover listeners to the body's immediate children;
|
|
540
209
|
// only needed because of broken event delegation on iOS
|
|
541
210
|
// https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
|
|
542
|
-
|
|
543
|
-
|
|
544
211
|
if ('ontouchstart' in document.documentElement) {
|
|
545
|
-
[].concat(...document.body.children)
|
|
546
|
-
|
|
547
|
-
}
|
|
212
|
+
for (const element of [].concat(...document.body.children)) {
|
|
213
|
+
EventHandler.on(element, 'mouseover', index_js.noop);
|
|
214
|
+
}
|
|
548
215
|
}
|
|
549
|
-
|
|
550
216
|
const complete = () => {
|
|
551
|
-
|
|
552
|
-
this.
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
if (prevHoverState === HOVER_STATE_OUT) {
|
|
556
|
-
this._leave(null, this);
|
|
217
|
+
EventHandler.trigger(this._element, this.constructor.eventName(EVENT_SHOWN));
|
|
218
|
+
if (this._isHovered === false) {
|
|
219
|
+
this._leave();
|
|
557
220
|
}
|
|
221
|
+
this._isHovered = false;
|
|
558
222
|
};
|
|
559
|
-
|
|
560
|
-
const isAnimated = this.tip.classList.contains(CLASS_NAME_FADE);
|
|
561
|
-
|
|
562
|
-
this._queueCallback(complete, this.tip, isAnimated);
|
|
223
|
+
this._queueCallback(complete, this.tip, this._isAnimated());
|
|
563
224
|
}
|
|
564
|
-
|
|
565
225
|
hide() {
|
|
566
|
-
if (!this.
|
|
226
|
+
if (!this._isShown()) {
|
|
567
227
|
return;
|
|
568
228
|
}
|
|
569
|
-
|
|
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);
|
|
591
|
-
|
|
229
|
+
const hideEvent = EventHandler.trigger(this._element, this.constructor.eventName(EVENT_HIDE));
|
|
592
230
|
if (hideEvent.defaultPrevented) {
|
|
593
231
|
return;
|
|
594
232
|
}
|
|
233
|
+
const tip = this._getTipElement();
|
|
234
|
+
tip.classList.remove(CLASS_NAME_SHOW);
|
|
595
235
|
|
|
596
|
-
|
|
236
|
+
// If this is a touch-enabled device we remove the extra
|
|
597
237
|
// empty mouseover listeners we added for iOS support
|
|
598
|
-
|
|
599
238
|
if ('ontouchstart' in document.documentElement) {
|
|
600
|
-
[].concat(...document.body.children)
|
|
239
|
+
for (const element of [].concat(...document.body.children)) {
|
|
240
|
+
EventHandler.off(element, 'mouseover', index_js.noop);
|
|
241
|
+
}
|
|
601
242
|
}
|
|
602
|
-
|
|
603
243
|
this._activeTrigger[TRIGGER_CLICK] = false;
|
|
604
244
|
this._activeTrigger[TRIGGER_FOCUS] = false;
|
|
605
245
|
this._activeTrigger[TRIGGER_HOVER] = false;
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
this._queueCallback(complete, this.tip, isAnimated);
|
|
246
|
+
this._isHovered = null; // it is a trick to support manual triggering
|
|
609
247
|
|
|
610
|
-
|
|
248
|
+
const complete = () => {
|
|
249
|
+
if (this._isWithActiveTrigger()) {
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
if (!this._isHovered) {
|
|
253
|
+
this._disposePopper();
|
|
254
|
+
}
|
|
255
|
+
this._element.removeAttribute('aria-describedby');
|
|
256
|
+
EventHandler.trigger(this._element, this.constructor.eventName(EVENT_HIDDEN));
|
|
257
|
+
};
|
|
258
|
+
this._queueCallback(complete, this.tip, this._isAnimated());
|
|
611
259
|
}
|
|
612
|
-
|
|
613
260
|
update() {
|
|
614
|
-
if (this._popper
|
|
261
|
+
if (this._popper) {
|
|
615
262
|
this._popper.update();
|
|
616
263
|
}
|
|
617
|
-
} // Protected
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
isWithContent() {
|
|
621
|
-
return Boolean(this.getTitle());
|
|
622
264
|
}
|
|
623
265
|
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
266
|
+
// Protected
|
|
267
|
+
_isWithContent() {
|
|
268
|
+
return Boolean(this._getTitle());
|
|
269
|
+
}
|
|
270
|
+
_getTipElement() {
|
|
271
|
+
if (!this.tip) {
|
|
272
|
+
this.tip = this._createTipElement(this._newContent || this._getContentForTemplate());
|
|
627
273
|
}
|
|
628
|
-
|
|
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
274
|
return this.tip;
|
|
636
275
|
}
|
|
276
|
+
_createTipElement(content) {
|
|
277
|
+
const tip = this._getTemplateFactory(content).toHtml();
|
|
637
278
|
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
_sanitizeAndSetContent(template, content, selector) {
|
|
643
|
-
const templateElement = SelectorEngine__default.default.findOne(selector, template);
|
|
644
|
-
|
|
645
|
-
if (!content && templateElement) {
|
|
646
|
-
templateElement.remove();
|
|
647
|
-
return;
|
|
648
|
-
} // we use append for html objects to maintain js events
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
this.setElementContent(templateElement, content);
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
setElementContent(element, content) {
|
|
655
|
-
if (element === null) {
|
|
656
|
-
return;
|
|
279
|
+
// TODO: remove this check in v6
|
|
280
|
+
if (!tip) {
|
|
281
|
+
return null;
|
|
657
282
|
}
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
element.append(content);
|
|
666
|
-
}
|
|
667
|
-
} else {
|
|
668
|
-
element.textContent = content.textContent;
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
return;
|
|
283
|
+
tip.classList.remove(CLASS_NAME_FADE, CLASS_NAME_SHOW);
|
|
284
|
+
// TODO: v6 the following can be achieved with CSS only
|
|
285
|
+
tip.classList.add(`bs-${this.constructor.NAME}-auto`);
|
|
286
|
+
const tipId = index_js.getUID(this.constructor.NAME).toString();
|
|
287
|
+
tip.setAttribute('id', tipId);
|
|
288
|
+
if (this._isAnimated()) {
|
|
289
|
+
tip.classList.add(CLASS_NAME_FADE);
|
|
672
290
|
}
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
291
|
+
return tip;
|
|
292
|
+
}
|
|
293
|
+
setContent(content) {
|
|
294
|
+
this._newContent = content;
|
|
295
|
+
if (this._isShown()) {
|
|
296
|
+
this._disposePopper();
|
|
297
|
+
this.show();
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
_getTemplateFactory(content) {
|
|
301
|
+
if (this._templateFactory) {
|
|
302
|
+
this._templateFactory.changeContent(content);
|
|
680
303
|
} else {
|
|
681
|
-
|
|
304
|
+
this._templateFactory = new TemplateFactory({
|
|
305
|
+
...this._config,
|
|
306
|
+
// the `content` var has to be after `this._config`
|
|
307
|
+
// to override config.content in case of popover
|
|
308
|
+
content,
|
|
309
|
+
extraClass: this._resolvePossibleFunction(this._config.customClass)
|
|
310
|
+
});
|
|
682
311
|
}
|
|
312
|
+
return this._templateFactory;
|
|
683
313
|
}
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
return this._resolvePossibleFunction(title);
|
|
314
|
+
_getContentForTemplate() {
|
|
315
|
+
return {
|
|
316
|
+
[SELECTOR_TOOLTIP_INNER]: this._getTitle()
|
|
317
|
+
};
|
|
689
318
|
}
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
if (attachment === 'right') {
|
|
693
|
-
return 'end';
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
if (attachment === 'left') {
|
|
697
|
-
return 'start';
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
return attachment;
|
|
701
|
-
} // Private
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
_initializeOnDelegatedTarget(event, context) {
|
|
705
|
-
return context || this.constructor.getOrCreateInstance(event.delegateTarget, this._getDelegateConfig());
|
|
319
|
+
_getTitle() {
|
|
320
|
+
return this._resolvePossibleFunction(this._config.title) || this._element.getAttribute('data-bs-original-title');
|
|
706
321
|
}
|
|
707
322
|
|
|
323
|
+
// Private
|
|
324
|
+
_initializeOnDelegatedTarget(event) {
|
|
325
|
+
return this.constructor.getOrCreateInstance(event.delegateTarget, this._getDelegateConfig());
|
|
326
|
+
}
|
|
327
|
+
_isAnimated() {
|
|
328
|
+
return this._config.animation || this.tip && this.tip.classList.contains(CLASS_NAME_FADE);
|
|
329
|
+
}
|
|
330
|
+
_isShown() {
|
|
331
|
+
return this.tip && this.tip.classList.contains(CLASS_NAME_SHOW);
|
|
332
|
+
}
|
|
333
|
+
_createPopper(tip) {
|
|
334
|
+
const placement = index_js.execute(this._config.placement, [this, tip, this._element]);
|
|
335
|
+
const attachment = AttachmentMap[placement.toUpperCase()];
|
|
336
|
+
return Popper__namespace.createPopper(this._element, tip, this._getPopperConfig(attachment));
|
|
337
|
+
}
|
|
708
338
|
_getOffset() {
|
|
709
339
|
const {
|
|
710
340
|
offset
|
|
711
341
|
} = this._config;
|
|
712
|
-
|
|
713
342
|
if (typeof offset === 'string') {
|
|
714
|
-
return offset.split(',').map(
|
|
343
|
+
return offset.split(',').map(value => Number.parseInt(value, 10));
|
|
715
344
|
}
|
|
716
|
-
|
|
717
345
|
if (typeof offset === 'function') {
|
|
718
346
|
return popperData => offset(popperData, this._element);
|
|
719
347
|
}
|
|
720
|
-
|
|
721
348
|
return offset;
|
|
722
349
|
}
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
return typeof content === 'function' ? content.call(this._element) : content;
|
|
350
|
+
_resolvePossibleFunction(arg) {
|
|
351
|
+
return index_js.execute(arg, [this._element, this._element]);
|
|
726
352
|
}
|
|
727
|
-
|
|
728
353
|
_getPopperConfig(attachment) {
|
|
729
354
|
const defaultBsPopperConfig = {
|
|
730
355
|
placement: attachment,
|
|
@@ -749,256 +374,170 @@
|
|
|
749
374
|
element: `.${this.constructor.NAME}-arrow`
|
|
750
375
|
}
|
|
751
376
|
}, {
|
|
752
|
-
name: '
|
|
377
|
+
name: 'preSetPlacement',
|
|
753
378
|
enabled: true,
|
|
754
|
-
phase: '
|
|
755
|
-
fn: data =>
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
this._handlePopperPlacementChange(data);
|
|
379
|
+
phase: 'beforeMain',
|
|
380
|
+
fn: data => {
|
|
381
|
+
// Pre-set Popper's placement attribute in order to read the arrow sizes properly.
|
|
382
|
+
// Otherwise, Popper mixes up the width and height dimensions since the initial arrow style is for top placement
|
|
383
|
+
this._getTipElement().setAttribute('data-popper-placement', data.state.placement);
|
|
760
384
|
}
|
|
761
|
-
}
|
|
385
|
+
}]
|
|
762
386
|
};
|
|
763
|
-
return {
|
|
764
|
-
...
|
|
387
|
+
return {
|
|
388
|
+
...defaultBsPopperConfig,
|
|
389
|
+
...index_js.execute(this._config.popperConfig, [undefined, defaultBsPopperConfig])
|
|
765
390
|
};
|
|
766
391
|
}
|
|
767
|
-
|
|
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
392
|
_setListeners() {
|
|
777
393
|
const triggers = this._config.trigger.split(' ');
|
|
778
|
-
|
|
779
|
-
triggers.forEach(trigger => {
|
|
394
|
+
for (const trigger of triggers) {
|
|
780
395
|
if (trigger === 'click') {
|
|
781
|
-
|
|
396
|
+
EventHandler.on(this._element, this.constructor.eventName(EVENT_CLICK), this._config.selector, event => {
|
|
397
|
+
const context = this._initializeOnDelegatedTarget(event);
|
|
398
|
+
context.toggle();
|
|
399
|
+
});
|
|
782
400
|
} else if (trigger !== TRIGGER_MANUAL) {
|
|
783
|
-
const eventIn = trigger === TRIGGER_HOVER ? this.constructor.
|
|
784
|
-
const eventOut = trigger === TRIGGER_HOVER ? this.constructor.
|
|
785
|
-
|
|
786
|
-
|
|
401
|
+
const eventIn = trigger === TRIGGER_HOVER ? this.constructor.eventName(EVENT_MOUSEENTER) : this.constructor.eventName(EVENT_FOCUSIN);
|
|
402
|
+
const eventOut = trigger === TRIGGER_HOVER ? this.constructor.eventName(EVENT_MOUSELEAVE) : this.constructor.eventName(EVENT_FOCUSOUT);
|
|
403
|
+
EventHandler.on(this._element, eventIn, this._config.selector, event => {
|
|
404
|
+
const context = this._initializeOnDelegatedTarget(event);
|
|
405
|
+
context._activeTrigger[event.type === 'focusin' ? TRIGGER_FOCUS : TRIGGER_HOVER] = true;
|
|
406
|
+
context._enter();
|
|
407
|
+
});
|
|
408
|
+
EventHandler.on(this._element, eventOut, this._config.selector, event => {
|
|
409
|
+
const context = this._initializeOnDelegatedTarget(event);
|
|
410
|
+
context._activeTrigger[event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER] = context._element.contains(event.relatedTarget);
|
|
411
|
+
context._leave();
|
|
412
|
+
});
|
|
787
413
|
}
|
|
788
|
-
}
|
|
789
|
-
|
|
414
|
+
}
|
|
790
415
|
this._hideModalHandler = () => {
|
|
791
416
|
if (this._element) {
|
|
792
417
|
this.hide();
|
|
793
418
|
}
|
|
794
419
|
};
|
|
795
|
-
|
|
796
|
-
EventHandler__default.default.on(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler);
|
|
797
|
-
|
|
798
|
-
if (this._config.selector) {
|
|
799
|
-
this._config = { ...this._config,
|
|
800
|
-
trigger: 'manual',
|
|
801
|
-
selector: ''
|
|
802
|
-
};
|
|
803
|
-
} else {
|
|
804
|
-
this._fixTitle();
|
|
805
|
-
}
|
|
420
|
+
EventHandler.on(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler);
|
|
806
421
|
}
|
|
807
|
-
|
|
808
422
|
_fixTitle() {
|
|
809
423
|
const title = this._element.getAttribute('title');
|
|
810
|
-
|
|
811
|
-
const originalTitleType = typeof this._element.getAttribute('data-bs-original-title');
|
|
812
|
-
|
|
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;
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
if (context.getTipElement().classList.contains(CLASS_NAME_SHOW) || context._hoverState === HOVER_STATE_SHOW) {
|
|
832
|
-
context._hoverState = HOVER_STATE_SHOW;
|
|
424
|
+
if (!title) {
|
|
833
425
|
return;
|
|
834
426
|
}
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
context._hoverState = HOVER_STATE_SHOW;
|
|
838
|
-
|
|
839
|
-
if (!context._config.delay || !context._config.delay.show) {
|
|
840
|
-
context.show();
|
|
841
|
-
return;
|
|
427
|
+
if (!this._element.getAttribute('aria-label') && !this._element.textContent.trim()) {
|
|
428
|
+
this._element.setAttribute('aria-label', title);
|
|
842
429
|
}
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
if (context._hoverState === HOVER_STATE_SHOW) {
|
|
846
|
-
context.show();
|
|
847
|
-
}
|
|
848
|
-
}, context._config.delay.show);
|
|
430
|
+
this._element.setAttribute('data-bs-original-title', title); // DO NOT USE IT. Is only for backwards compatibility
|
|
431
|
+
this._element.removeAttribute('title');
|
|
849
432
|
}
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
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()) {
|
|
433
|
+
_enter() {
|
|
434
|
+
if (this._isShown() || this._isHovered) {
|
|
435
|
+
this._isHovered = true;
|
|
859
436
|
return;
|
|
860
437
|
}
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
438
|
+
this._isHovered = true;
|
|
439
|
+
this._setTimeout(() => {
|
|
440
|
+
if (this._isHovered) {
|
|
441
|
+
this.show();
|
|
442
|
+
}
|
|
443
|
+
}, this._config.delay.show);
|
|
444
|
+
}
|
|
445
|
+
_leave() {
|
|
446
|
+
if (this._isWithActiveTrigger()) {
|
|
867
447
|
return;
|
|
868
448
|
}
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
if (
|
|
872
|
-
|
|
449
|
+
this._isHovered = false;
|
|
450
|
+
this._setTimeout(() => {
|
|
451
|
+
if (!this._isHovered) {
|
|
452
|
+
this.hide();
|
|
873
453
|
}
|
|
874
|
-
},
|
|
454
|
+
}, this._config.delay.hide);
|
|
455
|
+
}
|
|
456
|
+
_setTimeout(handler, timeout) {
|
|
457
|
+
clearTimeout(this._timeout);
|
|
458
|
+
this._timeout = setTimeout(handler, timeout);
|
|
875
459
|
}
|
|
876
|
-
|
|
877
460
|
_isWithActiveTrigger() {
|
|
878
|
-
|
|
879
|
-
if (this._activeTrigger[trigger]) {
|
|
880
|
-
return true;
|
|
881
|
-
}
|
|
882
|
-
}
|
|
883
|
-
|
|
884
|
-
return false;
|
|
461
|
+
return Object.values(this._activeTrigger).includes(true);
|
|
885
462
|
}
|
|
886
|
-
|
|
887
463
|
_getConfig(config) {
|
|
888
|
-
const dataAttributes =
|
|
889
|
-
Object.keys(dataAttributes)
|
|
890
|
-
if (DISALLOWED_ATTRIBUTES.has(
|
|
891
|
-
delete dataAttributes[
|
|
464
|
+
const dataAttributes = Manipulator.getDataAttributes(this._element);
|
|
465
|
+
for (const dataAttribute of Object.keys(dataAttributes)) {
|
|
466
|
+
if (DISALLOWED_ATTRIBUTES.has(dataAttribute)) {
|
|
467
|
+
delete dataAttributes[dataAttribute];
|
|
892
468
|
}
|
|
893
|
-
}
|
|
894
|
-
config = {
|
|
469
|
+
}
|
|
470
|
+
config = {
|
|
895
471
|
...dataAttributes,
|
|
896
472
|
...(typeof config === 'object' && config ? config : {})
|
|
897
473
|
};
|
|
898
|
-
config
|
|
899
|
-
|
|
474
|
+
config = this._mergeConfigObj(config);
|
|
475
|
+
config = this._configAfterMerge(config);
|
|
476
|
+
this._typeCheckConfig(config);
|
|
477
|
+
return config;
|
|
478
|
+
}
|
|
479
|
+
_configAfterMerge(config) {
|
|
480
|
+
config.container = config.container === false ? document.body : index_js.getElement(config.container);
|
|
900
481
|
if (typeof config.delay === 'number') {
|
|
901
482
|
config.delay = {
|
|
902
483
|
show: config.delay,
|
|
903
484
|
hide: config.delay
|
|
904
485
|
};
|
|
905
486
|
}
|
|
906
|
-
|
|
907
487
|
if (typeof config.title === 'number') {
|
|
908
488
|
config.title = config.title.toString();
|
|
909
489
|
}
|
|
910
|
-
|
|
911
490
|
if (typeof config.content === 'number') {
|
|
912
491
|
config.content = config.content.toString();
|
|
913
492
|
}
|
|
914
|
-
|
|
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
493
|
return config;
|
|
922
494
|
}
|
|
923
|
-
|
|
924
495
|
_getDelegateConfig() {
|
|
925
496
|
const config = {};
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
config[key] = this._config[key];
|
|
497
|
+
for (const [key, value] of Object.entries(this._config)) {
|
|
498
|
+
if (this.constructor.Default[key] !== value) {
|
|
499
|
+
config[key] = value;
|
|
930
500
|
}
|
|
931
|
-
}
|
|
501
|
+
}
|
|
502
|
+
config.selector = false;
|
|
503
|
+
config.trigger = 'manual';
|
|
504
|
+
|
|
505
|
+
// In the future can be replaced with:
|
|
932
506
|
// const keysWithDifferentValues = Object.entries(this._config).filter(entry => this.constructor.Default[entry[0]] !== this._config[entry[0]])
|
|
933
507
|
// `Object.fromEntries(keysWithDifferentValues)`
|
|
934
|
-
|
|
935
|
-
|
|
936
508
|
return config;
|
|
937
509
|
}
|
|
938
|
-
|
|
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
510
|
_disposePopper() {
|
|
970
511
|
if (this._popper) {
|
|
971
512
|
this._popper.destroy();
|
|
972
|
-
|
|
973
513
|
this._popper = null;
|
|
974
514
|
}
|
|
975
|
-
|
|
976
|
-
|
|
515
|
+
if (this.tip) {
|
|
516
|
+
this.tip.remove();
|
|
517
|
+
this.tip = null;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
977
520
|
|
|
521
|
+
// Static
|
|
978
522
|
static jQueryInterface(config) {
|
|
979
523
|
return this.each(function () {
|
|
980
524
|
const data = Tooltip.getOrCreateInstance(this, config);
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
}
|
|
986
|
-
|
|
987
|
-
data[config]();
|
|
525
|
+
if (typeof config !== 'string') {
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
528
|
+
if (typeof data[config] === 'undefined') {
|
|
529
|
+
throw new TypeError(`No method named "${config}"`);
|
|
988
530
|
}
|
|
531
|
+
data[config]();
|
|
989
532
|
});
|
|
990
533
|
}
|
|
991
|
-
|
|
992
534
|
}
|
|
535
|
+
|
|
993
536
|
/**
|
|
994
|
-
* ------------------------------------------------------------------------
|
|
995
537
|
* jQuery
|
|
996
|
-
* ------------------------------------------------------------------------
|
|
997
|
-
* add .Tooltip to jQuery only if jQuery is present
|
|
998
538
|
*/
|
|
999
539
|
|
|
1000
|
-
|
|
1001
|
-
defineJQueryPlugin(Tooltip);
|
|
540
|
+
index_js.defineJQueryPlugin(Tooltip);
|
|
1002
541
|
|
|
1003
542
|
return Tooltip;
|
|
1004
543
|
|