Há +- 6 anos. Hoje trabalho na Homem Máquina e sou instrutor do iLearn.
Na UFF, na longínqua terra de Niterói.
Muita gente não conhece o DOM, ou não gosta dele :'(
jQuery, YUI, Motools, Zepto, Dojo Tookit...
Mas você não deve ser totalmente dependente delas.
Saber como funciona te torna um desenvolvedor melhor!
<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
quando usadocument.anchors
, document.applets
, document.forms
, document.images
, document.links
, formElement.elements
, selectElement.options
, tableElement.rows
, tableElement.tBodies
, tableRowElement.cells
, document.embeds
.
NodeList
quando usagetElementsByTagName()
, getElementsByClassName()
, querySelectorAll()
ou Node.childNodes
.
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 id
s ou name
s 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
NodeList
s são dinâmicasHTML:
<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 Node
s de varias maneiras. Exemplos mais comuns
getElementById()
, querySelector()
document
, document.body
, document.head
...NodeList
/HTMLCollection
.Node
Node.nodeName
: nome do Node
. DIV, P, LI, #comment, #text...Node.nodeType
: tipo do Node
. 1, 2, 3, 4...
node.nodeType === Node.ELEMENT_NODE;
node.nodeType === Node.TEXT_NODE;
node.nodeType === Node.COMMENT_NODE;
node.nodeType === Node.DOCUMENT_FRAGMENT_NODE;
Node
Node.parentElement
: Element
pai (DOM4, IE9+)
document.getElementById( 'run' ).onclick = function(){
if ( this.parentElement ) {
this.parentElement.className += ' running';
}
}
Node
Node.parentNode
: Node
pai
document.getElementById( 'run' ).onclick = function(){
var parent = this.parentNode;
while ( parent ) {
if ( parent.nodeType === Node.ELEMENT_NODE ) {
this.parentElement.className += ' running';
return;
}
parent = parent.parentNode;
}
}
Node
Node.textContent
: todo o texto de dentro do Node (IE9+)
var style = document.querySelector( 'style.principal' );
var css = style.textContent; // ;)
document.getElementById( 'headline' ).textContent = 'Lorem ipsum dolor sit amet.';
Modifica sem causar reflow (android approved!)
Node
Node.cloneNode()
var $$ = document.getElementsByClassName;
var menuClone = $$( 'main-nav' )[0].cloneNode( true );
$$( 'footer' )[0].appendChild( menuClone );
Cuidado para não duplicar IDs!
Node
Node.insertBefore()
: insere um Node
antes de outro
var links = document.querySelectorAll( 'a.icon' );
var parent, icon;
for ( var i = 0, l = link.length; i < l; i++ ) {
icon = document.createElement( 'i' );
icon.className = link[ i ].getAttribute( 'data-icon' );
parent = link[ i ].parentElement;
parent.insertBefore( icon, link[ i ] )
}
Node
Node.removeChild()
: remove um Node
filho e retorna ele
var parent = node.parentNode;
parent.removeChild( node );
Node.replaceChild()
: substitui um Node
filho por outro e retorna o substituído
Element
sNode
s que são elementos HTMLclassName
, classList
(DOM4), attributes
, style
, tagName
...addEventListener
, getAttribute
, hasAttribute
...Element
sE 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!
Element
Element.matches()
: diz se um Element
casa com um seletor (IE9+; vendor prefix)
DocumentFragment
Node
sem Pai :'(Node
que nunca fez parte da àrvore. Não teve família! :'(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 );
Dúvidas, correções e sugestões são sempre bem-vindas.
Gostou?
/
#