Clean up after disconnect.

I was leaving the timer running even if the component was removed
from the page dynamically.  How rude!
This commit is contained in:
Elf M. Sternberg 2021-11-17 16:04:52 -08:00
parent 3b2a7f22f4
commit 6c9ac44eac
1 changed files with 61 additions and 49 deletions

View File

@ -1,9 +1,11 @@
type Times = number[]; type Times = number[];
type Cats = [string, Times] type Cats = [string, Times];
const MATRIX: Cats[] = [["o0", [1, 5, 8, 9, 11]], const MATRIX: Cats[] = [
["o1", [2, 5, 6, 10, 11]], ["o0", [1, 5, 8, 9, 11]],
["o2", [3, 6, 7, 9, 11]], ["o1", [2, 5, 6, 10, 11]],
["o3", [4, 7, 8, 10, 11]]]; ["o2", [3, 6, 7, 9, 11]],
["o3", [4, 7, 8, 10, 11]],
];
const TEMPLATE = ` const TEMPLATE = `
<style> <style>
@ -74,57 +76,67 @@ const TEMPLATE = `
</div> </div>
`; `;
type Face = "hours" | "minutes" | "seconds" type Face = "hours" | "minutes" | "seconds";
const isFace = (v: unknown): v is Face => { const isFace = (v: unknown): v is Face => {
if (typeof v === "string" && ["hours", "minutes", "seconds"].includes(v)) { return true; } if (typeof v === "string" && ["hours", "minutes", "seconds"].includes(v)) {
throw new Error(`Expected a Face, got ${v}`); return true;
} }
throw new Error(`Expected a Face, got ${v}`);
};
class DominoClock extends HTMLElement { class DominoClock extends HTMLElement {
elements: { [K in Face]: HTMLDivElement };
elements: { [K in Face]: HTMLDivElement }; timer: number;
timer: number; constructor() {
super();
this.timer = 0;
this.innerHTML = TEMPLATE;
this.elements = Object.fromEntries(
Array.from(this.getElementsByTagName("div"))
.filter(element => element.className === "face")
.map(element => [isFace(element.id) && element.id, element])
);
this.paint = this.paint.bind(this);
}
constructor() { connectedCallback() {
super() this.timer = window.setTimeout(this.paint, 250);
this.timer = 0; }
this.innerHTML = TEMPLATE;
this.elements = Object.fromEntries(
Array.from(this.getElementsByTagName('div'))
.filter((element) => element.className === "face")
.map((element) => [isFace(element.id) && element.id, element]));
this.paint = this.paint.bind(this);
}
connectedCallback() { disconnectedCallback() {
this.timer = window.setTimeout(this.paint, 250) window.clearTimeout(this.timer);
} }
tock(board: Face, time: number) { tock(board: Face, time: number) {
const dots = Array.from(this.elements[board].getElementsByTagName('div')); const dots = Array.from(this.elements[board].getElementsByTagName("div"));
dots.forEach((element) => { element.style.opacity = "0"; }); dots.forEach(element => {
dots.forEach((element) => { element.style.opacity = "0";
const row = MATRIX.find((i) => Array.from(element.classList).includes(i[0])); });
if (!row) { console.log(`Didn't find a row for ${element.className}?`); return; } dots.forEach(element => {
if (row[1].includes(time)) { const row = MATRIX.find(i => Array.from(element.classList).includes(i[0]));
element.style.opacity = "1" if (!row) {
} console.log(`Didn't find a row for ${element.className}?`);
}); return;
} }
if (row[1].includes(time)) {
paint() { element.style.opacity = "1";
const now = new Date(); }
const rawHours = now.getHours(); });
const hours = rawHours > 12 ? rawHours - 12 : rawHours; }
this.tock("hours", hours);
this.tock("minutes", Math.floor(now.getUTCMinutes() / 5)); paint() {
this.tock("seconds", Math.floor(now.getUTCSeconds() / 5)); const now = new Date();
window.clearTimeout(this.timer); const rawHours = now.getHours();
this.timer = window.setTimeout(this.paint, 250); const hours = rawHours > 12 ? rawHours - 12 : rawHours;
} this.tock("hours", hours);
this.tock("minutes", Math.floor(now.getUTCMinutes() / 5));
this.tock("seconds", Math.floor(now.getUTCSeconds() / 5));
window.clearTimeout(this.timer);
this.timer = window.setTimeout(this.paint, 250);
}
} }
customElements.define('domino-clock', DominoClock); customElements.define("domino-clock", DominoClock);