I did pretty well on studying today. Although I just wasn’t into it today. My excitement for learning is at a low right now. I feel depressed. Part of me thinks I should get up and ride the bike for a bit. Get off this chair. Another part of me isn’t caring right now. I mean, there aren’t many calories to burn. All I had today was some scrambled eggs and a bowl of cereal.
However, I’m not really feeling up to writing. I don’t have much to say at the moment. I just wanted to get my JavaScript notes up.
JavaScript notes…
—————————————-
Music Player Steps 1-30:
Step 1
In this project you will learn basic string and array methods by building a music player app. You will be able to play, pause, skip, and shuffle songs.
The HTML and CSS of this project have been provided for you, so you can focus on the JavaScript.
Start by accessing the #playlist-songs, #play, and #pause elements with the getElementById() method. Assign them to variables playlistSongs, playButton and pauseButton respectively.
const playlistSongs = document.getElementById('playlist-songs'); const playButton = document.getElementById('play'); const pauseButton = document.getElementById('pause');
Step 2
Access the #next, #previous and #shuffle elements from the HTML file.
Assign them to variables named nextButton, previousButton, and shuffleButton, respectively.
const nextButton = document.getElementById('next'); const previousButton = document.getElementById('previous'); const shuffleButton = document.getElementById('shuffle');
Step 3
Next, create an array to store all the songs.
Create an empty allSongs array.
const allSongs = [];
Step 4
Inside the allSongs array, create an object with the following properties and values:
id: 0,
title: “Scratching The Surface”,
artist: “Quincy Larson”,
duration: “4:25”,
src: “https://s3.amazonaws.com/org.freecodecamp.mp3-player-project/scratching-the-surface.mp3”,
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 shuffleButton = document.getElementById(“shuffle”);
const allSongs = [
];
{ id: 0, title: "Scratching The Surface", artist: "Quincy Larson", duration: "4:25", src: "https://s3.amazonaws.com/org.freecodecamp.mp3-player-project/scratching-the-surface.mp3", }
Step 5
Add a second object with the following keys and values:
id: 1,
title: “Can’t Stay Down”,
artist: “Quincy Larson”,
duration: “4:15”,
src: “https://s3.amazonaws.com/org.freecodecamp.mp3-player-project
{ id: 1, title: "Can't Stay Down", artist: "Quincy Larson", duration: "4:15", src: "https://s3.amazonaws.com/org.freecodecamp.mp3-player-project/cant-stay-down.mp3", }
Step 6
Add a third object with the following properties and values:
id: 2,
title: “Still Learning”,
artist: “Quincy Larson”,
duration: “3:51”,
src: “https://s3.amazonaws.com/org.freecodecamp.mp3-player-project/still-learn
{ id: 2, title: "Still Learning", artist: "Quincy Larson", duration: "3:51", src: "https://s3.amazonaws.com/org.freecodecamp.mp3-player-project/still-learning.mp3", }
Step 7
We’ve added the rest of the songs to the allSongs array for you.
Next, you’ll learn about the Web Audio API and how to use it to play songs. All modern browsers support the Web Audio API, which lets you generate and process audio in web applications.
Use const to create a variable named audio and set it equal to new Audio(). This will create a new HTML5 audio element.
const audio = new Audio();
Step 8
Create a userData object that will contain the songs, the current song playing, and the time of the current song.
Declare an empty userData object using the let keyword.
let userData = { };
Step 9
Since users will be able to shuffle and delete songs from the playlist, you will need to create a copy of the allSongs array without mutating the original. This is where the spread operator comes in handy.
The spread operator (…) allows you to copy all elements from one array into another. It can also be used to concatenate multiple arrays into one. In the example below, both arr1 and arr2 have been spread into combinedArr:
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combinedArr = […arr1, …arr2];
console.log(combinedArr); // Output: [1, 2, 3, 4, 5, 6]
Inside the userData object create a songs property. For the value, spread allSongs into an array.
let userData = { songs: [...allSongs] };
Step 10
To handle the current song’s information and track its playback time, create a currentSong and songCurrentTime properties. Set the values to null and 0 respectively.
let userData = { songs: [...allSongs], currentSong: null, songCurrentTime: 0 };
Step 11
Now you need a way to display the songs in the UI. To do this, you’ll create a renderSongs function using the arrow function syntax.
An arrow function is a shorter and more concise way to write functions in JavaScript. It’s a function expression, which is a function that’s assigned to a variable. To write an arrow function, you can use the following syntax:
// Traditional function
function add(a, b) {
return a + b;
}
console.log(add(3, 5)); // Output: 8
// Arrow function
const addArrow = (a, b) => {
return a + b;
};
console.log(addArrow(3, 5)); // Output: 8
If the function body consists of a single expression, you don’t need the curly braces and the return keyword. This is called an implicit return:
const addArrow = (a, b) => a + b;
console.log(addArrow(3, 5)); // Output: 8
Use the arrow function syntax to create a renderSongs function that takes in array as its parameter.
const renderSongs = (array) => { }
Step 12
Later when you call the renderSongs function, you’ll pass in the songs array inside the userData object. When you do, the function will loop through the array and build HTML for all the songs.
To do this, you’ll use the map() method, which you’ll learn more about in the following steps.
For now, use const to declare a variable named songsHTML and assign it array.map().
const songsHTML = array.map();
Step 13
The map() method is used to iterate through an array and return a new array. It’s helpful when you want to create a new array based on the values of an existing array. For example:
const numbers = [1, 2, 3];
const doubledNumbers = numbers.map((number) => number * 2); // doubledNumbers will be [2, 4, 6]
Notice that the map() method takes a function as an argument. This is called a callback function, which is a function that is passed to another function as an argument. In the example above, the callback function is (number) => number * 2, and it’s run on each element in the numbers array. The map() method then returns a new array with the results.
Pass in a callback function to the map() method. The callback function should take song as a parameter, use the arrow function syntax, and have an empty body.
const songsHTML = array.map((song) => { });
Step 14
Inside the map(), add a return statement with backticks where you will interpolate all the elements responsible to displaying the song details.
Inside the backticks, create an li tag with the id song-${song.id} as the first attribute. Also, add the class playlist-song as the second attribute.
return ``
Step 15
Create a button element with class playlist-song-info. Inside the button, add a span element with the class playlist-song-title, then interpolate song.title as the text.
Step 16
Inside the button, create two more span elements. The first span element should have class playlist-song-artist and interpolate song.artist. The second span element should have class playlist-song-duration and interpolate song.duration.
Step 17
Create another button element with the class playlist-song-delete and the aria-label attribute set to Delete interpolated with song.title. For the content of the delete icon, paste in the following SVG:
Step 18
Right now the songsHTML is an array. If you tried to display this as is, you would see the songs separated by commas. This is not the desired outcome because you want to display the songs as a list. To fix this, you will need to join the array into a single string by using the join() method.
The join() method is used to concatenate all the elements of an array into a single string. It takes an optional parameter called a separator which is used to separate each element of the array. For example:
const exampleArr = [“This”, “is”, “a”, “sentence”];
const sentence = exampleArray.join(” “); // Separator takes a space character
console.log(sentence); // Output: “This is a sentence”
Chain the join() method to your map() method and pass in an empty string for the separator.
To chain multiple methods together, you can call the join() method on the result of the map() method. For example:
array.map().join();
return `
Step 19
Next, you will need to update the playlist in your HTML document to display the songs.
Assign songsHTML to the innerHTML property of the playlistSongs element. This will insert the li element you just created into the ul element in the already provided HTML file.
playlistSongs.innerHTML = songsHTML;
Step 20
Now you need to call the renderSongs function and pass in userData?.songs in order to finally display the songs in the UI.
Optional chaining (?.) helps prevent errors when accessing nested properties that might be null or undefined. For example:
const user = {
name: “Quincy”,
address: {
city: “San Francisco”,
state: “CA”,
country: “USA”,
},
};
// Accessing nested properties without optional chaining
const state = user.address.state; // CA
// Accessing a non-existent nested property with optional chaining
const zipCode = user.address?.zipCode; // Returns undefined instead of throwing an error
Call the renderSongs function with the songs property of userData. This will render the songs in the playlist.
renderSongs(userData?.songs);
Step 21
Now that you have the list of songs displayed on the screen, it would be nice to sort them in alphabetical order by title. You could manually update the allSongs array, but JavaScript has an array method you can use called sort().
The sort() method converts elements of an array into strings and sorts them in place based on their values in the UTF-16 encoding.
const names = [“Tom”, “Jessica”, “Quincy”, “Naomi”];
names.sort() // [“Jessica”, “Naomi”, “Quincy”, “Tom”]
Add the sort() method to userData?.songs.
userData?.songs.sort();
Step 22
To sort the songs in alphabetical order by title, you will need to pass in a compare callback function into your sort() method.
Here is an example of sorting a list of fruits by name.
const fruits = [
{ name: “Apples”, price: 0.99 },
{ name: “Blueberries”, price: 1.49 },
{ name: “Grapes”, price: 2.99 },
];
fruits.sort((a, b) => {
if (a.name < b.name) {
return -1;
}
if (a.name > b.name) {
return 1;
}
return 0;
});
In the next few steps, you will learn what each of those if statements is doing inside that callback function. But for now, add an empty callback function to your sort() method and use a and b for the parameter names.
userData?.songs.sort((a, b) => { });
Step 23
The sort() method accepts a compare callback function that defines the sort order.
In this example, the first condition (a.name < b.name) checks if the name of the first fruit is less than the name of the second fruit. If so, the first fruit is sorted before the second fruit.
Strings are compared lexicographically which means they are compared character by character. For example, "Apples" is less than "Bananas" because "A" comes before "B" in the alphabet.
The reason why this example is returning numbers is because the sort() method is expecting a number to be returned. If you return a negative number, the first item is sorted before the second item.
const fruits = [
{ name: "Apples", price: 0.99 },
{ name: "Blueberries", price: 1.49 },
{ name: "Grapes", price: 2.99 },
];
fruits.sort((a, b) => {
if (a.name < b.name) {
return -1;
}
if (a.name > b.name) {
return 1;
}
return 0;
});
Inside your callback function, add an if statement to check if a.title is less than b.title. If so, return -1.
userData?.songs.sort((a,b) => { if (a.title < b.title) { return -1; } }); Step 24 The second condition in this example checks if a.name > b.name. If so, the function returns 1, which sorts the first fruit after the second fruit. const fruits = [ { name: "Apples", price: 0.99 }, { name: "Blueberries", price: 1.49 }, { name: "Grapes", price: 2.99 }, ]; fruits.sort((a, b) => { if (a.name < b.name) { return -1; } if (a.name > b.name) { return 1; } return 0; }); Inside your callback function, add another if statement to check if a.title is greater than b.title. If so, return the number 1.if (a.title > b.title) { return 1; }Step 25
In the example, if a.name is equal to b.name, then the function returns 0. This means that nothing changes and the order of a and b remains the same.const fruits = [
{ name: "Apples", price: 0.99 },
{ name: "Blueberries", price: 1.49 },
{ name: "Grapes", price: 2.99 },
];fruits.sort((a, b) => {
if (a.name < b.name) { return -1; } if (a.name > b.name) {
return 1;
}return 0;
});
Below your if statements, return the number 0 to leave the order of the two elements unchanged.Now you should see the songs in alphabetical order in the playlist.
return 0;Step 26
It's time to begin implementing the functionality for playing the displayed songs.Define a playSong function using const. The function should take an id parameter which will represent the unique identifier of the song you want to play.
const playSong = (id) => { }Step 27
The find() method retrieves the first element within an array that fulfills the conditions specified in the provided callback function. If no element satisfies the condition, the method returns undefined.In the example below, the find() method is used to find the first number greater than 25:
const numbers = [10, 20, 30, 40, 50];
// Find the first number greater than 25
const foundNumber = numbers.find((number) => number > 25);
console.log(foundNumber); // Output: 30
Use const to create a variable named song and assign it result of the find() method call on the userData?.songs array. Use song as the parameter of the find() callback and check if song.id is strictly equal to id.This will iterate through the userData?.songs array, searching for a song that corresponds to the id passed into the playSong function.
const playSong = (id) => { const song = userData?.songs.find(song => song.id === id); };Step 28
Inside the playSong function, set the audio.src property equal to song.src. This tells the audio element where to find the audio data for the selected song.Also, set the audio.title property equal to song.title. This tells the audio element what to display as the title of the song.
const playSong = (id) => { const song = userData?.songs.find((song) => song.id === id); audio.src = song.src; audio.title = song.title; };Step 29
Before playing the song, you need to make sure it starts from the beginning. This can be achieved by the use of the currentTime property of the audio object.Add an if statement to check whether the userData?.currentSong is null or if userData?.currentSong.id is strictly not equal song.id. Inside if block, set the currentTime property of the audio object to 0.
if (userData?.currentSong === null || userData?.currentSong.id !== song.id) { audio.currentTime = 0; }Step 30
Add an else block to handle the current song's position in the playlist.Within the else block, set the currentTime property of the audio object to the value stored in userData?.songCurrentTime.
if (userData?.currentSong === null || userData?.currentSong.id !== song.id) { audio.currentTime = 0; } else { audio.currentTime = userData?.songCurrentTime; }Category: Uncategorized