diff --git a/src/elements/canvas.mjs b/src/elements/canvas.mjs index 1a48963..a74fd81 100644 --- a/src/elements/canvas.mjs +++ b/src/elements/canvas.mjs @@ -2,96 +2,149 @@ import { fileDetails } from "../utils/file.mjs"; import { CustomElement, NotImplementedError } from "./base.mjs"; +/** + * The renderer of an Obsidian Canvas. + */ export class CanvasElement extends CustomElement { static getTemplate() { return document.getElementById("template-canvas") } - parsedJSON + /** + * Parsed value of the `contents` attribute at the moment of connection to the DOM. + * @type {any} + */ + parsedContents - nodesSlotted - edgesSlotted - nodeElements = {} - edgeElements = {} + /** + * `
` containing all the {@link NodeElement}s of this Canvas. + * @type {HTMLDivElement} + */ + nodesContainer + + /** + * `
` containing all the {@link NodeElement}s of this Canvas. + * @type {HTMLDivElement} + */ + edgesContainer + + /** + * Mapping associating ids to their respective {@link NodeElement}s of this Canvas. + * @type {{[id: string]: NodeElement}} + */ + nodeElementsById = {} + + /** + * Mapping associating names to their respective {@link NodeElement}s of this Canvas. + * @type {{[name: string]: NodeElement}} + */ + nodeElementsByName = {} + + /** + * Mapping associating vault-relative paths to their respective {@link NodeElement}s of this Canvas. + * @type {{[name: string]: NodeElement}} + */ + nodeElementsByPath = {} + + /** + * Mapping associating ids to their respective {@link EdgeElement}s of this Canvas. + * @type {{[id: string]: EdgeElement}} + */ + edgeElementsById = {} onConnected() { super.onConnected(); - this.parsedJSON = JSON.parse(this.getAttribute("contents")) + this.parsedContents = JSON.parse(this.getAttribute("contents")) - this.nodesSlotted = document.createElement("div") - this.nodesSlotted.slot = "canvas-nodes" + this.nodesContainer = document.createElement("div") + this.nodesContainer.slot = "canvas-nodes" - this.edgesSlotted = document.createElement("div") - this.edgesSlotted.slot = "canvas-edges" + this.edgesContainer = document.createElement("div") + this.edgesContainer.slot = "canvas-edges" let minX = { x: Infinity, width: 0 } let minY = { y: Infinity, height: 0 } let maxX = { x: -Infinity, width: 0 } let maxY = { y: -Infinity, height: 0 } - for(const node of this.parsedJSON["nodes"]) { - if(node["x"] < minX["x"]) minX = node - if(node["y"] < minY["y"]) minY = node - if(node["x"] + node["width"] > maxX["x"] + node["width"]) maxX = node - if(node["y"] + node["height"] > maxY["y"] + node["height"]) maxY = node + for(const node of this.parsedContents["nodes"]) { + let {x, y, width, height} = node + x, y, width, height = Number(x), Number(y), Number(width), Number(height) + + if(x < minX.x) minX = node + if(y < minY.y) minY = node + if(x + width > maxX.x + width) maxX = node + if(y + height > maxY.y + height) maxY = node } - for(const node of this.parsedJSON["nodes"]) { - const element = document.createElement(`x-node-${node["type"]}`) + for(const node of this.parsedContents["nodes"]) { + let {id, type, color, x, y, width, height} = node + x, y, width, height = Number(x), Number(y), Number(width), Number(height) - element.setAttribute("id", `node-${node["id"]}`) - element.setAttribute("x", node["x"] - minX["x"]) - element.setAttribute("y", node["y"] - minY["y"]) - element.setAttribute("width", node["width"]) - element.setAttribute("height", node["height"]) - if(node["color"]) element.setAttribute("color", node["color"]) + const element = document.createElement(`x-node-${type}`) - switch(node["type"]) { + element.setAttribute("id", `node-${id}`) + element.setAttribute("x", `${x - minX.x}`) + element.setAttribute("y", `${y - minY.y}`) + element.setAttribute("width", `${width}`) + element.setAttribute("height", `${height}`) + if(color) element.setAttribute("color", color) + + this.nodeElementsById[id] = element + + switch(type) { case "text": - element.setAttribute("text", node["text"]) + const {text} = node + element.setAttribute("text", text) break case "file": - element.setAttribute("file", node["file"]) - element.setAttribute("file-name", fileDetails(node["file"]).name) + const {file} = node + const {name} = fileDetails(file) + element.setAttribute("file", file) + element.setAttribute("file-name", name) + this.nodeElementsByPath[file] = element + this.nodeElementsByName[name] = element break case "group": - element.setAttribute("label", node["label"]) + const {label} = node + element.setAttribute("label", label) break default: - console.warn("Encountered node of unimplemented type: ", node["type"]) + console.warn("Encountered node of unimplemented type: ", type) break } - this.nodeElements[node["id"]] = element - this.nodesSlotted.appendChild(element) + this.nodesContainer.appendChild(element) } - for(const edge of this.parsedJSON["edges"]) { + for(const edge of this.parsedContents["edges"]) { + let {id, fromNode, fromSide, toNode, toSide, color, toEnd: arrows} = edge + const element = document.createElement("x-edge") - element.setAttribute("id", `edge-${edge["id"]}`) - element.setAttribute("node-from", edge["fromNode"]) - element.setAttribute("node-from-side", edge["fromSide"]) - element.setAttribute("node-to", edge["toNode"]) - element.setAttribute("node-to-side", edge["toSide"]) - if(edge["color"]) element.setAttribute("color", edge["color"]) - if(edge["arrows"]) element.setAttribute("arrows", edge["toEnd"]) + element.setAttribute("id", `edge-${id}`) + element.setAttribute("node-from", fromNode) + element.setAttribute("node-from-side", fromSide) + element.setAttribute("node-to", toNode) + element.setAttribute("node-to-side", toSide) + if(edge["color"]) element.setAttribute("color", color) + if(edge["arrows"]) element.setAttribute("arrows", arrows) - this.edgeElements[edge["id"]] = element - this.edgesSlotted.appendChild(element) + this.edgeElementsById[id] = element + this.edgesContainer.appendChild(element) } - this.nodesSlotted.style["width"] = `${maxX["x"] + maxX["width"] - minX["x"]}px` - this.nodesSlotted.style["height"] = `${maxY["y"] + maxY["height"] - minY["y"]}px` + this.nodesContainer.style["width"] = `${maxX.x + maxX.width - minX.x}px` + this.nodesContainer.style["height"] = `${maxY.y + maxY.height - minY.y}px` - this.edgesSlotted.style["width"] = `${maxX["x"] + maxX["width"] - minX["x"]}px` - this.edgesSlotted.style["height"] = `${maxY["y"] + maxY["height"] - minY["y"]}px` + this.edgesContainer.style["width"] = `${maxX.x + maxX.width - minX.x}px` + this.edgesContainer.style["height"] = `${maxY.y + maxY.height - minY.y}px` - this.appendChild(this.nodesSlotted) - this.appendChild(this.edgesSlotted) + this.appendChild(this.nodesContainer) + this.appendChild(this.edgesContainer) } }