Use web components for SVG icons

This commit is contained in:
2019-08-30 16:04:28 +09:00
parent b32005cdee
commit d974156d68
13 changed files with 113 additions and 61 deletions

View File

@ -13,8 +13,9 @@ import ServiceWorkerManager from "./ServiceWorkerManager"
import ServerEvents from "./ServerEvents"
import { displayAiringDate, displayDate, displayTime } from "./DateView"
import { findAll, supportsWebP, requestIdleCallback, swapElements, delay, findAllInside } from "./Utils"
import * as actions from "./Actions"
import ToolTip from "./Elements/tool-tip/tool-tip"
import * as actions from "./Actions"
import * as WebComponents from "./WebComponents"
export default class AnimeNotifier {
app: Application
@ -102,7 +103,7 @@ export default class AnimeNotifier {
}
// Web components
this.registerWebComponents()
WebComponents.register()
// Tooltip
this.tip = new ToolTip()
@ -210,23 +211,6 @@ export default class AnimeNotifier {
}
}
registerWebComponents() {
if(!("customElements" in window)) {
console.warn("Web components not supported in your current browser")
return
}
// Custom element names must have a dash in their name
const elements = new Map<string, Function>([
["tool-tip", ToolTip]
])
// Register all custom elements
for(const [tag, definition] of elements.entries()) {
window.customElements.define(tag, definition)
}
}
applyPageTitle() {
let headers = document.getElementsByTagName("h1")

View File

@ -147,6 +147,12 @@ export default class Diff {
}
}
// Never diff the contents of web components
if(a.nodeName.includes("-")) {
continue
}
// Child nodes
Diff.childNodes(a, b)
}
}

View File

@ -0,0 +1,10 @@
svg-icon
display inline-block
width 1em
height 1em
svg
display inherit
width 1em
height 1em
fill currentColor

View File

@ -0,0 +1,48 @@
import Diff from "scripts/Diff"
export default class SVGIcon extends HTMLElement {
static cache = new Map<string, Promise<string>>()
static get observedAttributes() {
return ["name"]
}
attributeChangedCallback(attrName) {
if(attrName === "name") {
this.render()
}
}
async render() {
let cache = SVGIcon.cache[this.name]
if(cache) {
let text = await cache
Diff.mutations.queue(() => this.innerHTML = text)
return
}
SVGIcon.cache[this.name] = new Promise(async (resolve, reject) => {
let url = `//media.notify.moe/images/icons/${this.name}.svg`
let response = await fetch(url)
if(!response.ok) {
console.warn(`Failed loading SVG icon: ${url}`)
reject(response.statusText)
return
}
let text = await response.text()
Diff.mutations.queue(() => this.innerHTML = text)
resolve(text)
})
}
get name() {
return this.getAttribute("name") || ""
}
set name(value: string) {
this.setAttribute("name", value)
}
}

20
scripts/WebComponents.ts Normal file
View File

@ -0,0 +1,20 @@
import ToolTip from "./Elements/tool-tip/tool-tip"
import SVGIcon from "./Elements/svg-icon/svg-icon"
export function register() {
if(!("customElements" in window)) {
console.warn("Web components not supported in your current browser")
return
}
// Custom element names must have a dash in their name
const elements = new Map<string, Function>([
["tool-tip", ToolTip],
["svg-icon", SVGIcon]
])
// Register all custom elements
for(const [tag, definition] of elements.entries()) {
window.customElements.define(tag, definition)
}
}