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 Detail

      • 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 Detail

      • 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)
      • rawListeners

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

        @DraftApi
        @NoDocs
        public void rawListeners​(DomListener[] listeners)
      • 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:
        add(DomContent)
      • 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
      • 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.