skip to Main Content

I’m making a simple music player in HTML, Javascript and CSS that plays the song/music files locally, in my html I have an audio element and 3 buttons (select files, previous song, next song) and a

element that should display the name of each song that is being played, this is my html code :

<button id="select-audio">Select Files</button>
    <button id="prv">Previous</button>
    <button id="nxt">Next</button>

    <audio id="aud" controls></audio>

    <p id="title"></p>

now in my Javascript code I try to get the name of the song and display it using this line (inside a for loop) where audName is the index
document.getElementById("title").innerHTML=input.files[audName].name
however the

element only displays the last song in the list without changing it when the song ends or when I click on the next or previous button (note in the following code I didn’t place the previous line in the next and previous and end functions but I tired it and it didn’t work), this is my JS code

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

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

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

let audios = [];

let selectAudio = document.getElementById("select-audio");

//Listen when the select-audio button is clicked to perform the action of selecting the audio files

selectAudio.addEventListener('click', function(){

//CREATE AN INPUT ELEMENT AND THEN CHECK FOR CHANGE
const input = document.createElement('input');

input.type = "file";
input.accept = "audio/*";
input.multiple = true;
input.onchange = function (e){

    audios = Array.from(e.target.files);
    playAudios(audios,0); //it's 0 here so that it plays the first audio
    
    for (let audName = 0; audName < audios.length; audName++){
        document.getElementById("demo").innerHTML = input.files[audName].name;
    }


    
};//END OF ONCHANGE FUNCTION OF THE INPUT

input.click();

}//END OF THE ADD EVENT LISTENER FUNCTION

);//END OF selectAudio EVENT LISTENER



//Play the Audios, NOTE that the following function was called previousely under the onchange function
// so that it changes once the audio player's value is changed


function playAudios (audios, index){

    //First let's define a function to play the next audio file
    function nxtAudio(){

        if (index < audios.length -1){ index++ }
            else { index=0; }
        const url = URL.createObjectURL(audios[index]);
        aud.src = url;
        aud.play();
        



    }//END OF nxtAudio FUNCTION


    //Next let's define a function to play the previous audio file

    function prvAudio(){

        if (index > 0){ index-- }
            else { index = audios.length - 1 ; }
        const url = URL.createObjectURL(audios[index]);
        aud.src = url;
        aud.play();

    }//END OF prvAudio FUNCTION


    //Listen when the Audio has ENDED

    aud.addEventListener('ended', function(){

        nxtAudio();

    }//END OF THE 'ENDED' FUNCTION
     );//END OF THE addEventListener


    //LISTEN WHEN THE NEXT BUTTON IS CLICKED
    nxt.addEventListener('click', function(){
        nxtAudio();
    });//END OF NXT


    //LISTEN WHEN THE PREVIOUS BUTTON IS CLICKED
    prv.addEventListener('click', function(){
        prvAudio();
    });//END OF PRV


    //START PLAYING THE FIRST AUDIO

    const url = URL.createObjectURL(audios[index]);
    aud.src = url;
    aud.play();



}// THE END OF THE playAudios FUNCTION

I mostly tried the following line
document.getElementById("title").innerHTML=input.files[audName].name
I expected the name to be update once the input value changes but nothing happened

2

Answers


  1. That’s because you need to change the title in several places inside your playAudios() funcion.

    You are currently placing the title change on file upload, but that’s not what plays the song.

    Inside the playAudios add following function:

    function setTitle(file) {
        document.getElementById("demo").innerHTML = file.name
    }
    

    Then add following line at end (last line before the }) of nxtAudio, prvAudio and playAudios functions:

        setTitle(audios[index])
    

    And remove your for loop after the playAudios(audios,0) call

    Login or Signup to reply.
    • Name your variables properly, don’t eat characters for sake of readability. Same goes for single character variables like the event’s e. Use rather evt or event
    • Don’t unnecessarily comment your code where not needed. Make is simple to read and concise. Like a prose.
    • Don’t repeat yourself. You’re copy pasting the play code three times. Create a single play() function instead
    • Don’t assign event listeners inside event listeners
    • There’s no need to pass around audios as argument to functions if you already use a scoped variable. Functions will have access to it regardless
    • When using URL.createObjectURL don’t forget to also use revokeObjectURL to free up memory
    • To loop-around an index, create a reusable function mod() that will do the job for you like: index = mod(++index, tot) for next and respectively -- for the prev action. (Notice the prev instead of prv ;))
    const el = (sel, par) => (document || par).querySelector(sel);
    const elNew = (tag, prop) => Object.assign(document.createElement(tag), prop);
    const mod = (n, m) => ((n % m) + m) % m; // Fix negative Modulo
    
    const elSelectAudio = el("#select-audio");
    const elAudio = el("#audio");
    const elPrev = el("#prev");
    const elNext = el("#next");
    const elTitle = el("#title");
    
    let audios = [];
    let tot = 0;     // Add this one too
    let index = 0;   // Forgot about this guy?
    
    const browse = () => {
      // In-memory input type file for files selection
      elNew("input", {
        type: "file",
        accept: "audio/*",
        multiple: true,
        onchange(evt) {
          audios = [...evt.currentTarget.files];
          tot = audios.length; // Set how many audios we have
          index = 0; // Reset index
          play();    // No need to pass `index` as argument
        }
      }).click();
    };
    
    const next = () => {
      index = mod(++index, tot);
      play()
    };
    
    const prev = () => {
      index = mod(--index, tot);
      play()
    };
    
    const play = () => {
      if (!tot) return; // No audios to play
      URL.revokeObjectURL(elAudio.src); // Don't forget to revoke!
      elAudio.src = URL.createObjectURL(audios[index]);
      elTitle.textContent = audios[index].name;
      elAudio.play();
    };
    
    // Init:
    elSelectAudio.addEventListener("click", browse);
    elAudio.addEventListener("ended", next);
    elNext.addEventListener("click", next);
    elPrev.addEventListener("click", prev);
    <button id="select-audio">Select Files</button>
    <button id="prev">Previous</button>
    <button id="next">Next</button>
    <audio id="audio" controls></audio>
    <p id="title"></p>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search