mirror of
https://github.com/videojs/video.js.git
synced 2025-01-25 11:13:52 +02:00
fix(shadow-dom): prevent warning 'element supplied is not included' (#8192)
Co-authored-by: Giuseppe Piscopo <g.piscopo@braincrumbz.com>
This commit is contained in:
parent
3dece507bc
commit
dc1e2bb42a
@ -52,7 +52,7 @@
|
||||
"minify:css:cdn": "cleancss dist/alt/video-js-cdn.css -o dist/alt/video-js-cdn.min.css",
|
||||
"minify:css:default": "cleancss dist/video-js.css -o dist/video-js.min.css",
|
||||
"watch": "npm-run-all -p watch:*",
|
||||
"watch:lang": "chokidar --initial 'lang/**/!(zh-Hans|zh-Hant)*.json' -c 'npm run build:lang'",
|
||||
"watch:lang": "chokidar --initial \"lang/**/!(zh-Hans|zh-Hant)*.json\" -c \"npm run build:lang\"",
|
||||
"watch:rollup": "rollup -c -w --no-progress",
|
||||
"watch:types": "tsc -w",
|
||||
"watch:css": "npm-run-all -p build:css:default build:css:cdn watch:css:*",
|
||||
|
79
sandbox/shadow-dom.html.example
Normal file
79
sandbox/shadow-dom.html.example
Normal file
@ -0,0 +1,79 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Video.js Sandbox</title>
|
||||
<link href="../dist/video-js.css" rel="stylesheet" type="text/css">
|
||||
<script src="../dist/video.js"></script>
|
||||
<link rel="icon" href="data:;base64,=">
|
||||
</head>
|
||||
<body>
|
||||
<div style="background-color:#eee; border: 1px solid #777; padding: 10px; margin-bottom: 20px; font-size: .8em; line-height: 1.5em; font-family: Verdana, sans-serif;">
|
||||
<p>You can use /sandbox/ for writing and testing your own code. Nothing in /sandbox/ will get checked into the repo, except files that end in .example (so don't edit or add those files). To get started run `npm start` and open the index.html</p>
|
||||
<pre>npm start</pre>
|
||||
<pre>open http://localhost:9999/sandbox/index.html</pre>
|
||||
</div>
|
||||
|
||||
<p>Tap on video to play/pause</p>
|
||||
|
||||
<test-custom-element id="customElement1"></test-custom-element>
|
||||
|
||||
<script>
|
||||
// Custom Element definition
|
||||
class TestCustomElement extends HTMLElement {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
const shadowRoot = this.attachShadow({ mode: 'closed' });
|
||||
|
||||
const styleLinkElem = document.createElement('link');
|
||||
|
||||
styleLinkElem.setAttribute('rel', 'stylesheet');
|
||||
styleLinkElem.setAttribute('href', '../dist/video-js.css')
|
||||
shadowRoot.append(styleLinkElem);
|
||||
|
||||
const containerElem = document.createElement('div');
|
||||
|
||||
containerElem.setAttribute('data-vjs-player', '');
|
||||
shadowRoot.appendChild(containerElem);
|
||||
|
||||
const videoElem = document.createElement('video');
|
||||
|
||||
videoElem.setAttribute('preload', 'auto');
|
||||
videoElem.setAttribute('width', 640);
|
||||
videoElem.setAttribute('height', 260);
|
||||
containerElem.appendChild(videoElem);
|
||||
|
||||
const sourceElem = document.createElement('source');
|
||||
|
||||
sourceElem.setAttribute('src', 'https://vjs.zencdn.net/v/oceans.mp4');
|
||||
sourceElem.setAttribute('type', 'video/mp4');
|
||||
videoElem.appendChild(sourceElem);
|
||||
|
||||
this.innerPlayer = videojs(videoElem);
|
||||
|
||||
containerElem.addEventListener('click', () => {
|
||||
if (this.innerPlayer.paused()) {
|
||||
this.innerPlayer.play();
|
||||
}
|
||||
else {
|
||||
this.innerPlayer.pause();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define('test-custom-element', TestCustomElement);
|
||||
|
||||
// Main entry point
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
var customElem = document.getElementById('customElement1');
|
||||
var innerPlayer = customElem.innerPlayer;
|
||||
innerPlayer.log('Shadow DOM inner player created', innerPlayer);
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -149,7 +149,12 @@ function videojs(id, options, ready) {
|
||||
// This will make sure that the element is indeed in the dom of that document.
|
||||
// Additionally, check that the document in question has a default view.
|
||||
// If the document is no longer attached to the dom, the defaultView of the document will be null.
|
||||
if (!el.ownerDocument.defaultView || !el.ownerDocument.body.contains(el)) {
|
||||
// If element is inside Shadow DOM (e.g. is part of a Custom element), ownerDocument.body
|
||||
// always returns false. Instead, use the Shadow DOM root.
|
||||
const inShadowDom = el.getRootNode() instanceof window.ShadowRoot;
|
||||
const rootNode = inShadowDom ? el.getRootNode() : el.ownerDocument.body;
|
||||
|
||||
if (!el.ownerDocument.defaultView || !rootNode.contains(el)) {
|
||||
log.warn('The element supplied is not included in the DOM');
|
||||
}
|
||||
|
||||
|
26
test/unit/utils/custom-element.test.js
Normal file
26
test/unit/utils/custom-element.test.js
Normal file
@ -0,0 +1,26 @@
|
||||
/* eslint-env browser */
|
||||
import videojs from '../../../src/js/video.js';
|
||||
|
||||
export class TestCustomElement extends HTMLElement {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
const shadowRoot = this.attachShadow({ mode: 'closed' });
|
||||
|
||||
const containerElem = document.createElement('div');
|
||||
|
||||
containerElem.setAttribute('data-vjs-player', '');
|
||||
shadowRoot.appendChild(containerElem);
|
||||
|
||||
const videoElem = document.createElement('video');
|
||||
|
||||
videoElem.setAttribute('width', 640);
|
||||
videoElem.setAttribute('height', 260);
|
||||
containerElem.appendChild(videoElem);
|
||||
|
||||
this.innerPlayer = videojs(videoElem);
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define('test-custom-element', TestCustomElement);
|
@ -4,6 +4,8 @@ import * as Dom from '../../src/js/utils/dom.js';
|
||||
import log from '../../src/js/utils/log.js';
|
||||
import document from 'global/document';
|
||||
import sinon from 'sinon';
|
||||
// import custom element for Shadow DOM test
|
||||
import './utils/custom-element.test';
|
||||
|
||||
QUnit.module('video.js', {
|
||||
beforeEach() {
|
||||
@ -84,6 +86,29 @@ QUnit.test(
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
'should not log if the supplied element is included in the Shadow DOM',
|
||||
function(assert) {
|
||||
const origWarnLog = log.warn;
|
||||
const fixture = document.getElementById('qunit-fixture');
|
||||
const warnLogs = [];
|
||||
|
||||
log.warn = (args) => {
|
||||
warnLogs.push(args);
|
||||
};
|
||||
|
||||
const customElem = document.createElement('test-custom-element');
|
||||
|
||||
fixture.appendChild(customElem);
|
||||
const innerPlayer = customElem.innerPlayer;
|
||||
|
||||
assert.ok(innerPlayer, 'created player within Shadow DOM');
|
||||
assert.equal(warnLogs.length, 0, 'no warn logs');
|
||||
|
||||
log.warn = origWarnLog;
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
'should log about already initialized players if options already passed',
|
||||
function(assert) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user