1

I am building a custom audio player in Javascript, but I have trouble attaching an event listener to each song in the list. When I click on a track in the playlist, I want to parse a data attribute through a function called selectTrack(x) to tell the player which song to play. However, I keep getting an error saying that this function is not defined.

This is is the part I have trouble with:

// attach event listener and get data value from div 
var myListener = document.getElementsByClassName("trackListRow");
for (var i=0; i < myListener.length; i++)
{
  myListener[i].getAttribute("data-track-index");
  mylistener[i].addEventListener("click", function(){

    selectTrack(datavalue);

  });
}

The full code is posted below.

var trackListContainer, playPrevBtn, playPauseBtn, PlayNextBtn;
var trackRow, songArray;
songArray = ["Aminaiyoamoore", "adg3com_chuckedknuckles" ];

// create track list - append to container
var i;
for (i = 0; i < songArray.length; i++) {
    trackRow = document.createElement("div");
    trackRow.textContent = songArray[i];
    trackRow.className = "trackListRow";
    // set data attribute to array index number for event handling
    trackRow.setAttribute("data-track-index", songArray.indexOf(songArray[i]));

    trackListContainer = document.getElementById("trackListContainer");
    trackListContainer.appendChild(trackRow);
   
}  
           
       //  Problems here
// attach event listener and get data value from div 
var myListener = document.getElementsByClassName("trackListRow");
for (var i=0; i < myListener.length; i++)
{
  myListener[i].getAttribute("data-track-index");
  mylistener[i].addEventListener("click", function(){
    
    selectTrack(datavalue);
    
  });
}


  
var playPrevBtn, playPauseBtn, playNextBtn;
playPrevBtn = document.getElementById("playPrevBtn");
playPauseBtn = document.getElementById("playPauseBtn");
playNextBtn = document.getElementById("playNextBtn");

function initBeatPlayer() {
   // var dir = "audio/";
   var dir =  "http://www.puntlandtvradio.net/placeholders/audio/"
 
    var ext = ".mp3";
    playlist_array_index = 0;
    audio = new Audio();


    playPauseBtn.addEventListener("click", playPause);
    playPrevBtn.addEventListener("click", seekBackward);
    playNextBtn.addEventListener("click", seekForward);
    audio.addEventListener("ended", function() {
        switchTrack()
    });


    // functions 

  
  function selectTrack(datavalue){
    
    playlist_array_index = datavalue
    audio.src = dir + songArray[playlist_array_index] + ext;          
            audio.play();
  
  }
  
  
  
  
  
  
    function playPause() {
        if (audio.paused) {
            audio.play();
            document.getElementById("playPauseBtn").textContent = "PAUSE";
        } else {
            audio.pause()
            document.getElementById("playPauseBtn").textContent = "PLAY"
        }
    }


    function seekBackward() {
        if (playlist_array_index <= 0) {

            playlist_array_index = 0;
            audio.src = dir + songArray[playlist_array_index] + ext;
            audio.pause();
            audio.currentTime = 0;
            audio.play();
        } else {

            playlist_array_index--;
            audio.src = dir + songArray[playlist_array_index] + ext;
            audio.play();
        }
    }

    function seekForward() {

        if (playlist_array_index == (songArray.length - 1)) {
            playlist_array_index = 0;

        } else {

            playlist_array_index++;
            audio.src = dir + songArray[playlist_array_index] + ext;          
            audio.play();

        }

    }

    //end functions
}
window.addEventListener("load", initBeatPlayer);
#container{width: 320px; margin: auto; overflow: hidden;}
#controls {}
#playPrevBtn, #playPauseBtn, #playNextBtn{  font-size: 25px; margin: 5px;}
.trackListRow {font-size: 20px;  background-color: aliceblue; color: black;  padding: 10px;  margin: 5px;}
.trackListRow:hover {background: brown; color: white; }
<!--player control buttions -->
<div id="container">
  <div id="trackListContainer"> </div> 
 
  
  <div id="controls">
    <button id="playPrevBtn"> << </button>
    <button id="playPauseBtn">PAUSE</button>
    <button id="playNextBtn">>></button>

  </div>
    
   <div> music by puntlandtvradio.net - for educational purposes </div> 
</div>
  • 2
    can you minify this code? half of it looks unnecessary to the question – Isaac Sep 25 '16 at 21:22
  • The function is not defined in the scope in which you are trying to use it. `selectTrack` is defined within `initBeatPlayer` so if you want to use it outside `initBeatPlayer`, move it outside. – Damon Sep 25 '16 at 21:33
  • Updated. I posted a snippet of the code in the question. – Ronald Thompson Sep 25 '16 at 21:35

2 Answers2

2

Couple of things:

  1. The second line inside the for loop: mylistener should be myListener (capitalised L)
  2. The datavalue in the event listener is undefined, declare it first.
  3. Like the comments pointed out, selectTrack is inside initBeatPlayer, hence not available publicly. However, given that selectTrack needs to refer to other vars inside initBeatPlayer as well, it's probably better to move your handler-binding work inside initBeatPlayer as well.

Here is a "working" jsFiddle, you still need to clean up other parts beside that snippet: https://jsfiddle.net/bosjuLmo/1/

J S
  • 1,068
  • 6
  • 7
  • Thanks for the solution. Would those public variables cause any problems with memory leaks or anything of that sort? Would public variables be a bad thing in this context? – Ronald Thompson Sep 25 '16 at 22:01
  • @RonaldThompson A couple global vars are not a big deal in terms of memory, but there might be other concerns. This post is a good read: http://stackoverflow.com/questions/19313248/global-variables-in-js-harmfull – J S Sep 25 '16 at 22:27
0

You need to declare all your variables, listeners at the top of the script; this way you know every element is defined when functions need them. Same thing for functions, better write them before the calls.

Keep in mind that variables declared with 'var' inside a function, are representative in a local scope. 'var dir' in a global scope is not the same as 'var dir' inside a function, JS will treat them as separate things.

Hope this helps, it's working OK:

var trackListContainer, playPrevBtn, playPauseBtn, PlayNextBtn;
var trackRow, songArray;
songArray = ["Aminaiyoamoore", "adg3com_chuckedknuckles" ];
var myListener = document.getElementById("trackListContainer");
var dir='';
var ext='';

var playPrevBtn, playPauseBtn, playNextBtn;
playPrevBtn = document.getElementById("playPrevBtn");
playPauseBtn = document.getElementById("playPauseBtn");
playNextBtn = document.getElementById("playNextBtn");

window.addEventListener("load", initBeatPlayer);

// functions 


  function selectTrack(datavalue){

    playlist_array_index = datavalue
    audio.src = dir + songArray[playlist_array_index] + ext;          
            audio.play();

  }






    function playPause() {
        if (audio.paused) {
            audio.play();
            document.getElementById("playPauseBtn").textContent = "PAUSE";
        } else {
            audio.pause()
            document.getElementById("playPauseBtn").textContent = "PLAY"
        }
    }


    function seekBackward() {
        if (playlist_array_index <= 0) {

            playlist_array_index = 0;
            audio.src = dir + songArray[playlist_array_index] + ext;
            audio.pause();
            audio.currentTime = 0;
            audio.play();
        } else {

            playlist_array_index--;
            audio.src = dir + songArray[playlist_array_index] + ext;
            audio.play();
        }
    }

    function seekForward() {

        if (playlist_array_index == (songArray.length - 1)) {
            playlist_array_index = 0;

        } else {

            playlist_array_index++;
            audio.src = dir + songArray[playlist_array_index] + ext;          
            audio.play();

        }

    }

function initBeatPlayer() {
   // var dir = "audio/";
   dir =  "http://www.puntlandtvradio.net/placeholders/audio/"

    ext = ".mp3";
    playlist_array_index = 0;
    audio = new Audio();


    playPauseBtn.addEventListener("click", playPause);
    playPrevBtn.addEventListener("click", seekBackward);
    playNextBtn.addEventListener("click", seekForward);
    audio.addEventListener("ended", function() {
        switchTrack()
    });
}

//end functions

// create track list - append to container

for (var i = 0; i < songArray.length; i++) {
    trackRow = document.createElement("div");
    trackRow.textContent = songArray[i];
    trackRow.className = "trackListRow";
    // set data attribute to array index number for event handling
    trackRow.setAttribute("data-track-index", songArray.indexOf(songArray[i]));

    trackListContainer = document.getElementById("trackListContainer");
    trackListContainer.appendChild(trackRow);

}  

       //  Problems here
// attach event listener and get data value from div 

for (var i=0; i < myListener.length; i++){
  myListener[i].getAttribute("data-track-index");
  mylistener[i].addEventListener("click", function(){

    selectTrack(datavalue);

  });
}
adr1Script
  • 109
  • 5