Vidstack creates duplicate video media-controls when using Plyr layout
Current Behavior:
I have multiple buttons that show videos on the same location in the page. To do this I keep an array of node subtrees of each player and I'm removing (with element.remove()) and adding back subtrees (with parent.appendChild()) to the main DOM. If visible video is playing and I remove it then append another one, then remove it and re-append the first one, controls of the first one are duplicated, but this happen only when using the PlyrLayout layout.
In prod I'm using Plyr (and my subtrees moving mechanics works without any problems) and I'm trying to move to Vidstack, so this bug is a blocker for me. Thanks!
Could be related to #1191 but I don't think so.
Expected Behavior:
No duplication of the controls when adding and removing node subtrees of players.
Steps To Reproduce:
Code
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>Vidstack Test</title>
<link rel="stylesheet" href="https://cdn.vidstack.io/player.css" />
<link rel="stylesheet" href="https://cdn.vidstack.io/plyr.css" />
<script type="module">
import {
PlyrLayout,
VidstackPlayer
} from 'https://cdn.vidstack.io/player';
const content = document.getElementById('content');
const playerContainers = [null, null];
async function createPlayer(button) {
const playerContainer = document.createElement('div');
playerContainer.className = 'video-wrapper';
playerContainer.innerHTML = `
<video class="video-player" preload="none" playsinline controls>
<source src="${button.dataset['src']}" type="video/mp4" />
</video>
`;
playerContainers[parseInt(button.dataset['index'])] = playerContainer;
const video = playerContainer.querySelector('.video-player');
const player = await VidstackPlayer.create({
target: video,
layout: new PlyrLayout({}),
});
}
for (const button of document.querySelectorAll('.video-button')) {
createPlayer(button);
button.addEventListener('click', () => {
const playerContainer = playerContainers[parseInt(button.dataset['index'])];
while (content.firstChild) {
content.firstChild.remove()
}
content.appendChild(playerContainer)
});
}
</script>
</head>
<body class="index-page">
<h1>Vidstack Test</h1>
<ul>
<li>
<button id="video1"
class="video-button"
data-index="0"
data-src="video/video-1.mp4">Video 1</button>
</li>
<li>
<button id="video2"
class="video-button"
data-index="1"
data-src="video/video-2.mp4">Video 2</button>
</li>
</ul>
<main id="content">
</main>
</body>
</html>
Set the two buttons' data-src to two different and accessible video sources then load the page and follow these steps
- Click
Video 1button - Click
Video 2button - Click
Video 1button - Click
Video 2button - Click
Video 1button (now there's at least two sets of player controls)
Environment:
- Framework: none
- Meta Framework: none
- Device: Macbook Pro@14
- OS: [email protected]
- Browser: Chrome@131
Anything Else?
I'm using the <video> tag because in production my site need to work without JS and the first video is already in the page, not like in my example.