UNPKG

@bokeh/bokehjs

Version:

Interactive, novel data visualization

114 lines 3.83 kB
import { DOMElement, DOMElementView } from "./dom_element"; import { UIElement } from "../ui/ui_element"; import { build_views, remove_views } from "../../core/build_views"; import { span } from "../../core/dom"; import { assert } from "../../core/util/assert"; import { isString, isArray } from "../../core/util/types"; import { Str, Ref, Or } from "../../core/kinds"; const HTMLRef = Or(Ref(DOMElement), Ref(UIElement)); const HTMLMarkup = Str; export class HTMLView extends DOMElementView { static __name__ = "HTMLView"; _refs = new Map(); get refs() { const { html, refs } = this.model; return [ ...isArray(html) ? html.filter((item) => !isString(item)) : [], ...refs, ]; } async _update_refs() { await build_views(this._refs, this.refs); } children_views() { return [...super.children_views(), ...this._refs.values()]; } async lazy_initialize() { await super.lazy_initialize(); await this._update_refs(); } remove() { remove_views(this._refs); super.remove(); } connect_signals() { super.connect_signals(); const { refs, html } = this.model.properties; this.on_change([refs, html], async () => { await this._update_refs(); this.render(); }); } render() { super.render(); const html = (() => { const { html } = this.model; if (isArray(html)) { return html.map((item) => isString(item) ? item : `<ref id="${item.id}"></ref>`).join(""); } else { return html; } })(); const nodes = (() => { if (isString(html)) { return this.parse_html(html); } else { return [html]; } })(); this.el.append(...nodes); this.finish(); } parse_html(html) { const parser = new DOMParser(); const document = parser.parseFromString(html, "text/html"); const iter = document.createNodeIterator(document, NodeFilter.SHOW_ELEMENT, (node) => { return node.nodeName.toLowerCase() == "ref" ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT; }); let node; next_node: while ((node = iter.nextNode()) != null) { assert(node instanceof Element); const id = node.getAttribute("id"); if (id != null) { for (const [model, view] of this._refs) { if (model.id == id) { view.render(); node.replaceWith(view.el); continue next_node; } } node.replaceWith(span(`<not found: id=${id}>`)); continue; } const name = node.getAttribute("name"); if (name != null) { for (const [model, view] of this._refs) { if (model.name == name) { view.render(); node.replaceWith(view.el); continue next_node; } } node.replaceWith(span(`<not found: name=${name}>`)); continue; } } return [...document.body.childNodes]; } } export class HTML extends DOMElement { static __name__ = "HTML"; constructor(attrs) { super(attrs); } static { this.prototype.default_view = HTMLView; this.define(({ Node, List, Or }) => ({ html: [Or(Node, HTMLMarkup, List(Or(HTMLMarkup, HTMLRef)))], refs: [List(HTMLRef), []], })); } } //# sourceMappingURL=html.js.map