All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.webfolder.ui4j.webkit.dom.WebKitElement Maven / Gradle / Ivy

There is a newer version: 4.0.0
Show newest version
package io.webfolder.ui4j.webkit.dom;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.html.HTMLElement;
import org.w3c.dom.html.HTMLFormElement;
import org.w3c.dom.html.HTMLFrameElement;
import org.w3c.dom.html.HTMLIFrameElement;
import org.w3c.dom.html.HTMLInputElement;
import org.w3c.dom.html.HTMLOptionElement;
import org.w3c.dom.html.HTMLSelectElement;

import com.sun.webkit.dom.DocumentImpl;
import com.sun.webkit.dom.HTMLElementImpl;
import com.sun.webkit.dom.HTMLFrameElementImpl;
import com.sun.webkit.dom.NodeImpl;

import io.webfolder.ui4j.api.browser.SelectorType;
import io.webfolder.ui4j.api.dom.CheckBox;
import io.webfolder.ui4j.api.dom.Document;
import io.webfolder.ui4j.api.dom.Element;
import io.webfolder.ui4j.api.dom.EventTarget;
import io.webfolder.ui4j.api.dom.Form;
import io.webfolder.ui4j.api.dom.Input;
import io.webfolder.ui4j.api.dom.Option;
import io.webfolder.ui4j.api.dom.RadioButton;
import io.webfolder.ui4j.api.dom.Select;
import io.webfolder.ui4j.api.event.EventHandler;
import io.webfolder.ui4j.api.util.Point;
import io.webfolder.ui4j.spi.DelegatingEventHandler;
import io.webfolder.ui4j.spi.JavaScriptEngine;
import io.webfolder.ui4j.spi.NodeUnbindVisitor;
import io.webfolder.ui4j.spi.PageContext;
import io.webfolder.ui4j.webkit.WebKitMapper;
import io.webfolder.ui4j.webkit.browser.WebKitPageContext;
import io.webfolder.ui4j.webkit.spi.WebKitJavaScriptEngine;
import netscape.javascript.JSObject;

public class WebKitElement implements Element, EventTarget {

    protected Node element;

    protected Document document;

    protected PageContext context;

    protected WebKitJavaScriptEngine engine;

    public WebKitElement(Node element, Document document, PageContext context, WebKitJavaScriptEngine engine) {
        this.element = element;
        this.document = document;
        this.context = context;
        this.engine = engine;
    }

    @Override
    public Optional getAttribute(String name) {
        String val = getHtmlElement().getAttribute(name);
        if (val == null || val.isEmpty()) {
            return Optional.empty();
        } else {
            return Optional.of(val);
        }
    }

    @Override
    public Element setAttribute(String name, String value) {
        getHtmlElement().setAttribute(name, value);
        return this;
    }

    @Override
    public Element setAttribute(Map attributes) {
        if (attributes == null) {
            return this;
        }
        for (Map.Entry next : attributes.entrySet()) {
            setAttribute(next.getKey(), next.getValue());
        }
        return this;
    }

    @Override
    public Element removeAttribute(String name) {
        getHtmlElement().removeAttribute(name);
        return this;
    }

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

    @Override
    public Element addClass(String... names) {
        if (names != null && names.length > 0) {
            for (String name : names) {
                JSObject classList = (JSObject) getProperty("classList");
                classList.call("add", name);
            }
        }
        return this;
    }

    @Override
    public Element removeClass(String... names) {
        if (names != null && names.length > 0) {
            for (String name : names) {
                JSObject classList = (JSObject) getProperty("classList");
                classList.call("remove", name);
            }
        }
        return this;
    }

    @Override
    public Element toggleClass(String name) {
        JSObject classList = (JSObject) getProperty("classList");
        classList.call("toggle", name);
        return this;
    }

    @Override
    public boolean hasClass(String name) {
        JSObject classList = (JSObject) getProperty("classList");
        Object result = classList.call("contains", name);
        return Boolean.parseBoolean(result.toString());
    }

    @Override
    public List getClasses() {
        HTMLElementImpl elementImpl = getHtmlElement();
        JSObject classList = (JSObject) elementImpl.getMember("classList");
        int length = (int) classList.getMember("length");
        List list = new ArrayList<>();
        for (int i = 0; i < length; i++) {
            String className = classList.call("item", i).toString();
            list.add(className);
        }
        return list;
    }

    @Override
    public Optional getText() {
        String textContent = element.getTextContent();
        if (textContent == null || textContent.isEmpty()) {
            return Optional.empty();
        }
        return Optional.of(textContent);
    }

    @Override
    public Element setText(String text) {
        HTMLElementImpl elementImpl = getHtmlElement();
        elementImpl.setTextContent(text);
        return this;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getTagName() {
        return getNode().getNodeName().toLowerCase(Locale.ENGLISH);
    }

    @Override
    public Optional getValue() {
        String value = null;
        if (element instanceof HTMLInputElement) {
            value = ((HTMLInputElement) element).getValue();
        } else if (element instanceof HTMLOptionElement) {
            value = ((HTMLOptionElement) element).getValue();
        }
        return value == null || value.isEmpty() ? Optional.empty() : Optional.of(value);
    }

    @Override
    public Element setValue(String value) {
        if (element instanceof HTMLInputElement) {
            ((HTMLInputElement) element).setValue(value);
        } else if (element instanceof HTMLOptionElement) {
            ((HTMLOptionElement) element).setValue(value);
        }
        return this;
    }

    @Override
    public Element bind(String event, EventHandler handler) {
        context.getEventManager().bind(this, event, handler);
        return this;
    }

    @Override
    public Element bindClick(EventHandler handler) {
        bind("click", handler);
        return this;
    }

    @Override
    public Element unbind(String event) {
        context.getEventManager().unbind(this, event);
        return this;
    }

    @Override
    public Element unbind(EventHandler handler) {
        context.getEventManager().unbind(this, handler);
        return this;
    }

    @Override
    public List getChildren() {
        NodeList nodes = element.getChildNodes();
        List elements = new ArrayList<>();
        for (int i = 0; i < nodes.getLength(); i++) {
            Node node = nodes.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                Element element = ((WebKitPageContext) context).createElement(node, document, engine);
                elements.add(element);
            }
        }
        return elements;
    }

    @Override
    public List find(String selector) {
        List elements = new ArrayList<>();
        find(getHtmlElement(), elements, selector);
        if (elements.isEmpty()) {
            return Collections.emptyList();
        }
        return elements;
    }

    private void find(Node node, List elements, String selector) {
        if (Node.ELEMENT_NODE != node.getNodeType()) {
            return;
        }
        NodeList nodes = node.getChildNodes();
        int length = nodes.getLength();
        if (length <= 0) {
            return;
        }
        for (int i = 0; i < length; i++) {
            Node item = nodes.item(i);
            if (Node.ELEMENT_NODE == item.getNodeType()) {
                Element element = ((WebKitPageContext) context).createElement(item, document, engine);
                if (element.is(selector)) {
                    elements.add(element);
                }
                find(item, elements, selector);
            }
        }
    }

    @Override
    public Element unbind() {
        context.getEventManager().unbind(this);
        return this;
    }

    @Override
    public Element empty() {
        HTMLElementImpl htmlElementImpl = getHtmlElement();
        Node child = htmlElementImpl.getLastChild();
        while (child != null) {
            new NodeUnbindVisitor(context, this).walk();
            htmlElementImpl.removeChild(child);
            child = htmlElementImpl.getLastChild();
        }
        return this;
    }

    @Override
    public void remove() {
        if (isHtmlElement() && !getTagName().equals("body")) {
            unbind();
            new NodeUnbindVisitor(context, this).walk();
            if (isAttached()) {
                HTMLElementImpl elementImpl = getHtmlElement();
                elementImpl.getParentElement().removeChild(elementImpl);
            }
        }
    }

    @Override
    public Element click() {
        HTMLElementImpl element = getHtmlElement();
        element.click();
        return this;
    }

    @Override
    public Optional getParent() {
        Node parentNode = element.getParentNode();
        if (parentNode == null) {
            return Optional.empty();
        }
        return Optional.of(((WebKitPageContext) context).createElement(element.getParentNode(), document, engine));
    }

    @Override
    public Optional getInput() {
        return Optional.of(new Input(this));
    }

    @Override
    public Optional getCheckBox() {
        return Optional.of(new CheckBox(this));
    }

    @Override
    public Optional getRadioButton() {
        return Optional.of(new RadioButton(this));
    }

    @Override
    public Optional