List icon Conteúdo

DOM

Este guia descreve como acessar a um documento DOM, encontrar elementos, modificar uma estrutura DOM, simular a entrada do usuário, etc.

Visão geral

Cada página Web carregada em um Browser tem um Frame principal . O próprio Frame pode ter frames filhos. Por exemplo, quando uma página web tem IFRAMEs, utilize a classe Frame para acessar o DOM e o JavaScript.

Acessando o documento

Cada Frame tem um Document DOM. Para acessar o Documento utilize o método Frame.document():

Java
Kotlin
frame.document().ifPresent(document -> {});
val document = frame.document
document?.let {
}

Encontrando elementos

Você pode encontrar elementos HTML dentro de um elemento através de diferentes condições. O exemplo a seguir demonstra como encontrar todos os elementos DIV dentro do elemento document:

Java
Kotlin
document.documentElement().ifPresent(documentElement ->
    documentElement.findElementsByTagName("div").forEach(element -> {}));
val divs = document.documentElement!!.findElementsByTagName("div")
divs.forEach { element -> }

Se você precisar encontrar apenas o primeiro elemento HTML, utilize a seguinte abordagem:

Java
Kotlin
documentElement.findElementByTagName("div").ifPresent(element -> {});
val div = documentElement.findByTagName("div")
div?.let {
}

Aqui estão os exemplos de pesquisa de elementos HTML por diferentes condições:

Java
Kotlin
documentElement.findElementsById("<id>");
documentElement.findElementsByName("<attr-name>");
documentElement.findElementsByTagName("<tag-name>");
documentElement.findElementsByClassName("<attr-class>");
documentElement.findElementsById("<id>")
documentElement.findElementsByName("<attr-name>")
documentElement.findElementsByTagName("<tag-name>")
documentElement.findElementsByClassName("<attr-class>")

XPath

A API DOM do JxBrowser permite a avaliação de expressões XPath utilizando Node.evaluate(String expression). É possível avaliar uma expressão XPath no âmbito de um Node especificado utilizando o seguinte código:

Java
Kotlin
try {
    var result = node.evaluate("count(//div)");
} catch (XPathException e) {
    // Falha ao avaliar a expressão fornecida.
}
val queryNumberOfDivs = XPathExpression("count(//div)")
try {
    val result: XPathResult = node.evaluate(queryNumberOfDivs)
} catch (e: XPathException) {
    // Falha ao avaliar a expressão fornecida.
}

O método lança XPathException quando a biblioteca não consegue avaliar a expressão fornecida.

O resultado da avaliação é armazenado no objeto XPathResult. Certifique-se de que o resultado contém o tipo de valor esperado em, por exemplo, Number, Boolean, String, Node, e extrai o próprio valor:

Java
Kotlin
if (result.isNumber()) {
    double number = result.asNumber();
}
if (result.isNumber) {
    val number: Double = result.asNumber()
}

Seletor de Query

Para encontrar os elementos que correspondem a um seletor especificado, por exemplo, #root, utilize o seguinte código:

Java
Kotlin
var elements = element.findElementsByCssSelector("#root");
val elements = element.findElementsByCssSelector("#root")

Node no Ponto

Para encontrar o Node num ponto específico, por exemplo, 100x150, na página Web, utilize a seguinte abordagem:

Java
Kotlin
var inspection = frame.inspect(Point.of(100, 150));
inspection.node().ifPresent(node -> {});
val inspection: PointInspection = frame.inspect(Point(100, 150))
val node: Node? = inspection.node

Trabalhando com elementos

Limites de elementos

Você pode obter os limites do Element com a posição relativa ao topo esquerdo da janela de visualização do Document atual da seguinte forma:

Java
Kotlin
var rect = element.boundingClientRect();
val rect = element.boundingClientRect()

Este método devolve um Rect vazio quando o elemento tem um atributo hidden ou o estilo CSS do elemento contém a declaração display: none;.

Atributos do elemento

A classe Element fornece métodos que permitem obter, adicionar, remover ou modificar os atributos de elementos HTML. O seguinte exemplo demonstra como obter todos os atributos do elemento e imprimir os seus nomes e valores:

Java
Kotlin
element.attributes().asMap().forEach((name, value) ->
    System.out.println(name + ": " + value));
element.attributes.asMap().forEach { (name, value) ->
    println("$name: $value")
}

O exemplo seguinte demonstra como adicionar/modificar um atributo de elemento:

Java
Kotlin
element.attributes().put("attrName", "attrValue");
element.attributes["attrName"] = "attrValue"

Criação de elementos

A API DOM permite modificar a estrutura DOM do documento. O exemplo seguinte demonstra como criar e inserir o elemento <p> com algum texto:

Java
Kotlin
// Cria um novo elemento de parágrafo.
var paragraph = document.createElement("p");
// Criar um nó de texto com o texto fornecido.
var text = document.createTextNode("Text");
// Inserir o nó de texto no elemento de parágrafo.
if (paragraph.appendChild(text)) {
    // Inserir o elemento de parágrafo no elemento necessário.
    boolean success = element.appendChild(paragraph);
}
// Cria um novo elemento de parágrafo.
val paragraph = document.createElement("p")
// Criar um nó de texto com o texto fornecido.
val text = document.createTextNode("Text")
// Inserir o nó de texto no elemento de parágrafo.
if (paragraph.appendChild(text)) {
    // Inserir o elemento de parágrafo no elemento necessário.
    val success = element.appendChild(paragraph)
}

Fechando Nodes

Objetos DOM que possuem uma contraparte Node não estão sujeitos à coleta de lixo do Blink. Por padrão, mantemos estes objetos na memória até a página ser descarregada.

Para otimizar a utilização da memória, pode ativar a recolha de lixo por objeto:

Java
Kotlin
node.close();
node.close()

Fechar o Node marca o objeto Blink correspondente como coletável, mas não libera o objeto imediatamente. Depois de chamar o método close(), as tentativas de usar Node levarão a ObjectClosedException.

Eventos DOM

Cada Node implementa a interface EventTarget que fornece métodos para registar eventos DOM. Você pode registrar DOM listener para receber eventos DOM como click, mousedown, mouseup, keydown, load, error etc.

O exemplo a seguir demonstra como registrar um ouvinte de evento click para um elemento HTML de documento:

Java
Kotlin
document.documentElement().ifPresent(element ->
    element.addEventListener(EventType.CLICK, event -> {
        // O evento de clique do mouse foi recebido.
        if (event instanceof MouseEvent) {
            var mouseEvent = (MouseEvent) event;
            var clickCount = mouseEvent.clickCount();
        }
    }, false));
val listener = Observer<Event> { event ->
    // O evento de clique do mouse foi recebido.
    if (event is MouseEvent) {
        val clickCount = event.clickCount()
    }
}
val useCapture = false
document.documentElement?.addEventListener(
    EventType.CLICK,
    listener,
    useCapture
)

Além disso, o JxBrowser permite que você ouça os eventos DOM personalizados e acessar sua carga útil:

Java
Kotlin
// Criar um tipo de evento DOM personalizado.
var eventType = EventType.of("MyEvent");
// Escuta os eventos do tipo de evento fornecido.
element.addEventListener(eventType, event -> {
    // O evento MyEvent foi recebido.
    if (event instanceof CustomEvent) {
        var customEvent = (CustomEvent) event;
        var payload = customEvent.detail();
    }
}, false);
// Criа um tipo de evento DOM personalizado.
val eventType = EventType.of("MyEvent")
val listener = Observer<Event> { event ->
    // O evento MyEvent foi recebido.
    if (event is CustomEvent) {
        val payload = event.detail<JsObject>()
    }
}
val useCapture = false
// Escuta os eventos do tipo de evento fornecido.
element.addEventListener(eventType, listener, useCapture)

Automatização

A API DOM do JxBrowser fornece tudo o que é necessário para automatizar o preenchimento de formulários Web. Esta seção descreve como atualizar o texto nos campos de texto, selecionar uma caixa de verificação ou um botão radio, selecionar uma ou várias opções numa lista drop-down, simular um clique, etc.

Para trabalhar com controles de formulários Web, utilize a interface FormControlElement. Esta interface permite verificar se o controle está ativado e modificar o seu valor. Todos os controles de formulário, tais como INPUT, SELECT, TEXTAREA, e outros herdam esta interface.

Entrada

Para trabalhar com elementos INPUT utilize a interface InputElement. Fornece todos os métodos necessários para verificar o tipo de entrada e definir o seu valor.

Texto, E-mail, Senha

Para substituir o valor padrão de um campo de texto, e-mail ou senha por um novo valor, utilize o método InputElement.value(String).

Por exemplo, se o seu formulário Web contiver os elementos <input> com os seguintes tipos:

<input type="text" id="firstname" placeholder="First Name">
<input type="email" id="email" placeholder="Email Address">
<input type="password" id="password" placeholder="Password">

você pode definir o seu valor utilizando a seguinte abordagem:

Java
Kotlin
documentElement.findElementById("firstname").ifPresent(element ->
    ((InputElement) element).value("John"));

documentElement.findElementById("email").ifPresent(element ->
    ((InputElement) element).value("me@company.com"));

documentElement.findElementById("password").ifPresent(element ->
    ((InputElement) element).value("Jkdl12!"));
val firstname = documentElement.findById("firstname") as InputElement
firstname.value = "John"

val email = documentElement.findById("email") as InputElement
email.value = "me@company.com"

val password = documentElement.findById("password") as InputElement
password.value = "Jkd12!"

Check Box, Radio Button

Para verificar um botão radio ou uma checkbox, utilize o método InputElement.check().

Por exemplo, se o seu formulário Web contiver os elementos <input> com os seguintes tipos:

<input type="checkbox" id="checkbox" value="Remember me">
<input type="radio" id="radio" checked>

você pode selecionar/desmarcar utilizando a seguinte abordagem:

Java
Kotlin
documentElement.findElementById("checkbox").ifPresent(element ->
    ((InputElement) element).check());

documentElement.findElementById("radio").ifPresent(element ->
    ((InputElement) element).uncheck());
val checkbox = documentElement.getById("checkbox") as InputElement
checkbox.check()

val radio = documentElement.getById("radio") as InputElement
radio.uncheck()

Arquivo

Os elementos <input> com type=file permitem ao usuário escolher um ou mais arquivos do seu dispositivo de armazenamento. JxBrowser lhe permite selecionar programaticamente um arquivo e atualizar o valor dos <input type=file> elementos.

Por exemplo, se o seu formulário web contiver um elemento <input> como:

<input type="file" id="avatar" accept="image/png, image/jpeg" multiple>

você pode selecionar o(s) arquivo(s) necessário(s) programaticamente utilizando a seguinte abordagem:

Java
Kotlin
documentElement.findElementById("avatar").ifPresent(element ->
    ((InputElement) element).file("file1.png", "file2.jpeg"));
val avatar = documentElement.getById("avatar") as InputElement
avatar.file("file1.png", "file2.png")

Área de texto

Para definir o texto num elemento <textarea> como:

<textarea id="details"></textarea>

utilize a seguinte abordagem:

Java
Kotlin
documentElement.findElementById("details").ifPresent(element ->
    ((TextAreaElement) element).value("Some text..."));
val details = documentElement.getById("details") as TextAreaElement
details.value = "Some text..."

Select & Option

Para selecionar todas as opções num controle SELECT como:

<select id="fruits" multiple>
    <option>Maçã</option>
    <option>Laranja</option>
    <option>Abacaxi</option>
    <option>Banana</option>
</select>

utilize a seguinte abordagem:

Java
Kotlin
documentElement.findElementById("fruits").ifPresent(element -> {
    var selectElement = (SelectElement) element;
    selectElement.options().forEach(optionElement ->
        optionElement.select());
});
val fruits = documentElement.getById("fruits") as SelectElement
fruits.options.forEach {
    it.select()
}

Com esta abordagem, você pode selecionar apenas uma opção necessária.

Simulação de clique

Para simular um clique do mouse num elemento, utilize o seguinte método:

Java
Kotlin
element.click();
element.click()

Quando click() é utilizado com os elementos suportados (como um <input>), ele dispara o evento de clique do elemento. Este evento é então transmitido para os elementos mais elevados na árvore do documento e ativa os respectivos eventos de clique.

Envio de eventos

É possível enviar um Event para o EventTarget especificado utilizando o método EventTarget.dispatch(Event).

O exemplo a seguir demonstra como enviar um evento click padrão para o elemento especificado:

Java
Kotlin
// Localização do cliente e da tela.
var location = Point.of(10, 10);
// Criar MouseEvent com as opções necessárias.
var mouseClickEvent = document.createMouseEvent(EventType.CLICK,
    MouseEventParams.newBuilder()
        // O botão principal pressionado.
        .button(MouseEvent.Button.MAIN)
        .clientLocation(location)
        .screenLocation(location)
        .uiEventModifierParams(
            UiEventModifierParams.newBuilder()
                .eventParams(EventParams.newBuilder()
                    .bubbles(true)
                    .cancelable(true)
                    .build())
                .build())
        .build());
// Gera um evento de clique no elemento de destino.
element.dispatch(mouseClickEvent);
// Localização do cliente e da tela.
val location = Point(10, 10)
// Criar MouseEvent com as opções necessárias.
val eventParams = EventParams(bubbles = true, cancelable = true)
val uiEventModifiers = UiEventModifierParams(eventParams)
val mouseEventParams = MouseEventParams(
    button = MouseEvent.Button.MAIN, // O botão principal pressionado.
    location = location,
    locationOnScreen = location,
    uiEventModifierParams = uiEventModifiers
)
val mouseClickEvent = document.createMouseEvent(
    EventType.CLICK,
    mouseEventParams
)
// Gera um evento de clique no elemento de destino.
element.dispatch(mouseClickEvent)

Utilizando esta abordagem, você pode criar e enviar vários eventos DOM. Tais eventos são normalmente designados por eventos sintéticos, por oposição aos eventos disparados pelo Browser propriamente dito.