2

I am creating an audio player in HTML using javascript and no jquery. I am doing so that it will work similar to this Example I have the first table as a drop down list and I will select one of the albums and the corresponding songs will show in the next pane, this part is all working fine. My problem is that I don't know how to code it so that when I click on a song in the middle pane the song will show up in the last pane along with the corresponding image, album name and song name.

Here is my code with a shortened version of my var albums. I am also a beginner so do forgive if the code is messy.

<html>
<head>
    <script type="text/javascript" src="music.js"></script>
    <style type="text/css"></style>
</head>    
<body>

    <table width="400" height="400" border="1" style="display: inline-block;">
    <caption>Albums</caption>
<tr>
  <td><p>Please select an album from the list</p>
<select id="album-select" name='Album'>
  <option></option>
</select>
</select>
</td>
</tr>
</table>


<table id="songs-table" width="400" height="400" border="1" style="display: inline-block;">
<caption>Songs</caption>
    <tr>
    </tr>
</table>


<table width="400" height="400" border="1" style="display: inline-block;">
<caption>
Selected Songs
</caption>
<tr>
<td>
  <audio controls='controls'>
    <source src='xxxxx.mp3' type='audio/mpeg'>
    <source src='xxxxx.wav' type='audio/wav'>
    Your browser does not support the audio element.
</audio>
</td>
</tr>
</table>
<script>
var albums=
[
    {   "title":"Birdsong Small Birds",
        "artist":"BBC",
        "artwork":"Wren",
        "tracks":[
            {"title":"Dunnock","mp3":"Birdsong-Dunnock.mp3",
            "lyrics":"The Dunnock or hedge sparrow has a fast warbling song often delivered from the top of a hedge or bush"},
            {"title":"Robin","mp3":"Birdsong-Robin.mp3",
            "lyrics":"Unusually among British birds, both the male and the femaale robins sing"},

var albumElement  = document.getElementById('album-select');
albumElement.addEventListener('change', function(){
  populateSongs(albumElement.value)
});

for(var i=0;albums.length;i++){
  var option = document.createElement("option");
  option.text = albums[i].title;
  albumElement.add(option)
}

function populateSongs(album) {
  var songsTable  = document.getElementById('songs-table');

  while(songsTable.rows.length > 0) {
    songsTable.deleteRow(0);
  }

  for(var i=0;albums.length;i++){

    if(albums[i].title == album) { 

      for(var track=0;albums[i].tracks.length;track++) {
        var row = songsTable.insertRow(track);
        var cell = row.insertCell(0);    

        cell.innerHTML = albums[i].tracks[track].title;

        cell.setAttribute("file",albums[i].tracks[track].mp3);
        cell.addEventListener('click',function(){
          play(this.getAttribute('file'));
        });

      }
    }
  }


}

function play(song) {
  var audioElement  = document.getElementById('audio-player');

  audioElement.src = song;
  console.log(song);

}
</script>
</body>
</html>

Any help would be greatly appreciated.

5
  • You have missing statement in both for loops i < albums.length . Those albums you can load as JSON files. Make function (or module) for last pane, and when user clicks on song, pass object containing all necessary information. Commented Dec 8, 2015 at 23:32
  • I am not sure how to load albums as JSON files nor make a function like that. I will admit I have had a fair bit of help to get me to this point already. Commented Dec 8, 2015 at 23:51
  • You can have your albums in separate file as JSON and load it with xhr request. Its not that hard. When user clicks on second pane, make object with properties that you will need in third pane and pass it to function that will build third pane. (object example-> var displaySong = { title: 'Album title', song: { title: 'Song title', ... ) I can look your code, but you will need to send me all of it. Commented Dec 9, 2015 at 0:08
  • I don't know how to do that. This is all my code, I only shortened the var albums as it is fairly big. Sorry to be a nuisance, I've only just started learning Commented Dec 9, 2015 at 0:21
  • I will try to review it tomorrow :) Commented Dec 9, 2015 at 0:26

1 Answer 1

1

First of all:

  • Your HTML structure is awful and incorrect
  • Don't write inline css
  • Try to understand code you write

I did not have too much time to review all code. Hope this will help you. Some lines of code are commented, and if something is unclear just ask.

You will need some type of local server, because you can't use xhr request on local files. If you have python installed you can go with python -m SimpleHTTPServer 3001 from root dir of your project and than navigate to 127.0.0.1:3001 (or localhost). Or you can use live preview of Brackets editor that will create local server for you. Or you can use Mozilla Firefox browser if you don't want to run local server.

I changed structure to:

|css |--style.css |data |--albums.json |js |--script.js index.html

Here is your code:

index.html

<!DOCTYPE html>

<html>

<head>
    <meta charset="utf-8" />
    <title>JS audio player</title>
    <link rel="stylesheet" type="text/css" href="./css/style.css" />
</head>

<body>
    <table>
        <thead>
            <tr>
                <td>Albums</td>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>Please select an album from the list:</td>
            </tr>
            <tr>
                <td>
                    <select id="album-select" name='Album'>
                        <option></option>
                    </select>
                </td>
            </tr>

        </tbody>
    </table>

    <table id="songs-table">
        <thead>
            <tr>
                <td>Songs</td>
            </tr>
        </thead>
    </table>

    <table id="selected-songs">
        <thead>
            <tr>
                <td>Selected Songs</td>
            </tr>
        </thead>
        <tbody>
            <tr class="title">
                <td></td>
            </tr>
            <tr class="lyrics">
                <td></td>
            </tr>
            <tr>
                <td>
                    <audio id="player" controls='controls'>
                        <source src=''>
                    </audio>
                </td>
            </tr>
        </tbody>
    </table>

    <script type="text/javascript" src="./js/script.js"></script>
</body>

</html>

style.css

body {
    width: 1024px;
    height: 100%;
    margin: 0 auto;
}

table {
    float: left;
    width: 33%;
}

thead tr td {
    padding: 10px;
    background-color: lightslategray;
    color: #fff;
    text-align: center;
}

tbody:before {
    content: '-';
    display: block;
    line-height: 20px;
    color: transparent;
}

#songs-table tbody tr {
    cursor: pointer;
}

#songs-table tbody tr:hover {
    background-color: lightgray;
}

albums.json

[
    {
        "title": "Birdsong Small Birds",
        "artist": "BBC",
        "artwork": "Wren",
        "tracks": [
            {
                "title": "Dunnock",
                "mp3": "Birdsong-Dunnock.mp3",
                "lyrics": "The Dunnock or hedge sparrow has a fast warbling song often delivered from the top of a hedge or bush"
            }, {
                "title": "Another Dunnock",
                "mp3": "http://www.noiseaddicts.com/samples_1w72b820/272.mp3",
                "lyrics": "The Dunnock or hedge sparrow has a fast warbling song often delivered from the top of a hedge or bush"
            }, {
                "title": "Third Dunnock",
                "mp3": "Third-Dunnock.mp3",
                "lyrics": "The Dunnock or hedge sparrow has a fast warbling song often delivered from the top of a hedge or bush"
            }
        ]
    },
    {
        "title": "Second Birdsong Birds",
        "artist": "BBC",
        "artwork": "Wren",
        "tracks": [
            {
                "title": "Dunnock in Second",
                "mp3": "Birdsong-Dunnock.mp3",
                "lyrics": "The Dunnock or hedge sparrow has a fast warbling song often delivered from the top of a hedge or bush"
            }, {
                "title": "Another Dunnock  in Second",
                "mp3": "http://www.noiseaddicts.com/samples_1w72b820/272.mp3",
                "lyrics": "The Dunnock or hedge sparrow has a fast warbling song often delivered from the top of a hedge or bush"
            }, {
                "title": "Third Dunnock  in Second",
                "mp3": "Third-Dunnock.mp3",
                "lyrics": "The Dunnock or hedge sparrow has a fast warbling song often delivered from the top of a hedge or bush"
            }
        ]
    }
]

script.js

window.onload = function () {
    'use strict';

    // Make xhr request to get JSON file
    function getAlbums() {
        var xhttp = new XMLHttpRequest();

        // Detect when response is ready
        xhttp.onreadystatechange = function () {
            if (xhttp.readyState === 4 && xhttp.status === 200) {
                // Parse our response, so we can use it as object
                buildHTML(JSON.parse(xhttp.responseText));
            }
        };

        // Send request
        xhttp.open('GET', './data/albums.json', true);
        xhttp.send();
    }

    // Build page when request comes
    function buildHTML(albums) {
        var albumElement = document.getElementById('album-select'),
            len = albums.length,
            option,
            i;

        for (i = 0; i < len; i++) {
            option = document.createElement('option');
            option.innerHTML = albums[i].title;
            albumElement.add(option);
        }

        albumElement.addEventListener('change', function () {
            var self = this; // Reference self
            albums.forEach(function (album) {
                if (album.title === self.value) {
                    // Pass album object
                    populateSongs(album);
                }
            });
        });
    }

    function populateSongs(album) {
        var songsTable = document.getElementById('songs-table'),
            tbody = document.createElement('tbody'),
            row,
            cell;

        // Add row for each track
        (album.tracks).forEach(function (track) {
            row = tbody.insertRow(0);
            cell = row.insertCell(0);
            cell.innerHTML = track.title;

            cell.addEventListener('click', function () {
                if (this.innerHTML === track.title) {
                    playSong(track);
                }
            });
        });

        // Remove tbody if exist
        Object.keys(songsTable.children).forEach(function (key) {
            if (songsTable.children[key].nodeName === 'TBODY') {
                songsTable.removeChild(songsTable.children[key]);
            }
        });
        songsTable.appendChild(tbody); // Add new tbody
    }

    function playSong(track) {
        var player = document.getElementById('player'),
            selectedSongs = document.getElementById('selected-songs'),
            tbody = selectedSongs.children[1],
            title = tbody.children[0].children[0],
            lyrics = tbody.children[1].children[0];

        title.innerHTML = track.title;
        title.style.fontWeight = 'bold';
        lyrics.innerHTML = track.lyrics;

        // Play song
        player.src = track.mp3;
        player.play();
    }

    getAlbums();
};
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.