DOM é um acrônimo para Document Object Model (Modelo de Objetos de Documento) ele representa os objetos de uma página HTML em forma de uma árvore. O DOM é importante pois é através dele que acessamos os elementos dentro de uma página HTML. Em outra palavras, obtemos acesso ao documento HTML através do DOM.

O exemplo abaixo…

<!DOCTYPE html>
<html>
    <head>
        <title>Sample Document</title>
    </head>
    <body>
        <h1>An HTML Docuemnt</h1>
        <p>This is a <i>simple</i> document</p>
    </body>
</html>

.. gera a seguinte árvore DOM:

Figura ilustrando o DOM - Document Object Model

Quando um documento HTML é baixado no navegador, esse navegador precisa transformar em uma página Web o que é basicamente uma longa string de caracteres. Para tanto, o navegador decide quais partes são parágrafos, quais são cabeçalhos, quais são texto e assim por diante. Para evitar que os pobres programadores de JavaScript tenham de fazer exatamente o mesmo trabalho, o navegador armazena sua interpretação do código HTML como um estrutura de objetos, chamada Document Object Model ou DOM. Como resultado da maneira pela qual o código HTML é escrito - como uma hierarquia de elementos aninhados, marcados com tags de início e fim - o DOM cria um objeto diferente para cada elemento, mas vincula cada objeto de elemento ao seu elemento circundante (ou elemento pai). Isso cria uma relação pai-filho (parent-children) explícita entre os elementos e torna mais imediata a visualização do DOM como uma estrutura em árvore.

Abaixo vemos outro exemplo da árvore DOM, repare que os nós de texto também foram incluídos.

Figura ilustrando o DOM - Document Object Model

Document Object Model ou DOM, é a API fundamental para representar e manipular o conteúdo de documentos HTML e XML. A API não é especialmente complicada, mas existem vários detalhes de arquitetura que precisam ser entendidos.

Trabalhar com a árvore DOM de uma página é uma das tarefas mais comuns do JavaScript no lado do cliente. Isso também é uma das principais causas de dores de cabeça ( e dá ao JavaScript uma má reputação), porque os métodos DOM são implementados de forma inconsistente nos navegadores. É por isso que usar uma boa biblioteca JavaScript, que abstraia as diferenças dos navegadores, pode acelerar significativamente o desenvolvimento. Considere ao menos aprender 2 ou 3 bibliotecas JavaScript.

O acesso ao DOM é caro; ele é o maior gargalo no que diz respeito a desempenho no JavaScript. É por isso que o DOM costuma ser implementado separadamente do mecanismo JavaScript. Do ponto de vista de um programador, faz sentido usar essa abordagem, porque uma aplicação JavaScript pode nem precisar do DOM. O ponto principal é que é o acesso ao DOM deveria ser reduzido ao mínimo, leia o artigo Reduzindo o acesso ao DOM para obter mais informações.

Métodos diretos para acessar o documento

O DOM define várias maneiras de selecionar elemento, você poderá consultar um documento através de uma das abordagens abaixo:

Selecionando elementos pela identificação

Qualquer elemento HTML pode ter um atributo id. O valor desse atributo deve ser único dentro do documento - dois elementos no mesmo documento não podem ter a mesma identificação. Você pode selecionar um elemento com base nessa identificação exclusiva com o método getElementById() do objeto document.

var elemento = document.getElementById("identificacao");

Leia mais sobre a função getElementById()

Selecionando elementos pelo nome

A atributo HTML name se destinava originalmente a atribuir nomes a elementos de formulário e o valor desse atributo é usado quando dados de formulário são enviados para um servidor. Assim como o atributo id, name atribui um nome a um elemento. Ao contrário de id, contudo, o valor de um atributo name não precisa ser único: vários elementos podem ter o mesmo nome e isso é comum no caso de botões de seleção e caixa de seleção em formulários web. Além disso ao contrário de id, o atributo name é válido somento em alguns elementos HTML, incluindo formulários, elementos de formulário, tag iframe e tag img.

var elementos = document.getElementsByName("nome-dos-elementos");

Leia mais sobre a função getElementsByName()

Selecionando elementos pela tag

Para obter um objeto semelhante a um array somente leitura, contendo os objetos Element de todos os elementos span em um documento, por exemplo, você poderia escrever:

var spans = document.getElementsByTagName("span");

Leia mais sobre a função getElementsByTagName()

Selecionando elementos pela classe CSS

A atributo class de uma HTML é uma lista separada de zero ou mais identificadores por espaços. Ele descreve uma maneira de definir conjuntos de elementos relacionados do documento: todos os elementos que têm o mesmo identificador em seu atributo class fazem parte do mesmo conjunto.

A HTML 5 define um método getElementsByClassName() que nos permite selecionar conjuntos de elementos de documento com base nos identificadores que estão em seu atributo class.

var elementos = document.getElementsByClassName("nome-da-classe");

Leia mais sobre a função getElementsByClassName()

Selecionando elementos através dos seletores CSS

O padrão da W3C conhecido como API de Seletores define métodos JavaScript para obter os elementos que coincidem com determinado seletor CSS. O segredo dessa API é o método querySelectorAll(), ele recebe um argumento de string contendo um seletor CSS e retorna um objeto NodeList representando todos os elementos do documento que correspondem ao seletor.

Leia mais sobre a função querySelectorAll()

Figura ilustrando o DOM - Document Object Model

Os métodos para encontrar elementos DOM que descrevemos até aqui foram muito direcionados, estamos pulando diretamente para um nó específico na árvore, sem nos preocuparmos com as conexões no meio. Após ter selecionado um elemento do documento, às vezes você precisa encontrar partes estruturalmente relacionada:

  • parent (pais)
  • siblings (irmãos)
  • childrens (filhos)

Figura ilustrando o DOM - Document Object Model

Localizando um pai (parent)

Todo nó de elemento possui um pai, exceto o nó do documento. Consequentemente, cada nó de elemento tem uma propriedade chamada parentNode, uma referência para o pai do elemento distinto.

elem.parentNode

Localizando filhos (childrens)

Um elemento só pode ter um pai (parent), mas pode ter muitos filhos (childrens). Você pode encontrar todos os filhos de um elemento, usando a propriedade childNodes. Ela é, na verdade, uma lista de nós que contém todos os filhos do elemento, no ordem de origem.

elem.childNodes     // lista completa de filhos
elem.childNodes[0]  //
elem.childNodes[1]  // Acessando filhos individualmente
elem.childNodes[2]  //
//etc...

Podemos também localizar o primeiro filho:

elem.firstChild

Ou o último filho:

elem.lastChild

Localizando irmãos (siblings)

Assim como podemos navegar para cima e para baixo na árvore DOM, também podemos ir de um lado para o outro, obtendo o próximo nó ou o anterior (ambos no mesmo nível). As propriedades que utilizamos para isso são nextSibling e previousSibling.

var proximoIrmao  = elem.nextSibling
var anteriorIrmao = elem.previousSibling

Acessando os atributos

Os elementos HTML consistem em um nome de tag e um conjunto de pares nome/valor conhecidos como atributos. Por exemplo, o elemento <a> que define um hiperlink utiliza o valor de seu atributo href como destino do link.

<a href="www.defuria.com.br" id="um-link-qualquer">link</a>"

Os valores de atributo dos elementos HTML estão disponíveis como propriedades dos objetos HTMLElement que representam esses elementos. Dessa forma

var link = document.getElementById("um-link-qualquer");
console.log(link.href);

O DOM também oferece outras API’s para obter e configurar os valores de atributos HTML não pradonizados, mas que também funcionam com os demais atributos.

var link = document.getElementById("um-link-qualquer");
link.setAtributte("href", "http://www.w3.org/")
console.log(link.getAtributte("href"));

Resumo

  • elem.[nome do atributo] para leitura e escrita
  • elem.getElementById("nome do atributo") para leitura
  • elem.setAtributte("nome do atributo", "valor do atributo") para escrita

Manipulando o DOM

Podemos criar, inserir e excluir elementos da árvore DOM.

A função document.createElement() aceita como parâmetro o nome da tag e retorna o elemento recém criado (mas ainda não inserido).

var elem = document.createElement("li");

Inserimos o elemento com a função elemento_pai.appendChild(), mas ainda precisamos criar um nó de texto para o elemento, caso contrário, estaremos inserindo apenas o elemento, sem texto. Para criar um nó de texto utilizamos a função document.createTextNode().

var texto = document.createTextNode("mais um item");

Antes de inserir o elemento, devemos anexar o nó de texto a ele.

elem.appendChild(texto);

Imaginado que temos um único elemento ul em nosso documento podemos fazer uso da função getElementsByTagName(). Ela retorna um coleção, um array de elementos. Como sabemos previamente que precisamos do primeiro item, acessaremos a coleção dessa forma colecao[0] ou mais resumidamente getElementsByTagName()[0], veja:

var lista = document.getElementsByTagName('ul')[0];

De posse de um elemento completo, podemos então, anexá-lo a um elemento <ul> já existente em nossa página HTML. A função elemento_pai.appendChild() insere o novo elemento filho ao final do elemento pai.

lista.appendChild(elem);

Também podemos inserir um elemento através da função insertBefore(), ela aceita dois parâmetros: o primeiro é o elemento filho e o segundo é o elemento que servirá de referência para inserir o elemento filho.

Para remover um elemento utilizamos a função removeChild().

Leia o artigo Manipulando o DOM para obter mais detalhes.

Resumo

  • document.createElement("nome-da-tag") para criar um elemento
  • document.createTextNode("algum texto") para criar um nó de texto
  • elemento_pai.appendChild(elemento_filho) para inserir um elemento na última posição
  • elemento_pai.insertBefore(elemento_filho, elemento_anterior) pra inserir um elemento em posição específica
  • elemento_pai.removeChild(elemento_filho) para remover um elemento

Especificações

Leia também