top of page
logo-2-color_2x.png

Interactive Website - Review Exercise

Points: 

10

Due By:

April 30, 2026 at 5:00:00 PM

Starting Files






This guide will help you work through the Spotify-style player step by step. The goal is not to memorize one finished script. The goal is to understand how each JavaScript concept helps make the interface interactive.


The main pattern is:


Data changes → state changes → function runs → DOM updates → user sees the result


You have practiced each piece already. This review exercise puts them together in one interface.





Suggested Work Order

Use this order while building. It should reduce confusion.

  1. Create the songs array.

  2. Create the state variables.

  3. Select the DOM elements.

  4. Write and test formatTime().

  5. Write updateNowPlaying().

  6. Call updateNowPlaying() and test the first song.

  7. Write renderQueue().

  8. Add click events to queue items.

  9. Write playSongAtIndex().

  10. Write play/pause.

  11. Write next/previous.

  12. Write like/unlike.

  13. Write queue toggle.

  14. Write clear queue.

  15. Add debugging checks.

  16. Test the full interface.







Troubleshooting Guide

Problem: The page does not update

Check:

console.log(currentSong);

If the correct song appears, check your DOM selectors.

If currentSong is undefined, check currentSongIndex.

Problem: I get “Cannot set properties of null”

This usually means JavaScript could not find an element. Check:

  • spelling of the ID

  • capitalization

  • whether the element exists in HTML

  • whether the script is connected correctly


Use:

console.log(mainTrackTitle);

Problem: The queue keeps duplicating

Make sure you clear the parent before rendering again:

queueList.innerHTML = "";

Problem: The wrong song loads

Check the index.

Inside your queue click event, log:

console.log(index);

Problem: The button does nothing

Check the event listener.

Use a temporary test:

button.addEventListener("click", function() {
  console.log("Button works");
});

Problem: Next or previous creates undefined

The index probably moved outside the array.

Check:

console.log(currentSongIndex);
console.log(queue.length);

The last valid index is:

queue.length - 1

Problem: The heart changes but does not stay changed

Make sure you are changing the song object:

currentSong.liked = !currentSong.liked;




Step 1: Understand What JavaScript Needs to Control

Before writing code, look at the interface and ask:

What parts of the page should change when the user interacts with it?

In this project, JavaScript needs to update:

  • the main song title

  • the main artist name

  • the album name

  • the year

  • the album art

  • the footer song title

  • the footer artist name

  • the queue list

  • the Up Next panel

  • the play/pause icon

  • the like button

  • the queue panel visibility


You do not need JavaScript for every visual detail. The CSS already handles most of the design. Your job is to connect the data and the interactions.


Lesson connection: This connects to the DOM lesson, where you practiced selecting elements and changing text, image sources, and classes.






Step 2: Start with Song Data

You need an array called songs. Each song should be an object because each song has several related pieces of information.


A song object should include:

title
artist
album
year
duration
albumArt
liked

Think of one object as one complete “song card” of data.


A helpful starting pattern:

const songs = [
  {
    title: "Song Title",
    artist: "Artist Name",
    album: "Album Name",
    year: 2024,
    duration: 200,
    albumArt: "image-url-here",
    liked: false
  }
];


Hint

Start with just two songs while testing. Once those work, add the rest.




Check Yourself

Can you explain why this should be an array of objects instead of one long list of strings?


Lesson connection: This connects to the arrays and objects lessons, especially the practice with song libraries, playlists, liked songs, durations, and arrays of song objects.







Step 3: Create State Variables

State means “what is currently true in the app.” You need a way to remember:

  • Which song is currently selected?

  • Is the player playing or paused?

  • What songs are currently in the queue?


A helpful starting point:

let currentSongIndex = 0;
let isPlaying = false;
let queue = [...songs];


What These Mean

currentSongIndex tells JavaScript which song is active.

isPlaying stores a true/false value.

queue gives you a working copy of the song list.



Hint

The first item in an array is index 0, not index 1.




Check Yourself

If currentSongIndex is 2, which song is selected?


Look at your array and count carefully.


Lesson connection: This connects to Module 1 and Module 2 ideas: values, variables, Booleans, program structure, and decisions. You are using numbers and Booleans to help the app “remember” what is happening.







Step 4: Select the DOM Elements

Before JavaScript can change the page, it has to find the page elements.

You will use IDs from the HTML.

Example:

const mainTrackTitle = document.getElementById("mainTrackTitle");

You need to select the major areas you plan to update.




Important Elements to Select

mainTrackTitle
mainArtistName
mainAlbumName
mainYear
mainAlbumArt


footerTrackTitle
footerArtistName
footerAlbumArt

queueList
upNextList
queuePanel

playPauseBtn
nextBtn
prevBtn
likeBtn
queueToggleBtn
clearQueueBtn

Hint

Do not guess the ID names. Look at the HTML and copy the IDs exactly.

JavaScript is case-sensitive.


These are all different:

mainTrackTitle
maintracktitle
MainTrackTitle


Troubleshooting Tip

After selecting an element, test it:

console.log(mainTrackTitle);

If the console shows null, JavaScript did not find the element. That usually means:

  • the ID was misspelled

  • capitalization does not match

  • the script is running before the HTML loads

  • the element does not exist in the HTML


You can also use:

console.assert(mainTrackTitle !== null, "mainTrackTitle was not found.");

Lesson connection: This connects directly to the DOM practice where you selected page elements, changed textContent, changed an image src, and added or removed classes.






Step 5: Write a Small Helper Function First

Before building the whole app, write a smaller function that solves one clear problem.


For example, song durations are stored as seconds:

200

But the interface should show:

3:20

So you can create a function called formatTime().



Your Goal

The function should accept seconds as input and return a formatted time.

function formatTime(seconds) {  
  // calculate minutes  
  // calculate remaining seconds  
  // return time as a string
}


Hints

You may need:

Math.floor()

You may need the remainder operator:

%

You may need:

padStart(2, "0")


Check Yourself

Before using the function in the interface, test it in the console:

console.log(formatTime(200)); 
// should be 3🕑

console.log(formatTime(175)); 
// should be 2:55

Lesson connection: This connects to the functions module, especially parameters and return values. A function can accept input, do a reusable job, and give a value back.







Step 6: Create updateNowPlaying()

This is one of the most important functions in the exercise.

Its job is to take the current song and update the visible interface.


Start by finding the current song:

const currentSong = queue[currentSongIndex];

Then use that object to update the DOM.




What This Function Should Update

It should update:

  • main song title

  • main artist name

  • main album name

  • main year

  • main album art

  • footer song title

  • footer artist name

  • footer album art

  • total duration



Hint

Use textContent for text.


You can use innerHTML carefully if you are inserting an image.


Example pattern:

mainTrackTitle.textContent = currentSong.title;

For album art, think about what HTML needs to appear inside the album art container.




Check Yourself

Inside the function, add:

console.log(currentSong);

If the correct song object appears in the console, your data and index are working.


If the correct song logs but the page does not update, check your DOM selectors.



Lesson connection: This connects to the DOM lesson because JavaScript is changing visible page content. It also connects to the functions lesson because updateNowPlaying() is a reusable job that creates a side effect on the page.








Step 7: Render the Queue

The queue should be created from the array. You should not manually write every song row in HTML. Instead, your function should:

  1. Clear the current queue display.

  2. Loop through the queue array.

  3. Create one element for each song.

  4. Add song information to that element.

  5. Add a click event to that element.

  6. Append it to the page.




Starter Thinking

function renderQueue() {  
    queueList.innerHTML = "";   
    
    queue.forEach(function(song, index) {    
        // create an element    
        // add classes    
        // add song information    
        // add a click event    
        // append to queueList  
    });

}


Hint

The index matters because it tells you which song was clicked.

Inside the loop, ask:

  • What song am I currently creating?

  • What index does this song have?

  • How can I use that index later when the user clicks this row?




Check Yourself

Add this inside the loop:

console.log(song.title, index);

You should see every song title and its index.




Common Problem

If your queue duplicates every time you click a song, you probably forgot to clear the queue first:

queueList.innerHTML = "";



Lesson connection: This combines looping through arrays, working with arrays of objects, creating elements, and inserting them into the DOM.







Step 8: Make Each Song Clickable

Once the queue appears, each song row should respond to a click. You will need a function that accepts an index.

function playSongAtIndex(index) {  
    // update currentSongIndex  
    // set isPlaying  
    // update the interface
}



Hint

The function should not manually update every element itself. Let updateNowPlaying() do that job. That means playSongAtIndex() can stay short.


Think:

  1. Change the state.

  2. Run the update function.




Check Yourself

When you click a song, does the console show the correct index?

console.log("Clicked song index:", index);

If the index is correct but the interface does not change, the problem is probably in updateNowPlaying().


If clicking does nothing at all, the event listener may not be attached.



Lesson connection: This connects to the event lessons. The user clicks something, and JavaScript responds by running a function.







Step 9: Toggle Play and Pause

The play/pause button should use the isPlaying Boolean. The main idea is:

isPlaying = !isPlaying;

This flips the value. If it was false, it becomes true. If it was true, it becomes false.



Hint

Separate the logic into two functions:

function togglePlayPause() {  
    // changes the state
}

function updatePlayPauseButton() {  
    // changes the icon
}

That keeps your code easier to read.



Check Yourself

Add:

console.log(isPlaying);

Click the button several times. You should see the value switch between true and false.



Common Problem

If isPlaying changes but the icon does not, check the function that updates the button.


If the icon function works but clicking does nothing, check the event listener.


Lesson connection: This connects to Booleans, decisions, functions, DOM changes, and events.






Step 10: Add Next and Previous

The next and previous buttons should change currentSongIndex. For next, you are moving forward. For previous, you are moving backward.




Hint

You need to think about the beginning and end of the array.


Ask:

  • What should happen if the user clicks Next on the last song?

  • What should happen if the user clicks Previous on the first song?


You can either stop at the edge or loop around. Just make your choice clear and consistent.




Check Yourself

Log the index:

console.log("Current index:", currentSongIndex);console.log("Queue length:", queue.length);

Remember:

The last valid index is:

queue.length - 1



Common Problem

If you see undefined, your index probably went outside the array.

That means JavaScript is trying to find a song that does not exist.



Lesson connection: This connects to arrays, indexes, program structure, decisions, and functions.







Step 11: Toggle the Like Button

Each song object has a liked property. That means liking a song should change the data first.

currentSong.liked = !currentSong.liked;

Then the button should update visually.



Hint

Use the existing CSS class:

track-info__like-btn--liked

You can add or remove this class depending on whether the current song is liked.




Check Yourself

Log the song after clicking like:

console.log(currentSong);

Does the liked property change from false to true?




Common Problem

If the heart changes but does not stay changed when you leave the song and come back, you may have changed only the icon, not the song object.


Make sure the data changes too.


Lesson connection: This connects to updating object properties, methods/behavior, DOM class changes, and click events.







Step 12: Show and Hide the Queue Panel


The queue panel can be shown or hidden by toggling a class. You do not need to rewrite the layout.


Use the existing class from your CSS file:

hidden


Hint

This is a good place for:

classList.toggle()

Think of it as a light switch for a class.




Check Yourself

Open the browser inspector and click the queue button. Does the hidden class appear and disappear on the queue panel?


  • If yes, JavaScript is doing its job.


If the visual does not change even though the class changes, the issue may be CSS.



Lesson connection: This connects to DOM class changes and events.







Step 13: Clear the Queue

The Clear Queue button should leave only the current song. This is an array problem.


You need to:

  1. Save the current song.

  2. Replace the queue with a new array containing only that song.

  3. Reset the current song index.

  4. Re-render the queue.




Hint

Do not clear the queue before saving the current song. Think through the order:

const currentSong = queue[currentSongIndex];

Then change the queue.




Check Yourself


After clearing, log the queue:

console.log(queue);

You should see an array with one song object inside it.




Common Problem

If the wrong song remains, check the order of your steps. If the data changes but the screen does not, make sure you call the render functions again.



Lesson connection: This connects to array mutation/copying, state, DOM rendering, and events.







Step 14: Add Event Listeners

At this point, many of your functions may exist, but they will not run until something calls them.


Buttons need event listeners.


Example pattern:

playPauseBtn.addEventListener("click", togglePlayPause);



You Need Events For

playPauseBtn
nextBtn
prevBtn
likeBtn
queueToggleBtn
clearQueueBtn

Queue items also need click events, but those are created inside renderQueue() because the queue items are created with JavaScript.




Hint

If a button does nothing, ask:

  • Did I select the button?

  • Did I write the function?

  • Did I attach the event listener?

  • Is there an error happening before this code runs?




Check Yourself

Temporarily test an event with:

playPauseBtn.addEventListener("click", function() {  
   console.log("Play button clicked");
});

Once you know the button works, connect it to the real function.




Lesson connection: This connects directly to the event lessons, especially click events, event listeners, and making visible changes on the page.








Step 15: Initialize the App

After writing the functions, you need to call one function when the page first loads.


Usually, this will be:

updateNowPlaying();

That first call makes the interface match the starting data.




Hint

Functions do not run just because they exist. Defining a function is like writing instructions. Calling a function is like actually following the instructions.




Check Yourself

When the page first opens:

  • Does the first song appear?

  • Does the queue appear?

  • Does the footer match the main song?

  • Does the like button match the song’s liked value?



Locked Message

bottom of page