This pattern is a natural fit for the js module system in the browser. This gets rid of globals. Instead, index.js creates an instance of Main, which then instantiates each of the specialized classes. We should probably do class inheritance for the setMain pattern. On the other hand it's currently only 3 lines of code, so we'd only be saving 1 LOC per class, while creating a new class, and it wouldn't really be simpler. If our classes take on more features, we can further refactor.
62 lines
1.4 KiB
JavaScript
62 lines
1.4 KiB
JavaScript
import { Element } from "./element.js";
|
|
|
|
export class Elements {
|
|
elements = new Map(); // id -> Element
|
|
classes = [];
|
|
div = undefined;
|
|
|
|
constructor({ classes } = {}) {
|
|
this.classes = classes;
|
|
this.div = document.createElement("div");
|
|
this.div.classList.add("elements");
|
|
this.div.classList.add("droptarget");
|
|
for (const className of (classes ?? [])) {
|
|
this.div.classList.add(className);
|
|
}
|
|
}
|
|
setMain(main) {
|
|
this.main = main;
|
|
this.main.div.appendChild(this.div);
|
|
}
|
|
|
|
add(props) {
|
|
// Make sure we have a unique id
|
|
let id = props.id;
|
|
if (!id) {
|
|
if (crypto?.randomUUID) {
|
|
id = crypto.randomUUID();
|
|
} else {
|
|
id = 1;
|
|
while (this.elements.has(id)) {
|
|
id++;
|
|
}
|
|
}
|
|
}
|
|
// Create element
|
|
const element = new Element(this, { ...props, id });
|
|
element.setMain(this.main);
|
|
// Append to div
|
|
this.div.appendChild(element.el);
|
|
// Add to collection
|
|
this.elements.set(id, element);
|
|
return element;
|
|
}
|
|
|
|
remove(id) {
|
|
const element = this.elements.get(id);
|
|
if (element) {
|
|
this.div.removeChild(element.el);
|
|
this.elements.delete(id);
|
|
}
|
|
}
|
|
|
|
getElementFromDOM(target) {
|
|
return Array.from(this.elements.values()).find(({ el }) => el === target);
|
|
}
|
|
|
|
renderAll() {
|
|
for (const element of this.elements.values()) {
|
|
element.render();
|
|
}
|
|
}
|
|
} |