#----------------------------------------------------------------------------- # Copyright (c) Anaconda, Inc., and Bokeh Contributors. # All rights reserved. # # The full license is in the file LICENSE.txt, distributed with this software. #----------------------------------------------------------------------------- """ An abstraction over the document object model (DOM). """ #----------------------------------------------------------------------------- # Boilerplate #----------------------------------------------------------------------------- from __future__ import annotations import logging # isort:skip log = logging.getLogger(__name__) #----------------------------------------------------------------------------- # Imports #----------------------------------------------------------------------------- # Standard library imports from typing import Any # Bokeh imports from ..core.has_props import HasProps, abstract from ..core.properties import ( Bool, Dict, Either, Instance, List, Required, String, ) from ..core.property.bases import Init from ..core.property.singletons import Intrinsic from ..core.validation import error from ..core.validation.errors import NOT_A_PROPERTY_OF from ..model import Model, Qualified from .css import Styles from .ui.ui_element import UIElement #----------------------------------------------------------------------------- # Globals and constants #----------------------------------------------------------------------------- __all__ = ( "Div", "HTML", "Span", "Table", "TableRow", "Text", ) #----------------------------------------------------------------------------- # General API #----------------------------------------------------------------------------- @abstract class DOMNode(Model, Qualified): """ Base class for DOM nodes. """ # explicit __init__ to support Init signatures def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) class Text(DOMNode): """ DOM text node. """ # explicit __init__ to support Init signatures def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) content = String("") @abstract class DOMElement(DOMNode): """ Base class for DOM elements. """ # explicit __init__ to support Init signatures def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) style = Either(Instance(Styles), Dict(String, String), default={}) children = List(Either(String, Instance(DOMNode), Instance(UIElement)), default=[]) class Span(DOMElement): # explicit __init__ to support Init signatures def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) class Div(DOMElement): # explicit __init__ to support Init signatures def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) class Table(DOMElement): # explicit __init__ to support Init signatures def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) class TableRow(DOMElement): # explicit __init__ to support Init signatures def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) @abstract class Action(Model, Qualified): # explicit __init__ to support Init signatures def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) class Template(DOMElement): # explicit __init__ to support Init signatures def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) actions = List(Instance(Action)) class ToggleGroup(Action): # explicit __init__ to support Init signatures def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) groups = List(Instance(".models.renderers.RendererGroup")) @abstract class Placeholder(DOMNode): # explicit __init__ to support Init signatures def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) class ValueOf(Placeholder): """ A placeholder for the value of a model's property. """ def __init__(self, obj: Init[HasProps] = Intrinsic, attr: Init[str] = Intrinsic, **kwargs) -> None: super().__init__(obj=obj, attr=attr, **kwargs) obj: HasProps = Required(Instance(HasProps), help=""" The object whose property will be observed. """) attr: str = Required(String, help=""" The name of the property whose value will be observed. """) @error(NOT_A_PROPERTY_OF) def _check_if_an_attribute_is_a_property_of_a_model(self): if self.obj.lookup(self.attr, raises=False): return None else: return f"{self.attr} is not a property of {self.obj}" class Index(Placeholder): # explicit __init__ to support Init signatures def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) class ValueRef(Placeholder): # explicit __init__ to support Init signatures def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) field = Required(String) class ColorRef(ValueRef): # explicit __init__ to support Init signatures def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) hex = Bool(default=True) swatch = Bool(default=True) class HTML(DOMNode): """ A parsed HTML fragment with optional references to DOM nodes and UI elements. """ def __init__(self, *html: str | DOMNode | UIElement, **kwargs: Any) -> None: if html and "html" in kwargs: raise TypeError("'html' argument specified multiple times") processed_html: Init[str | list[str | DOMNode | UIElement]] if not html: processed_html = kwargs.pop("html", Intrinsic) else: processed_html = list(html) super().__init__(html=processed_html, **kwargs) html = Required(Either(String, List(Either(String, Instance(DOMNode), Instance(UIElement)))), help=""" Either a parsed HTML string with optional references to Bokeh objects using ```` syntax. Or a list of parsed HTML interleaved with Bokeh's objects. Any DOM node or UI element (even a plot) can be referenced here. """) refs = List(Either(String, Instance(DOMNode), Instance(UIElement)), default=[], help=""" A collection of objects referenced by ```` from `the `html`` property. Objects already included by instance in ``html`` don't have to be repeated here. """) #----------------------------------------------------------------------------- # Dev API #----------------------------------------------------------------------------- #----------------------------------------------------------------------------- # Private API #----------------------------------------------------------------------------- #----------------------------------------------------------------------------- # Code #-----------------------------------------------------------------------------