Home > database >  indirectly changing the play button style using JavaScript event
indirectly changing the play button style using JavaScript event

Time:10-30

I am building a music player using HTML-css-javascript only. I have a list of music which I have stored in an array as shown below.

let songs = [
   {songName: "Butter", filePath:"songs/1.mp3",coverPath:'covers/1.png'},
   {songName: "Boy With Luv", filePath:"songs/2.mp3",coverPath:'covers/2.jpeg'},
   {songName: "Dynamite", filePath:"songs/3.mp3",coverPath:'covers/3.jpeg'},
   {songName: "Idol", filePath:"songs/4.mp3",coverPath:'covers/4.png'},
   {songName: "Life Goes On", filePath:"songs/5.mp3",coverPath:'covers/5.jpeg'},
   {songName: "Mic Drop", filePath:"songs/6.mp3",coverPath:'covers/6.jpeg'},
]

And the UI looks like this:

ignore the bad UI

Things look good that on clicking specific songs, the play icon on the side of the song name changes, but when I change the song with the next button at the bottom, the song changes but the icon still remains unchanged. As you can see in the second image, I changed to the fourth song but the music list still shows the third song playing.

enter image description here

I need to change the styling of the icon with the click of the next&previous button at the bottom. I have songindex of the current song playing in the function.

for reference attached the nextButton code:

//next button
document.getElementById('next').addEventListener('click', (e)=>{
 
 songIndex = (songIndex >=5) ? 0 : songIndex 1;
 audioElement.src = `songs/${songIndex}.mp3`;
 audioElement.currentTime = 0;
 audioElement.play();
 masterPlay.classList.remove('fa-play-circle');
 masterPlay.classList.add('fa-pause-circle');
 mastersongName.innerText = "BTS - " songs[songIndex].songName;
 masterSideImg.src = songs[songIndex].coverPath;

})

COmplete HTML code:

    <!DOCTYPE HTML>
    <html lang="en">
    <head>
     <meta charset="UTF-8">
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <title>Redify - listen music here</title>
    <link rel="stylesheet" href="style.css">
 </head>
<body>
   <nav>
       <ul>
           <li class="brand"><img src="logo.png" alt="logo">Spotify</li>
           <li>Home</li>
           <li>About</li>
       </ul>
   </nav>

<div class="container">
    <div class="songList">
        <h1>Best of BTS</h1>
        <div class="songitemContainer">
            <div class="songItem">
                <img alt="1">
                <span class="songName">Butter</span>
                <span class="songlistPlay">
                    <span class="timestamp">3:41
                        <i id="0" class="far songItemPlay fa-1.5x fa-play-circle"></i>
                    </span> 
                </span>
            </div>
            <div class="songItem">
                <img alt="1">
                <span class="songName">Butter</span>
                <span class="songlistPlay">
                    <span class="timestamp">3:41
                        <i id="1" class="far songItemPlay fa-1.5x fa-play-circle"></i>
                    </span> 
                </span>
            </div>
            <div class="songItem">
                <img alt="1">
                <span class="songName">Butter</span>
                <span class="songlistPlay">
                    <span class="timestamp">3:41
                        <i id="2" class="far songItemPlay fa-1.5x fa-play-circle"></i>
                    </span> 
                </span>
            </div>
            <div class="songItem">
                <img alt="1">
                <span class="songName">Butter</span>
                <span class="songlistPlay">
                    <span class="timestamp">3:41
                        <i id="3" class="far songItemPlay fa-1.5x fa-play-circle"></i>
                    </span> 
                </span>
            </div>
            <div class="songItem">
                <img alt="1">
                <span class="songName">Butter</span>
                <span class="songlistPlay">
                    <span class="timestamp">3:41
                        <i id="4" class="far songItemPlay fa-1.5x fa-play-circle"></i>
                    </span> 
                </span>
            </div>
            <div class="songItem">
                <img alt="1">
                <span class="songName">Butter</span>
                <span class="songlistPlay">
                    <span class="timestamp">3:41
                        <i id="5" class="far songItemPlay fa-1.5x fa-play-circle"></i>
                    </span> 
                </span>
            </div>
        </div>
    </div>

    <div class="songBanner">
      
    </div>
</div>


<div class="bottom">
    <img src="covers/1.png" alt="side_img" width="60px" id="masterSideImg">
    <div class="bottomprogress">
        <input type="range" name="range" id="myProgressBar" min="0" max="100" value=0>
        <div class="icons">
            <i class="fas fa-2x fa-step-backward" id="previous"></i>
            <i class="far fa-2x fa-play-circle" id="masterPlay"></i>
            <i class="fas fa-2x fa-step-forward" id="next"></i>
        </div>
        <div class="songInfo">
            <img src="playing.gif" width="32px" alt="playing" id="gif"><span id="mastersongName">BTS - Butter</span> 
        </div>
    </div>
</div>
<script src="https://kit.fontawesome.com/06646b7200.js" crossorigin="anonymous"></script>
<script src="script.js"></script>

The complete link of the project is given here: https://github.com/mohitm15/Redify

CodePudding user response:

I refactored your play/pause icon setting part into a function:

const ICON_PLAY = 1;
const ICON_STOP = 0;

const handleSongPlayIcon = (target, isPlaying) => {
  if (isPlaying == ICON_PLAY) {
    target.classList.remove("fa-pause-circle");
    target.classList.add("fa-play-circle");
  } else if (isPlaying == ICON_STOP) {
    target.classList.remove("fa-play-circle");
    target.classList.add("fa-pause-circle");
  }
};

and adjusted several functions in your code, toggling the icons

//Variable initialisation

let songIndex = 0;
let audioElement = new Audio("songs/0.mp3");
let masterPlay = document.getElementById("masterPlay");
let myProgressBar = document.getElementById("myProgressBar");
let gif = document.getElementById("gif");
let songItems = Array.from(document.getElementsByClassName("songItem"));
let songTitle = document.getElementsByClassName("songInfo");
let mastersongName = document.getElementById("mastersongName");
let masterSideImg = document.getElementById("masterSideImg");
//console.log(songTitle.innerText)


let songs = [
  { songName: "Butter", filePath: "songs/1.mp3", coverPath: "covers/1.png" },
  {
    songName: "Boy With Luv",
    filePath: "songs/2.mp3",
    coverPath: "covers/2.jpeg",
  },
  { songName: "Dynamite", filePath: "songs/3.mp3", coverPath: "covers/3.jpeg" },
  { songName: "Idol", filePath: "songs/4.mp3", coverPath: "covers/4.png" },
  {
    songName: "Life Goes On",
    filePath: "songs/5.mp3",
    coverPath: "covers/5.jpeg",
  },
  { songName: "Mic Drop", filePath: "songs/6.mp3", coverPath: "covers/6.jpeg" },
];


const ICON_PLAY = 1;
const ICON_STOP = 0;

const handleSongPlayIcon = (target, isPlaying) => {
  if (isPlaying == ICON_PLAY) {
    target.classList.remove("fa-pause-circle");
    target.classList.add("fa-play-circle");
  } else if (isPlaying == ICON_STOP) {
    target.classList.remove("fa-play-circle");
    target.classList.add("fa-pause-circle");
  }
};

songItems.forEach((item, i) => {
  //console.log(item, i);
  item.getElementsByTagName("img")[0].src = songs[i].coverPath;
  item.getElementsByClassName("songName")[0].innerText = songs[i].songName;
  //item.getElementsByClassName("timestamp")[0].innerText = parseInt(audioElement.duration*1);
});
//audioElement.play();

//handle play/pause
masterPlay.addEventListener("click", () => {
  // grab all the icon elements on the page
  const allSongsPlayItemElements = document.querySelectorAll(".songItemPlay");

  

  if (audioElement.paused || audioElement.currentTime <= 0) {
    audioElement.play();
    handleSongPlayIcon(masterPlay, ICON_STOP);
    handleSongPlayIcon(allSongsPlayItemElements[songIndex], ICON_STOP);
    gif.style.opacity = 1;
  } else {
    audioElement.pause();
    handleSongPlayIcon(masterPlay, ICON_PLAY);
    handleSongPlayIcon(allSongsPlayItemElements[songIndex], ICON_PLAY);
    gif.style.opacity = 0;
  }
});

//Listen to event
audioElement.addEventListener("timeupdate", () => {
  //update songbar
  progress = parseInt((audioElement.currentTime / audioElement.duration) * 100);
  myProgressBar.value = progress;
});

myProgressBar.addEventListener("change", () => {
  audioElement.currentTime =
    (myProgressBar.value * audioElement.duration) / 100;
});

//songlist appear on landing page

//makes button of all songs to display play symbol
const makeAllPlay = () => {
  Array.from(document.getElementsByClassName("songItemPlay")).forEach(
    (item) => {
      handleSongPlayIcon(item, ICON_PLAY);
    }
  );
};

//songList :eventListener for song playing/pausing
let selectedSongIndex;
Array.from(document.getElementsByClassName("songItemPlay")).forEach((item) => {
  item.addEventListener("click", (e) => {
    //console.log(e.target) gives => <i  aria-hidden="true"></i>

    makeAllPlay();
    songIndex = parseInt(e.target.id);
    //songIndex = the song is playing currently (for first time)
    //selectedsongIndex = the song that user clicked when any song is playing (after first time)
    if (audioElement.paused === true) {
      selectedSongIndex = songIndex;
      audioElement.src = `songs/${songIndex}.mp3`;
      audioElement.currentTime = 0;
      audioElement.play();
      //console.log("song is playing" );
      handleSongPlayIcon(e.target, ICON_STOP);
      handleSongPlayIcon(masterPlay, ICON_STOP);
      gif.style.opacity = 1;
    } else if (audioElement.paused === false) {
      if (selectedSongIndex === songIndex) {
        audioElement.pause();
        //console.log("audio is paused now")
        handleSongPlayIcon(e.target, ICON_PLAY);
        handleSongPlayIcon(masterPlay, ICON_PLAY);
        gif.style.opacity = 0;
      } else {
        makeAllPlay();
        songIndex = parseInt(e.target.id);
        selectedSongIndex = songIndex;

        audioElement.src = `songs/${songIndex}.mp3`;
        audioElement.currentTime = 0;
        audioElement.play();
        //console.log("song is playing" );
        handleSongPlayIcon(e.target, ICON_STOP);
        handleSongPlayIcon(masterPlay, ICON_STOP);
        gif.style.opacity = 1;
      }
    }
    //console.log("songIndexx = ",songIndex);
    //console.log("selected  = "  selectedSongIndex);
    mastersongName.innerText = "BTS - "   songs[songIndex].songName;
    masterSideImg.src = songs[songIndex].coverPath;

    audioElement.addEventListener("timeupdate", () => {
      // console.log("songcurrentTime = " parseInt(audioElement.currentTime))
      // console.log("song duartion = "  parseInt(audioElement.duration));
      if (audioElement.currentTime === audioElement.duration) {
        makeAllPlay();
        console.log("song Completed");
        songIndex = songIndex >= 5 ? 0 : songIndex   1;
        audioElement.src = `songs/${songIndex}.mp3`;
        audioElement.currentTime = 0;
        audioElement.play();
        mastersongName.innerText = "BTS - "   songs[songIndex].songName;
        masterSideImg.src = songs[songIndex].coverPath;

        // grab all the icon elements on the page
        const allSongsPlayItemElements = document.querySelectorAll(".songItemPlay");
        handleSongPlayIcon(allSongsPlayItemElements[songIndex], ICON_STOP);
        //previous can be accessed with e.target.id
        //how to access the next element (as it is not being clicked by user)
      }
    });
  });
});

//next button
document.getElementById("next").addEventListener("click", (e) => {
  // grab all the icon elements on the page
  const allSongsPlayItemElements = document.querySelectorAll(".songItemPlay");
  // set the currently playing icon to "play"
  handleSongPlayIcon(allSongsPlayItemElements[songIndex], ICON_PLAY);

  songIndex = songIndex >= 5 ? 0 : songIndex   1;
  audioElement.src = `songs/${songIndex}.mp3`;
  audioElement.currentTime = 0;
  audioElement.play();

  handleSongPlayIcon(masterPlay, ICON_STOP);
  mastersongName.innerText = "BTS - "   songs[songIndex].songName;
  masterSideImg.src = songs[songIndex].coverPath;

  // set the next song icon to "stop"
  handleSongPlayIcon(allSongsPlayItemElements[songIndex], ICON_STOP);
});

//previous button
document.getElementById("previous").addEventListener("click", (e) => {
  // grab all the icon elements on the page
  const allSongsPlayItemElements = document.querySelectorAll(".songItemPlay");
  // set the currently playing icon to "play"
  handleSongPlayIcon(allSongsPlayItemElements[songIndex], ICON_PLAY);

  songIndex = songIndex <= 0 ? 5 : songIndex - 1;
  audioElement.src = `songs/${songIndex}.mp3`;
  audioElement.currentTime = 0;
  audioElement.play();

  handleSongPlayIcon(masterPlay, ICON_STOP);
  mastersongName.innerText = "BTS - "   songs[songIndex].songName;
  masterSideImg.src = songs[songIndex].coverPath;

  // set the next song icon to "stop"
  handleSongPlayIcon(allSongsPlayItemElements[songIndex], ICON_STOP);
});

CodePudding user response:

Looks to me like you forgot to call makeAllPlay(); at the beginning of the previous/next button click handlers. Also you'll want to change the newly playing song item to show the pause button.

Near the beginning of the two click handlers (for previous/next buttons) add:

makeAllPlay();
const itemElem = document.getElementsByClassName("songItemPlay")[songIndex];
itemElem.classList.remove('fa-play-circle');
itemElem.classList.add('fa-pause-circle');
  • Related