javascriptdombuttonaudio

How to add an audio to a DOM button?


I am trying to enhance my Js knowledge by building a simple music player in HTML, JS and Tailwind CSS.

I am trying to add the DOM buttons to all of the audios. I expect the buttons to play the audio if you click on it. Although, it does not play an audio and it does not show any errors. I don't understand what is wrong with my code.

const playlist = document.getElementById('playlist');
const allSongs = [{
    id: 0,
    title: "Scratching The Surface",
    artist: "Quincy Larson",
    duration: "4:25",
    src: 'https://here is a link'
  },
  {
    id: 1,
    title: "Can't Stay Down",
    artist: "Quincy Larson",
    duration: "4:15",
    src: 'https://here is a link'
  },
  {
    id: 2,
    title: "Still Learning",
    artist: "Quincy Larson",
    duration: "3:51",
    src: 'https://here is a link'
  },
  {
    id: 3,
    title: "Cruising for a Musing",
    artist: "Quincy Larson",
    duration: "3:34",
    src: 'https://here is a link'
  },
  {
    id: 4,
    title: "Never Not Favored",
    artist: "Quincy Larson",
    duration: "3:35",
    src: 'https://here is a link'
  },
  {
    id: 5,
    title: "From the Ground Up",
    artist: "Quincy Larson",
    duration: "3:12",
    src: 'https://here is a link'
  },
  {
    id: 6,
    title: "Walking on Air",
    artist: "Quincy Larson",
    duration: "3:25",
    src: 'https://here is a link'
  },
  {
    id: 7,
    title: "Can't Stop Me. Can't Even Slow Me Down.",
    artist: "Quincy Larson",
    duration: "3:52",
    src: 'https://here is a link'
  },
  {
    id: 8,
    title: "The Surest Way Out is Through",
    artist: "Quincy Larson",
    duration: "3:10",
    src: 'https://here is a link'
  },
  {
    id: 9,
    title: "Chasing That Feeling",
    artist: "Quincy Larson",
    duration: "2:43",
    src: 'https://here is a link'
  },
];

const songs = allSongs.sort((a, b) => a.title.localeCompare(b.title));
const currentSongTime = 0;
const currentSong = null;
const song = songs.find((song, id) => song.id === id);
const audio = new Audio();

const renderSongs = () => {
  songs.forEach(data => {
    playlist.innerHTML += `
    <li class="flex flex-row items-center gap-2 border-b border-b-yellow-600 border-b-2 border-dashed px-3 py-4">
    <button id="playlistBtn" class="flex flex-row items-center gap-3">
    <div class="flex-1 flex-wrap">${data.title}</div>
    <div class="text-[13px] flex-none mr-2">${data.artist}</div>
    <div>${data.duration}</div>
    </button>
    <button id="removeBtn">
        <svg width="30" height="25" fill="white" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M342.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L192 210.7 86.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L146.7 256 41.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 301.3 297.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L237.3 256 342.6 150.6z"/></svg>
    </button>
    </li>
    `;
  });

  playlist.appendChild(li);
  playlist.appendChild(playlistBtn);
  playlist.appendChild(removeBtn);

  // by clicking on a song, it will play a clicked song
  playlistBtn.addEventListener("click", () => {
    audio.src = song.src;
    audio.play();
  })
}
renderSongs();
<ul id="playlist"></ul>


Solution

  • In this earlier answer, we have this example to play audio upon button click:

    <!doctype html>
    <html>
      <head>
        <title>Audio</title>
      </head>
      <body>
    
        <script>
          function play() {
            var audio = document.getElementById("audio");
            audio.play();
          }
        </script>
    
        <input type="button" value="PLAY" onclick="play()">
        <audio id="audio" src="https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3"></audio>
    
      </body>
    </html>

    So it can definitely work. So the problem is to make it work with your Javascript code.

    const allSongs = [
        {
        id: 0,
        title: "Scratching The Surface",
        artist: "Quincy Larson",
        duration: "4:25",
        src:  "https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3"
      },
      {
        id: 1,
        title: "Can't Stay Down",
        artist: "Quincy Larson",
        duration: "4:15",
        src:  "https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3"
      },
      {
        id: 2,
        title: "Still Learning",
        artist: "Quincy Larson",
        duration: "3:51",
        src:  "https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3"
      },
      {
        id: 3,
        title: "Cruising for a Musing",
        artist: "Quincy Larson",
        duration: "3:34",
        src:  "https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3"
      },
      {
        id: 4,
        title: "Never Not Favored",
        artist: "Quincy Larson",
        duration: "3:35",
        src:  "https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3"
      },
      {
        id: 5,
        title: "From the Ground Up",
        artist: "Quincy Larson",
        duration: "3:12",
        src:  "https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3"
      },
      {
        id: 6,
        title: "Walking on Air",
        artist: "Quincy Larson",
        duration: "3:25",
        src:  "https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3"
      },
      {
        id: 7,
        title: "Can't Stop Me. Can't Even Slow Me Down.",
        artist: "Quincy Larson",
        duration: "3:52",
        src:  "https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3"
      },
      {
        id: 8,
        title: "The Surest Way Out is Through",
        artist: "Quincy Larson",
        duration: "3:10",
        src:  "https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3"
      },
      {
        id: 9,
        title: "Chasing That Feeling",
        artist: "Quincy Larson",
        duration: "2:43",
        src:  "https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3"
      },
    ];
    
    const songs = allSongs.sort((a, b) => a.title.localeCompare(b.title));
    const currentSongTime = 0;
    const currentSong = null;
    const song = songs.find((song, id) => song.id === id);
    const audio = new Audio();
    const playlist = document.getElementById("playlist");
    
    function play(context) {
        context.querySelector("audio").play();
    }
    
    
    const renderSongs = () => {
    
      songs.forEach(data => {
        playlist.innerHTML +=`
        <li class="flex flex-row items-center gap-2 border-b border-b-yellow-600 border-b-2 border-dashed px-3 py-4">
        <div id="playlistBtn${playlist.children.length}" class="flex flex-row items-center gap-3" style="background-color:gray; cursor: pointer;" onclick="play(this);">
        <div class="flex-1 flex-wrap">${data.title}</div>
        <div class="text-[13px] flex-none mr-2">${data.artist}</div>
        <div>${data.duration}</div>
        <audio src="${data.src}"></audio>
        </div>
        <button id="removeBtn${playlist.children.length}">
            <svg width="30" height="25" fill="white" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M342.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L192 210.7 86.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L146.7 256 41.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 301.3 297.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L237.3 256 342.6 150.6z"/></svg>
        </button>
        </li>
        `;
      });
     
      /*playlist.appendChild(li);
      playlist.appendChild(playlistBtn);
      playlist.appendChild(removeBtn);*/
    
      // by clicking on a song, it will play a clicked song
      /*playlistBtn.addEventListener("click", () => {
        audio.src = song.src;
        audio.play();
      })*/
    
    }
    renderSongs();
    <div id="playlist"></div>

    So why is my code fixing yours? There are several bugs I have fixed: