That points to this line:
wrappers = container.querySelectorAll(".wrap");
Clicking the exit button causes the error.
Clicking on the exit button is supposed to remove the player, after the blue play button is clicked.
To test jsitor code click run not update.
code https://jsitor.com/KZMNnkSf5
https://jsfiddle.net/e631o2rq/
How is that fixed in the code?
function removePlayerHandler(evt) {
const el = evt.target;
let container = el.closest(".container");
let wrappers;
if (container) { //if multiple players
wrappers = container.querySelectorAll(".remove .wrap");
} else { //if single player
container = el.closest(".remove");
wrappers = container.querySelectorAll(".wrap");
}
wrappers.forEach(function (wrapper) {
if (wrapper.player) {
removePlayer(wrapper);
}
});
}
It used to look like this:
function removePlayerHandler(evt) {
const el = evt.target;
const container = el.closest(".container");
const wrapper = container.querySelector(".wrap");
if (wrapper.player) {
return removePlayer(wrapper);
}
}
</div>
</div>
</div>
</div>
</div>
<div >
<button type="button"></button>
<button type="button"></button>
<button type="button"></button>
</div>
CodePudding user response:
I'm not entirely sure what you're trying to do here, but it does look a little complicated. I might suggest just keeping things a lot simpler.
Here's an idea: https://jsitor.com/JOlxKAhhbL
Code attached below also so it can be read, but due to the sandboxing of iframes in stackoverflow, it fails to load the youtube player, instead, load the jsitor link above.
// Note: move data-id to `.wrap` element
const DEFAULT_PLAY_OPTIONS = {
events: {
onReady: function onPlayerReady(event) {
event.target.playVideo()
},
onStateChange: function onPlayerStateChange(event) {
// whatever you'd like
}
},
height: 360,
host: "https://www.youtube-nocookie.com",
playerVars: {
autoplay: 1,
controls: 1,
disablekb: 1,
fs: 0,
iv_load_policy: 3
},
width: 640
}
const removeAllPlayers = () => {
for (const wrapperEle of [...document.querySelectorAll('.embed-youtube.active')]) {
wrapperEle.querySelector('iframe').remove()
const videoEle = document.createElement('div')
videoEle.classList.add('video', 'embed-youtube')
wrapperEle.append(videoEle)
const curtainEle = wrapperEle.closest('.curtain,.curtain1')
curtainEle.classList.remove('slide')
wrapperEle.classList.remove('active')
}
}
const createAndPlayVideo = (playBtnEle) => {
const curtainEle = playBtnEle.closest('.curtain,.curtain1')
const wrapperEle = playBtnEle.closest('.wrap')
const embedYoutubeEle = wrapperEle.querySelector('.video')
const playOptions = {...DEFAULT_PLAY_OPTIONS}
playOptions.videoId = wrapperEle.getAttribute('data-id')
const player = new YT.Player(embedYoutubeEle, playOptions)
curtainEle.classList.add('slide')
wrapperEle.classList.add('active')
}
const bindPlayers = () => {
for (const playBtn of [...document.querySelectorAll('.playa')]) {
playBtn.addEventListener('click', function(clickEvent) {
createAndPlayVideo(clickEvent.target)
})
}
for (const stopBtn of [...document.querySelectorAll('.exit')]) {
stopBtn.addEventListener('click', function(clickEvent) {
removeAllPlayers()
})
}
}
const init = () => {
bindPlayers()
}
init()
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
body {
background: #302b63;
}
.button-container {
display: flex;
flex-wrap: wrap;
min-height: 100%;
margin: auto;
justify-content: center;
align-content: center;
width: 290px;
gap: 10px;
background: green;
}
.container2 .container {
background: teal;
}
.container3 .container {
background: green;
}
.container1 {
position: absolute;
left: 0;
right: 0;
min-height: 100%;
min-width: 255px;
display: flex;
padding: 8px 8px;
}
.curtain1 {
flex: 1 0 0;
margin: auto;
max-width: 640px;
border: 21px solid;
border-radius: 12px;
border-color: #000 #101010 #000 #101010;
position: relative;
}
.ratio-keeper {
position: relative;
height: 0;
padding-top: 56.25%;
margin: auto;
overflow: hidden;
}
.container {
position: absolute;
left: 0;
right: 0;
min-height: 100%;
padding: 8px 8px;
}
.curtain {
margin: auto auto 40px;
max-width: 640px;
border: 21px solid;
border-radius: 12px;
border-color: #000 #101010 #000 #101010;
position: relative;
}
.embed-youtube iframe,
.embed-youtube .embed-youtube-play,
.embed-youtube .embed-youtube-play::before {
position: absolute;
}
.embed-youtube iframe {
height: 100%;
width: 100%;
top: 0;
left: 0;
}
.embed-youtube .embed-youtube-play {
-webkit-appearance: none;
appearance: none;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
margin: auto;
display: flex;
justify-content: center;
align-items: center;
width: 90px;
height: 90px;
border-radius: 50%;
cursor: pointer;
border: 9px solid blue;
background: transparent;
filter: drop-shadow(3px 3px 3px #000000b3);
z-index: 1;
}
.embed-youtube-play::before {
content: "";
width: 0;
height: 0;
border-top: 20px solid transparent;
border-bottom: 20px solid transparent;
border-left: 27px solid blue;
transform: translateX(4px);
}
.embed-youtube-play:hover {
box-shadow: 0 0 0 5px rgba(43, 179, 20, 0.5);
}
.embed-youtube-play:focus {
outline: 0;
box-shadow: 0 0 0 5px rgba(0, 255, 255, 0.5);
}
.embed-youtube.active .embed-youtube-play {
display: none;
}
@keyframes rotate {
0% {
transform: rotate(0deg);
}
99.9% {
border-color: red transparent red transparent;
pointer-events: none;
}
100% {
transform: rotate(360deg);
border-color: blue;
}
}
@keyframes triangle {
0% {
opacity: 0;
}
99.9% {
opacity: 0;
}
100% {
border-left-color: blue;
opacity: 1;
}
}
.exit {
position: absolute;
top: auto;
bottom: -47.63px;
margin: auto;
right: 0;
left: 0;
width: 47px;
height: 47px;
cursor: pointer;
border-radius: 100%;
background: transparent;
border: 5px solid red;
box-sizing: border-box;
clip-path: circle(50%);
}
.exit::before,
.exit::after {
content: "";
background-color: red;
width: 47px;
height: 5px;
position: absolute;
top: 0px;
left: -5px;
right: 0;
bottom: 0;
margin: auto;
}
.exit::before {
transform: rotate(45deg);
}
.exit::after {
transform: rotate(-45deg);
}
.exit.exitpPage2 {
position: absolute;
top: auto;
bottom: -47.63px;
margin: auto;
right: 200px;
left: 0;
border: 5px solid blue;
}
.exit.exitpPage2::before,
.exit.exitpPage2::after {
background-color: blue;
}
.exit.exitpPage3 {
position: absolute;
top: auto;
bottom: -47.63px;
margin: auto;
right: 0px;
left: 200px;
border: 5px solid purple;
}
.exit.exitpPage3::before,
.exit.exitpPage3::after {
background-color: purple;
}
.hide {
display: none;
}
<div >
<div >
<div >
<div ></div>
<div data-id="djV11Xbc914">
<div >
</div>
<button type="button"></button>
</div>
</div>
</div>
</div>
<div >
<div >
<div >
<div >
<div ></div>
<div >
<div data-id="djV11Xbc914">
</div>
<button type="button"></button>
</div>
</div>
</div>
<div >
<div >
<div ></div>
<div >
<div data-id="djV11Xbc914">
</div>
<button type="button"></button>
</div>
</div>
</div>
<div >
<div >
<div ></div>
<div >
<div data-id="djV11Xbc914">
</div>
<button type="button"></button>
</div>
</div>
</div>
<div >
<div >
<div ></div>
<div >
<div data-id="djV11Xbc914">
</div>
<button type="button"></button>
</div>
</div>
</div>
<div >
<div >
<div ></div>
<div >
<div data-id="djV11Xbc914">
</div>
<button type="button"></button>
</div>
</div>
</div>
</div>
</div>
<div >
<div >
<div >
<div >
<div ></div>
<div >
<div data-id="djV11Xbc914">
</div>
<button type="button"></button>
</div>
</div>
</div>
<div >
<div >
<div ></div>
<div >
<div data-id="djV11Xbc914">
</div>
<button type="button"></button>
</div>
</div>
</div>
<div >
<div >
<div ></div>
<div >
<div data-id="djV11Xbc914">
</div>
<button type="button"></button>
</div>
</div>
</div>
<div >
<div >
<div ></div>
<div >
<div data-id="djV11Xbc914">
</div>
<button type="button"></button>
</div>
</div>
</div>
<div >
<div >
<div ></div>
<div >
<div data-id="djV11Xbc914">
</div>
<button type="button"></button>
</div>
</div>
</div>
</div>
</div>
<div >
<button type="button"></button>
<button type="button"></button>
<button type="button"></button>
</div>
<script src="https://www.youtube.com/player_api"></script>