Skip to content

Instantly share code, notes, and snippets.

@colabottles
Created April 7, 2020 05:44
Show Gist options
  • Select an option

  • Save colabottles/5fa1bfcb82eb397ae91a37560c7f6e84 to your computer and use it in GitHub Desktop.

Select an option

Save colabottles/5fa1bfcb82eb397ae91a37560c7f6e84 to your computer and use it in GitHub Desktop.
VanillaJS Academy: Day 45, Project: Debugging Broken Code
<!DOCTYPE html>
<html>
<head>
<title>Monsters! - Debug</title>
<style type="text/css">
body {
margin: 1em auto;
max-width: 40em;
width: 88%;
}
/**
* A simple grid layout
*/
.row {
display: grid;
grid-template-columns: auto auto auto;
text-align: center;
}
.grid {
min-height: 6em;
padding: 1em;
}
/**
* Make sure images scale
*/
img {
height: auto;
max-width: 100%;
}
/**
* Scale image to the full width of the page
*/
.img-full {
width: 100%;
}
/**
* Style buttons to not look like buttons
*/
[data-monster-id] {
background-color: transparent;
border: 0;
}
</style>
</head>
<body>
<h1>Monsters! - Debug</h1>
<div id="app" aria-live="polite"></div>
<footer>
<hr>
<p class="text-small text-muted">Icons by <a href="https://thenounproject.com/term/door/311732/">Jamie Dickinson</a>, <a href="https://thenounproject.com/term/monster/184225/">Nicky Knicky</a>, <a href="https://thenounproject.com/term/monster/1510400/">Alvaro Cabrera</a>, <a href="https://thenounproject.com/term/monster/28460/">Eliricon</a>, <a href="https://thenounproject.com/term/monster/82823/">April Yang</a>, <a href="https://thenounproject.com/term/monster/1062009/">tk66</a>, <a href="https://thenounproject.com/term/monster/24990/">Alex WaZa</a>, <a href="https://thenounproject.com/term/monster/37212/">Husein Aziz</a>, <a href="https://thenounproject.com/term/monster/2236082">iconcheese</a>, and <a href="https://thenounproject.com/term/socks/38451/">Yazmin Alanis</a>.</p>
</footer>
<script>
//
// Variables
//
// The monsters and socks
var monsters = [
'monster1',
'monster2',
'monster3',
'monster4',
'monster5',
'monster6',
'monster7',
'monster8',
'monster9',
'monster10',
'monster11',
'sock'
];
// Get the #app element
var app = document.querySelector('#app');
// The number of monsters who have been found
/**
* @bug {hanged from 'count' to 'found'} var count;
*/
var found;
//
// Methods
//
/**
* Randomly shuffle an array
* https://stackoverflow.com/a/2450976/1293256
* @param {Array} array The array to shuffle
* @return {String} The first item in the shuffled array
*/
var shuffle = function (array) {
var currentIndex = array.length;
var temporaryValue, randomIndex;
// While there remain elements to shuffle...
while (0 !== currentIndex) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
// And swap it with the current element.
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
};
/**
* Render the grid of monsters onto the game board
*/
var renderMonsters = function () {
// Reset the number of monsters who have been found
found = 0;
// Shuffle the monsters array
shuffle(monsters);
// Create the HTML and inject it into the DOM
// A button element is focusable and conveys to screen readers that it can be clicked
// The data-monster-id stores the index of the monster in our array
app.innerHTML =
'<p>Click a door to reveal a monster. Try not to find the sock.</p>' +
'<div class="row">' +
monsters.map(function (monster, index) {
var html =
'<div class="grid">' +
'<button data-monster-id="' + index + '">' +
'<img alt="Click the door to see what\'s behind it" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/200582/door.svg">' +
'</button>' +
'</div>';
return html;
}).join('') +
'</div>';
};
/**
* Render a new UI when the player loses
*/
var renderLost = function () {
app.innerHTML =
'<img class="img-full" alt="" src="https://media.giphy.com/media/13zUNhE9WZspMc/giphy.gif">' +
'<h2>Oops, you found a sock!</h2>' +
'<p>' +
'<button class="btn" data-monster-play-again>Play Again</button>' +
'</p>';
};
/**
* Render a new UI when the player wins
*/
var renderWon = function () {
app.innerHTML =
'<img class="img-full" alt="" src="https://media.giphy.com/media/1242bJFCbb3FxC/giphy.gif">' +
'<h2>You won!</h2>' +
'<p>You found all of the monsters. Congrats!</p>' +
'<p>' +
'<button data-monster-play-again>Play Again</button>' +
'</p>';
};
/**
* Handle click events
* @param {Event} event The event object
*/
var clickHandler = function (event) {
// If a "play again" button was clicked, reset the UI and end the callback function
/**
* @bug {Do not need the brackets around the dataset}
* if (event.target.hasAttribute('[data-monster-play-again]')) {
*/
if (event.target.hasAttribute('data-monster-play-again')) {
renderMonsters();
return;
}
// Check if clicked element or it's parent has a [data-monster-id] attribute
// If not, it's not a monster
// return and stop running our callback function
/**
* @bug {Need the brackets around the dataset}
* var monster = event.target.closest('data-monster-id');
*/
var monster = event.target.closest('[data-monster-id]');
if (!monster) return;
// Get the monster's index in the array
var id = monster.getAttribute('data-monster-id');
// If the door reveals a sock, render the lost UI
// Then, end the callback function
/**
* @bug {Using '=' instead of '===' & 'sock' instead of 'socks'}
* if (monsters[id] = 'socks') {
*/
if (monsters[id] === 'sock') {
renderLost();
return;
}
// Update the HTML for the button's parent element
// This will replace the button so that the content can't be clicked again
// We'll use the id to get the monster from our shuffled array
monster.parentNode.innerHTML = '<img alt="' + monsters[id] + '" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/200582/' + monsters[id] + '.svg">';
// Increase the number of monsters who have been found by 1
found++;
// If the number of monsters found is equal to the total number (-1 for the sock)
// then all monsters have been found and we can render the win UI
if (found === (monsters.length - 1)) {
renderWon();
}
};
//
// Inits & Event Listeners
//
// Render the initial game board
renderMonsters();
// Listen for click events
document.addEventListener('click', clickHandler, false);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment