Skip to content

Commit

Permalink
Update demo-web-component.js
Browse files Browse the repository at this point in the history
  • Loading branch information
cacheflowe committed Dec 26, 2023
1 parent d2ed9fc commit 4089b1e
Showing 1 changed file with 108 additions and 52 deletions.
160 changes: 108 additions & 52 deletions demo/demo-web-component.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,32 @@
import DemoBase from "./demo--base.js";
import URLUtil from "../src/url-util.js";

// TODO:
// - Add Intersection observer to know if we're on screen or not
// - What else would we want a web component to do?

// Resources:
// - https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements
// - https://mxb.dev/blog/container-queries-web-components/

class WebComponentDemo extends DemoBase {
constructor(parentEl) {
super(
parentEl,
[],
"Web Component",
"web-component-container",
"Testing out the Web Component API with container queries, ResizeObserver, custom Events and more."
"Testing out the Web Component API with lifecycle event callbacks, container queries, ResizeObserver, custom Event dispatching, and more."
);
}

init() {
this.addWebComponentsOuterCSS();
this.addWebComponentsToDOM();
this.testUpdateComponent();
}

addWebComponentsOuterCSS() {
this.injectCSS(`
#web-component-container {
display: grid;
Expand All @@ -25,20 +39,21 @@ class WebComponentDemo extends DemoBase {
grid-row: 1;
}
`);
}

addWebComponentsToDOM() {
this.el.innerHTML = `
<custom-element color="#000066"></custom-element>
<custom-element color="#006600" debug></custom-element>
`;
this.testUpdateComponent();
}

testUpdateComponent() {
// re-render after manually setting different attributes
// manually set different attributes from the outside of the component
this.component = document.querySelector("custom-element");
this.component.setAttribute("resolution", 200);
this.component.setAttribute("color", "#444444");
this.component.setAttribute("color", "#444444"); // should trigger attributeChangedCallback()
this.component.setAttribute("debug", true);
this.component.update();

// query a child in the web component - relies on {mode: "open"}
let div = this.component.shadowRoot.querySelector("div");
Expand All @@ -49,37 +64,70 @@ class WebComponentDemo extends DemoBase {
this.debugEl.innerHTML = "Color updated: " + e.detail.color;
this.debugEl.innerHTML = "Color updated: " + e.target.curColor();
});

// set a different attribute to trigger the callback
setTimeout(() => {
this.component.setAttribute("color", "#ff0000");
}, 1500);
}
}

// Custom Web Component

class CustomWebComponent extends HTMLElement {
constructor() {
super();
this.renderCount = 0;
this.el = this.attachShadow({ mode: "open" }); // "open" allows querying and probably lots more
this.update();
}

update() {
// Web Component API callbacks --------------------------------------------

connectedCallback() {
console.log("Custom element added to page.");
this.render();
}

disconnectedCallback() {
console.log("Custom element removed from page.");
}

adoptedCallback() {
console.log("Custom element moved to new page.");
}

static observedAttributes = ["color"]; // list of properties to watch for changes - these will trigger attributeChangedCallback()

attributeChangedCallback(name, oldValue, newValue) {
// only update if it's not the first render and we have a color picker
if (oldValue != null && name == "color" && this.colorPicker) {
console.log(`Attribute ${name} has changed.`, oldValue, newValue);
this.colorPicker.value = newValue;
this.colorPicked({ target: this.colorPicker });
}
}

// custom code below --------------------------------------------

initComponent() {
// get props
this.defColor = String(this.getAttribute("color")) || "#ff0000";
const resolution = Number(this.getAttribute("resolution")) || 100;
const debug = this.hasAttribute("debug");
const size = { w: resolution, h: resolution };

// render!
this.render();
this.initComponent();
}
// get elements
this.container = this.el.querySelector(".container");
this.article = this.el.querySelector("article");

initComponent() {
// remove listeners
this.resizeObserver?.disconnect();
this.colorPicker?.removeEventListener("input", this.colorPicked);

// add color picker listener
if (!this.colorPicked)
this.colorPicked = this.colorPickedListener.bind(this);
this.colorPicked = !this.colorPicked
? this.colorPickedListener.bind(this)
: this.colorPicked;
this.colorPicker = this.el.querySelector("input.color");
this.colorPicker.value = this.defColor;
this.colorPicker.addEventListener("input", this.colorPicked);
Expand Down Expand Up @@ -115,56 +163,64 @@ class CustomWebComponent extends HTMLElement {
`;
}

render() {
this.el.innerHTML = `
<div class="container">
<article></article>
<input class="color" type="color" value="#00ff00" />
</div>
css() {
return `
article {
width: 100%;
aspect-ratio: 1 / 1;
padding: 2rem;
box-sizing: border-box;
}
<style>
article {
width: 100%;
aspect-ratio: 1 / 1;
padding: 2rem;
box-sizing: border-box;
}
.color {
grid-column: 1 / span 2;
margin-top: 1rem;
}
.color {
grid-column: 1 / span 2;
margin-top: 1rem;
}
/* Testing container queries */
/* :host sets the context for the container queries */
/* Testing container queries */
/* :host sets the context for the container queries */
:host {
display: block;
container-type: inline-size;
}
:host {
display: block;
container-type: inline-size;
@container (max-width: 199px) {
article {
color:#ff0000;
}
}
@container (max-width: 199px) {
article {
color:#ff0000;
}
@container (min-width: 200px) and (max-width: 399px) {
article {
color:#ffff00;
}
}
@container (min-width: 200px) and (max-width: 399px) {
article {
color:#ffff00;
}
@container (min-width: 400px) {
article {
color:#ffffff;
}
}
`;
}

@container (min-width: 400px) {
article {
color:#ffffff;
}
}
</style>
html() {
return `
<div class="container">
<article></article>
<input class="color" type="color" value="#00ff00" />
</div>
`;
}

render() {
this.renderCount++;
this.container = this.el.querySelector(".container");
this.article = this.el.querySelector("article");
this.el.innerHTML = `
${this.html()}
<style>${this.css()}</style>
`;
this.initComponent();
}
}

Expand Down

0 comments on commit 4089b1e

Please sign in to comment.