Home > Blockchain >  Cannot read properties of null (reading 'querySelectorAll') at line 189
Cannot read properties of null (reading 'querySelectorAll') at line 189

Time:11-16

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>

  • Related