Dominando o seu DOM

Este cara feio que vos fala

Leonardo Alberto Souza

Document Object Model

Muita gente não conhece o DOM, ou não gosta dele :'(

Usar bibliotécas não é ruim...

Mas você não deve ser totalmente dependente delas.

Saber como funciona te torna um desenvolvedor melhor!

O DOM é uma árvore

Representação do DOM da RioJS Conference 2013

O DOM é uma árvore

Árvore representando o código ao lado
<html>
    <body>
        <p>Text</p>
        <div><img></div>
    </body>
</html>

HTMLCollection vs. NodeList

Ambas são listas contendo referencias ao DOM.

Você obtem uma...

HTMLCollection

HTML:
<body>
    <form id="form1">
        <!-- ... -->
    </form>
    <form name="form2">
        <!-- ... -->
    </form>
</body>

JS:
document.forms[ 'form1' ] === document.forms[ 0 ]; //true
document.forms.namedItem( 'form2' ) === document.form.item( 1 ); //true

HTMLCollection

Não use ids ou names repetidos num documento...

HTML:
<body>
    <form name="contato">
        <!-- ... -->
    </form>
    <form name="contato">
        <!-- ... -->
    </form>
</body>

Gecko:
document.forms[ 'contato' ]
// primeiro form[name='contato']

Webkit/IE:
document.forms[ 'contato' ]
// HTMLCollection com todos os form[name='contato']

Presto:
document.forms[ 'form' ]
// NodeList com todos os form[name='contato']

HTMLCollection

A especificação diz que o name tem precedência sobre id... mas nem sempre ela é respeitada

NodeList

São parecidas com HTMLColections, mas não tem os método namedItem() e, pela especificação, não deveriam poder ser acessadas via id ou name. Mas algumas engines implementam esse comportamento

HTML:
<body>
    <form id="contato1">
        <!-- ... -->
    </form>
    <form id="contato2">
        <!-- ... -->
    </form>
</body>

JS:
var forms = document.getElementsByTagName( 'form' );

forms[ 'contato1' ] // pode funcionar ou não

NodeLists são dinâmicas

HTML:
<body>
    <p>Paragrafo 1</p>
    <p>Paragrafo 2</p>
    <p>Paragrafo 3</p>
</body>

JS:
var paragrafos = document.getElementsByTagName( 'p' );
paragrafos.length; // 3
var novoParagrafo = document.createElement( 'p' );
document.body.appendChild( novoParagrafo );
paragrafos.length; // 4

querySelectorAll() não retorna uma NodeList dinâmica :(

Apesar da especificação não dizer, na prática, HTMLCollections também são dinâmicas

NodeLists e HTMLCollections não são Arrays

NodeList instaceof Array; // false
HTMLCollection instaceof Array; // false

Mas podem ser transformadas

var paragrafos = document.querySelectorAll( 'p' );
paragrafos = Array.prototype.slice.call( paragrafos );
paragrafos.forEach(function( p ) {
    p.classList.add( 'red' );
});

Node

São cada um dos nós da árvore. Elementos, comentarios, texto. Tudo é um Node. Inclusive document. Element é um tipo de Node. TextNode também.

Você obtem Nodes de varias maneiras. Exemplos mais comuns

Alguns atributos legais de Node

Outro atributo legal de Node

Mais outro atributo legal de Node

Outro atributo legal de Node

Método legal de Node

Método legal de Node

Outros métodos legais de Node

Elements

Elements

E você pode pesquisar dentro deles!

var container = document.getElementById( 'container' );
var items = container.getElementsByClassName( 'item' );

Você não precisa pecorrer o DOM inteiro quando sabe onde achar!
Use getElementsByClassName, getElementsByTagName, querySelector e querySelectorAll à vontade!

Um futuro método muito legal de Element

DocumentFragment

DocumentFragment

Ele precisa ser adotado!

var ul = document.querySelector( '.list');
var frag = document.createDocumentFragment();
var frutas = [ 'Laranja', 'Maçã', 'Pera', 'Morango', 'Melancia', 'Jaca' ];
 
frutas.forEach(function( fruta ) {
    var li = document.createElement( 'li' );
    li.innerHTML = fruta;
    frag.appendChild( li );
});
 
ul.appendChild( frag );

Links

Obrigado! ;)

Dúvidas, correções e sugestões são sempre bem-vindas.
Gostou?

/

#