mirror of
https://github.com/twbs/bootstrap.git
synced 2025-08-08 22:56:46 +02:00
Allow Tooltips/Popovers to work in shadow DOM
This commit is contained in:
@@ -244,8 +244,9 @@ class Tooltip {
|
|||||||
if (this.isWithContent() && this._isEnabled) {
|
if (this.isWithContent() && this._isEnabled) {
|
||||||
$(this.element).trigger(showEvent)
|
$(this.element).trigger(showEvent)
|
||||||
|
|
||||||
|
const shadowRoot = Util.findShadowRoot(this.element)
|
||||||
const isInTheDom = $.contains(
|
const isInTheDom = $.contains(
|
||||||
this.element.ownerDocument.documentElement,
|
shadowRoot !== null ? shadowRoot : this.element.ownerDocument.documentElement,
|
||||||
this.element
|
this.element
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -142,6 +142,29 @@ const Util = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
findShadowRoot(element) {
|
||||||
|
if (!document.documentElement.attachShadow) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can find the shadow root otherwise it'll return the document
|
||||||
|
if (typeof element.getRootNode === 'function') {
|
||||||
|
const root = element.getRootNode()
|
||||||
|
return root instanceof ShadowRoot ? root : null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element instanceof ShadowRoot) {
|
||||||
|
return element
|
||||||
|
}
|
||||||
|
|
||||||
|
// when we don't find a shadow root
|
||||||
|
if (!element.parentNode) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return Util.findShadowRoot(element.parentNode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -124,4 +124,42 @@ $(function () {
|
|||||||
assert.expect(1)
|
assert.expect(1)
|
||||||
assert.ok(Util.supportsTransitionEnd())
|
assert.ok(Util.supportsTransitionEnd())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
QUnit.test('Util.findShadowRoot should find the shadow DOM root', function (assert) {
|
||||||
|
// Only for newer browsers
|
||||||
|
if (!document.documentElement.attachShadow) {
|
||||||
|
assert.expect(0)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.expect(2)
|
||||||
|
var $div = $('<div id="test"></div>').appendTo($('#qunit-fixture'))
|
||||||
|
var shadowRoot = $div[0].attachShadow({
|
||||||
|
mode: 'open'
|
||||||
|
})
|
||||||
|
console.warn($div[0].attachShadow, shadowRoot)
|
||||||
|
|
||||||
|
assert.equal(shadowRoot, Util.findShadowRoot(shadowRoot))
|
||||||
|
shadowRoot.innerHTML = '<button>Shadow Button</button>'
|
||||||
|
assert.equal(shadowRoot, Util.findShadowRoot(shadowRoot.firstChild))
|
||||||
|
})
|
||||||
|
|
||||||
|
QUnit.test('Util.findShadowRoot should return null when attachShadow is not available', function (assert) {
|
||||||
|
assert.expect(1)
|
||||||
|
|
||||||
|
var $div = $('<div id="test"></div>').appendTo($('#qunit-fixture'))
|
||||||
|
if (!document.documentElement.attachShadow) {
|
||||||
|
assert.equal(null, Util.findShadowRoot($div[0]))
|
||||||
|
} else {
|
||||||
|
var sandbox = sinon.createSandbox()
|
||||||
|
|
||||||
|
sandbox.replace(document.documentElement, 'attachShadow', function () {
|
||||||
|
// to avoid empty function
|
||||||
|
return $div
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.equal(null, Util.findShadowRoot($div[0]))
|
||||||
|
sandbox.restore()
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@@ -62,7 +62,12 @@
|
|||||||
</button>
|
</button>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-3">
|
||||||
<div id="target" title="Test tooltip on transformed element"></div>
|
<div id="target" title="Test tooltip on transformed element"></div>
|
||||||
|
</div>
|
||||||
|
<div id="shadow" class="pt-5"></div>
|
||||||
|
</div>
|
||||||
<div id="customContainer"></div>
|
<div id="customContainer"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -72,6 +77,21 @@
|
|||||||
<script src="../../dist/tooltip.js"></script>
|
<script src="../../dist/tooltip.js"></script>
|
||||||
<script>
|
<script>
|
||||||
$(function () {
|
$(function () {
|
||||||
|
if (typeof document.body.attachShadow === 'function') {
|
||||||
|
var shadowRoot = $('#shadow')[0].attachShadow({ mode: 'open' })
|
||||||
|
shadowRoot.innerHTML =
|
||||||
|
'<button type="button" class="btn btn-secondary" data-toggle="tooltip" data-placement="top" title="Tooltip on top in a shadow dom">' +
|
||||||
|
' Tooltip on top in a shadow dom' +
|
||||||
|
'</button>' +
|
||||||
|
'<button id="secondTooltip" type="button" class="btn btn-secondary" data-toggle="tooltip" data-placement="top" title="Tooltip on top in a shadow dom with container option">' +
|
||||||
|
' Tooltip on top in a shadow dom' +
|
||||||
|
'</button>'
|
||||||
|
|
||||||
|
$(shadowRoot.firstChild).tooltip()
|
||||||
|
$(shadowRoot.getElementById('secondTooltip')).tooltip({
|
||||||
|
container: shadowRoot
|
||||||
|
})
|
||||||
|
}
|
||||||
$('[data-toggle="tooltip"]').tooltip()
|
$('[data-toggle="tooltip"]').tooltip()
|
||||||
$('#tooltipElement').tooltip({
|
$('#tooltipElement').tooltip({
|
||||||
container: $('#customContainer')[0]
|
container: $('#customContainer')[0]
|
||||||
|
@@ -20,6 +20,7 @@ Things to know when using the popover plugin:
|
|||||||
- Popovers for `.disabled` or `disabled` elements must be triggered on a wrapper element.
|
- Popovers for `.disabled` or `disabled` elements must be triggered on a wrapper element.
|
||||||
- When triggered from anchors that wrap across multiple lines, popovers will be centered between the anchors' overall width. Use `.text-nowrap` on your `<a>`s to avoid this behavior.
|
- When triggered from anchors that wrap across multiple lines, popovers will be centered between the anchors' overall width. Use `.text-nowrap` on your `<a>`s to avoid this behavior.
|
||||||
- Popovers must be hidden before their corresponding elements have been removed from the DOM.
|
- Popovers must be hidden before their corresponding elements have been removed from the DOM.
|
||||||
|
- Popovers can be triggered thanks to an element inside a shadow DOM.
|
||||||
|
|
||||||
{% include callout-info-prefersreducedmotion.md %}
|
{% include callout-info-prefersreducedmotion.md %}
|
||||||
|
|
||||||
|
@@ -19,6 +19,7 @@ Things to know when using the tooltip plugin:
|
|||||||
- Tooltips for `.disabled` or `disabled` elements must be triggered on a wrapper element.
|
- Tooltips for `.disabled` or `disabled` elements must be triggered on a wrapper element.
|
||||||
- When triggered from hyperlinks that span multiple lines, tooltips will be centered. Use `white-space: nowrap;` on your `<a>`s to avoid this behavior.
|
- When triggered from hyperlinks that span multiple lines, tooltips will be centered. Use `white-space: nowrap;` on your `<a>`s to avoid this behavior.
|
||||||
- Tooltips must be hidden before their corresponding elements have been removed from the DOM.
|
- Tooltips must be hidden before their corresponding elements have been removed from the DOM.
|
||||||
|
- Tooltips can be triggered thanks to an element inside a shadow DOM.
|
||||||
|
|
||||||
{% include callout-info-prefersreducedmotion.md %}
|
{% include callout-info-prefersreducedmotion.md %}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user