mirror of
https://github.com/tabler/tabler.git
synced 2026-10-12 05:06:55 +04:00
Fix tab/tooltip/popover/dropdown/toast init firing too early (#3218)
This commit is contained in:
1 parent
d104e78947
commit
0f6e843977
7 files changed
+62
-42
No files matched your search
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/core": patch
|
||||
---
|
||||
|
||||
Fixed tab, tooltip, popover, dropdown and toast init running before `DOMContentLoaded`, dropping early listeners.
|
||||
+11
-8
@@ -1,15 +1,18 @@
|
||||
import { Dropdown } from './bootstrap'
|
||||
import Manipulator from './bootstrap/dom/manipulator'
|
||||
import { onDOMContentLoaded } from './bootstrap/util/index'
|
||||
|
||||
// js-docs-start dropdown-init
|
||||
for (const dropdownTriggerEl of document.querySelectorAll<HTMLElement>('[data-bs-toggle="dropdown"], [data-tblr-toggle="dropdown"]')) {
|
||||
try {
|
||||
const options = {
|
||||
boundary: Manipulator.getDataAttribute(dropdownTriggerEl, 'boundary') === 'viewport' ? document.documentElement : ('clippingParents' as const),
|
||||
onDOMContentLoaded(() => {
|
||||
for (const dropdownTriggerEl of document.querySelectorAll<HTMLElement>('[data-bs-toggle="dropdown"], [data-tblr-toggle="dropdown"]')) {
|
||||
try {
|
||||
const options = {
|
||||
boundary: Manipulator.getDataAttribute(dropdownTriggerEl, 'boundary') === 'viewport' ? document.documentElement : ('clippingParents' as const),
|
||||
}
|
||||
Dropdown.getOrCreateInstance(dropdownTriggerEl, options)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
Dropdown.getOrCreateInstance(dropdownTriggerEl, options)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
})
|
||||
// js-docs-end dropdown-init
|
||||
+12
-9
@@ -1,16 +1,19 @@
|
||||
import { Popover } from './bootstrap'
|
||||
import Manipulator from './bootstrap/dom/manipulator'
|
||||
import { onDOMContentLoaded } from './bootstrap/util/index'
|
||||
|
||||
// js-docs-start popover-init
|
||||
for (const popoverTriggerEl of document.querySelectorAll<HTMLElement>('[data-bs-toggle="popover"], [data-tblr-toggle="popover"]')) {
|
||||
try {
|
||||
const options = {
|
||||
delay: Manipulator.getDataAttribute(popoverTriggerEl, 'delay') ?? { show: 50, hide: 50 },
|
||||
placement: Manipulator.getDataAttribute(popoverTriggerEl, 'placement') ?? 'auto',
|
||||
onDOMContentLoaded(() => {
|
||||
for (const popoverTriggerEl of document.querySelectorAll<HTMLElement>('[data-bs-toggle="popover"], [data-tblr-toggle="popover"]')) {
|
||||
try {
|
||||
const options = {
|
||||
delay: Manipulator.getDataAttribute(popoverTriggerEl, 'delay') ?? { show: 50, hide: 50 },
|
||||
placement: Manipulator.getDataAttribute(popoverTriggerEl, 'placement') ?? 'auto',
|
||||
}
|
||||
Popover.getOrCreateInstance(popoverTriggerEl, options)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
Popover.getOrCreateInstance(popoverTriggerEl, options)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
})
|
||||
// js-docs-end popover-init
|
||||
+2
-1
@@ -1,4 +1,5 @@
|
||||
import { Tab } from './bootstrap'
|
||||
import { onDOMContentLoaded } from './bootstrap/util/index'
|
||||
|
||||
// js-docs-start tab-init
|
||||
export const EnableActivationTabsFromLocationHash = (): void => {
|
||||
@@ -23,5 +24,5 @@ export const EnableActivationTabsFromLocationHash = (): void => {
|
||||
}
|
||||
}
|
||||
|
||||
EnableActivationTabsFromLocationHash()
|
||||
onDOMContentLoaded(EnableActivationTabsFromLocationHash)
|
||||
// js-docs-end tab-init
|
||||
+18
-15
@@ -1,22 +1,25 @@
|
||||
import { Toast } from './bootstrap'
|
||||
import SelectorEngine from './bootstrap/dom/selector-engine'
|
||||
import { onDOMContentLoaded } from './bootstrap/util/index'
|
||||
|
||||
// js-docs-start toast-init
|
||||
for (const toastTriggerEl of document.querySelectorAll<HTMLElement>('[data-bs-toggle="toast"], [data-tblr-toggle="toast"]')) {
|
||||
try {
|
||||
// A trigger whose target is missing is left alone instead of getting a
|
||||
// click handler that throws.
|
||||
const toastEl = SelectorEngine.getElementFromSelector(toastTriggerEl)
|
||||
if (!toastEl) {
|
||||
continue
|
||||
}
|
||||
onDOMContentLoaded(() => {
|
||||
for (const toastTriggerEl of document.querySelectorAll<HTMLElement>('[data-bs-toggle="toast"], [data-tblr-toggle="toast"]')) {
|
||||
try {
|
||||
// A trigger whose target is missing is left alone instead of getting a
|
||||
// click handler that throws.
|
||||
const toastEl = SelectorEngine.getElementFromSelector(toastTriggerEl)
|
||||
if (!toastEl) {
|
||||
continue
|
||||
}
|
||||
|
||||
const toast = Toast.getOrCreateInstance(toastEl) as InstanceType<typeof Toast>
|
||||
toastTriggerEl.addEventListener('click', () => {
|
||||
toast.show()
|
||||
})
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
const toast = Toast.getOrCreateInstance(toastEl) as InstanceType<typeof Toast>
|
||||
toastTriggerEl.addEventListener('click', () => {
|
||||
toast.show()
|
||||
})
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
// js-docs-end toast-init
|
||||
+12
-9
@@ -1,19 +1,22 @@
|
||||
import { Tooltip } from './bootstrap'
|
||||
import Manipulator from './bootstrap/dom/manipulator'
|
||||
import { onDOMContentLoaded } from './bootstrap/util/index'
|
||||
|
||||
// js-docs-start tooltip-init
|
||||
// One element with a broken config must not stop the rest of the bundle, so
|
||||
// every instance is created on its own. `data-bs-delay` on the element wins
|
||||
// over the shorter default delay.
|
||||
for (const tooltipTriggerEl of document.querySelectorAll<HTMLElement>('[data-bs-toggle="tooltip"], [data-tblr-toggle="tooltip"]')) {
|
||||
try {
|
||||
const options = {
|
||||
delay: Manipulator.getDataAttribute(tooltipTriggerEl, 'delay') ?? { show: 50, hide: 50 },
|
||||
placement: Manipulator.getDataAttribute(tooltipTriggerEl, 'placement') ?? 'auto',
|
||||
onDOMContentLoaded(() => {
|
||||
for (const tooltipTriggerEl of document.querySelectorAll<HTMLElement>('[data-bs-toggle="tooltip"], [data-tblr-toggle="tooltip"]')) {
|
||||
try {
|
||||
const options = {
|
||||
delay: Manipulator.getDataAttribute(tooltipTriggerEl, 'delay') ?? { show: 50, hide: 50 },
|
||||
placement: Manipulator.getDataAttribute(tooltipTriggerEl, 'placement') ?? 'auto',
|
||||
}
|
||||
Tooltip.getOrCreateInstance(tooltipTriggerEl, options)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
Tooltip.getOrCreateInstance(tooltipTriggerEl, options)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
})
|
||||
// js-docs-end tooltip-init
|
||||
@@ -233,6 +233,8 @@ Tabler activates the tab that matches the URL hash on page load, so you can link
|
||||
|
||||
<CodeDocs name="tab-init" file="core/js/src/tab.ts" />
|
||||
|
||||
This runs on `DOMContentLoaded`, so `show.bs.tab` and `shown.bs.tab` for the hash tab fire before any script that itself waits for `DOMContentLoaded`. Add the listener earlier (a plain `<script>`, not one that is deferred or waits for the load event), or read `Tab.getInstance(triggerEl)` after `DOMContentLoaded` to find the tab that was activated.
|
||||
|
||||
## Accessibility
|
||||
|
||||
- Wrap the tabs in an element with `role="tablist"`, give each trigger `role="tab"` and each panel `role="tabpanel"`, and link them with `aria-controls` and `aria-labelledby`.
|
||||
|
||||
Reference in new issue
Block a user