const isInTheDom = (shadowRoot || this._element.ownerDocument.documentElement).contains(this._element)
if (showEvent.defaultPrevented || !isInTheDom) {
+ // Reset the transient hover/active state so a prevented (or not-in-DOM)
+ // show doesn't leave `_isHovered` stuck true — otherwise a click-triggered
+ // tip would hit the `_enter()` early-return on every later click and never
+ // reopen.
+ this._isHovered = false
return
}
}
}
- if (typeof config.title === 'number') {
+ // Coerce number/boolean title and content to strings. `data-bs-title="true"`
+ // / `data-bs-content="false"` are auto-converted to booleans by the data-API,
+ // which would otherwise fail the (null|string|element|function) type check.
+ if (typeof config.title === 'number' || typeof config.title === 'boolean') {
config.title = config.title.toString()
}
- if (typeof config.content === 'number') {
+ if (typeof config.content === 'number' || typeof config.content === 'boolean') {
config.content = config.content.toString()
}
expect(tooltip._config.content).toEqual('7')
})
+ it('should convert title and content to string if booleans (e.g. data-bs-content="true")', () => {
+ fixtureEl.innerHTML = '<a href="#" rel="tooltip" data-bs-title="true" data-bs-content="false"></a>'
+
+ const tooltipEl = fixtureEl.querySelector('a')
+ const tooltip = new Tooltip(tooltipEl)
+
+ expect(tooltip._config.title).toEqual('true')
+ expect(tooltip._config.content).toEqual('false')
+ })
+
it('should enable selector delegation', () => {
return new Promise(resolve => {
fixtureEl.innerHTML = '<div></div>'
})
})
+ it('should reset hover state when show is prevented so the tip can reopen', () => {
+ return new Promise(resolve => {
+ fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
+
+ const tooltipEl = fixtureEl.querySelector('a')
+ const tooltip = new Tooltip(tooltipEl)
+
+ const preventOnce = ev => {
+ ev.preventDefault()
+ tooltipEl.removeEventListener('show.bs.tooltip', preventOnce)
+ }
+
+ tooltipEl.addEventListener('show.bs.tooltip', preventOnce)
+
+ tooltipEl.addEventListener('shown.bs.tooltip', () => {
+ expect(document.querySelector('.tooltip')).not.toBeNull()
+ resolve()
+ })
+
+ // First show is prevented — `_isHovered` must not stay stuck true,
+ // otherwise the `_enter()` retry below would early-return and never reopen.
+ tooltip.show()
+ expect(tooltip._isHovered).toBeFalse()
+
+ tooltip._enter()
+ })
+ })
+
it('should show tooltip if leave event hasn\'t occurred before delay expires', () => {
return new Promise(resolve => {
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'