Проблема с неперехваченным DOMException, когда я пытаюсь нажать на кнопку

#javascript

#javascript

Вопрос:

Я создаю свою первую драм-машину, и когда я попытался написать код для добавления EventListener к кнопкам, чтобы воспроизвести ритм при нажатии на него, я получаю эту ошибку в консоли DevTools:

 index.js:76 Uncaught DOMException: Failed to execute 'querySelector' on 'Document': '.
      <span>I</span><span class="sound">CRASH</span>
    ' is not a valid selector.
at buttonAnimation (http://127.0.0.1:5500/index.js:76:31)
at HTMLButtonElement.<anonymous> (http://127.0.0.1:5500/index.js:6:5)
  

Я не знаю, почему здесь ошибка, потому что функция makeSound, а также buttonAnimations хорошо работают, когда я играю удары клавишами…

 // Detection Button Press
for (var i = 0; i < document.querySelectorAll(".beat").length; i  ) {
  document.querySelectorAll(".beat")[i].addEventListener("click", function () {
    var buttonInnerHTML = this.innerHTML;
    makeSound(buttonInnerHTML);
    buttonAnimation(buttonInnerHTML);
  });
}
// Detection Keyboard Press
document.addEventListener("keydown", function (event) {
  makeSound(event.key);
  buttonAnimation(event.key);
});
function makeSound(key) {
  switch (key) {
    case "q":
      var conga = new Audio(
        "https://sampleswap.org/samples-ghost/DRUMS (FULL KITS)/DRUM MACHINES/808 Basic/22[kb]conga1.aif.mp3"
      );
      conga.play();
      break;
    case "w":
      var hiHat = new Audio(
        "https://sampleswap.org/samples-ghost/DRUMS (FULL KITS)/DRUM MACHINES/808 Basic/4[kb]cl_hihat.aif.mp3"
      );
      hiHat.play();
      break;
    case "e":
      var handClap = new Audio(
        "https://sampleswap.org/samples-ghost/DRUMS (FULL KITS)/DRUM MACHINES/808 Basic/31[kb]handclap.aif.mp3"
      );
      handClap.play();
      break;
    case "r":
      var highTom = new Audio(
        "https://sampleswap.org/samples-ghost/DRUMS (FULL KITS)/DRUM MACHINES/808 Basic/17[kb]hightom.aif.mp3"
      );
      highTom.play();
      break;
    case "t":
      var openHighHat = new Audio(
        "https://sampleswap.org/samples-ghost/DRUMS (FULL KITS)/DRUM MACHINES/808 Basic/51[kb]open_hh.aif.mp3"
      );
      openHighHat.play();
      break;
    case "y":
      var snare = new Audio(
        "https://sampleswap.org/samples-ghost/DRUMS (FULL KITS)/DRUM MACHINES/808 Basic/8[kb]snare.aif.mp3"
      );
      snare.play();
      break;
    case "u":
      var lowConga = new Audio(
        "https://sampleswap.org/samples-ghost/DRUMS (FULL KITS)/DRUM MACHINES/80s Drum Machine/16[kb]80s-LOWCONGA.aif.mp3"
      );
      lowConga.play();
      break;
    case "i":
      var crash = new Audio(
        "https://sampleswap.org/samples-ghost/DRUMS (FULL KITS)/DRUM MACHINES/80s Drum Machine/83[kb]80s-CRASH1.aif.mp3"
      );
      crash.play();
      break;
    case "o":
      var tamb = new Audio(
        "https://sampleswap.org/samples-ghost/DRUMS (FULL KITS)/DRUM MACHINES/80s Drum Machine/20[kb]80s-TAMB1.aif.mp3"
      );
      tamb.play();
      break;

    default:
  }
}

function buttonAnimation(currentKey) {
  var activeButton = document.querySelector("."   currentKey);
  activeButton.classList.add("playing");
  setTimeout(function () {
    activeButton.classList.remove("playing");
  }, 100);
}  
 body {
  font-family: "Righteous", cursive;
  text-align: center;
  background-color: rgb(43, 0, 43);
  display: flex;
  justify-content: center;
  margin-top: 60px;
}

.container-808 {
  width: 480px;
  background-color: #000;
  padding-top: 20px;
  border: 3px solid rgba(247, 161, 1, 0.575);
  border-radius: 20px;
}
.name-and-display-container {
  padding-left: 10px;
  border-right-width: 10px;
  padding-right: 10px;
  margin-bottom: 30px;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
}
.name {
  color: rgb(240, 90, 36);
  display: flex;
  justify-content: flex-end;
  align-items: baseline;
}
button {
  align-items: center;
}
button:focus {
  outline: none;
}
h1 {
  font-size: 25px;
  margin-right: 5px;
}
h3 {
  font-size: 15px;
}
.display {
  background-color: rgba(128, 128, 128, 0.192);
  border: 2px solid rgb(245, 245, 90);
  box-shadow: 0px 0px 3px yellow;
  border-radius: 5px;
  font-family: "Wallpoet", cursive;
  width: 150px;
  height: 50px;
  display: flex;
  justify-content: center;
  align-items: center;
}
.beats-controler {
  font-size: 20px;
  color: rgb(255, 255, 126);
  text-shadow: 0px 0px 10px yellow;
}
.keys-container {
  padding-bottom: 20px;
  padding-right: 4px;
  padding-left: 4px;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
}
.beat {
  width: 120px;
  height: 120px;
  border-radius: 10px;
  margin-bottom: 8px;
  margin-right: 5px;
  transition: all 0.07s ease;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.playing {
  transform: scale(1.1);
}
span {
  font-family: "Righteous", cursive;
  font-size: 25px;
}
.sound {
  font-size: 10px;
  margin-top: 5px;
}

.first-row {
  background: linear-gradient(
    180deg,
    rgba(255, 0, 0, 1) 0%,
    rgba(255, 72, 0, 1) 35%
  );
  border: rgba(255, 72, 0, 1);
  box-shadow: 0px 0px 5px rgba(255, 72, 0, 1);
}
.second-row {
  background: linear-gradient(
    180deg,
    rgba(255, 72, 0, 1) 0%,
    rgba(255, 102, 0, 1) 35%
  );
  border: rgba(255, 102, 0, 1);
  box-shadow: 0px 0px 5px rgba(255, 102, 0, 1);
}
.third-row {
  background: linear-gradient(
    180deg,
    rgba(255, 102, 0, 1) 0%,
    rgba(255, 184, 0, 1) 35%
  );
  border: rgba(255, 184, 0, 1);
  box-shadow: 0px 0px 5px rgba(255, 184, 0, 1);
}

@media (max-width: 510px) {
  .beat {
    width: 100px;
    height: 100px;
  }
  h1 {
    font-size: 15px;
    margin-right: 5px;
  }
  h3 {
    font-size: 10px;
    margin-right: 5px;
  }
}

@media (max-width: 500px) {
  .beat {
    width: 100px;
    height: 100px;
  }
  h1 {
    font-size: 15px;
    margin-right: 5px;
  }
  h3 {
    font-size: 10px;
    margin-right: 5px;
  }
}  
 <!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="style.css" />
    <link
      href="https://fonts.googleapis.com/css2?family=Righteousamp;display=swap"
      rel="stylesheet"
    />
    <link
      href="https://fonts.googleapis.com/css2?family=Wallpoetamp;display=swap"
      rel="stylesheet"
    />

    <title>BEATS MACHINE</title>
  </head>
  <body>
    <div class="container-808">
      <div class="name-and-display-container">
        <div class="display">
          <span class="beats-controler">120.BPM</span>
        </div>
        <div class="name">
          <h1>Rhythm Designer</h1>
          <h3>RD-808</h3>
        </div>
      </div>
      <div class="keys-container">
        <button class="q drum beat first-row">
          <span>Q</span><span class="sound">CONGA</span>
        </button>
        <button class="w drum beat first-row">
          <span>W</span><span class="sound">HI HAT</span>
        </button>
        <button class="e drum beat first-row">
          <span>E</span><span class="sound">HAND CLAP</span>
        </button>
        <button class="r drum beat second-row">
          <span>R</span><span class="sound">HIGH TOM</span>
        </button>
        <button class="t drum beat second-row">
          <span>T</span><span class="sound">OPEN HIGH HAT</span>
        </button>
        <button class="y drum beat second-row">
          <span>Y</span><span class="sound">SNARE</span>
        </button>
        <button class="u drum beat third-row">
          <span>U</span><span class="sound">LOW CONGA</span>
        </button>
        <button class="i drum beat third-row">
          <span>I</span><span class="sound">CRASH</span>
        </button>
        <button class="o drum beat third-row">
          <span>O</span><span class="sound">TAMB</span>
        </button>
      </div>
    </div>
    <script src="index.js"></script>
  </body>
</html>  

Комментарии:

1. Обратите внимание, что не очень эффективно помещать document.querySelectorAll в if() , а затем искать ту же коллекцию на каждой итерации, когда вы можете запросить один раз перед if() и перебирать коллекцию, хранящуюся в переменной. Меньше кода для записи тоже

2. Из-за ошибки кажется, что вы передаете html-код диапазона в querySelector что-то вроде querySelector ('<span>I</span><span class="sound">CRASH</span>') . Проверьте используемые вами переменные, которые вы передаете ему

Ответ №1:

Проблема здесь в том, что вы передаете неверное key в makeSound и buttonAnimation , когда делаете свое for loop .

 for (var i = 0; i < document.querySelectorAll(".beat").length; i  ) {
  document.querySelectorAll(".beat")[i].addEventListener("click", function () {

    // get the first currrent button's span innerHTML then lowercase 
    var key = this.querySelector("span").innerHTML.toLowerCase();

    makeSound(key);
    buttonAnimation(key);
  });
}
  

Как и предлагал @charlietfl, было бы лучше кэшировать ваши кнопки, вот так.

 const buttons = document.querySelectorAll(".beat");
buttons.forEach((button) => {
  button.addEventListener("click", () => {
    const key = button.querySelector("span").innerHTML.toLowerCase();
    makeSound(key);
    buttonAnimation(key);
  });
});
  

 // Detection Button Press

for (var i = 0; i < document.querySelectorAll(".beat").length; i  ) {
  document.querySelectorAll(".beat")[i].addEventListener("click", function() {
    var key = this.querySelector("span").innerHTML.toLowerCase();
    makeSound(key);
    buttonAnimation(key);
  });
}

// Detection Keyboard Press
document.addEventListener("keydown", function(event) {
  makeSound(event.key);
  buttonAnimation(event.key);
});

function makeSound(key) {
  switch (key) {
    case "q":
      var conga = new Audio(
        "https://sampleswap.org/samples-ghost/DRUMS (FULL KITS)/DRUM MACHINES/808 Basic/22[kb]conga1.aif.mp3"
      );
      conga.play();
      break;
    case "w":
      var hiHat = new Audio(
        "https://sampleswap.org/samples-ghost/DRUMS (FULL KITS)/DRUM MACHINES/808 Basic/4[kb]cl_hihat.aif.mp3"
      );
      hiHat.play();
      break;
    case "e":
      var handClap = new Audio(
        "https://sampleswap.org/samples-ghost/DRUMS (FULL KITS)/DRUM MACHINES/808 Basic/31[kb]handclap.aif.mp3"
      );
      handClap.play();
      break;
    case "r":
      var highTom = new Audio(
        "https://sampleswap.org/samples-ghost/DRUMS (FULL KITS)/DRUM MACHINES/808 Basic/17[kb]hightom.aif.mp3"
      );
      highTom.play();
      break;
    case "t":
      var openHighHat = new Audio(
        "https://sampleswap.org/samples-ghost/DRUMS (FULL KITS)/DRUM MACHINES/808 Basic/51[kb]open_hh.aif.mp3"
      );
      openHighHat.play();
      break;
    case "y":
      var snare = new Audio(
        "https://sampleswap.org/samples-ghost/DRUMS (FULL KITS)/DRUM MACHINES/808 Basic/8[kb]snare.aif.mp3"
      );
      snare.play();
      break;
    case "u":
      var lowConga = new Audio(
        "https://sampleswap.org/samples-ghost/DRUMS (FULL KITS)/DRUM MACHINES/80s Drum Machine/16[kb]80s-LOWCONGA.aif.mp3"
      );
      lowConga.play();
      break;
    case "i":
      var crash = new Audio(
        "https://sampleswap.org/samples-ghost/DRUMS (FULL KITS)/DRUM MACHINES/80s Drum Machine/83[kb]80s-CRASH1.aif.mp3"
      );
      crash.play();
      break;
    case "o":
      var tamb = new Audio(
        "https://sampleswap.org/samples-ghost/DRUMS (FULL KITS)/DRUM MACHINES/80s Drum Machine/20[kb]80s-TAMB1.aif.mp3"
      );
      tamb.play();
      break;

    default:
  }
}

function buttonAnimation(currentKey) {
  var activeButton = document.querySelector("."   currentKey);
  activeButton.classList.add("playing");
  setTimeout(function() {
    activeButton.classList.remove("playing");
  }, 100);
}  
 body {
  font-family: "Righteous", cursive;
  text-align: center;
  background-color: rgb(43, 0, 43);
  display: flex;
  justify-content: center;
  margin-top: 60px;
}

.container-808 {
  width: 480px;
  background-color: #000;
  padding-top: 20px;
  border: 3px solid rgba(247, 161, 1, 0.575);
  border-radius: 20px;
}

.name-and-display-container {
  padding-left: 10px;
  border-right-width: 10px;
  padding-right: 10px;
  margin-bottom: 30px;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
}

.name {
  color: rgb(240, 90, 36);
  display: flex;
  justify-content: flex-end;
  align-items: baseline;
}

button {
  align-items: center;
}

button:focus {
  outline: none;
}

h1 {
  font-size: 25px;
  margin-right: 5px;
}

h3 {
  font-size: 15px;
}

.display {
  background-color: rgba(128, 128, 128, 0.192);
  border: 2px solid rgb(245, 245, 90);
  box-shadow: 0px 0px 3px yellow;
  border-radius: 5px;
  font-family: "Wallpoet", cursive;
  width: 150px;
  height: 50px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.beats-controler {
  font-size: 20px;
  color: rgb(255, 255, 126);
  text-shadow: 0px 0px 10px yellow;
}

.keys-container {
  padding-bottom: 20px;
  padding-right: 4px;
  padding-left: 4px;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
}

.beat {
  width: 120px;
  height: 120px;
  border-radius: 10px;
  margin-bottom: 8px;
  margin-right: 5px;
  transition: all 0.07s ease;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.playing {
  transform: scale(1.1);
}

span {
  font-family: "Righteous", cursive;
  font-size: 25px;
}

.sound {
  font-size: 10px;
  margin-top: 5px;
}

.first-row {
  background: linear-gradient( 180deg, rgba(255, 0, 0, 1) 0%, rgba(255, 72, 0, 1) 35%);
  border: rgba(255, 72, 0, 1);
  box-shadow: 0px 0px 5px rgba(255, 72, 0, 1);
}

.second-row {
  background: linear-gradient( 180deg, rgba(255, 72, 0, 1) 0%, rgba(255, 102, 0, 1) 35%);
  border: rgba(255, 102, 0, 1);
  box-shadow: 0px 0px 5px rgba(255, 102, 0, 1);
}

.third-row {
  background: linear-gradient( 180deg, rgba(255, 102, 0, 1) 0%, rgba(255, 184, 0, 1) 35%);
  border: rgba(255, 184, 0, 1);
  box-shadow: 0px 0px 5px rgba(255, 184, 0, 1);
}

@media (max-width: 510px) {
  .beat {
    width: 100px;
    height: 100px;
  }
  h1 {
    font-size: 15px;
    margin-right: 5px;
  }
  h3 {
    font-size: 10px;
    margin-right: 5px;
  }
}

@media (max-width: 500px) {
  .beat {
    width: 100px;
    height: 100px;
  }
  h1 {
    font-size: 15px;
    margin-right: 5px;
  }
  h3 {
    font-size: 10px;
    margin-right: 5px;
  }
}  
 <!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <link rel="stylesheet" href="style.css" />
  <link href="https://fonts.googleapis.com/css2?family=Righteousamp;display=swap" rel="stylesheet" />
  <link href="https://fonts.googleapis.com/css2?family=Wallpoetamp;display=swap" rel="stylesheet" />

  <title>BEATS MACHINE</title>
</head>

<body>
  <div class="container-808">
    <div class="name-and-display-container">
      <div class="display">
        <span class="beats-controler">120.BPM</span>
      </div>
      <div class="name">
        <h1>Rhythm Designer</h1>
        <h3>RD-808</h3>
      </div>
    </div>
    <div class="keys-container">
      <button class="q drum beat first-row">
          <span>Q</span><span class="sound">CONGA</span>
        </button>
      <button class="w drum beat first-row">
          <span>W</span><span class="sound">HI HAT</span>
        </button>
      <button class="e drum beat first-row">
          <span>E</span><span class="sound">HAND CLAP</span>
        </button>
      <button class="r drum beat second-row">
          <span>R</span><span class="sound">HIGH TOM</span>
        </button>
      <button class="t drum beat second-row">
          <span>T</span><span class="sound">OPEN HIGH HAT</span>
        </button>
      <button class="y drum beat second-row">
          <span>Y</span><span class="sound">SNARE</span>
        </button>
      <button class="u drum beat third-row">
          <span>U</span><span class="sound">LOW CONGA</span>
        </button>
      <button class="i drum beat third-row">
          <span>I</span><span class="sound">CRASH</span>
        </button>
      <button class="o drum beat third-row">
          <span>O</span><span class="sound">TAMB</span>
        </button>
    </div>
  </div>
</body>

</html>  

Комментарии:

1. Также лучше кэшировать этот querySelectorAll перед циклом. Бессмысленный запрос к dom на каждой итерации