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 trialSamuel Ekholm
6,341 PointsUncaught TypeError: Cannot read property 'drawHTMLToken' of undefined
Hi, I'm having trouble with my code for the 4 in a row challenge, getting the error "Uncaught TypeError: Cannot read property 'drawHTMLToken' of undefined". I looked at all the others with the same issue but found nothing of use.. Anyone know what could be wrong?
class Player { constructor(name, id, color, active = false) { this.name = name; this.id = id; this.color = color; this.active = active; this.tokens = this.createTokens(21); } createTokens(num) { const tokens = [];
for (let i = 0; i<num.length; i++) {
let token = new Token(i, this);
tokens.push(token);
}
return tokens;
}
get unusedTokens() {
return this.tokens.filter(token => !token.dropped);
}
get activeToken() {
return this.unusedTokens[0];
}
}
const game = new Game();
document.getElementById("begin-game").addEventListener("click", function() { game.startGame(); this.style.display = 'none'; document.getElementById('play-area').style.opacity = '1'; });
class Game { constructor() { this.board = new Board(); this.players = this.createPlayers(); this.ready = false; }
get activePlayer() {
return this.players.find(player => player.active);
}
createPlayers() {
const players = [new Player("Player 1", 1, "#e15258", true),
new Player("Player 2", 2, "#e59a13")];
return players;
}
startGame() {
this.board.drawHTMLboard();
this.activePlayer.activeToken.drawHTMLToken();
this.ready = true;
}
}
class Token {
constructor(index, owner) {
this.owner = owner;
this.id = token-${index}-${owner.id}
;
this.dropped = false;
}
drawHTMLToken() {
const token = document.createElement("div");
document.getElementById("game-board-underlay").appendChild(token);
token.setAttribute("id", this.id);
token.setAttribute("class", "token");
token.style.backgroundColor = this.owner.color;
}
get htmlToken() { return this.drawHTMLToken(); } }
class Space {
constructor(x, y) {
this.x = x;
this.y = y;
this.id = space-${x}-${y}
;
this.token = null;
this.diameter = 76;
this.radius = this.diameter/2;
}
drawSVGSpace() {
const svgSpace = document.createElementNS("http://www.w3.org/2000/svg", "circle");
svgSpace.setAttributeNS(null, "id", this.id);
svgSpace.setAttributeNS(null, "cx", (this.x * this.diameter) + this.radius);
svgSpace.setAttributeNS(null, "cy", (this.y * this.diameter) + this.radius);
svgSpace.setAttributeNS(null, "r", this.radius - 8);
svgSpace.setAttributeNS(null, "fill", "black");
svgSpace.setAttributeNS(null, "stroke", "none");
document.getElementById("mask").appendChild(svgSpace);
}
}
class Board { constructor() { this.rows = 6; this.columns = 7; this.spaces = this.createSpaces(); } createSpaces() { const spaces = [];
for (let x = 0; x < this.columns; x++) {
const col = [];
for (let y = 0; y < this.rows; y++) {
const space = new Space(x, y);
col.push(space);
}
spaces.push(col);
}
return spaces;
}
drawHTMLboard() {
for (let col of this.spaces) {
for (let space of col) {
space.drawSVGSpace();
}
}
}
}
1 Answer
Brandon White
Full Stack JavaScript Techdegree Graduate 34,662 PointsHi Samuel,
If you’d like to post a link to your repo I can run your code and almost assuredly find out what’s causing your error.
I think I may have spotted what’s going on, but I don’t want to say with 100% certainty that the following is your issue.
Here’s what I think is going on though... In your createTokens function (in the Players class) you’re calling the length property on the num parameter. But you’re passing in a number primitive as the argument. I’m pretty sure that a number doesn’t have a length property. And if I’m right, that’s likely causing your for loop to never actually run. Which would mean that when you return tokens at the end of the createTokens function you’re simply returning an empty array. And so when you try to get the activeToken from an array with no items in it, your activeToken ends up being undefined. And you can’t call drawHTMLToken on a value/object that’s undefined. And so JavaScript raises an error.
Hopefully, that helps you out. If not, again, if you link your repo I’ll be able to actually run your code.
Samuel Ekholm
6,341 PointsYou're spot on, thanks a bunch Brandon! Can't count the times I've gone over the for loop, yet I overlooked this. It makes perfect sense a number can't have a length property.
Samuel Ekholm
6,341 PointsSamuel Ekholm
6,341 PointsJust realized the code wasn't so easy to read, trying to post it all again.