Class DomElement

All Implemented Interfaces:
DomAttributes, Cloneable

@NoTests public class DomElement extends DomContainer implements DomAttributes
Element in PushMode DOM tree. Every element inherits from DomContainer, which means it has a list of DomContent children. In addition, element has attributes, attached listeners, and some special properties like tagname(), id(), and key().

DomElement cannot be directly instantiated by calling constructor DomElement(String). Application code can instantiate elements more intuitively using Html class. Attributes can be set by calling specialized fluent setters inherited from DomAttributes.

Every element can have an id(). Element ID is serialized as an id attribute in HTML. Element ID has a special meaning in PushMode. Listeners require the element to have an ID. Listeners on ID-less elements are ignored. ID is also the default value of key().

Every element can have a key(). It is the same as id() by default, but it can be set separately via key(String). While id() is sent to the browser and it should be unique in the document, key() is used only server-side and it only needs to be unique among sibling elements. It is used in hierarchical DOM diff to pair corresponding elements in cases where some DOM nodes have been inserted or removed from parent's child list. If neither key() nor id() is specified, DOM diff uses element position to pair elements in compared DOM trees, which might result in unnecessarily big diffs if an element is inserted at the beginning of a long list. Absence of key() thus doesn't impact functionality, only performance. And even then it matters only if siblings are inserted or removed.

In order to provide interactivity for elements, application can call onX() methods to add event handlers or call binding overrides for two-way attributes like e.g. value attribute on <input> element.

DomElement is not thread-safe. Concurrent writes will corrupt internal state. It is however safe for multiple threads to read the same DomElement as far as there are no concurrent writers. Application can freeze() DOM subtree to prevent its accidental modification. This is particularly useful for DOM trees in caches that are likely to be read by multiple threads.

  • Constructor Details

    • DomElement

      @NoDocs public DomElement(String tagname)
    • DomElement

      public DomElement(DomElement other)
      Creates deep unfrozen copy of another element.
      Parameters:
      other - element to clone
      Throws:
      NullPointerException - if the parameter is null
  • Method Details

    • tagname

      @NoDocs public String tagname()
    • id

      public String id()
      Gets element ID. This method returns element ID set via id(String). ID is null by default.
      Returns:
      element ID
    • id

      public DomElement id(String id)
      Sets element's ID. Once set, the ID is available from id() method.

      Element ID is serialized as the id attribute in HTML. It must therefore fulfill criteria for proper element ID in HTML, which most importantly means the ID should be unique in the document. PushMode however doesn't check whether the ID is really unique and instead takes some steps to tolerate accidental duplicates. This method only checks for an empty string and treats it as null.

      Element ID has a special meaning in PushMode. Listeners require the element to have an ID. Listeners on ID-less elements are ignored. DOM diffing algorithm also uses ID when key() is not set.

      Internally, ID gets its own field in the class unlike other attributes. This makes access to ID much faster than access to other attributes.

      Parameters:
      id - new element ID
      Returns:
      this
      Throws:
      IllegalStateException - if element is frozen
    • key

      public String key()
      Gets element's pairing key. This method returns element key set via key(String).
      Returns:
      element's key
    • key

      public DomElement key(String key)
      Sets element's pairing key. Key, if set, must be unique among siblings in the DOM tree. Once set, the key is available from key().

      While id() is sent to the browser and it should be unique in the document, key() is used only server-side and it only needs to be unique among sibling elements.

      Key is used in hierarchical DOM diff to pair corresponding elements in cases where some DOM nodes have been inserted or removed from parent's child list. If key() is null, DOM diff falls back to element's id(). If that is null too, DOM diff uses element position to pair elements in compared DOM trees, which might result in unnecessarily big diffs if an element is inserted at the beginning of a long list. Absence of key thus doesn't impact functionality, only performance. And even then it matters only if siblings are inserted or removed.

      Parameters:
      key - new element key or null
      Returns:
      this
      Throws:
      IllegalStateException - if this element is frozen
    • rawAttributes

      @DraftApi @NoDocs public String[] rawAttributes()
    • rawAttributes

      @DraftApi @NoDocs public void rawAttributes(String[] attributes)
    • unset

      @NoDocs public DomElement unset(String name)
      Specified by:
      unset in interface DomAttributes
    • set

      @NoDocs public DomElement set(String name, String value)
      Specified by:
      set in interface DomAttributes
    • set

      @NoDocs public DomElement set(String name, boolean value)
      Specified by:
      set in interface DomAttributes
    • set

      @NoDocs public DomElement set(String name)
      Specified by:
      set in interface DomAttributes
    • set

      @NoDocs public DomElement set(String name, int value)
      Specified by:
      set in interface DomAttributes
    • set

      @NoDocs public DomElement set(String name, double value)
      Specified by:
      set in interface DomAttributes
    • set

      @NoDocs public DomElement set(DomAttribute attribute)
      Specified by:
      set in interface DomAttributes
    • set

      @NoDocs @DraftApi("should be probably Collection instead of Iterable") public DomElement set(Iterable<DomAttribute> attributes)
    • set

      @NoDocs public DomElement set(Stream<DomAttribute> attributes)
    • attributes

      @NoDocs public List<DomAttribute> attributes()
      Specified by:
      attributes in interface DomAttributes
    • attribute

      @NoDocs public DomAttribute attribute(String name)
      Specified by:
      attribute in interface DomAttributes
    • attributeAsString

      @NoDocs public String attributeAsString(String name)
      Specified by:
      attributeAsString in interface DomAttributes
    • attributeAsBoolean

      @NoDocs public boolean attributeAsBoolean(String name)
      Specified by:
      attributeAsBoolean in interface DomAttributes
    • attributeAsInt

      @NoDocs public OptionalInt attributeAsInt(String name)
      Specified by:
      attributeAsInt in interface DomAttributes
    • attributeAsDouble

      @NoDocs public OptionalDouble attributeAsDouble(String name)
      Specified by:
      attributeAsDouble in interface DomAttributes
    • rawListeners

      @DraftApi @NoDocs public DomListener[] rawListeners()
    • rawListeners

      @DraftApi @NoDocs public void rawListeners(DomListener[] listeners)
    • subscribe

      @DraftApi @NoDocs public DomElement subscribe(DomListener listener)
    • listeners

      @DraftApi @NoDocs public List<DomListener> listeners()
    • add

      public DomElement add(DomContent child)
      Adds new child node to this element.
      Overrides:
      add in class DomContainer
      Parameters:
      child - node to add (ignored if null)
      Returns:
      this
      Throws:
      IllegalStateException - if this element is frozen
      See Also:
    • add

      public <C extends DomContent> DomElement add(Collection<C> children)
      Adds all nodes in a Collection to this element.
      Overrides:
      add in class DomContainer
      Type Parameters:
      C - item type
      Parameters:
      children - collection of child nodes to add (ignored if null)
      Returns:
      this
      Throws:
      IllegalStateException - if this element is frozen
      See Also:
    • add

      public <C extends DomContent> DomElement add(Stream<C> children)
      Adds all nodes in a Stream to this element.
      Overrides:
      add in class DomContainer
      Type Parameters:
      C - item type
      Parameters:
      children - Stream of child nodes to add (ignored if null)
      Returns:
      this
      Throws:
      IllegalStateException - if this element is frozen
      See Also:
    • add

      public DomElement add(String text)
      Adds literal text to this element The text is first wrapped in DomText. If the text is null or empty, this method has no effect. If there is already some text at the end of this element, this method replaces it with concatenation with the supplied text.
      Overrides:
      add in class DomContainer
      Parameters:
      text - text to add (ignored if null or empty)
      Returns:
      this
      Throws:
      IllegalStateException - if this element is frozen
      See Also:
    • descendantsAndSelf

      @NoDocs public Stream<DomElement> descendantsAndSelf()
    • clone

      public DomElement clone()
      Creates deep unfrozen clone of this element. All child nodes are cloned recursively. The clone is completely independent of this element.
      Specified by:
      clone in class DomContainer
      Returns:
      deep mutable clone
    • equals

      public boolean equals(Object object)
      Compares two elements. This method compares tagname(), link #id()}, key(), attributes, listeners, and element's children. Children are compared recursively by calling their DomContent.equals(Object) methods. If the only difference is that one of the elements is frozen and the other is not, this method returns true. Order of attributes and listeners is significant. Listeners must have identical callback pointers to compare equal.
      Overrides:
      equals in class DomContainer
      Parameters:
      object - object to compare this element with
      Returns:
      true if the two elements are equal, false otherwise
    • hashCode

      public int hashCode()
      Computes deep hash code of the element. Hash code changes with tagname(), link #id()}, key(), attributes, listeners, and element's children Freezing the element doesn't change its hash code. Order of attributes and listeners is significant. Listeners must have identical callback pointers to have the same hash code.
      Overrides:
      hashCode in class DomContainer
      Returns:
      hash code of the element
    • assign

      @NoDocs public DomElement assign(DomElement other)
    • freeze

      public DomElement freeze()
      Protects this element from further modification. For more information, use cases, and thread safety, see DomContent.freeze().
      Overrides:
      freeze in class DomContainer
      Returns:
      this
    • toPoster

      @NoDocs public DomElement toPoster()
    • onclick

      @DraftApi public DomElement onclick(Runnable handler)
      Adds event handler for click event. Single event can have multiple event handlers. This method adds new event handler to the end of the list. Event handlers are executed in order.
      Parameters:
      handler - Event handler to add. If null, an empty event handler is added.
      Returns:
      this
    • onchange

      @DraftApi public DomElement onchange(Runnable handler)
      Adds event handler for change event. Single event can have multiple event handlers. This method adds new event handler to the end of the list. Event handlers are executed in order.
      Parameters:
      handler - Event handler to add. If null, an empty event handler is added.
      Returns:
      this
    • oninput

      @DraftApi public DomElement oninput(Runnable handler)
      Adds event handler for input event. Single event can have multiple event handlers. This method adds new event handler to the end of the list. Event handlers are executed in order.
      Parameters:
      handler - Event handler to add. If null, an empty event handler is added.
      Returns:
      this
    • checked

      @DraftApi public DomElement checked(boolean value, Consumer<Boolean> setter)
      Sets up two-way binding on attribute checked. Changes in the attribute are synchronized both ways between the client and the server. When parameter value changes between two invocations of PushPage.document(), the change is sent to the client. When user's actions cause the browser to change client-side value of the attribute, PushMode javascript sends the change to the server, which then invokes callback specified in setter parameter.

      When setter completes, the next invocation of PushPage.document() should set value parameter to the same value that was passed to the setter. If the value is different, PushMode assumes that setter has performed coercion of the value. Coerced value is then sent to the client where it replaces user's input.

      Bindings require id() to be set. Bindings on elements with null ID are ignored.

      Parameters:
      value - Server-supplied value of the attribute.
      setter - Callback accepting the most recent value available on the client side.
      Returns:
      this
      Throws:
      NullPointerException - The setter parameter is null.
    • checked

      @DraftApi public DomElement checked(Boolean value, Consumer<Boolean> setter)
      Sets up two-way binding on attribute checked. Changes in the attribute are synchronized both ways between the client and the server. When parameter value changes between two invocations of PushPage.document(), the change is sent to the client. When user's actions cause the browser to change client-side value of the attribute, PushMode javascript sends the change to the server, which then invokes callback specified in setter parameter.

      When setter completes, the next invocation of PushPage.document() should set value parameter to the same value that was passed to the setter. If the value is different, PushMode assumes that setter has performed coercion of the value. Coerced value is then sent to the client where it replaces user's input.

      Bindings require id() to be set. Bindings on elements with null ID are ignored.

      Parameters:
      value - Server-supplied value of the attribute. If null, false is substituted by this method.
      setter - Callback accepting the most recent value available on the client side.
      Returns:
      this
      Throws:
      NullPointerException - The setter parameter is null.
    • value

      @DraftApi public DomElement value(String value, Consumer<String> setter)
      Sets up two-way binding on attribute value. Changes in the attribute are synchronized both ways between the client and the server. When parameter value changes between two invocations of PushPage.document(), the change is sent to the client. When user's actions cause the browser to change client-side value of the attribute, PushMode javascript sends the change to the server, which then invokes callback specified in setter parameter.

      When setter completes, the next invocation of PushPage.document() should set value parameter to the same value that was passed to the setter. If the value is different, PushMode assumes that setter has performed coercion of the value. Coerced value is then sent to the client where it replaces user's input.

      Bindings require id() to be set. Bindings on elements with null ID are ignored.

      Parameters:
      value - Server-supplied value of the attribute. If null, empty string is substituted by this method.
      setter - Callback accepting the most recent value available on the client side.
      Returns:
      this
      Throws:
      NullPointerException - The setter parameter is null.
    • fromXml

      @NoDocs public static DomElement fromXml(Element xml)
    • fromXml

      @NoDocs public static DomElement fromXml(String serialized)