Build a Drum Machine - Build a Drum Machine

Tell us what’s happening:

Greetings! I’ve been working on the Build a Drum Machine project, and I can’t pass the 9th test:

When you press one of the keys Q, W, E, A, S, D, Z, X, C on your keyboard, the corresponding audio element should play the corresponding sound.

When I press the keys, the buttons do react as if I clicked on them (correct audio & display). I also tried spamming the keys quickly to see if any bugs appear, but that doesn’t seem to be the case.

Source code:

https://codepen.io/LiThon-Hong/pen/jErwjwd

Your code so far

<!-- file: index.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Drum Machine</title>
    <link rel="stylesheet" href="styles.css" />
  </head>
  <body>
    <div id="drum-machine">
      <h1>Drum Machine</h1>
      <div id="pad-bank">
        <!-- to be filled with js -->
      </div>
      <div id="ctn-display">
        <p id="display"></p>
      </div>

      <div id="ctn-volume">
        <label for="volume" id="label-volume">Volume</label>
        <input type="range" id="volume" min="0" max="100" value="50" class="slider"></input>
      </div>
    </div>
    <script src="script.js"></script>
  </body>
</html>
/* file: styles.css */
body {
  margin: 0px;
  background-color: #2D252C;
  font-family: sans-serif;
}

#drum-machine {
  width: 60vw;
  background-color: #483C46;
  display: block;
  margin: auto;
  min-height: 100vh;
  padding-bottom: 20px;
}

h1 {
  text-align: center;
  padding-top: 5vw;
  margin: 0px;
  color: #cb8;
}

#pad-bank {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 5%;
  padding: 10%;
}

.drum-pad {
  aspect-ratio: 1/1;
  background-color: #aaa;
  align-content: center;  
  text-align: center;
  border-radius: 10%;
  size: 2em;
  font-weight: 600;
  border: none;
  box-shadow: none;
}

#display {
  margin: 30px;
}

.active {
  background-color: #F4743B !important;
}

.drum-pad:hover {
  background-color: #888;
}

#ctn-display {
  margin: 30px auto;
  height: 10vw;
  min-height: 30px;
  width: 80%;
  background-color: #9E5841;
  text-align: center;
  display: grid;
  place-items: center;
  border-radius: 5px;
}

#display {
  color: #CB8;
  margin: 0px;
  size: 2em;
  font-weight: 600;
}

#ctn-volume {
  display: flex;
  padding: 10px 10%;
  align-items: center;
}

label {
  color: #CB8;
  size: 2em;
  font-weight: 600;
}

.slider {
  width: 100%;
  margin-left: 10px;
  -webkit-appearance: none;
  border-radius: 5px;
}

.slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  height: 15px;
  width: 15px;
  border-radius: 5px;
  background: #F4743B;
}
/* file: script.js */
const pads = {
  "Q": ["Heater 1", "Heater-1.mp3"],
  "W": ["Heater 2", "Heater-2.mp3"],
  "E": ["Heater 3", "Heater-3.mp3"],
  "A": ["Heater 4", "Heater-4_1.mp3"],
  "S": ["Clap", "Heater-6.mp3"],
  "D": ["open_HH", "Dsc_Oh.mp3"],
  "Z": ["Kick-n'-Hat", "Kick_n_Hat.mp3"],
  "X": ["Kick", "RP4_KICK_1.mp3"],
  "C": ["Closed-HH", "Cev_H2.mp3"]
};

const padBank = document.getElementById("pad-bank");
const display = document.getElementById("display")

let playing = null;

function playAudio(tgtPad) {
  display.innerText = pads[tgtPad][0]
  let tgtAudio = document.getElementById(tgtPad);
  let tgtDiv = document.getElementById(`ctn-${tgtPad}`)

  if (tgtAudio) {

    if (playing != null) {
      let oldAudio = document.getElementById(playing)
      let oldDiv = document.getElementById(`ctn-${playing}`)
      if (oldAudio) {
        oldAudio.pause();
        oldAudio.currentTime = 0;
        oldDiv.classList.remove("active");
      }
    };
    playing = tgtPad;
    display.innerText = pads[tgtPad][0]
    tgtDiv.classList.add("active")
    tgtAudio.currentTime = 0;
    tgtAudio.play();
  };
}

for (let pad in pads) {

  // create container div
  let padNode = document.createElement("button");
  padNode.classList = ["drum-pad"];
  padNode.id = `ctn-${pad}`;
  padNode.innerText = pad;

  // create audio element
  let padAudio = document.createElement("audio");
  padAudio.id = pad;
  padAudio.classList = ["clip"];
  padAudio.src = `https://cdn.freecodecamp.org/curriculum/drum/${pads[pad][1]}`;

  // add onclick event listener
  padNode.addEventListener("click", () => {
    playAudio(pad);
  });

  padAudio.addEventListener("ended", () => {
    padNode.classList.remove("active");
    playing = null;
    display.innerHTML = "";
  });

  padNode.appendChild(padAudio);
  padBank.appendChild(padNode);

};

let padList = Array.from(document.querySelectorAll(".clip"))

let slider = document.getElementById("volume")
slider.addEventListener("input", () => {
  padList.forEach((item) => {
    item.volume = slider.value / 100;
  });
});

document.addEventListener("keydown", (char) => {
  if (Array.from("QWEASDZXC").includes(char.code.slice(3))) {
    playAudio(char.code.slice(3));
  }
});

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 OPR/125.0.0.0

Challenge Information:

Build a Drum Machine - Build a Drum Machine

During tests, the dispatched keyboard events are using key attribute, instead of code. Problem with code attribute is two-part: it doesn’t under consideration the keyboard layout, and is not supported on mobile. See KeyboardEvent - Web APIs | MDN

1 Like

Yep, that seems to do the trick. I was looking at the Mozilla documentation for keydown events, which only demonstrated the use of code. Thank you!