Это указывает на эту строку:
wrappers = container.querySelectorAll(".wrap");
Нажатие кнопки выхода вызывает ошибку.
Нажатие на кнопку выхода должно удалить игрока после нажатия синей кнопки воспроизведения.
Чтобы протестировать код jsitor, нажмите «Выполнить, а не обновлять».
код https://jsitor.com/KZMNnkSf5
https://jsfiddle.net/e631o2rq/
Как это фиксируется в коде?
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);
}
});
}
Раньше это выглядело так:
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 class = "button-container">
<button class = "exit" type = "button"></button>
<button class = "exit exitpPage2" type = "button"></button>
<button class = "exit exitpPage3" type = "button"></button>
</div>
Как исправить это в коде?
В настоящее время ваш код предполагает, что элемент находится где-то «под» элементом с классом «удалить». По-видимому, это не всегда так, поэтому вам придется либо исправить свой HTML, либо убедиться, что опубликованный код проверяет, возвращает ли этот .closest() вызов null.
Если он выше этого, как это будет исправлено в коде? Что бы изменить в javascript, чтобы справиться с этим? Что изменится в javascript, чтобы он мог смотреть вверх, а не вниз?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Я не совсем уверен, что вы пытаетесь сделать здесь, но это выглядит немного сложно. Я мог бы предложить просто сделать вещи намного проще.
Вот идея: https://jsitor.com/JOlxKAhhbL
Код также прикреплен ниже, чтобы его можно было прочитать, но из-за песочницы iframes в stackoverflow он не может загрузить проигрыватель YouTube, вместо этого загрузите ссылку jsitor выше.
// 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 class = "container1">
<div class = "curtain1 remove">
<div class = "ratio-keeper">
<div class = "video-one"></div>
<div class = "wrap embed-youtube" data-id = "djV11Xbc914">
<div class = "video embed-youtube ">
</div>
<button class = "playa cover embed-youtube-play" type = "button"></button>
</div>
</div>
</div>
</div>
<div class = "container2 hide">
<div class = "container ">
<div class = "curtain remove">
<div class = "ratio-keeper">
<div class = "video-two"></div>
<div class = "wrap embed-youtube">
<div class = "video embed-youtube" data-id = "djV11Xbc914">
</div>
<button class = "playb cover embed-youtube-play" type = "button"></button>
</div>
</div>
</div>
<div class = "curtain remove">
<div class = "ratio-keeper">
<div class = "video-three"></div>
<div class = "wrap embed-youtube">
<div class = "video embed-youtube" data-id = "djV11Xbc914">
</div>
<button class = "playc cover embed-youtube-play" type = "button"></button>
</div>
</div>
</div>
<div class = "curtain remove">
<div class = "ratio-keeper">
<div class = "video-four"></div>
<div class = "wrap embed-youtube">
<div class = "video embed-youtube" data-id = "djV11Xbc914">
</div>
<button class = "playd cover embed-youtube-play" type = "button"></button>
</div>
</div>
</div>
<div class = "curtain remove">
<div class = "ratio-keeper">
<div class = "video-five"></div>
<div class = "wrap embed-youtube">
<div class = "video embed-youtube" data-id = "djV11Xbc914">
</div>
<button class = "playe cover embed-youtube-play" type = "button"></button>
</div>
</div>
</div>
<div class = "curtain remove">
<div class = "ratio-keeper">
<div class = "video-six"></div>
<div class = "wrap embed-youtube">
<div class = "video embed-youtube" data-id = "djV11Xbc914">
</div>
<button class = "playf cover embed-youtube-play" type = "button"></button>
</div>
</div>
</div>
</div>
</div>
<div class = "container3 hide">
<div class = "container ">
<div class = "curtain remove">
<div class = "ratio-keeper">
<div class = "video-seven"></div>
<div class = "wrap embed-youtube">
<div class = "video embed-youtube" data-id = "djV11Xbc914">
</div>
<button class = "playg cover embed-youtube-play" type = "button"></button>
</div>
</div>
</div>
<div class = "curtain remove">
<div class = "ratio-keeper">
<div class = "video-eight"></div>
<div class = "wrap embed-youtube">
<div class = "video embed-youtube" data-id = "djV11Xbc914">
</div>
<button class = "playh cover embed-youtube-play" type = "button"></button>
</div>
</div>
</div>
<div class = "curtain remove">
<div class = "ratio-keeper">
<div class = "video-nine"></div>
<div class = "wrap embed-youtube">
<div class = "video embed-youtube" data-id = "djV11Xbc914">
</div>
<button class = "playi cover embed-youtube-play" type = "button"></button>
</div>
</div>
</div>
<div class = "curtain remove">
<div class = "ratio-keeper">
<div class = "video-ten"></div>
<div class = "wrap embed-youtube">
<div class = "video embed-youtube" data-id = "djV11Xbc914">
</div>
<button class = "playj cover embed-youtube-play" type = "button"></button>
</div>
</div>
</div>
<div class = "curtain remove">
<div class = "ratio-keeper">
<div class = "video-eleven"></div>
<div class = "wrap embed-youtube">
<div class = "video embed-youtube" data-id = "djV11Xbc914">
</div>
<button class = "playk cover embed-youtube-play" type = "button"></button>
</div>
</div>
</div>
</div>
</div>
<div class = "button-container">
<button class = "exit" type = "button"></button>
<button class = "exit exitpPage2" type = "button"></button>
<button class = "exit exitpPage3" type = "button"></button>
</div>
<script src = "https://www.youtube.com/player_api"></script>Этот код настроен аналогично, с контейнером внизу. Сможете ли вы заставить это работать? Этот код, который я пытаюсь заставить работать, имеет кнопки воспроизведения внизу внутри своего собственного контейнера. jsitor.com/MIYiywN4HC / jsfiddle.net/kxhyLdr8 Что странно в этом коде, так это то, что после нажатия на кнопки не появляются ошибки, хотя они должны быть. Вот демонстрационный код, который работает с кнопками воспроизведения не внутри их собственного контейнера. jsfiddle.net/24xf0avp
Никто не смог понять, как это можно сделать, заставив кнопки воспроизведения работать внутри их собственного контейнера.
Я честно с трудом понимаю, чего вы хотите. Я думаю, вы пытаетесь сформулировать множество разных проблем или пытаетесь достичь чего-то, что, вероятно, выходит за рамки вашего текущего уровня навыков. Для того, чтобы все могли помочь (и мы будем), пожалуйста, постарайтесь четко определить, чего именно вы пытаетесь достичь. Попробуйте использовать каркасный инструмент, такой как wireframe.cc, чтобы дать нам представление о том, чего вы хотите достичь. У вас много javascript-кода и html-разметки, но это очень запутывает даже некоторых из нас с опытом. Спасибо
Вот рабочий демонстрационный код только с 1 кнопкой. jsitor.com/Qer_1Oi9Jv / jsfiddle.net/1bmrwuzn Вот битый код только с 1 кнопкой. jsitor.com/D38vgjs3g / jsfiddle.net/gt57k29h
Возможно, мне просто нужно расширить код javascript, чтобы он достиг внутреннего узла html. Если да, то как это сделать? Это было доведено до моего сведения: «в событии нажатия кнопки он, вероятно, захватывает родительский элемент вместо целевого элемента?»
Еще раз, пожалуйста, позвольте мне быть ясным. Можете ли вы сказать, чего вы хотите? «Вот рабочая демонстрация» интерпретируется как «Я решил свою проблему». Но я точно не знаю, чего ты хочешь. Можете ли вы нарисовать каркас или диаграмму, которая ясно показывает ожидаемый результат, пожалуйста.
Единственная разница между рабочим и нерабочим примером — дополнительный слой HTML. В других частях кода ничего не трогали.
Мой инструктор сказал мне, что кнопки воспроизведения должны находиться внутри своего собственного контейнера. Это помогает? Я пытаюсь заставить код работать, когда кнопки находятся внутри своего собственного контейнера. Код, который сломан, я пытаюсь исправить, чтобы он работал.
Это кнопка воспроизведения внутри собственного контейнера: <div class = "playButtonContainer"> <button class = "playa cover" type = "button" aria-label = "Open"></button> </div>
Пожалуйста, нарисуйте то, что вы хотите. например, что вы определяете как «контейнер». Пожалуйста, без лишних слов, просто несколько диаграмм, показывающих желаемый результат всех нарисованных элементов (большая кнопка воспроизведения, 3 кнопки выхода, черная рамка вокруг видео, само видео, зеленый фон и все). Нарисуйте отдельные диаграммы, чтобы показать, что должно быть видно на каждом этапе, и что происходит, чтобы запустить этот этап (например, каждый щелчок). Спасибо
Давайте продолжим обсуждение в чате.
Привет, можешь вернуться в чат, пожалуйста? У меня работает код. Но у меня было несколько вопросов, чтобы задать вам о том, что я сделал.
Из сообщения об ошибке довольно ясно, что
el.closest(".remove")— этоnull.