com.google.gwt.dom.client.Element.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gwt.dom.client.Element.java

Source

/*
 * Copyright 2008 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.dom.client;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Supplier;
import java.util.stream.Collectors;

import com.google.common.base.Preconditions;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JavascriptObjectEquivalent;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.EventListener;
import com.google.gwt.user.client.LocalDomDebug;
import com.google.gwt.user.client.ui.UIObject;

import cc.alcina.framework.common.client.util.Ax;
import cc.alcina.framework.common.client.util.CommonUtils;
import cc.alcina.framework.common.client.util.FormatBuilder;
import cc.alcina.framework.gwt.client.util.TextUtils;

/**
 * All HTML element interfaces derive from this class.
 */
public class Element extends Node implements DomElement {
    public static final String REMOTE_DEFINED = "__localdom-remote-defined";

    /**
     * Constant returned from {@link #getDraggable()}.
     */
    public static final String DRAGGABLE_AUTO = "auto";

    /**
     * Constant returned from {@link #getDraggable()}.
     */
    public static final String DRAGGABLE_FALSE = "false";

    /**
     * Constant returned from {@link #getDraggable()}.
     */
    public static final String DRAGGABLE_TRUE = "true";

    /**
     * Assert that the given {@link Node} is an {@link Element} and
     * automatically typecast it.
     */
    public static Element as(JavascriptObjectEquivalent o) {
        assert is(o);
        if (o instanceof EventTarget) {
            return ((EventTarget) o).cast();
        } else if (o instanceof JavaScriptObject) {
            JavaScriptObject jso = (JavaScriptObject) o;
            return LocalDom.nodeFor(jso);
        } else {
            return (Element) o;
        }
    }

    /**
     * Assert that the given {@link Node} is an {@link Element} and
     * automatically typecast it.
     */
    public static Element as(Node node) {
        assert is(node);
        return (Element) node;
    }

    /**
     * Determines whether the given {@link JavaScriptObject} can be cast to an
     * {@link Element}. A <code>null</code> object will cause this method to
     * return <code>false</code>.
     */
    public static boolean is(JavascriptObjectEquivalent o) {
        if (o instanceof EventTarget) {
            if (((EventTarget) o).is(Element.class)) {
                return true;
            } else {
                return false;
            }
        } else if (o instanceof JavaScriptObject) {
            JavaScriptObject jso = (JavaScriptObject) o;
            return ElementRemote.is(jso);
        } else {
            return o instanceof Element;
        }
    }

    /**
     * Determine whether the given {@link Node} can be cast to an
     * {@link Element}. A <code>null</code> node will cause this method to
     * return <code>false</code>.
     */
    public static boolean is(Node node) {
        return (node != null) && (node.getNodeType() == Node.ELEMENT_NODE);
    }

    private ElementLocal local;

    private DomElement remote;

    private Style style;

    public UIObject uiObject;

    public EventListener uiObjectListener;

    private boolean pendingResolution;

    protected Element() {
    }

    @Override
    public boolean addClassName(String className) {
        ensureRemoteCheck();
        boolean result = local().addClassName(className);
        remote().addClassName(className);
        return result;
    }

    @Override
    public void blur() {
        runIfWithRemote(false, () -> remote().blur());
    }

    @Override
    public <T extends JavascriptObjectEquivalent> T cast() {
        return (T) this;
    }

    public void cloneLocalStyle(Element from) {
        if (from.hasStyle()) {
            getStyle().cloneStyleFrom(from.getStyle());
        }
    }

    public String debugLocalDom() {
        return local().provideLocalDomTree();
    }

    @Override
    public void dispatchEvent(NativeEvent evt) {
        remote().dispatchEvent(evt);
    }

    public String dump(boolean linkToRemote) {
        // Ax.out("\n\n**dump:\n");
        // if (linkedToRemote()) {
        // Ax.out("Outer html: \n%s\n\n", typedRemote().getOuterHtml());
        // }
        StringBuilder stringBuilder = new StringBuilder();
        dumpLocal0(0, "0", linkToRemote, stringBuilder);
        return stringBuilder.toString();
    }

    @Override
    public Element elementFor() {
        return nodeFor();
    }

    @Override
    public void ensureId() {
        if (!linkedToRemote()) {
            local().ensureId();
        }
    }

    @Override
    public void focus() {
        ensureRemote().focus();
    }

    @Override
    public int getAbsoluteBottom() {
        return ensureRemote().getAbsoluteBottom();
    }

    @Override
    public int getAbsoluteLeft() {
        return ensureRemote().getAbsoluteLeft();
    }

    @Override
    public int getAbsoluteRight() {
        return ensureRemote().getAbsoluteRight();
    }

    @Override
    public int getAbsoluteTop() {
        return ensureRemote().getAbsoluteTop();
    }

    @Override
    public String getAttribute(String name) {
        return local().getAttribute(name);
    }

    @Override
    public Map<String, String> getAttributes() {
        return local().getAttributes();
    }

    @Override
    public Node getChild(int index) {
        return super.getChild(index);
    }

    public Element getChildElement(int index) {
        for (int idx = 0; idx < getChildCount(); idx++) {
            Node child = getChild(idx);
            if (child.provideIsElement()) {
                if (index-- == 0) {
                    return (Element) child;
                }
            }
        }
        return null;
    }

    public int getChildIndexLocal(Element child) {
        if (child.getParentElement() != this) {
            return -1;
        }
        return child.indexInParentChildren();
    }

    @Override
    public String getClassName() {
        if (DomState.domResolveSvgStyles && linkedToRemote()) {
            return getClassNameSvg();
        } else {
            return local().getClassName();
        }
    }

    @Override
    public int getClientHeight() {
        return remote().getClientHeight();
    }

    @Override
    public int getClientWidth() {
        return remote().getClientWidth();
    }

    @Override
    public String getDir() {
        return local().getDir();
    }

    @Override
    public String getDraggable() {
        return remote().getDraggable();
    }

    @Override
    public NodeList<Element> getElementsByTagName(String name) {
        ensureRemote();
        return remote().getElementsByTagName(name);
    }

    @Override
    public Element getFirstChildElement() {
        return local().getFirstChildElement();
    }

    @Override
    public String getId() {
        return local().getId();
    }

    @Override
    public String getInnerHTML() {
        return local().getInnerHTML();
    }

    @Override
    public String getInnerText() {
        return local().getInnerText();
    }

    @Override
    public String getLang() {
        return local().getLang();
    }

    @Override
    public Node getLastChild() {
        return local().getLastChild();
    }

    @Override
    public Node getNextSibling() {
        return local().getNextSibling();
    }

    @Override
    public Element getNextSiblingElement() {
        return local().getNextSiblingElement();
    }

    @Override
    public String getNodeName() {
        return local().getNodeName();
    }

    @Override
    public short getNodeType() {
        return local().getNodeType();
    }

    @Override
    public String getNodeValue() {
        return local().getNodeValue();
    }

    @Override
    public int getOffsetHeight() {
        return callWithRemoteOrDefault(true, () -> remote().getOffsetHeight(), 0);
    }

    @Override
    public int getOffsetLeft() {
        return callWithRemoteOrDefault(true, () -> remote().getOffsetLeft(), 0);
    }

    @Override
    public Element getOffsetParent() {
        return callWithRemoteOrDefault(true, () -> remote().getOffsetParent(), null);
    }

    @Override
    public int getOffsetTop() {
        return callWithRemoteOrDefault(true, () -> remote().getOffsetTop(), 0);
    }

    @Override
    public int getOffsetWidth() {
        return callWithRemoteOrDefault(true, () -> remote().getOffsetWidth(), 0);
    }

    @Override
    public String getOuterHtml() {
        return local().getOuterHtml();
    }

    @Override
    public Element getPreviousSiblingElement() {
        return local().getPreviousSiblingElement();
    }

    @Override
    public boolean getPropertyBoolean(String name) {
        return implForPropertyName(name).getPropertyBoolean(name);
    }

    @Override
    public double getPropertyDouble(String name) {
        return implForPropertyName(name).getPropertyDouble(name);
    }

    @Override
    public int getPropertyInt(String name) {
        return implForPropertyName(name).getPropertyInt(name);
    }

    @Override
    public JavaScriptObject getPropertyJSO(String name) {
        return remote().getPropertyJSO(name);
    }

    @Override
    public Object getPropertyObject(String name) {
        return implForPropertyName(name).getPropertyObject(name);
    }

    @Override
    public String getPropertyString(String name) {
        return implForPropertyName(name).getPropertyString(name);
    }

    @Override
    public int getScrollHeight() {
        return callWithRemoteOrDefault(true, () -> remote().getScrollHeight(), 0);
    }

    @Override
    public int getScrollLeft() {
        return callWithRemoteOrDefault(true, () -> remote().getScrollLeft(), 0);
    }

    @Override
    public int getScrollTop() {
        return callWithRemoteOrDefault(true, () -> remote().getScrollTop(), 0);
    }

    @Override
    public int getScrollWidth() {
        return callWithRemoteOrDefault(true, () -> remote().getScrollWidth(), 0);
    }

    @Override
    public String getString() {
        return local().getString();
    }

    @Override
    public Style getStyle() {
        if (style == null) {
            style = new Style(this);
        }
        return style;
    }

    @Override
    public int getTabIndex() {
        return local().getTabIndex();
    }

    @Override
    public String getTagName() {
        return local().getTagName();
    }

    @Override
    public String getTitle() {
        return local().getTitle();
    }

    @Override
    public boolean hasAttribute(String name) {
        return local().hasAttribute(name);
    }

    @Override
    public boolean hasClassName(String className) {
        return local().hasClassName(className);
    }

    public boolean hasStyle() {
        return style != null;
    }

    @Override
    public boolean hasTagName(String tagName) {
        return local().hasTagName(tagName);
    }

    public ElementImplAccess implAccess() {
        return new ElementImplAccess();
    }

    public int localEventBitsSunk() {
        return local().eventBits;
    }

    @Override
    public Element nodeFor() {
        return this;
    }

    @Override
    public void removeAttribute(String name) {
        ensureRemoteCheck();
        local().removeAttribute(name);
        remote().removeAttribute(name);
    }

    @Override
    public boolean removeClassName(String className) {
        ensureRemoteCheck();
        boolean result = local().removeClassName(className);
        remote().removeClassName(className);
        return result;
    }

    @Override
    public void replaceClassName(String oldClassName, String newClassName) {
        ensureRemoteCheck();
        local().replaceClassName(oldClassName, newClassName);
        remote().replaceClassName(oldClassName, newClassName);
    }

    /**
     * When it's quicker to redraw the whole DOM. Tree filtering springs to mind
     */
    public void resolvedToPending() {
        implAccess().resolvedToPending();
    }

    public void resolvePending() {
        pendingResolution = false;
    }

    public boolean resolveRemoteDefined() {
        if (getClassName().contains(REMOTE_DEFINED)) {
            Ax.out("resolve remote defined: %s", hashCode());
            ensureRemote();
            LocalDom.syncToRemote(this);
            UIObject.setStyleName(this, REMOTE_DEFINED, false);
            return true;
        } else {
            return false;
        }
    }

    @Override
    public void scrollIntoView() {
        runIfWithRemote(true, () -> remote().scrollIntoView());
    }

    @Override
    public void setAttribute(String name, String value) {
        String current = local().getAttribute(name);
        if (Objects.equals(current, value)) {
            return;
        }
        ensureRemoteCheck();
        local().setAttribute(name, value);
        remote().setAttribute(name, value);
    }

    @Override
    public void setClassName(String className) {
        String current = local().getClassName();
        if (Objects.equals(current, className)) {
            return;
        }
        ensureRemoteCheck();
        local().setClassName(className);
        remote().setClassName(className);
    }

    @Override
    public void setDir(String dir) {
        ensureRemoteCheck();
        local().setDir(dir);
        remote().setDir(dir);
    }

    @Override
    public void setDraggable(String draggable) {
        ensureRemoteCheck();
        local().setDraggable(draggable);
        remote().setDraggable(draggable);
    }

    @Override
    public void setId(String id) {
        ensureRemoteCheck();
        local().setId(id);
        remote().setId(id);
    }

    @Override
    public void setInnerHTML(String html) {
        ensureRemoteCheck();
        clearResolved();
        List<Node> oldChildren = getChildNodes().stream().collect(Collectors.toList());
        removeAllChildren();
        if (notPendingAndLinked()) {
            remote().setInnerHTML(html);
            // tbodies? foots? proudfeet?
            String remoteHtml = typedRemote().getInnerHTML0();
            local().setInnerHTML(remoteHtml);
            LocalDom.wasResolved(this);
        } else {
            local().setInnerHTML(html);
        }
        oldChildren.forEach(LocalDom::detach);
    }

    public void setInnerHTMLWithValidation(String html) {
        String validatedHtml = LocalDom.validateHtml(html);
        setInnerHTML(validatedHtml);
    }

    @Override
    public void setInnerSafeHtml(SafeHtml html) {
        setInnerSafeHtml(html, true);
    }

    @Override
    public void setInnerText(String text) {
        ensureRemoteCheck();
        clearResolved();
        List<Node> oldChildren = getChildNodes().stream().collect(Collectors.toList());
        removeAllChildren();
        if (notPendingAndLinked()) {
            remote().setInnerText(text);
            local().setInnerText(text);
            LocalDom.wasResolved(this);
        } else {
            local().setInnerText(text);
        }
        oldChildren.forEach(LocalDom::detach);
    }

    @Override
    public void setLang(String lang) {
        ensureRemoteCheck();
        local().setLang(lang);
        remote().setLang(lang);
    }

    @Override
    public void setNodeValue(String nodeValue) {
        ensureRemoteCheck();
        local().setNodeValue(nodeValue);
        remote().setNodeValue(nodeValue);
    }

    public void setOuterHtml(String html) {
        Preconditions.checkState(!linkedToRemote());
        local().setOuterHtml(html);
    }

    @Override
    public void setPropertyBoolean(String name, boolean value) {
        ensureRemoteCheck();
        local().setPropertyBoolean(name, value);
        remote().setPropertyBoolean(name, value);
    }

    @Override
    public void setPropertyDouble(String name, double value) {
        ensureRemoteCheck();
        local().setPropertyDouble(name, value);
        remote().setPropertyDouble(name, value);
    }

    @Override
    public void setPropertyInt(String name, int value) {
        ensureRemoteCheck();
        local().setPropertyInt(name, value);
        remote().setPropertyInt(name, value);
    }

    @Override
    public void setPropertyJSO(String name, JavaScriptObject value) {
        ensureRemoteCheck();
        local().setPropertyJSO(name, value);
        remote().setPropertyJSO(name, value);
    }

    @Override
    public void setPropertyObject(String name, Object value) {
        ensureRemoteCheck();
        local().setPropertyObject(name, value);
        remote().setPropertyObject(name, value);
    }

    @Override
    public void setPropertyString(String name, String value) {
        ensureRemoteCheck();
        local().setPropertyString(name, value);
        remote().setPropertyString(name, value);
        if (!GWT.isScript() && linkedToRemote()) {
            String remoteValue = remote().getPropertyString(name);
            // CHROME 33 hack, looks like ... works
            if (getTagName().equals("input") && getParentElement().getChildCount() == 1) {
                ElementRemote parentElement0 = typedRemote().getParentElementRemote();
                typedRemote().removeFromParent0();
                parentElement0.appendChild0(typedRemote());
            }
        }
    }

    @Override
    public void setScrollLeft(int scrollLeft) {
        ensureRemote().setScrollLeft(scrollLeft);
    }

    @Override
    public void setScrollTop(int scrollTop) {
        ensureRemote().setScrollTop(scrollTop);
    }

    @Override
    public void setTabIndex(int tabIndex) {
        ensureRemoteCheck();
        local().setTabIndex(tabIndex);
        remote().setTabIndex(tabIndex);
    }

    @Override
    public void setTitle(String title) {
        ensureRemoteCheck();
        local().setTitle(title);
        remote().setTitle(title);
    }

    @Override
    public void sinkEvents(int eventBits) {
        local().sinkEvents(eventBits);
        remote().sinkEvents(eventBits);
    }

    @Override
    public void toggleClassName(String className) {
        ensureRemoteCheck();
        local().toggleClassName(className);
        remote().toggleClassName(className);
    }

    @Override
    public String toString() {
        FormatBuilder fb = new FormatBuilder();
        fb.format("%s#%s.%s - %s", local().toString(), Ax.blankTo(local.getId(), "---"),
                Ax.blankTo(local.getClassName(), "---"),
                (uiObject == null ? "(no uiobject)" : uiObject.getClass().getSimpleName()));
        if (getChildCount() != 0) {
            fb.format("\n\t");
            NodeLocal cursor = local();
            while (cursor.getChildCount() > 0) {
                cursor = cursor.getChildren().get(0);
                fb.format("%s ", cursor.getNodeName());
            }
        }
        return fb.toString();
    }

    private <T> T callWithRemoteOrDefault(boolean flush, Supplier<T> supplier, T defaultValue) {
        if (!linkedToRemote() && flush) {
            ensureRemote();
        }
        if (linkedToRemote()) {
            return supplier.get();
        } else {
            return defaultValue;
        }
    }

    private void dumpLocal0(int depth, String prefix, boolean linkToRemote, StringBuilder stringBuilder) {
        String indent = CommonUtils.padStringLeft("", depth * 2, ' ');
        String paadedPrefix = CommonUtils.padStringRight(prefix, 30, ' ');
        if (!linkedToRemote() && linkToRemote) {
            implAccess().ensureRemote();
        }
        String code = !linkedToRemote() ? "f" : "t";
        if (linkedToRemote()) {
            if (local().getChildren().size() != typedRemote().getChildNodes0().getLength()) {
                code = "x";
            }
        }
        String message = Ax.format("%s%s%s [%s]: ", prefix, indent, getTagName(), code);
        stringBuilder.append(message);
        stringBuilder.append("\n");
        LocalDom.log(LocalDomDebug.DUMP_LOCAL, message);
        int idx = 0;
        for (Node node : getChildNodes()) {
            switch (node.getNodeType()) {
            case Node.TEXT_NODE:
                message = Ax.format("%s%s%s [t]: %s", prefix, indent, getNodeName(),
                        CommonUtils.trimToWsChars(TextUtils.normalizeWhitespace(node.getNodeValue()), 50, true));
                stringBuilder.append(message);
                stringBuilder.append("\n");
                LocalDom.log(LocalDomDebug.DUMP_LOCAL, message);
                break;
            case ELEMENT_NODE:
                ((Element) node).dumpLocal0(depth + 1, prefix + "." + (idx++), linkToRemote, stringBuilder);
                break;
            }
        }
    }

    private DomElement implForPropertyName(String name) {
        switch (name) {
        case "clientWidth":
        case "offsetWidth":
            // TODO - warn maybe? non optimal. SliderBar one major cause
            return ensureRemote();
        }
        if (!wasResolved()) {
            return local();
        }
        ensureRemoteCheck();
        if (linkedToRemote()) {
            return remote();
        } else {
            return local();
        }
        // may need to make more conservative
        // return ensureRemote();
    }

    private boolean notPendingAndLinked() {
        return linkedToRemote() && !isPendingResolution();
    }

    private void runIfWithRemote(boolean flush, Runnable runnable) {
        if (!linkedToRemote() && flush) {
            ensureRemote();
        }
        if (linkedToRemote()) {
            runnable.run();
        }
    }

    protected ElementRemote ensureRemote() {
        LocalDom.flush();
        LocalDom.ensureRemote(this);
        return typedRemote();
    }

    @Override
    protected boolean isPendingResolution() {
        return this.pendingResolution;
    }

    @Override
    protected boolean linkedToRemote() {
        return remote() != ElementNull.INSTANCE;
    }

    @Override
    protected ElementLocal local() {
        return local;
    }

    @Override
    protected void putRemote(NodeRemote remote, boolean resolved) {
        if (getTagName().equalsIgnoreCase("body")) {
            int debug = 3;
        }
        if (!GWT.isScript()) {
            Preconditions.checkState(remote.getNodeName().equalsIgnoreCase(local.getNodeName()));
        }
        Preconditions.checkState(wasResolved() == resolved);
        Preconditions.checkState(this.remote == ElementNull.INSTANCE || remote == this.remote);
        Preconditions.checkState(remote != null);
        this.remote = (ElementRemote) remote;
        if (remote != null) {
            if (local() != null && local().getEventBits() != 0) {
                int existingBits = DOM.getEventsSunk(this);
                DOM.sinkEvents(this, existingBits | local().getEventBits());
            }
        }
    }

    @Override
    protected DomElement remote() {
        if (LocalDom.isDisableRemoteWrite()) {
            return ElementNull.INSTANCE;
        }
        return remote;
    }

    @Override
    protected void resetRemote0() {
        if (getTagName().equalsIgnoreCase("body")) {
            int debug = 3;
        }
        this.remote = ElementNull.INSTANCE;
        if (this.hasStyle()) {
            this.style.resetRemote();
        }
    }

    protected void setInnerSafeHtml(SafeHtml html, boolean withPreRemove) {
        ensureRemoteCheck();
        clearResolved();
        List<Node> oldChildren = getChildNodes().stream().collect(Collectors.toList());
        if (withPreRemove) {
            removeAllChildren();
        } else {
            local().getChildren().clear();
        }
        if (notPendingAndLinked()) {
            remote().setInnerSafeHtml(html);
            String remoteHtml = typedRemote().getInnerHTML0();
            local().setInnerHTML(remoteHtml);
            LocalDom.wasResolved(this);
        } else {
            local().setInnerSafeHtml(html);
        }
        oldChildren.forEach(LocalDom::detach);
    }

    @Override
    protected ElementRemote typedRemote() {
        return (ElementRemote) remote();
    }

    final native String getClassNameSvg() /*-{
                                          var elem = this.@com.google.gwt.dom.client.Element::typedRemote()();
                                          var cn = elem.className;
                                          //note - someone says IE DOM objects don't support - hence try/catch
                                          try {
                                          if (cn.hasOwnProperty("baseVal")) {
                                          cn = cn.baseVal;
                                          }
                                          if ((typeof cn).toLowerCase() != "string") {
                                          if (cn && cn.toString().toLowerCase().indexOf("svg") != -1) {
                                          cn = 'svg-string';
                                          } else {
                                          debugger;
                                          }
                                          }
                                          } catch (e) {
                                          return "";
                                          }
                                          return cn;
                                          }-*/;

    void pendingResolution() {
        this.pendingResolution = true;
    }

    Element putLocal(ElementLocal local) {
        Preconditions.checkState(this.local == null);
        this.local = local;
        local.putElement(this);
        this.remote = ElementNull.INSTANCE;
        return this;
    }

    void replaceRemote(ElementRemote remote) {
        ElementRemote parentRemote = typedRemote().getParentElementRemote();
        if (parentRemote != null) {
            parentRemote.insertBefore0(remote, typedRemote());
            typedRemote().removeFromParent0();
        }
        Preconditions.checkState(remote != null);
        this.remote = remote;
    }

    public class ElementImplAccess {
        public void appendChildLocalOnly(Element localOnly) {
            // IE special case
            local.getChildren().add(localOnly.local);
        }

        public ElementRemote ensureRemote() {
            return Element.this.ensureRemote();
        }

        public boolean linkedToRemote() {
            return Element.this.linkedToRemote();
        }

        public ElementLocal local() {
            return Element.this.local();
        }

        public Node provideSelfOrAncestorLinkedToRemote() {
            return Element.this.provideSelfOrAncestorLinkedToRemote();
        }

        public DomElement remote() {
            return Element.this.remote();
        }

        public void resolvedToPending() {
            if (linkedToRemote()) {
                ElementRemote oldRemote = typedRemote();
                oldRemote.removeAllChildrenElement();
                local().walk(ln -> ln.node.resetRemote());
                resetRemote();
                LocalDom.ensureRemoteNodeMaybePendingResolution(Element.this);
                oldRemote.replaceWith(typedRemote());
            }
        }

        public void setRemote(ElementRemote remote) {
            LocalDom.putRemote(Element.this, remote);
        }

        public NodeRemote typedChild(int index) {
            return ensureRemote().getChildNodes0().getItem0(index);
        }

        public ElementRemote typedRemote() {
            return Element.this.typedRemote();
        }

        public ElementRemote typedRemoteOrNull() {
            return linkedToRemote() ? Element.this.typedRemote() : null;
        }

        public boolean wasResolved() {
            return Element.this.wasResolved();
        }
    }
}