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. NodeListAmbas 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.
HTMLCollectionHTML:
<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
HTMLCollectionNã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']
HTMLCollectionA especificação diz que o name tem precedência sobre id... mas nem sempre ela é respeitada
NodeListSã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â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 ArraysNodeList 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' );
});
NodeSã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
getElementById(), querySelector()document, document.body, document.head...NodeList/HTMLCollection.NodeNode.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;
NodeNode.parentElement: Element pai (DOM4, IE9+)
document.getElementById( 'run' ).onclick = function(){
if ( this.parentElement ) {
this.parentElement.className += ' running';
}
}
NodeNode.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;
}
}
NodeNode.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!)
NodeNode.cloneNode()
var $$ = document.getElementsByClassName;
var menuClone = $$( 'main-nav' )[0].cloneNode( true );
$$( 'footer' )[0].appendChild( menuClone );
Cuidado para não duplicar IDs!
NodeNode.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 ] )
}
NodeNode.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
ElementsNodes que são elementos HTMLclassName, classList (DOM4), attributes, style, tagName...addEventListener, getAttribute, hasAttribute...ElementsE 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!
ElementElement.matches(): diz se um Element casa com um seletor (IE9+; vendor prefix)
DocumentFragmentNode sem Pai :'(Node que nunca fez parte da àrvore. Não teve família! :'(DocumentFragmentEle 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?
/
#