Skip to content

Instantly share code, notes, and snippets.

@cferdinandi
Created January 30, 2019 15:04
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save cferdinandi/5e0763c686be45ca0a686a1906a841af to your computer and use it in GitHub Desktop.
Save cferdinandi/5e0763c686be45ca0a686a1906a841af to your computer and use it in GitHub Desktop.
A refactor of the vanilla JS Who's Driving app.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Who should drive?</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Styles -->
<style type="text/css">
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
font-size: 112.5%;
margin-left: auto;
margin-right: auto;
max-width: 40em;
width: 88%;
}
/**
* Visually hide an element, but leave it available for screen readers
* @link https://github.com/h5bp/html5-boilerplate/blob/master/dist/css/main.css
* @link http://snook.ca/archives/html_and_css/hiding-content-for-accessibility
*/
.screen-reader {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
white-space: nowrap;
width: 1px;
}
</style>
</head>
<body>
<h1>Who should drive?</h1>
<div id="app" aria-live="polite"></div>
<form id="add-driver">
<label class="screen-reader" for="potential-driver">Name of driver</label>
<input id="potential-driver" placeholder="Name of driver...">
<button>Add Driver</button>
</form>
<button id="pick-driver">Who's driving?</button>
<button id="clear">Clear Drivers</button>
<!-- Scripts -->
<script>
//
// Data
//
var data = {
drivers: [],
selected: null
};
//
// Methods
//
// Create the markup string
var template = function () {
// Create driver items
var driverList = data.drivers.map(function (driver, index) {
return '<li>' + driver + ' <button data-remove-driver="' + index + '">Remove Driver</button></li>';
});
// Create page markup
var html = '';
if (driverList.length > 0) {
html += '<ul>' + driverList.join('') + '</ul>';
}
if (data.selected) {
html += '<p><strong>' + data.selected + ' is driving.</strong></p>';
}
return html;
};
// Emit a custom event
var emitEvent = function (elem, detail) {
// Create a new event
var event = new CustomEvent('render', {
bubbles: true,
cancelable: true,
detail: detail || {}
});
// Dispatch the event
elem.dispatchEvent(event);
};
// Render our template into the DOM
var render = function () {
var app = document.querySelector('#app');
if (!app) return;
app.innerHTML = template();
emitEvent(app, data);
};
// Shuffle our array of drivers and pick one
var shuffle = function (arr) {
// Create a clone of the array so that we don't shuffle the original one
var arrClone = arr.slice();
// Shuffle the array
return arrClone.sort(function() {
return Math.random() - 0.5;
});
};
// Get drivers from localStorage
var getDriversFromLocalStorage = function () {
var drivers = localStorage.getItem('whosDriving');
if (drivers) {
data.drivers = JSON.parse(drivers);
}
};
// Handle submit events
var submitHandler = function (event) {
// Make sure it was our add driver form
if (!event.target.matches('#add-driver')) return;
// Prevent default form behavior
event.preventDefault();
// Get the field
var driver = event.target.querySelector('#potential-driver');
if (!driver || driver.value.length < 1) return;
// Update our data and UI
data.drivers.push(driver.value);
render();
// Clear the field and refocus
driver.value = '';
driver.focus();
};
// Remove a driver from the list
var removeDriver = function (event) {
var index = event.target.getAttribute('data-remove-driver');
data.drivers.splice(index, 1);
render();
};
// Pick a driver
var pickDriver = function () {
var randomize = shuffle(data.drivers);
data.selected = randomize[0];
render();
};
// Clear all drivers from the list
var clearDrivers = function () {
data.drivers = [];
render();
};
// Handle click events
var clickHandler = function (event) {
if (event.target.matches('[data-remove-driver]')) {
removeDriver(event);
}
if (event.target.matches('#pick-driver')) {
pickDriver();
}
if (event.target.matches('#clear')) {
clearDrivers();
}
};
// Save to localStorage on render
var renderHandler = function (event) {
localStorage.setItem('whosDriving', JSON.stringify(event.detail.drivers));
};
//
// Inits and Event Listeners
// Event listeners
document.addEventListener('submit', submitHandler, false);
document.documentElement.addEventListener('click', clickHandler, false);
document.addEventListener('render', renderHandler, false);
// Initial render
getDriversFromLocalStorage();
render();
</script>
</body>
</html>
@vasileVas
Copy link

codepen for this: https://codepen.io/cferdinandi/pen/zeoJqy

nice work Chris

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment