Skip to content

Instantly share code, notes, and snippets.

@cferdinandi
Last active June 20, 2024 17:00
Show Gist options
  • Save cferdinandi/088d7f4ca088f7becd911e3e60efeec1 to your computer and use it in GitHub Desktop.
Save cferdinandi/088d7f4ca088f7becd911e3e60efeec1 to your computer and use it in GitHub Desktop.
Can you build a modern web app using only vanilla Web Components in 2024? Watch the tutorial on YouTube: https://youtu.be/2S4-42vjZwY
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Pick at Random</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style type="text/css">
body {
margin: 1em auto;
max-width: 40em;
width: 88%;
}
pick-at-random [role="status"]:not(:empty) {
background-color: #f7f7f7;
border: 1px solid #e5e5e5;
border-radius: 0.25em;
padding: 0.5rem 1rem;
margin-top: 0.5rem;
}
</style>
</head>
<body>
<h1>Pick at Random</h1>
<pick-at-random></pick-at-random>
<script>
customElements.define('pick-at-random', class extends HTMLElement {
/**
* Instantiate the component
*/
constructor () {
// Inherits parent class properties
super();
// Create a unique ID for the instance
this.uuid = `pick-${crypto.randomUUID()}`;
// Render our initial HTML
this.innerHTML =
`<form>
<label for="${this.uuid}">Add an Item</label>
<input type="text" id="${this.uuid}">
<button>Add Item</button>
</form>
<ul></ul>
<p><button pick-item>Pick an Item</button></p>
<div role="status" pick-result></div>`;
// Get our elements
this.form = this.querySelector('form');
this.list = this.querySelector('ul');
this.field = this.form.querySelector('input');
this.pickBtn = this.querySelector('[pick-item]');
this.result = this.querySelector('[pick-result]');
// Listen for event
this.form.addEventListener('submit', this);
this.pickBtn.addEventListener('click', this);
}
/**
* Handle events
* @param {Event} event The event object
*/
handleEvent (event) {
this[`on${event.type}`](event);
}
/**
* Handle submit events
* @param {Event} event The event object
*/
onsubmit (event) {
// Stop the form from reloading the page
event.preventDefault();
// Create a list item
let li = document.createElement('li');
li.textContent = this.field.value;
this.list.append(li);
// Show a status message
this.showStatus(`"${this.field.value}" has been added to the list.`);
// Clear text from field
this.field.value = '';
}
/**
* Handle click event
* @param {Event} event The event object
*/
onclick (event) {
// Get all of the list items
let items = Array.from(this.list.querySelectorAll('li')).map(function (item) {
return item.textContent;
});
// Randomize the items
this.shuffle(items);
// Show the result
this.result.textContent = `You picked ${items[0]}`;
}
/**
* Show a status message in the form
* @param {String} msg The message to display
*/
showStatus (msg) {
// Create a notification
let notification = document.createElement('div');
notification.setAttribute('role', 'status');
// Inject it into the DOM
this.form.append(notification);
// Add text after it's in the UI
setTimeout(function () {
notification.textContent = msg;
}, 1);
// Remove it after 4 seconds
setTimeout(function () {
notification.remove();
}, 4000);
}
/**
* Randomly shuffle an array
* https://stackoverflow.com/a/2450976/1293256
* @param {Array} array The array to shuffle
* @return {Array} The shuffled array
*/
shuffle (array) {
let currentIndex = array.length;
let 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;
}
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment