Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: refactor music player project #669

Merged
merged 2 commits into from
Nov 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 165 additions & 0 deletions frontend-cert/js-projects/music-player-lab/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link href="https://fonts.googleapis.com/css2?family=Roboto+Mono&display=swap" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css2?family=Lato&family=Roboto+Mono&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="styles.css" />
<title>
Build a Music Player App
</title>
</head>

<body>
<div class="container">
<div class="player">
<div class="player-bar">
<div class="parallel-lines">
<div></div>
<div></div>
</div>
<h1 class="fcc-title">freeCodeCamp</h1>
<div class="parallel-lines">
<div></div>
<div></div>
</div>
</div>
<div class="player-content">
<div id="player-album-art">
<img src="https://cdn.freecodecamp.org/curriculum/js-music-player/quincy-larson-album-art.jpg"
alt="song cover art" />
</div>
<div class="player-display">
<div class="player-display-song-artist">
<p id="player-song-title"></p>
<p id="player-song-artist"></p>
</div>
<div class="player-buttons">
<button id="previous" class="previous" aria-label="Previous">
<svg width="24" height="19" viewBox="0 0 24 19" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M23.2248 0L7.03964 9.5L23.2248 19L23.2248 0Z" />
<rect width="4.63633" height="18.5453" transform="matrix(-1 0 0 1 4.63633 0)" />
</svg>
</button>
<button id="play" class="play" aria-label="Play">
<svg width="17" height="19" viewBox="0 0 17 19" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 0L16.1852 9.5L1.88952e-07 19L0 0Z" />
</svg>
</button>
<button id="pause" class="pause" aria-label="Pause">
<svg width="17" height="19" viewBox="0 0 17 19" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 6.54013e-07H4.75V19H0V6.54013e-07Z" />
<path d="M11.4 0H16.15V19H11.4V0Z" />
</svg>
</button>
<button id="next" class="next" aria-label="Next">
<svg width="24" height="19" viewBox="0 0 24 19" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 0L16.1852 9.5L1.88952e-07 19L0 0Z" />
<rect x="18.5885" width="4.63633" height="18.5453" />
</svg>
</button>
</div>
</div>
</div>
</div>
<div class="playlist">
<div class="playlist-bar">
<div class="parallel-lines">
<div></div>
<div></div>
</div>
<h2 class="playlist-title" id="playlist">Playlist</h2>
<div class="parallel-lines">
<div></div>
<div></div>
</div>
</div>
<ul id="playlist-songs">
<li id="song-0" class="playlist-song">
<button class="playlist-song-info" onclick="playSong(0)">
<span class="playlist-song-title">Scratching The Surface</span>
<span class="playlist-song-artist">Quincy Larson</span>
<span class="playlist-song-duration">4:25</span>
</button>
</li>

<li id="song-1" class="playlist-song">
<button class="playlist-song-info" onclick="playSong(1)">
<span class="playlist-song-title">Can't Stay Down</span>
<span class="playlist-song-artist">Quincy Larson</span>
<span class="playlist-song-duration">4:15</span>
</button>
</li>

<li id="song-2" class="playlist-song">
<button class="playlist-song-info" onclick="playSong(2)">
<span class="playlist-song-title">Still Learning</span>
<span class="playlist-song-artist">Quincy Larson</span>
<span class="playlist-song-duration">3:51</span>
</button>
</li>

<li id="song-3" class="playlist-song">
<button class="playlist-song-info" onclick="playSong(3)">
<span class="playlist-song-title">Cruising for a Musing</span>
<span class="playlist-song-artist">Quincy Larson</span>
<span class="playlist-song-duration">3:34</span>
</button>
</li>

<li id="song-4" class="playlist-song">
<button class="playlist-song-info" onclick="playSong(4)">
<span class="playlist-song-title">Never Not Favored</span>
<span class="playlist-song-artist">Quincy Larson</span>
<span class="playlist-song-duration">3:35</span>
</button>
</li>

<li id="song-5" class="playlist-song">
<button class="playlist-song-info" onclick="playSong(5)">
<span class="playlist-song-title">From the Ground Up</span>
<span class="playlist-song-artist">Quincy Larson</span>
<span class="playlist-song-duration">3:12</span>
</button>
</li>

<li id="song-6" class="playlist-song">
<button class="playlist-song-info" onclick="playSong(6)">
<span class="playlist-song-title">Walking on Air</span>
<span class="playlist-song-artist">Quincy Larson</span>
<span class="playlist-song-duration">3:25</span>
</button>
</li>

<li id="song-7" class="playlist-song">
<button class="playlist-song-info" onclick="playSong(7)">
<span class="playlist-song-title">Can't Stop Me. Can't Even Slow Me Down.</span>
<span class="playlist-song-artist">Quincy Larson</span>
<span class="playlist-song-duration">3:52</span>
</button>
</li>

<li id="song-8" class="playlist-song">
<button class="playlist-song-info" onclick="playSong(8)">
<span class="playlist-song-title">The Surest Way Out is Through</span>
<span class="playlist-song-artist">Quincy Larson</span>
<span class="playlist-song-duration">3:10</span>
</button>
</li>

<li id="song-9" class="playlist-song">
<button class="playlist-song-info" onclick="playSong(9)">
<span class="playlist-song-title">Chasing That Feeling</span>
<span class="playlist-song-artist">Quincy Larson</span>
<span class="playlist-song-duration">2:43</span>
</button>
</li>
</ul>
</div>
</div>
<script src="script.js"></script>
</body>

</html>
198 changes: 198 additions & 0 deletions frontend-cert/js-projects/music-player-lab/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
const playlistSongs = document.getElementById("playlist-songs");
const playButton = document.getElementById("play");
const pauseButton = document.getElementById("pause");
const nextButton = document.getElementById("next");
const previousButton = document.getElementById("previous");

const allSongs = [
{
id: 0,
title: "Scratching The Surface",
artist: "Quincy Larson",
duration: "4:25",
src: "https://cdn.freecodecamp.org/curriculum/js-music-player/scratching-the-surface.mp3",
},
{
id: 1,
title: "Can't Stay Down",
artist: "Quincy Larson",
duration: "4:15",
src: "https://cdn.freecodecamp.org/curriculum/js-music-player/can't-stay-down.mp3",
},
{
id: 2,
title: "Still Learning",
artist: "Quincy Larson",
duration: "3:51",
src: "https://cdn.freecodecamp.org/curriculum/js-music-player/still-learning.mp3",
},
{
id: 3,
title: "Cruising for a Musing",
artist: "Quincy Larson",
duration: "3:34",
src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cruising-for-a-musing.mp3",
},
{
id: 4,
title: "Never Not Favored",
artist: "Quincy Larson",
duration: "3:35",
src: "https://cdn.freecodecamp.org/curriculum/js-music-player/never-not-favored.mp3",
},
{
id: 5,
title: "From the Ground Up",
artist: "Quincy Larson",
duration: "3:12",
src: "https://cdn.freecodecamp.org/curriculum/js-music-player/from-the-ground-up.mp3",
},
{
id: 6,
title: "Walking on Air",
artist: "Quincy Larson",
duration: "3:25",
src: "https://cdn.freecodecamp.org/curriculum/js-music-player/walking-on-air.mp3",
},
{
id: 7,
title: "Can't Stop Me. Can't Even Slow Me Down.",
artist: "Quincy Larson",
duration: "3:52",
src: "https://cdn.freecodecamp.org/curriculum/js-music-player/cant-stop-me-cant-even-slow-me-down.mp3",
},
{
id: 8,
title: "The Surest Way Out is Through",
artist: "Quincy Larson",
duration: "3:10",
src: "https://cdn.freecodecamp.org/curriculum/js-music-player/the-surest-way-out-is-through.mp3",
},
{
id: 9,
title: "Chasing That Feeling",
artist: "Quincy Larson",
duration: "2:43",
src: "https://cdn.freecodecamp.org/curriculum/js-music-player/chasing-that-feeling.mp3",
}
];

const audio = new Audio();
let userData = {
songs: allSongs,
currentSong: null,
songCurrentTime: 0,
};

const playSong = (id, start = true) => {
const song = userData.songs.find((song) => song.id === id);
audio.src = song.src;
audio.title = song.title;

if (
userData.currentSong === null ||
playButton.classList.contains("playing") ||
start
) {
audio.currentTime = 0;
} else {
audio.currentTime = userData.songCurrentTime;
}
userData.currentSong = song;
playButton.classList.add("playing");

highlightCurrentSong();
setPlayerDisplay();
setPlayButtonAccessibleText();
audio.play();
};

const pauseSong = () => {
userData.songCurrentTime = audio.currentTime;
playButton.classList.remove("playing");
audio.pause();
};

const getCurrentSongIndex = () => userData.songs.indexOf(userData.currentSong);

const getNextSong = () => userData.songs[getCurrentSongIndex() + 1];

const getPreviousSong = () => userData.songs[getCurrentSongIndex() - 1];

const playNextSong = () => {
if (userData.currentSong === null) {
playSong(userData.songs[0].id);
return
}
const nextSong = getNextSong();
if (nextSong) {
playSong(nextSong.id);
} else {
userData.currentSong = null;
userData.songCurrentTime = 0;
pauseSong();
setPlayerDisplay();
highlightCurrentSong();
setPlayButtonAccessibleText();
}
};

const playPreviousSong = () => {
if (userData.currentSong === null) return;
const previousSong = getPreviousSong();
if (previousSong) {
playSong(previousSong.id);
} else {
playSong(userData.songs[0].id);
}
};

const setPlayerDisplay = () => {
const playingSong = document.getElementById("player-song-title");
const songArtist = document.getElementById("player-song-artist");
const currentTitle = userData.currentSong?.title;
const currentArtist = userData.currentSong?.artist;

playingSong.textContent = currentTitle ? currentTitle : "";
songArtist.textContent = currentArtist ? currentArtist : "";
};

const highlightCurrentSong = () => {
const playlistSongElements = document.querySelectorAll(".playlist-song");
const songToHighlight = document.getElementById(
`song-${userData.currentSong?.id}`
);

playlistSongElements.forEach((songEl) => {
songEl.removeAttribute("aria-current");
});

if (songToHighlight) songToHighlight.setAttribute("aria-current", "true");
};

const setPlayButtonAccessibleText = () => {
const song = userData.currentSong || userData.songs[0];

playButton.setAttribute(
"aria-label",
song.title ? `Play ${song.title}` : "Play"
);
};

playButton.addEventListener("click", () => {
if (userData.currentSong === null) {
playSong(userData.songs[0].id);
} else {
playSong(userData.currentSong.id, false);
}
});

pauseButton.addEventListener("click", pauseSong);

nextButton.addEventListener("click", playNextSong);

previousButton.addEventListener("click", playPreviousSong);

audio.addEventListener("ended", playNextSong);

setPlayButtonAccessibleText();
Loading