UNPKG

@bokeh/bokehjs

Version:

Interactive, novel data visualization

110 lines 3.9 kB
import { DOMNode, DOMNodeView } from "./dom_node"; import { StylesLike } from "../ui/styled_element"; import { UIElement } from "../ui/ui_element"; import { build_views, remove_views } from "../../core/build_views"; import { isString } from "../../core/util/types"; import { apply_styles } from "../../core/css"; import { empty, bounding_box } from "../../core/dom"; export class DOMElementView extends DOMNodeView { static __name__ = "DOMElementView"; get bbox() { return bounding_box(this.el).relative(); } get self_target() { return this.el; } child_views = new Map(); *children() { yield* super.children(); yield* this.child_views.values(); } async lazy_initialize() { await super.lazy_initialize(); const children = this.model.children.filter((obj) => !isString(obj)); await build_views(this.child_views, children, { parent: this }); } remove() { remove_views(this.child_views); super.remove(); } connect_signals() { super.connect_signals(); const { children, style } = this.model.properties; this.on_change(children, async () => { await this._update_children(); }); this.on_change(style, () => { this.el.removeAttribute("style"); apply_styles(this.el.style, this.model.style); }); } async _build_children() { const children = this.model.children.filter((obj) => !isString(obj)); return await build_views(this.child_views, children, { parent: this }); } async _update_children() { const { created } = await this._build_children(); const created_elements = new Set(created); // First remove and then either reattach existing elements or render and // attach new elements, so that the order of children is consistent, while // avoiding expensive re-rendering of existing views. for (const element_view of this.child_views.values()) { element_view.el.remove(); } for (const child of this.model.children) { if (isString(child)) { const node = document.createTextNode(child); this.el.append(node); } else { const child_view = this.child_views.get(child); if (child_view == null) { continue; } const is_new = created_elements.has(child_view); const target = child_view.rendering_target() ?? this.self_target; if (is_new) { child_view.render_to(target); } else { target.append(child_view.el); } } } this.r_after_render(); } render() { empty(this.el); apply_styles(this.el.style, this.model.style); for (const child of this.model.children) { if (isString(child)) { const node = document.createTextNode(child); this.el.append(node); } else { const child_view = this.child_views.get(child); if (child_view == null) { continue; } const target = child_view.rendering_target() ?? this.self_target; child_view.render_to(target); } } this.finish(); } } export class DOMElement extends DOMNode { static __name__ = "DOMElement"; constructor(attrs) { super(attrs); } static { this.define(({ Str, List, Or, Ref }) => { return { style: [StylesLike, {}], children: [List(Or(Str, Ref(DOMNode), Ref(UIElement))), []], }; }); } } //# sourceMappingURL=dom_element.js.map