mirror of
https://github.com/glassflame/glassflame.github.io.git
synced 2024-11-25 17:44:26 +00:00
Abstract connectedCallback
into onConnected
This commit is contained in:
parent
1bb664b593
commit
dd4ddb7620
6 changed files with 100 additions and 131 deletions
64
src/elements/base.mjs
Normal file
64
src/elements/base.mjs
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
export class NotImplementedError extends Error {}
|
||||||
|
|
||||||
|
|
||||||
|
export class CustomElement extends HTMLElement {
|
||||||
|
|
||||||
|
template
|
||||||
|
shadow
|
||||||
|
instance
|
||||||
|
|
||||||
|
// noinspection JSUnusedGlobalSymbols
|
||||||
|
connectedCallback() {
|
||||||
|
// The template to duplicate.
|
||||||
|
this.template = this.constructor.getTemplate()
|
||||||
|
// The shadow root, the inner contents of the element..
|
||||||
|
this.shadow = this.attachShadow({ mode: "open" })
|
||||||
|
// The element contained inside the shadow root..
|
||||||
|
this.instance = this.template.content.cloneNode(true)
|
||||||
|
|
||||||
|
// Call the custom callback.
|
||||||
|
this.onConnected()
|
||||||
|
|
||||||
|
// Add the instance to the DOM.
|
||||||
|
this.shadow.appendChild(this.instance)
|
||||||
|
}
|
||||||
|
|
||||||
|
findFirstAncestor(constructor) {
|
||||||
|
let current = this
|
||||||
|
// Keep iterating over nodes
|
||||||
|
while(current) {
|
||||||
|
// The ancestor has been found!
|
||||||
|
if(current instanceof constructor) {
|
||||||
|
return current
|
||||||
|
}
|
||||||
|
// Use .host to access the parent of a ShadowRoot
|
||||||
|
else if(current instanceof ShadowRoot) {
|
||||||
|
current = current.host
|
||||||
|
}
|
||||||
|
// Use .parentNode to access the parent of a HTMLElement
|
||||||
|
else if(current instanceof HTMLElement) {
|
||||||
|
current = current.parentNode
|
||||||
|
}
|
||||||
|
// Something went wrong?
|
||||||
|
else {
|
||||||
|
console.warn("[findFirstAncestor] Reached unknown node:", current)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// The ancestor has NOT been found...
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
if(this.constructor === CustomElement) {
|
||||||
|
throw new NotImplementedError("CustomElement is being used as-is.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onConnected() {}
|
||||||
|
|
||||||
|
static getTemplate() {
|
||||||
|
throw new NotImplementedError("CustomElement.getTemplate has not been overridden.")
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,26 +1,8 @@
|
||||||
import { fileDetails } from "../utils/file.mjs";
|
import { fileDetails } from "../utils/file.mjs";
|
||||||
|
import { CustomElement, NotImplementedError } from "./base.mjs";
|
||||||
|
|
||||||
|
|
||||||
export class CanvasElement extends HTMLElement {
|
export class CanvasElement extends CustomElement {
|
||||||
/**
|
|
||||||
* Return the closest {@link CanvasElement} ancestor in the tree.
|
|
||||||
*
|
|
||||||
* @param initial {HTMLElement} The element to start the search from.
|
|
||||||
*/
|
|
||||||
static findFirstCanvasAncestor(initial) {
|
|
||||||
let current = initial
|
|
||||||
while(current) {
|
|
||||||
if(current instanceof ShadowRoot) {
|
|
||||||
current = current.host
|
|
||||||
}
|
|
||||||
if(current instanceof CanvasElement) {
|
|
||||||
return current
|
|
||||||
}
|
|
||||||
current = current.parentNode
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
static getTemplate() {
|
static getTemplate() {
|
||||||
return document.getElementById("template-canvas")
|
return document.getElementById("template-canvas")
|
||||||
}
|
}
|
||||||
|
@ -32,10 +14,8 @@ export class CanvasElement extends HTMLElement {
|
||||||
nodeElements = {}
|
nodeElements = {}
|
||||||
edgeElements = {}
|
edgeElements = {}
|
||||||
|
|
||||||
// noinspection JSUnusedGlobalSymbols
|
onConnected() {
|
||||||
connectedCallback() {
|
super.onConnected();
|
||||||
const instanceDocument = CanvasElement.getTemplate().content.cloneNode(true)
|
|
||||||
const shadow = this.attachShadow({ mode: "open" })
|
|
||||||
|
|
||||||
this.parsedJSON = JSON.parse(this.getAttribute("contents"))
|
this.parsedJSON = JSON.parse(this.getAttribute("contents"))
|
||||||
|
|
||||||
|
@ -112,16 +92,11 @@ export class CanvasElement extends HTMLElement {
|
||||||
|
|
||||||
this.appendChild(this.nodesSlotted)
|
this.appendChild(this.nodesSlotted)
|
||||||
this.appendChild(this.edgesSlotted)
|
this.appendChild(this.edgesSlotted)
|
||||||
|
|
||||||
shadow.appendChild(instanceDocument)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
export class CanvasItemElement extends CustomElement {
|
||||||
* Element representing the generic skeleton of an Obsidian Canvas item.
|
|
||||||
*/
|
|
||||||
export class CanvasItemElement extends HTMLElement {
|
|
||||||
colorToHex() {
|
colorToHex() {
|
||||||
const color = this.getAttribute("color")
|
const color = this.getAttribute("color")
|
||||||
|
|
||||||
|
@ -133,7 +108,6 @@ export class CanvasItemElement extends HTMLElement {
|
||||||
return color
|
return color
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// TODO: Check which colors correspond to what
|
|
||||||
return {
|
return {
|
||||||
"0": "var(--color-gray)",
|
"0": "var(--color-gray)",
|
||||||
"1": "var(--color-red)",
|
"1": "var(--color-red)",
|
||||||
|
@ -145,4 +119,12 @@ export class CanvasItemElement extends HTMLElement {
|
||||||
}[color]
|
}[color]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
if(this.constructor === CanvasItemElement) {
|
||||||
|
throw new NotImplementedError("CanvasItemElement is being used as-is.")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,28 +2,10 @@ import { fileDetails } from "../utils/file.mjs";
|
||||||
import { CanvasElement } from "./canvas.mjs";
|
import { CanvasElement } from "./canvas.mjs";
|
||||||
import { MarkdownElement } from "./markdown.mjs";
|
import { MarkdownElement } from "./markdown.mjs";
|
||||||
import { FetchError } from "./node.mjs";
|
import { FetchError } from "./node.mjs";
|
||||||
|
import { CustomElement } from "./base.mjs";
|
||||||
|
|
||||||
|
|
||||||
export class DisplayElement extends HTMLElement {
|
export class DisplayElement extends CustomElement {
|
||||||
/**
|
|
||||||
* Return the closest {@link DisplayElement} ancestor in the tree.
|
|
||||||
*
|
|
||||||
* @param initial {HTMLElement} The element to start the search from.
|
|
||||||
*/
|
|
||||||
static findFirstDisplayAncestor(initial) {
|
|
||||||
let current = initial
|
|
||||||
while(current) {
|
|
||||||
if(current instanceof ShadowRoot) {
|
|
||||||
current = current.host
|
|
||||||
}
|
|
||||||
if(current instanceof DisplayElement) {
|
|
||||||
return current
|
|
||||||
}
|
|
||||||
current = current.parentNode
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
static getTemplate() {
|
static getTemplate() {
|
||||||
return document.getElementById("template-display")
|
return document.getElementById("template-display")
|
||||||
}
|
}
|
||||||
|
@ -31,11 +13,7 @@ export class DisplayElement extends HTMLElement {
|
||||||
containerSlotted
|
containerSlotted
|
||||||
loadButton
|
loadButton
|
||||||
|
|
||||||
// noinspection JSUnusedGlobalSymbols
|
onConnected() {
|
||||||
connectedCallback() {
|
|
||||||
const instanceDocument = DisplayElement.getTemplate().content.cloneNode(true)
|
|
||||||
const shadow = this.attachShadow({ mode: "open" })
|
|
||||||
|
|
||||||
this.containerSlotted = document.createElement("div")
|
this.containerSlotted = document.createElement("div")
|
||||||
this.containerSlotted.slot = "display-container"
|
this.containerSlotted.slot = "display-container"
|
||||||
this.loadButton = document.createElement("button")
|
this.loadButton = document.createElement("button")
|
||||||
|
@ -43,8 +21,6 @@ export class DisplayElement extends HTMLElement {
|
||||||
this.loadButton.addEventListener("click", this.load.bind(this))
|
this.loadButton.addEventListener("click", this.load.bind(this))
|
||||||
this.containerSlotted.appendChild(this.loadButton)
|
this.containerSlotted.appendChild(this.loadButton)
|
||||||
this.appendChild(this.containerSlotted)
|
this.appendChild(this.containerSlotted)
|
||||||
|
|
||||||
shadow.appendChild(instanceDocument)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data
|
data
|
||||||
|
|
|
@ -9,12 +9,8 @@ export class EdgeElement extends CanvasItemElement {
|
||||||
svgSlotted
|
svgSlotted
|
||||||
lineElement
|
lineElement
|
||||||
|
|
||||||
// noinspection JSUnusedGlobalSymbols
|
onConnected() {
|
||||||
connectedCallback() {
|
const canvas = this.findFirstAncestor(CanvasElement)
|
||||||
const instanceDocument = EdgeElement.getTemplate().content.cloneNode(true)
|
|
||||||
const shadow = this.attachShadow({ mode: "open" })
|
|
||||||
|
|
||||||
const canvas = CanvasElement.findFirstCanvasAncestor(this)
|
|
||||||
|
|
||||||
const fromNode = canvas.nodeElements[this.getAttribute("node-from")]
|
const fromNode = canvas.nodeElements[this.getAttribute("node-from")]
|
||||||
const fromSide = this.getAttribute("node-from-side")
|
const fromSide = this.getAttribute("node-from-side")
|
||||||
|
@ -48,7 +44,5 @@ export class EdgeElement extends CanvasItemElement {
|
||||||
|
|
||||||
this.svgSlotted.appendChild(this.lineElement)
|
this.svgSlotted.appendChild(this.lineElement)
|
||||||
this.appendChild(this.svgSlotted)
|
this.appendChild(this.svgSlotted)
|
||||||
|
|
||||||
shadow.appendChild(instanceDocument)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,12 +1,11 @@
|
||||||
import { Marked } from "https://unpkg.com/marked@9.1.2/lib/marked.esm.js";
|
import { Marked } from "https://unpkg.com/marked@9.1.2/lib/marked.esm.js";
|
||||||
import { fileDetails } from "../utils/file.mjs";
|
import { CustomElement } from "./base.mjs";
|
||||||
import { DisplayElement } from "./display.mjs";
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Element rendering the Markdown contents of an Obsidian page.
|
* Element rendering the Markdown contents of an Obsidian page.
|
||||||
*/
|
*/
|
||||||
export class MarkdownElement extends HTMLElement {
|
export class MarkdownElement extends CustomElement {
|
||||||
static marked = new Marked({
|
static marked = new Marked({
|
||||||
extensions: [
|
extensions: [
|
||||||
{
|
{
|
||||||
|
@ -15,7 +14,7 @@ export class MarkdownElement extends HTMLElement {
|
||||||
start(src) {
|
start(src) {
|
||||||
return src.match(/^(-{3,})/)?.index
|
return src.match(/^(-{3,})/)?.index
|
||||||
},
|
},
|
||||||
tokenizer(src, tokens) {
|
tokenizer(src, _) {
|
||||||
const match = src.match(/^(-{3,})(.+)?\n((?:.+\n)*)\1\n/)
|
const match = src.match(/^(-{3,})(.+)?\n((?:.+\n)*)\1\n/)
|
||||||
if(match) {
|
if(match) {
|
||||||
return {
|
return {
|
||||||
|
@ -36,7 +35,7 @@ export class MarkdownElement extends HTMLElement {
|
||||||
start(src) {
|
start(src) {
|
||||||
return src.match(/^\[\[/)?.index
|
return src.match(/^\[\[/)?.index
|
||||||
},
|
},
|
||||||
tokenizer(src, tokens) {
|
tokenizer(src, _) {
|
||||||
const match = src.match(/^\[\[([^|\]]+)(?:\|([^\]]+))?]]/)
|
const match = src.match(/^\[\[([^|\]]+)(?:\|([^\]]+))?]]/)
|
||||||
if(match) {
|
if(match) {
|
||||||
return {
|
return {
|
||||||
|
@ -57,7 +56,7 @@ export class MarkdownElement extends HTMLElement {
|
||||||
start(src) {
|
start(src) {
|
||||||
return src.match(/^#/)?.index
|
return src.match(/^#/)?.index
|
||||||
},
|
},
|
||||||
tokenizer(src, tokens) {
|
tokenizer(src, _) {
|
||||||
const match = src.match(/^#([A-Za-z0-9]+)/)
|
const match = src.match(/^#([A-Za-z0-9]+)/)
|
||||||
if(match) {
|
if(match) {
|
||||||
return {
|
return {
|
||||||
|
@ -80,11 +79,7 @@ export class MarkdownElement extends HTMLElement {
|
||||||
return document.getElementById("template-markdown")
|
return document.getElementById("template-markdown")
|
||||||
}
|
}
|
||||||
|
|
||||||
// noinspection JSUnusedGlobalSymbols
|
onConnected() {
|
||||||
connectedCallback() {
|
|
||||||
const instanceDocument = MarkdownElement.getTemplate().content.cloneNode(true)
|
|
||||||
const shadow = this.attachShadow({ mode: "open" })
|
|
||||||
|
|
||||||
const markdown = this.getAttribute("contents")
|
const markdown = this.getAttribute("contents")
|
||||||
|
|
||||||
this.contentsElement = document.createElement("div")
|
this.contentsElement = document.createElement("div")
|
||||||
|
@ -92,65 +87,41 @@ export class MarkdownElement extends HTMLElement {
|
||||||
this.contentsElement.innerHTML = MarkdownElement.marked.parse(markdown)
|
this.contentsElement.innerHTML = MarkdownElement.marked.parse(markdown)
|
||||||
|
|
||||||
this.appendChild(this.contentsElement)
|
this.appendChild(this.contentsElement)
|
||||||
|
|
||||||
shadow.appendChild(instanceDocument)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Element rendering Obsidian front matter.
|
* Element rendering Obsidian front matter.
|
||||||
*/
|
*/
|
||||||
export class FrontMatterElement extends HTMLElement {
|
export class FrontMatterElement extends CustomElement {
|
||||||
static getTemplate() {
|
static getTemplate() {
|
||||||
return document.getElementById("template-frontmatter")
|
return document.getElementById("template-frontmatter")
|
||||||
}
|
}
|
||||||
|
|
||||||
// noinspection JSUnusedGlobalSymbols
|
|
||||||
connectedCallback() {
|
|
||||||
const instanceDocument = FrontMatterElement.getTemplate().content.cloneNode(true)
|
|
||||||
const shadow = this.attachShadow({ mode: "open" })
|
|
||||||
|
|
||||||
shadow.appendChild(instanceDocument)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Element rendering an Obsidian Hashtag.
|
* Element rendering an Obsidian Hashtag.
|
||||||
*/
|
*/
|
||||||
export class HashtagElement extends HTMLElement {
|
export class HashtagElement extends CustomElement {
|
||||||
static getTemplate() {
|
static getTemplate() {
|
||||||
return document.getElementById("template-hashtag")
|
return document.getElementById("template-hashtag")
|
||||||
}
|
}
|
||||||
|
|
||||||
// noinspection JSUnusedGlobalSymbols
|
|
||||||
connectedCallback() {
|
|
||||||
const instanceDocument = HashtagElement.getTemplate().content.cloneNode(true)
|
|
||||||
const shadow = this.attachShadow({ mode: "open" })
|
|
||||||
|
|
||||||
shadow.appendChild(instanceDocument)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Element rendering an Obsidian Wikilink.
|
* Element rendering an Obsidian Wikilink.
|
||||||
*/
|
*/
|
||||||
export class WikilinkElement extends HTMLElement {
|
export class WikilinkElement extends CustomElement {
|
||||||
static getTemplate() {
|
static getTemplate() {
|
||||||
return document.getElementById("template-wikilink")
|
return document.getElementById("template-wikilink")
|
||||||
}
|
}
|
||||||
|
|
||||||
// noinspection JSUnusedGlobalSymbols
|
onConnected() {
|
||||||
connectedCallback() {
|
const instanceElement = this.instance.querySelector(".wikilink")
|
||||||
const instanceDocument = WikilinkElement.getTemplate().content.cloneNode(true)
|
|
||||||
const shadow = this.attachShadow({ mode: "open" })
|
|
||||||
|
|
||||||
const instanceElement = instanceDocument.querySelector(".wikilink")
|
|
||||||
|
|
||||||
const destinationURL = new URL(window.location)
|
const destinationURL = new URL(window.location)
|
||||||
destinationURL.hash = this.getAttribute("wref")
|
destinationURL.hash = this.getAttribute("wref")
|
||||||
|
|
||||||
instanceElement.href = destinationURL
|
instanceElement.href = destinationURL
|
||||||
|
|
||||||
shadow.appendChild(instanceDocument)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,12 +54,8 @@ export class NodeGroupElement extends NodeElement {
|
||||||
instanceElement
|
instanceElement
|
||||||
labelSlotted
|
labelSlotted
|
||||||
|
|
||||||
// noinspection JSUnusedGlobalSymbols
|
onConnected() {
|
||||||
connectedCallback() {
|
this.instanceElement = this.instance.querySelector(".node-group")
|
||||||
const instanceDocument = NodeGroupElement.getTemplate().content.cloneNode(true)
|
|
||||||
const shadow = this.attachShadow({ mode: "open" })
|
|
||||||
|
|
||||||
this.instanceElement = instanceDocument.querySelector(".node-group")
|
|
||||||
|
|
||||||
this.instanceElement.style.setProperty("left", `${this.getAttribute("x")}px`)
|
this.instanceElement.style.setProperty("left", `${this.getAttribute("x")}px`)
|
||||||
this.instanceElement.style.setProperty("top", `${this.getAttribute("y")}px`)
|
this.instanceElement.style.setProperty("top", `${this.getAttribute("y")}px`)
|
||||||
|
@ -71,8 +67,6 @@ export class NodeGroupElement extends NodeElement {
|
||||||
this.labelSlotted.slot = "node-label"
|
this.labelSlotted.slot = "node-label"
|
||||||
this.labelSlotted.innerText = this.getAttribute("label")
|
this.labelSlotted.innerText = this.getAttribute("label")
|
||||||
this.appendChild(this.labelSlotted)
|
this.appendChild(this.labelSlotted)
|
||||||
|
|
||||||
shadow.appendChild(instanceDocument)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,12 +80,8 @@ export class NodeFileElement extends NodeElement {
|
||||||
nameSlotted
|
nameSlotted
|
||||||
contentsSlotted
|
contentsSlotted
|
||||||
|
|
||||||
// noinspection JSUnusedGlobalSymbols
|
onConnect() {
|
||||||
connectedCallback() {
|
this.instanceElement = this.instance.querySelector(".node-file")
|
||||||
const instanceDocument = NodeFileElement.getTemplate().content.cloneNode(true)
|
|
||||||
const shadow = this.attachShadow({ mode: "open" })
|
|
||||||
|
|
||||||
this.instanceElement = instanceDocument.querySelector(".node-file")
|
|
||||||
|
|
||||||
this.instanceElement.style.setProperty("left", `${this.getAttribute("x")}px`)
|
this.instanceElement.style.setProperty("left", `${this.getAttribute("x")}px`)
|
||||||
this.instanceElement.style.setProperty("top", `${this.getAttribute("y")}px`)
|
this.instanceElement.style.setProperty("top", `${this.getAttribute("y")}px`)
|
||||||
|
@ -111,12 +101,10 @@ export class NodeFileElement extends NodeElement {
|
||||||
this.contentsSlotted = document.createElement(customElements.getName(DisplayElement))
|
this.contentsSlotted = document.createElement(customElements.getName(DisplayElement))
|
||||||
this.contentsSlotted.slot = "node-contents"
|
this.contentsSlotted.slot = "node-contents"
|
||||||
|
|
||||||
const firstDisplayAncestor = DisplayElement.findFirstDisplayAncestor(this)
|
const firstDisplayAncestor = this.findFirstAncestor(DisplayElement)
|
||||||
this.contentsSlotted.setAttribute("vref", firstDisplayAncestor.getAttribute("vref"))
|
this.contentsSlotted.setAttribute("vref", firstDisplayAncestor.getAttribute("vref"))
|
||||||
this.contentsSlotted.setAttribute("wref", this.getAttribute("file"))
|
this.contentsSlotted.setAttribute("wref", this.getAttribute("file"))
|
||||||
this.appendChild(this.contentsSlotted)
|
this.appendChild(this.contentsSlotted)
|
||||||
|
|
||||||
shadow.appendChild(instanceDocument)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,12 +116,8 @@ export class NodeTextElement extends NodeElement {
|
||||||
instanceElement
|
instanceElement
|
||||||
contentsSlotted
|
contentsSlotted
|
||||||
|
|
||||||
// noinspection JSUnusedGlobalSymbols
|
onConnected() {
|
||||||
connectedCallback() {
|
this.instanceElement = this.instance.querySelector(".node-text")
|
||||||
const instanceDocument = NodeTextElement.getTemplate().content.cloneNode(true)
|
|
||||||
const shadow = this.attachShadow({ mode: "open" })
|
|
||||||
|
|
||||||
this.instanceElement = instanceDocument.querySelector(".node-text")
|
|
||||||
|
|
||||||
this.instanceElement.style.setProperty("left", `${this.getAttribute("x")}px`)
|
this.instanceElement.style.setProperty("left", `${this.getAttribute("x")}px`)
|
||||||
this.instanceElement.style.setProperty("top", `${this.getAttribute("y")}px`)
|
this.instanceElement.style.setProperty("top", `${this.getAttribute("y")}px`)
|
||||||
|
@ -145,7 +129,5 @@ export class NodeTextElement extends NodeElement {
|
||||||
this.contentsSlotted.slot = "node-contents"
|
this.contentsSlotted.slot = "node-contents"
|
||||||
this.contentsSlotted.setAttribute("contents", this.getAttribute("text"))
|
this.contentsSlotted.setAttribute("contents", this.getAttribute("text"))
|
||||||
this.appendChild(this.contentsSlotted)
|
this.appendChild(this.contentsSlotted)
|
||||||
|
|
||||||
shadow.appendChild(instanceDocument)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue