diff options
author | Johann-S <johann.servoire@gmail.com> | 2017-11-30 12:54:27 +0300 |
---|---|---|
committer | Johann-S <johann.servoire@gmail.com> | 2018-12-05 18:02:59 +0300 |
commit | b16127fc105f159ebd06b02df2853941b2aba67c (patch) | |
tree | 45f5a0138c633e0e3aa6bd5357ffef4d14c8bc6f /js | |
parent | 850d99bb13b895b83a860c38092755253ceb5b4a (diff) |
Allow Tooltips/Popovers to work in shadow DOM
Diffstat (limited to 'js')
-rw-r--r-- | js/src/tooltip.js | 3 | ||||
-rw-r--r-- | js/src/util.js | 23 | ||||
-rw-r--r-- | js/tests/unit/util.js | 38 | ||||
-rw-r--r-- | js/tests/visual/tooltip.html | 22 |
4 files changed, 84 insertions, 2 deletions
diff --git a/js/src/tooltip.js b/js/src/tooltip.js index 1c40dfed34..9fa53a71b4 100644 --- a/js/src/tooltip.js +++ b/js/src/tooltip.js @@ -244,8 +244,9 @@ class Tooltip { if (this.isWithContent() && this._isEnabled) { $(this.element).trigger(showEvent) + const shadowRoot = Util.findShadowRoot(this.element) const isInTheDom = $.contains( - this.element.ownerDocument.documentElement, + shadowRoot !== null ? shadowRoot : this.element.ownerDocument.documentElement, this.element ) diff --git a/js/src/util.js b/js/src/util.js index e9665d24fd..1d804cf9da 100644 --- a/js/src/util.js +++ b/js/src/util.js @@ -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) } } diff --git a/js/tests/unit/util.js b/js/tests/unit/util.js index 61727304d4..2fd6f6b7cb 100644 --- a/js/tests/unit/util.js +++ b/js/tests/unit/util.js @@ -124,4 +124,42 @@ $(function () { assert.expect(1) 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() + } + }) }) diff --git a/js/tests/visual/tooltip.html b/js/tests/visual/tooltip.html index 436f5c1cd8..831f26d0a7 100644 --- a/js/tests/visual/tooltip.html +++ b/js/tests/visual/tooltip.html @@ -62,7 +62,12 @@ </button> </p> </div> - <div id="target" title="Test tooltip on transformed element"></div> + <div class="row"> + <div class="col-sm-3"> + <div id="target" title="Test tooltip on transformed element"></div> + </div> + <div id="shadow" class="pt-5"></div> + </div> <div id="customContainer"></div> </div> @@ -72,6 +77,21 @@ <script src="../../dist/tooltip.js"></script> <script> $(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() $('#tooltipElement').tooltip({ container: $('#customContainer')[0] |