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!

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.