Alan
Alan

Reputation: 349

add addEventListener to all the buttons

Well the thing is this, I already match up the audio with the keys using the atribute "data-key" doing in this way:

const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
const key = document.querySelector(`.key[data-key="${e.keyCode}"]`);

Now, I want to do the same but with the click of the bottom. I already try like you can see at the end of the snippet of JavaScript, adding a loop for all the buttons, but looks awkward and only run with one audio.

function playSound(e) {
  const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
  const key = document.querySelector(`.key[data-key="${e.keyCode}"]`);
  if (!audio) return; // this stop the function from running all together.
  audio.currentTime = 0; // this rewind the audio to the start
  audio.play(key);
  key.classList.add("playing");
}

function removeTransition(e) {
  if (e.propertyName !== "transform") return; // skip it if it's not a transform
  this.classList.remove("playing");
}
const keys = document.querySelectorAll(".key");
keys.forEach((key) => key.addEventListener("transitionend", removeTransition));
document.addEventListener("keydown", playSound);

for (var i = 0; i < document.querySelectorAll(".beat").length; i++) {
  document.querySelectorAll(".beat")[i].addEventListener("click", function () {
    var clickAudio = new Audio(
      "https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/808%20Basic/22[kb]conga1.aif.mp3"
    );
    clickAudio.play();
  });
}
<!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=Righteous&display=swap"
      rel="stylesheet"
    />
    <link
      href="https://fonts.googleapis.com/css2?family=Wallpoet&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 data-key="81" class="key beat first-row">
          <kbd>Q</kbd><span class="sound">CONGA</span>
        </button>
        <button data-key="87" class="key beat first-row">
          <kbd>W</kbd><span class="sound">HI HAT</span>
        </button>
        <button data-key="69" class="key beat first-row">
          <kbd>E</kbd><span class="sound">HAND CLAP</span>
        </button>
        <button data-key="82" class="key beat second-row">
          <kbd>R</kbd><span class="sound">HIGH TOM</span>
        </button>
        <button data-key="84" class="key beat second-row">
          <kbd>T</kbd><span class="sound">OPEN HIGH HAT</span>
        </button>
        <button data-key="89" class="key beat second-row">
          <kbd>Y</kbd><span class="sound">SNARE</span>
        </button>
        <button data-key="85" class="key beat third-row">
          <kbd>U</kbd><span class="sound">LOW CONGA</span>
        </button>
        <button data-key="73" class="key beat third-row">
          <kbd>I</kbd><span class="sound">CRASH</span>
        </button>
        <button data-key="79" class="key beat third-row">
          <kbd>O</kbd><span class="sound">TAMB</span>
        </button>

        <audio
          data-key="81"
          src="https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/808%20Basic/22[kb]conga1.aif.mp3"
        ></audio>

        <audio
          data-key="87"
          src="https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/808%20Basic/4[kb]cl_hihat.aif.mp3"
        ></audio>

        <audio
          data-key="69"
          src="https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/808%20Basic/31[kb]handclap.aif.mp3"
        ></audio>

        <audio
          data-key="82"
          src="https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/808%20Basic/17[kb]hightom.aif.mp3"
        ></audio>

        <audio
          data-key="84"
          src="https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/808%20Basic/51[kb]open_hh.aif.mp3"
        ></audio>

        <audio
          data-key="89"
          src="https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/808%20Basic/8[kb]snare.aif.mp3"
        ></audio>

        <audio
          data-key="85"
          src="https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/80s%20Drum%20Machine/16[kb]80s-LOWCONGA.aif.mp3"
        ></audio>

        <audio
          data-key="73"
          src="https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/80s%20Drum%20Machine/83[kb]80s-CRASH1.aif.mp3"
        ></audio>

        <audio
          data-key="79"
          src="https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/80s%20Drum%20Machine/20[kb]80s-TAMB1.aif.mp3"
        ></audio>
      </div>
    </div>
    <script src="index.js"></script>
  </body>
</html>

Upvotes: 1

Views: 480

Answers (3)

Roko C. Buljan
Roko C. Buljan

Reputation: 206121

  • We're not machines, we're programmers, use use Event.key or rather, in your specific case, since you'd like to internationalize your keyboard - use Event.code - BTW, I'm on a QWERTZ keyboard, so finally the below should work for my keyboard as well as for yours.
  • Preload your sounds! You don't want to load a sound once I start typing on the keyboard or after clicking a button!
  • Handle the buttons styles in the same function you play sounds!
  • Don't bloat HTML - Use JS!
  • Create a path string with your route to your sounds.
  • Create a sounds object holding the minimal known data, just like a library - where every key is actually a Keyboard Event.code
  • Use the Audio onended Event to remove the "playing" CSS class from your buttons

const path = "https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/";
const sounds = {
  "KeyQ": {src:"808%20Basic/22[kb]conga1.aif.mp3", name:"CONGA"},
  "KeyW": {src:"808%20Basic/4[kb]cl_hihat.aif.mp3", name:"HI HAT"},
  "KeyE": {src:"808%20Basic/31[kb]handclap.aif.mp3", name:"HAND CLAP"},
  "KeyR": {src:"808%20Basic/17[kb]hightom.aif.mp3", name:"HIGH TOM"},
  "KeyT": {src:"808%20Basic/51[kb]open_hh.aif.mp3", name:"OPEN HIGH HAT"},
  "KeyY": {src:"808%20Basic/8[kb]snare.aif.mp3", name:"SNARE"},
  "KeyU": {src:"80s%20Drum%20Machine/16[kb]80s-LOWCONGA.aif.mp3", name:"LOW CONGA"},
  "KeyI": {src:"80s%20Drum%20Machine/83[kb]80s-CRASH1.aif.mp3", name:"CRASH"},
  "KeyO": {src:"80s%20Drum%20Machine/20[kb]80s-TAMB1.aif.mp3", name:"TAMB"},
};

const ELNew = (sel, attr) => Object.assign(document.createElement(sel), attr || {});
const EL_keys = document.querySelector(".keys-container");
const keyBtn = (k) => ELNew("button", {
  classList: "key beat",
  type: "button",
  innerHTML: `<kbd>${k.replace("Key","")}</kbd><span class="sound">${sounds[k].name}</span>`,
  onmousedown: () => playSound(k)
});

// PRELOAD ALL SOUNDS. You dont' want loading delays, right?!
// Also... CREATE KEY BUTTONS as well.
Object.keys(sounds).forEach(k => {
  const soundObj = sounds[k];
  soundObj.audio = new Audio();
  soundObj.audio.src = path + soundObj.src;
  soundObj.audio.preload = true;
  soundObj.audio.load();
  soundObj.button = keyBtn(k); // Create button
  EL_keys.append(soundObj.button); // Append button
});

function playSound(k) {
  if (!(k in sounds)) return;
  const obj = sounds[k];
  obj.audio.currentTime = 0; // this rewind the audio to the start
  obj.audio.play();
  // Animate button:
  obj.button.classList.add("playing");
  obj.audio.addEventListener("ended", () => obj.button.classList.remove("playing"), {once: true});
}

document.addEventListener("keydown", (ev) => playSound(ev.code));
.key kbd { display: inline-block; text-transform: uppercase; padding: 0.5em; margin-right: 5px; }
.key { transition: 0.5s; }
.key.playing { box-shadow: 0 0 100px #0bf, inset 0 0 2em #0bf; }
<div class="keys-container"></div>

TODO: while loading sounds (see: "PRELOAD ALL SOUNDS") you could create a loading bar. Have an idea by reading this link

PRO-TIP: Since browsers only allow playing sounds after a user gesture like a click, create a button i.e: "Load App" that, by clicking, plays a silent (muted) audio. That way you'll circumvent the browser from that restriction of preloading and playing your other sounds.

Upvotes: 1

Dan Mullin
Dan Mullin

Reputation: 4435

You can clean it up nicely by using the forEach() funciton:

document.querySelectorAll(".beat").forEach(el => {
    el.addEventListener("click", function () {
        clickAudio.play();
    });
});

Upvotes: 0

Saadi Toumi Fouad
Saadi Toumi Fouad

Reputation: 2829

You can use event delegation so attach the event listener to the container and on each click on the span element we get the data-key of the button element(its parent) and then search for the audio element that has the same data-key attribute and play it

document.querySelector(".keys-container").onclick = function(e) {
  if(e.target.nodeName === "SPAN") {
    var key = e.target.parentElement.getAttribute("data-key");
    document.querySelector(`audio[data-key='${key}']`).play();
  }
}
    <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 data-key="81" class="key beat first-row">
          <kbd>Q</kbd><span class="sound">CONGA</span>
        </button>
        <button data-key="87" class="key beat first-row">
          <kbd>W</kbd><span class="sound">HI HAT</span>
        </button>
        <button data-key="69" class="key beat first-row">
          <kbd>E</kbd><span class="sound">HAND CLAP</span>
        </button>
        <button data-key="82" class="key beat second-row">
          <kbd>R</kbd><span class="sound">HIGH TOM</span>
        </button>
        <button data-key="84" class="key beat second-row">
          <kbd>T</kbd><span class="sound">OPEN HIGH HAT</span>
        </button>
        <button data-key="89" class="key beat second-row">
          <kbd>Y</kbd><span class="sound">SNARE</span>
        </button>
        <button data-key="85" class="key beat third-row">
          <kbd>U</kbd><span class="sound">LOW CONGA</span>
        </button>
        <button data-key="73" class="key beat third-row">
          <kbd>I</kbd><span class="sound">CRASH</span>
        </button>
        <button data-key="79" class="key beat third-row">
          <kbd>O</kbd><span class="sound">TAMB</span>
        </button>

        <audio
          data-key="81"
          src="https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/808%20Basic/22[kb]conga1.aif.mp3"
        ></audio>

        <audio
          data-key="87"
          src="https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/808%20Basic/4[kb]cl_hihat.aif.mp3"
        ></audio>

        <audio
          data-key="69"
          src="https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/808%20Basic/31[kb]handclap.aif.mp3"
        ></audio>

        <audio
          data-key="82"
          src="https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/808%20Basic/17[kb]hightom.aif.mp3"
        ></audio>

        <audio
          data-key="84"
          src="https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/808%20Basic/51[kb]open_hh.aif.mp3"
        ></audio>

        <audio
          data-key="89"
          src="https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/808%20Basic/8[kb]snare.aif.mp3"
        ></audio>

        <audio
          data-key="85"
          src="https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/80s%20Drum%20Machine/16[kb]80s-LOWCONGA.aif.mp3"
        ></audio>

        <audio
          data-key="73"
          src="https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/80s%20Drum%20Machine/83[kb]80s-CRASH1.aif.mp3"
        ></audio>

        <audio
          data-key="79"
          src="https://sampleswap.org/samples-ghost/DRUMS%20(FULL%20KITS)/DRUM%20MACHINES/80s%20Drum%20Machine/20[kb]80s-TAMB1.aif.mp3"
        ></audio>
      </div>
    </div>

Upvotes: 1

Related Questions