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 Cats = [string, Times]
const MATRIX: Cats[] = [["o0", [1, 5, 8, 9, 11]],
["o1", [2, 5, 6, 10, 11]],
["o2", [3, 6, 7, 9, 11]],
["o3", [4, 7, 8, 10, 11]]];
type Cats = [string, Times];
const MATRIX: Cats[] = [
["o0", [1, 5, 8, 9, 11]],
["o1", [2, 5, 6, 10, 11]],
["o2", [3, 6, 7, 9, 11]],
["o3", [4, 7, 8, 10, 11]],
];
const TEMPLATE = `
<style>
@ -74,57 +76,67 @@ const TEMPLATE = `
</div>
`;
type Face = "hours" | "minutes" | "seconds"
type Face = "hours" | "minutes" | "seconds";
const isFace = (v: unknown): v is Face => {
if (typeof v === "string" && ["hours", "minutes", "seconds"].includes(v)) { return true; }
throw new Error(`Expected a Face, got ${v}`);
}
if (typeof v === "string" && ["hours", "minutes", "seconds"].includes(v)) {
return true;
}
throw new Error(`Expected a Face, got ${v}`);
};
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() {
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);
}
connectedCallback() {
this.timer = window.setTimeout(this.paint, 250);
}
connectedCallback() {
this.timer = window.setTimeout(this.paint, 250)
}
tock(board: Face, time: number) {
const dots = Array.from(this.elements[board].getElementsByTagName('div'));
dots.forEach((element) => { element.style.opacity = "0"; });
dots.forEach((element) => {
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; }
if (row[1].includes(time)) {
element.style.opacity = "1"
}
});
}
paint() {
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));
this.tock("seconds", Math.floor(now.getUTCSeconds() / 5));
window.clearTimeout(this.timer);
this.timer = window.setTimeout(this.paint, 250);
}
disconnectedCallback() {
window.clearTimeout(this.timer);
}
tock(board: Face, time: number) {
const dots = Array.from(this.elements[board].getElementsByTagName("div"));
dots.forEach(element => {
element.style.opacity = "0";
});
dots.forEach(element => {
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;
}
if (row[1].includes(time)) {
element.style.opacity = "1";
}
});
}
paint() {
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));
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);