Refactored element creation (now centralized)

This commit is contained in:
squidfunk 2020-03-29 14:18:18 +02:00
parent 7e42f78e92
commit eb0e8ac85d
12 changed files with 50 additions and 23 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
{ {
"assets/javascripts/bundle.js": "assets/javascripts/bundle.d8f7c943.min.js", "assets/javascripts/bundle.js": "assets/javascripts/bundle.f34104ec.min.js",
"assets/javascripts/bundle.js.map": "assets/javascripts/bundle.d8f7c943.min.js.map", "assets/javascripts/bundle.js.map": "assets/javascripts/bundle.f34104ec.min.js.map",
"assets/javascripts/vendor.js": "assets/javascripts/vendor.c1fcc1cc.min.js", "assets/javascripts/vendor.js": "assets/javascripts/vendor.c1fcc1cc.min.js",
"assets/javascripts/vendor.js.map": "assets/javascripts/vendor.c1fcc1cc.min.js.map", "assets/javascripts/vendor.js.map": "assets/javascripts/vendor.c1fcc1cc.min.js.map",
"assets/javascripts/worker/search.js": "assets/javascripts/worker/search.3bc815f0.min.js", "assets/javascripts/worker/search.js": "assets/javascripts/worker/search.3bc815f0.min.js",

View File

@ -179,7 +179,7 @@
</div> </div>
{% block scripts %} {% block scripts %}
<script src="{{ 'assets/javascripts/vendor.c1fcc1cc.min.js' | url }}"></script> <script src="{{ 'assets/javascripts/vendor.c1fcc1cc.min.js' | url }}"></script>
<script src="{{ 'assets/javascripts/bundle.d8f7c943.min.js' | url }}"></script> <script src="{{ 'assets/javascripts/bundle.f34104ec.min.js' | url }}"></script>
{%- set translations = {} -%} {%- set translations = {} -%}
{%- for key in [ {%- for key in [
"clipboard.copy", "clipboard.copy",

View File

@ -90,6 +90,21 @@ export function getElements<T extends HTMLElement>(
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/**
* Create an element
*
* @template T - Tag name type
*
* @param tagName - Tag name
*
* @return Element
*/
export function createElement<
T extends keyof HTMLElementTagNameMap
>(tagName: T): HTMLElementTagNameMap[T] {
return document.createElement(tagName)
}
/** /**
* Replace an element with another element * Replace an element with another element
* *

View File

@ -23,6 +23,8 @@
import { Observable, fromEvent } from "rxjs" import { Observable, fromEvent } from "rxjs"
import { filter, map, share, startWith } from "rxjs/operators" import { filter, map, share, startWith } from "rxjs/operators"
import { createElement } from "browser"
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* Functions * Functions
* ------------------------------------------------------------------------- */ * ------------------------------------------------------------------------- */
@ -47,7 +49,7 @@ export function getLocationHash(): string {
* @param hash - Location hash * @param hash - Location hash
*/ */
export function setLocationHash(hash: string): void { export function setLocationHash(hash: string): void {
const el = document.createElement("a") const el = createElement("a")
el.href = hash el.href = hash
el.addEventListener("click", ev => ev.stopPropagation()) el.addEventListener("click", ev => ev.stopPropagation())
el.click() el.click()

View File

@ -29,6 +29,8 @@ import {
tap tap
} from "rxjs/operators" } from "rxjs/operators"
import { createElement } from "browser"
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* Types * Types
* ------------------------------------------------------------------------- */ * ------------------------------------------------------------------------- */
@ -57,7 +59,7 @@ export function setupDialog(
const dialog$ = new Subject<string>() const dialog$ = new Subject<string>()
/* Create dialog */ /* Create dialog */
const dialog = document.createElement("div") // TODO: improve scoping const dialog = createElement("div") // TODO: improve scoping
dialog.classList.add("md-dialog", "md-typeset") dialog.classList.add("md-dialog", "md-typeset")
/* Display dialog */ /* Display dialog */

View File

@ -23,7 +23,11 @@
import { Observable } from "rxjs" import { Observable } from "rxjs"
import { map, skip, withLatestFrom } from "rxjs/operators" import { map, skip, withLatestFrom } from "rxjs/operators"
import { getElements } from "browser" import {
createElement,
getElements,
replaceElement
} from "browser"
import { useComponent } from "components" import { useComponent } from "components"
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
@ -63,10 +67,10 @@ export function patchScripts(
els$.subscribe(els => { els$.subscribe(els => {
for (const el of els) { for (const el of els) {
if (el.src || /(^|\/javascript)$/i.test(el.type)) { if (el.src || /(^|\/javascript)$/i.test(el.type)) {
const script = document.createElement("script") const script = createElement("script")
const key = el.src ? "src" : "textContent" const key = el.src ? "src" : "textContent"
script[key] = el[key]! script[key] = el[key]!
el.replaceWith(script) replaceElement(el, script)
} }
} }
}) })

View File

@ -23,7 +23,11 @@
import { Observable } from "rxjs" import { Observable } from "rxjs"
import { map } from "rxjs/operators" import { map } from "rxjs/operators"
import { getElements } from "browser" import {
createElement,
getElements,
replaceElement
} from "browser"
import { renderTable } from "templates" import { renderTable } from "templates"
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
@ -52,15 +56,15 @@ interface MountOptions {
export function patchTables( export function patchTables(
{ document$ }: MountOptions { document$ }: MountOptions
): void { ): void {
const sentinel = document.createElement("table") const sentinel = createElement("table")
document$ document$
.pipe( .pipe(
map(() => getElements<HTMLTableElement>("table:not([class])")) map(() => getElements<HTMLTableElement>("table:not([class])"))
) )
.subscribe(els => { .subscribe(els => {
for (const el of els) { for (const el of els) {
el.replaceWith(sentinel) replaceElement(el, sentinel)
sentinel.replaceWith(renderTable(el)) replaceElement(sentinel, renderTable(el))
} }
}) })
} }

View File

@ -54,21 +54,21 @@ type Child =
/** /**
* Create an element * Create an element
* *
* @param tag - HTML or SVG tag * @param tagName - HTML or SVG tag
* *
* @return Element * @return Element
*/ */
function createElement(tag: string): HTMLElement | SVGElement { function createElement(tagName: string): HTMLElement | SVGElement {
switch (tag) { switch (tagName) {
/* SVG elements */ /* SVG elements */
case "svg": case "svg":
case "path": case "path":
return document.createElementNS("http://www.w3.org/2000/svg", tag) return document.createElementNS("http://www.w3.org/2000/svg", tagName)
/* HTML elements */ /* HTML elements */
default: default:
return document.createElement(tag) return document.createElement(tagName)
} }
} }
@ -137,16 +137,16 @@ function appendChild(
/** /**
* JSX factory * JSX factory
* *
* @param tag - HTML or SVG tag * @param tagName - HTML or SVG tag
* @param attributes - HTML attributes * @param attributes - HTML attributes
* @param children - Child elements * @param children - Child elements
* *
* @return Element * @return Element
*/ */
export function h( export function h(
tag: string, attributes: Attributes | null, ...children: Child[] tagName: string, attributes: Attributes | null, ...children: Child[]
): HTMLElement | SVGElement { ): HTMLElement | SVGElement {
const el = createElement(tag) const el = createElement(tagName)
/* Set attributes, if any */ /* Set attributes, if any */
if (attributes) if (attributes)