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>
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:
audio
tag into the inner HTML of the play controlbutton
to div
and added an onclick
eventonclick
from your li