Skip to content

Instantly share code, notes, and snippets.

@angusgrant
Created March 3, 2023 21:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save angusgrant/5c3580d1ff17f394f6bfec66b33db630 to your computer and use it in GitHub Desktop.
Save angusgrant/5c3580d1ff17f394f6bfec66b33db630 to your computer and use it in GitHub Desktop.
Shaddow Root in components
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Dice - Shadow DOM</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style type="text/css">
body {
margin: 0 auto;
max-width: 40em;
width: 88%;
}
</style>
</head>
<body>
<h1>Dice - Shadow DOM</h1>
<roll-dice>Roll a D6</roll-dice>
<script>
class RollDice extends HTMLElement {
#dice;
/**
* The constructor object
*/
constructor () {
// Access parent class properties and methods
super();
//create a shadow root
this.root = this.attachShadow({mode: 'closed'});
// Define properties
this.#dice = [1, 2, 3, 4, 5, 6];
// Render HTML
this.root.innerHTML =
`<p>
<button><slot>Roll Dice</slot></button>
</p>
<div aria-live="polite"></div>`;
}
/**
* 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;
}
/**
* Shuffle dice array and return first number
* @return {Number} The result
*/
#roll () {
this.#shuffle(this.#dice);
return this.#dice[0];
}
/**
* Handle click events
* @param {Event} event The event object
*/
#clickHandler (event) {
// Get the host component
let host = event.target.getRootNode().host;
// Get the message element
let target = host.root.querySelector('[aria-live="polite"]');
if (!target) return;
// Roll the dice
let roll = host.#roll();
// Inject the message into the UI
target.textContent = `You rolled a ${roll}`;
}
/**
* Runs each time the element is appended to or moved in the DOM
*/
connectedCallback () {
// Attach a click event listener to the button
let btn = this.root.querySelector('button');
if (!btn) return;
btn.addEventListener('click', this.#clickHandler);
}
/**
* Runs when the element is removed from the DOM
*/
disconnectedCallback () {
// Remove the click event listener from the button
let btn = this.root.querySelector('button');
if (!btn) return;
btn.removeEventListener('click', this.#clickHandler);
}
}
if ('customElements' in window) {
customElements.define('roll-dice', RollDice);
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment