<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>GOAT group</title>
<style>
</style>
</head>
<body>
<h1>Who's the GREATEST GROUP OF ALL TIME?!</h1>
<input id="group-sub-input"/>
<button id="group-sub-btn">Submit</button>
<goat-group guess="">🤔</goat-group>
</body>
</html>
body {
font-family: monospace; /* notice how the font crosses the shadow DOM boundary*/
}
h1 {
color: green;
}
// light DOM stuff
const groupSubmitInput = document.querySelector('#group-sub-input');
const groupSubmitBtn = document.querySelector('#group-sub-btn');
const goatGroupEl = document.querySelector('goat-group');
groupSubmitBtn.addEventListener('click', () => {
console.log('button clicked!', groupSubmitInput.value);
goatGroupEl.setAttribute('guess', groupSubmitInput.value);
groupSubmitInput.value = '';
})
// Listen for the Custom Event dispatched from the Web Component
window.addEventListener('guessed', (e)=>{
alert(e.detail);
})
// Create the template element
const template = document.createElement('template');
template.innerHTML = `
<slot></slot>
<h1></h1>
<div id='verdict'></div>
`
//HTMLElement is the base class that powers other native elements like <input>, <button>, <video> etc.
class GoatGroup extends HTMLElement {
// which attributes do we want to listen for changes
static get observedAttributes() { return ['guess']; };
constructor() {
super(); // get all the HTMLElement goodness (methods and properties)
// clone the Template so we can use it.
const clone = document.importNode(template.content, true);
// using Shadow DOM
this.attachShadow({ mode: 'open' }); // should the shadow root's internal features be accessible via JavaScript? open or closed.
this.shadowRoot.appendChild(clone);
//
this.addEventListener('click', () => {
this.style.color = 'red';
});
}
// lifecycle callback invoked each time your custom element is appended to the DOM. Can be called multiple times.
connectedCallback() {
console.log('goat group connected!');
this.style.color = 'blue';
}
// called when an attribute has been changed.
attributeChangedCallback(name, oldValue, newValue) {
console.log('attribute changed!: ', name, newValue);
if (newValue.trim() === ''){
this.shadowRoot.querySelector('#verdict').innerText = "";
} else if (newValue.toLowerCase() === 'outkast'){
this.shadowRoot.querySelector('h1').innerText = `${newValue.toUpperCase()}!!!!`;
this.shadowRoot.querySelector('#verdict').innerText = "You're RIGHT!!";
this.dispatchEvent(new CustomEvent('guessed', {
detail: 'yup',
bubbles: true, //bubble up through the component
composed: true //allows event to cross into light DOM
}));
} else {
this.shadowRoot.querySelector('h1').innerText = `${newValue}?!`;
this.shadowRoot.querySelector('#verdict').innerText = "They're okay, I guess.";
this.dispatchEvent(new CustomEvent('guessed', {
detail: 'nope',
bubbles: true, //bubble up through the component
composed: true //allows event to cross into light DOM
}));
}
}
// called when your custom element is disconnected from the page. Useful to remove event listeners, intervals etc to prevent memory leaks
disconnectedCallback() {
console.log('goat group disconnected!');
}
}
// connects our custom element to our class.
customElements.define('goat-group', GoatGroup);
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.