Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript Object-Oriented JavaScript (2015) Constructor Functions and Prototypes Making the UI Work

Nick Prodromou
Nick Prodromou
12,824 Points

No errors in console, yet no HTML of songs being rendered.. please help

Hi community..

so I originally had the problem of

Uncaught TypeError: Cannot set property of 'innerHTML' of null

then

TypeError: this.songs[i].toHTML is not a function

but now, I've cleared up those errors, gone through the code... until it's made my head hurt and I still can't work out what's wrong, as I mentioned.. there are no console errors

here's my code

playlist.js

function Playlist() {
  this.songs = [];
  this.nowPlayingIndex= 0;
}

Playlist.prototype.add = function(Song) {
  this.songs.push(Song);
};  

Playlist.prototype.play = function() {
  var currentSong = this.song[this.nowPlayingIndex];
  currentSong.play();
};

Playlist.prototype.stop = function(){
  var currentSong = this.song[this.nowPlayingIndex];
  currentSong.stop();
};

Playlist.prototype.next = function() {
  this.stop();
  this.nowPlayingIndex++;
  if (this.nowpPlayingIndex === this.songs.length) {
    this.nowPlayingIndex = 0;
  }  
  this.play();

};

Playlist.prototype.renderInElement = function(list) {
  list.innerHTML = "";
    for (var i = 0; i < this.songs.length; i++) {
      list.innerHTML += this.songs[i].toHTML();
    }

};

song.js

function Song(title, artist, duration) {
  this.title = title;
  this.artist = artist;
  this.duration = duration;
  this.isPlaying = false;
}

Song.prototype.play = function() {
  this.isPlaying = true;
};

Song.prototype.stop = function() {
  this.isPlaying = false;
};

Song.prototype.toHTML = function() {
  var htmlString = '<li';

  if (this.isPlaying) {
  htmlString += 'class="current">';
  }

  htmlString += this.title;
  htmlString += ' - ';
  htmlString += this.artist;
  htmlString+= '<span class="duration"';
  htmlString += this.duration;
  htmlString += '</span></li>';

  return htmlString;
};

app.js

var playlist = new Playlist();

var hereComesTheSun = new Song("Here comes the sun", "The Beatles", "2:54");
var walkingOnSunshine = new Song("Walking on sunshine", "Katrina and the waves", "3:43");

playlist.add(hereComesTheSun);
playlist.add(walkingOnSunshine);

var playlistElement = document.getElementById("playlist");

playlist.renderInElement(playlistElement);                                              

Also, just my thoughts on this course so far..

I think the difficulty is that, if I were writing the code myself, I would be more consistent with what is caps and what isn't, it seems that when Andrew is creating a new constructor he uses title case (ie: Song) whereas, since the beginning of JavaScript basics, we've been told to use camelCase, so it's been confusing.. because he hasn't explicitly stated that "We will name our constructor functions with title case"

also the pace of this video was just way too fast.. it's like we were just introduces to prototypes and constructors, and then we've gone from 0 - 100 in a single video... just my feedback

2 Answers

Maxwell Bernard
Maxwell Bernard
11,953 Points

Adding to the previous comment, since the opening 'li' inside the tag doesn't have a space after it, when you add the class it does need a space before. If it doesn't have one it will be rendered to html like this:

<liclass="current">...</li>

rather than:

<li class="current">...</li>

I just did the exact same thing, and it took me a while too.

Nathan Wakefield
Nathan Wakefield
7,065 Points

Thanks, Maxwell. I missed that. I've updated my answer to include the space.

Nathan Wakefield
Nathan Wakefield
7,065 Points

This may not fix the whole thing, but it's a start. In your Song.prototype.toHTML method, you are only completing the first li tag if the song is playing. It should look more like this:

Song.prototype.toHTML = function() {
  var htmlString = '<li';

  if (this.isPlaying) {
  htmlString += ' class="current"';
  }
  htmlString += '>';

  htmlString += this.title;
  htmlString += ' - ';
  htmlString += this.artist;
  htmlString+= '<span class="duration"';
  htmlString += this.duration;
  htmlString += '</span></li>';

  return htmlString;
};