Home > Software design >  Onclick handler for dynamic button (added via JS) returning null
Onclick handler for dynamic button (added via JS) returning null

Time:05-27

I have a button, in my markup called .open-video.

Clicking .open-video opens up a modal which then contains another button .close--modal. The code for the modal (which includes the markup for .modal--close) is added when the .open-video button is clicked.

Now, I'm aware that the EventListener for .modal--close needs to exist after the markup is added to the DOM on the first EventListener for .open-video. But, doing this isn't doing anything at the moment, I instead get the error message Cannot read properties of null (reading 'addEventListener') and I believe this is because the DOMContentLoaded event was already fired at this point.

Currently, when clicking .modal--close, I just want to do a simple console.log("test");.

See my demo below:

if (document.readyState === "complete") {
  ready();
} else {
  document.addEventListener("DOMContentLoaded", ready);
}

function ready() {

  let video_btn = document.querySelector(".open-video");
  let close_btn = document.querySelector(".modal--close");
  let modal = document.querySelector(".modal");

  console.log(close_btn);

  if (video_btn) {
    video_btn.addEventListener("click", function(e) {

      e.preventDefault();

      // get data
      var triggerURL = this.getAttribute("href");
      var triggerID = this.getAttribute("data-modal");

      // update modal attributes  with trigger data
      modal.setAttribute("data-video", triggerURL);
      modal.setAttribute("id", triggerID);

      var modalID = '#'   triggerID;
      modal.classList.add("modal--open");

      var html = '<a href="#" ></a><div ><iframe width="640" height="360" src="'   triggerURL   '?rel=0&autoplay=1" frameborder="0" allowfullscreen></iframe></div><div ></div>';

      // modal.insertAdjacentHTML('beforeend', html);
      modal.innerHTML = html;

      close_btn.addEventListener("click", function(e) {
        e.preventDefault();
        console.log("test");
      });

      return false;

    });

  }

}
.modal {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 99999;
  overflow: hidden;
  display: none;
  padding: 70px 80px;
}

.modal--close {
  position: fixed;
  right: 50%;
  top: 32px;
  width: 16px;
  height: 16px;
  z-index: 999999;
  pointer-events: auto !important;
}

.modal--close:hover:before,
.modal--close:hover:after {
  background-color: #F15A40;
}

.modal--close:before,
.modal--close:after {
  content: "";
  position: absolute;
  left: 15px;
  height: 16px;
  width: 2px;
  background-color: #FFFFFF;
}

.modal--close:before {
  transform: rotate(45deg);
}

.modal--close:after {
  transform: rotate(-45deg);
}

.modal--open {
  display: block;
}

.modal .modal__wrapper {
  position: relative;
  top: 50%;
  transform: translateY(-50%);
  max-height: 100%;
  overflow: hidden;
  z-index: 150;
}

.modal .modal__wrapper:before {
  content: "";
  display: block;
  padding-top: 56.25%;
}

.modal .modal__wrapper iframe,
.modal .modal__wrapper video {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  outline: none;
}

.modal .modal__overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: #000000;
}
<a  data-modal="video--1" href="https://www.youtube.com/embed/NpEaa2P7qZI">Click me</a>

<div >
  <div ></div>
  <div ></div>
</div>

How can I get my .modal--close button to print the log? Where am I going wrong?

CodePudding user response:

Because you call closeElement before you create closeElement.
You can call this element after creating.

video_btn.addEventListener("click", function(e) {

    e.preventDefault();
    
    // ... codes
  
    // modal.insertAdjacentHTML('beforeend', html);
    modal.innerHTML = html;
    let close_btn = document.querySelector(".modal--close");
    close_btn.addEventListener("click", function(e) {
        e.preventDefault();
        console.log("test");
    });

    return false;

});

CodePudding user response:

You can't document.querySelect an element before it's added to the DOM, you should move the line of

let close_btn = document.querySelector(".modal--close"); // here

to inside the video_btn.addEventListener callback function after you've added the element .modal--close to the DOM.

if (document.readyState === "complete") {
  ready();
} else {
  document.addEventListener("DOMContentLoaded", ready);
}

function ready() {

  let video_btn = document.querySelector(".open-video");
  let modal = document.querySelector(".modal");

  if (video_btn) {
    video_btn.addEventListener("click", function(e) {

      e.preventDefault();

      // get data
      var triggerURL = this.getAttribute("href");
      var triggerID = this.getAttribute("data-modal");

      // update modal attributes  with trigger data
      modal.setAttribute("data-video", triggerURL);
      modal.setAttribute("id", triggerID);

      var modalID = '#'   triggerID;
      modal.classList.add("modal--open");

      var html = '<a href="#" ></a><div ><iframe width="640" height="360" src="'   triggerURL   '?rel=0&autoplay=1" frameborder="0" allowfullscreen></iframe></div><div ></div>';

      // modal.insertAdjacentHTML('beforeend', html);
      modal.innerHTML = html;
      let close_btn = document.querySelector(".modal--close"); // here

      close_btn.addEventListener("click", function(e) {
        e.preventDefault();
        console.log("test");
      });

      return false;

    });

  }

}
.modal {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 99999;
  overflow: hidden;
  display: none;
  padding: 70px 80px;
}

.modal--close {
  position: fixed;
  right: 50%;
  top: 32px;
  width: 16px;
  height: 16px;
  z-index: 999999;
  pointer-events: auto !important;
}

.modal--close:hover:before,
.modal--close:hover:after {
  background-color: #F15A40;
}

.modal--close:before,
.modal--close:after {
  content: "";
  position: absolute;
  left: 15px;
  height: 16px;
  width: 2px;
  background-color: #FFFFFF;
}

.modal--close:before {
  transform: rotate(45deg);
}

.modal--close:after {
  transform: rotate(-45deg);
}

.modal--open {
  display: block;
}

.modal .modal__wrapper {
  position: relative;
  top: 50%;
  transform: translateY(-50%);
  max-height: 100%;
  overflow: hidden;
  z-index: 150;
}

.modal .modal__wrapper:before {
  content: "";
  display: block;
  padding-top: 56.25%;
}

.modal .modal__wrapper iframe,
.modal .modal__wrapper video {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  outline: none;
}

.modal .modal__overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: #000000;
}
<a  data-modal="video--1" href="https://www.youtube.com/embed/NpEaa2P7qZI">Click me</a>

<div >
  <div ></div>
  <div ></div>
</div>

  • Related