NF2 - Model d'objectes del document

De wikiserver
Dreceres ràpides: navegació, cerca

Document Object Model

És un conjunt d'objectes (API) Javascript que permeten interactuar amb el document HTML. Podem realitzar les següents operacions:

  • Canviar i llegir el contingut i la estructura
  • Canviar i llegir estils CSS
  • Gestionar events

Existeixen diversos nivells (versions) de DOM :

  • Nivell 0: Introduït per Netscape i Microsoft a principis dels 90 durant la guerra dels navegadors. Per aixó, no existeix un DOM estàndard.
  • Nivell 1: A partir d'aquí es va fer càrrec del DOM el W3C. Va introduir contingut dinàmic.
  • Nivell 2: "Serialització" de XML (ex: permet guardar documents), events de teclat,...

Els navegadors per poder utilitzar les utilitats de DOM, necessiten transformar la pàgina original. Una pàgina HTML normal no és més que una successió de caràcters, per la qual cosa és un format molt difícil de manipular. Per això, els navegadors web transformen automàticament totes les pàgines web en una estructura més eficient de manipular.

Arbre DOM

DOM transforma tots els documents XHTML en un conjunt d'elements anomenats nodes, que estan interconnectats i que representen els continguts de les pàgines web i les relacions entre ells. Pel seu aspecte, la unió de tots els nodes es diu "arbre de nodes".

Dom1.png

L'arrel de l'arbre de nodes de qualsevol pàgina XHTML sempre és la mateixa: un node de tipus especial denominat Document.

A partir d'aquest node arrel, cada etiqueta XHTML es transforma en un node de tipus Element. La conversió d'etiquetes en nodes es realitza de forma jeràrquica. D'aquesta forma, del node arrel solament poden derivar els nodes HEAD i BODY. A partir d'aquesta derivació inicial, cada etiqueta XHTML es transforma en un node que deriva del node corresponent a la seva etiqueta pare.

La transformació de les etiquetes XHTML habituals genera dos nodes: el primer és el node de tipus Element (corresponent a la pròpia etiqueta XHTML) i el segon és un node de tipus Text que conté el text tancat per aquesta etiqueta XHTML. Exemple:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
		<title>Página sencilla</title>
	</head>
 
	<body>
		<p>Esta página es <strong>muy sencilla</strong></p>
	</body>
</html>
Dom2.gif

L'especificació completa de DOM defineix 12 tipus de nodes:

Dom3.png

Encara que les pàgines XHTML habituals es poden manipular manejant solament quatre o cinc tipus de nodes:

  • Document, node arrel del que deriven tots els altres nodes de l'arbre.
  • Element, representa cadascuna de les etiquetes XHTML. Es tracta de l'únic node que pot contenir atributs i l'únic del que poden derivar altres nodes.
  • Attr, es defineix un node d'aquest tipus per representar cadascun dels atributs de les etiquetes XHTML, és a dir, un per cada parell atribut=valor.
  • Text, node que conté el text tancat per una etiqueta XHTML.
  • Comment, representa els comentaris inclosos a la pàgina XHTML.

Cada node té diverses propietats que reflecteixen el grau parentiu amb els altres. Alguna d'aquestes propietats son les següents:

  • childNodes: array amb els nodes fills.
  • firstChild: primer node fills
  • lastchild: últim node fill
  • parentNode: node pare
  • nextSibling: següent germà (node al mateix nivell i amb el mateix pare)
  • lastSibling: germà anterior.

Exemple:

Dom4.png
<ul id="myList"><li>Coffee</li><li id="arribaHermano">Tea</li><li>Mejillones</li></ul>
<div id="demo"></div>

var pri = document.getElementById("myList").firstChild.innerHTML;
var ulti = document.getElementById("myList").lastChild.innerHTML;
var x = document.getElementById("myList").parentNode.nodeName;
var Upbrother = document.getElementById("arribaHermano").previousSibling.innerHTML;
var ProHermano = document.getElementById("arribaHermano").nextSibling.innerHTML;

var nuevoItem = document.createElement("LI");       // Crear un nodo <li>
var nodoTexto = document.createTextNode("Nuevo Elemnto");  // crea un texto de nodo
nuevoItem.appendChild(nodoTexto);                    // Adjunta el texto a la <li>

var list = document.getElementById("myList");    // Obtiene el <ul> elemento para insertar un nuevo nodo
list.insertBefore(nuevoItem, list.childNodes[0]);

document.getElementById("demo").innerHTML ="primer Hijo: "+ pri+" Último Hijo: "+ ulti +" Nodo Padre: "+ x +" Hermano Previo: "+ Upbrother + " Próximo Hermano: "+ProHermano;


!CUIDADO

<ul id="myList">
	<li>Coffee</li>
	<li id="arribaHermano">Tea</li>
	<li>Mejillones</li>
</ul>
<div id="demo"></div>


var primerHijoEspacio=document.getElementById("myList").firstChild; //selecciona primer espacio
var PrimerElementoCoffe=primerHijoEspacio.nextSibling;  // selecciona el siguiente nodo que corresponde con el elemento.
var siguienteNodoEspacio=PrimerElementoCoffe.nextSibling; //selecciona el siguiente nodo que es un espacio.
var SegundoElementoTea=siguienteNodoEspacio.nextElementSibling;  //selecciona el siguiente elemento.
var TercerElementoMejillones=SegundoElementoTea.nextElementSibling;  //selecciona el siguiente elemento.


var TodoHijosEspacioElementos=document.getElementById("myList").childNodes; //incluye texto/comentarios y elementos
var ElementosHijos=document.getElementById("myList").children;  //sólo elementos

//let primerElementoHijo=document.getElementById("myList").firstElementChild();  //selecciona el primer Nodo que corresponde con un Elemento

Mètodes d'accés als nodes de l'arbre

És important recordar que l'accés als nodes, la seva modificació i la seva eliminació solament és possible quan l'arbre DOM ha estat construït completament, és a dir, després que la pàgina XHTML es carregui per complet. A continuació es mostren les diferents formes per aconseguir un node de l'arbre de manera directa, sense haver de recórrer-ho:

  • getElementsByTagName(nomEtiqueta) : obté tots els elements de la pàgina XHTML l'etiqueta de la qual sigui igual que el paràmetre que se li passa a la funció.

El següent exemple mostra com obtenir tots els paràgrafs d'una pàgina XHTML:

var parrafos = document.getElementsByTagName("p");

El valor que retorna la funció és un array amb tots els nodes que compleixen la condició que la seva etiqueta coincideix amb el paràmetre proporcionat. El valor retornat és un array de nodes DOM, no un array de cadenes de text o un array d'objectes normals. Per tant, s'ha de processar cada valor del array de la forma que es mostra:

for(var i=0; i<parrafos.length; i++) {
  //Obtenim tots els enllaços del cada paràgraf  
  var enlaces = parrafos[i].getElementsByTagName("a");
	...
}
  • getElementsByName("nomElement"):En aquest cas es busquen els elements l'atribut dels quals name sigui igual al paràmetre proporcionat.

En el següent exemple, s'obté directament l'únic paràgraf amb el nom indicat:

var parrafoEspecial = document.getElementsByName("especial");
<p name="prueba">...</p>
<p name="especial">...</p>
<p>...</p>

Normalment l'atribut name és únic per als elements HTML que ho defineixen, per la qual cosa és un mètode molt pràctic per accedir directament al node desitjat. En el cas dels elements HTML radiobutton, l'atribut name és comú a tots els radiobutton que estan relacionats, per la qual cosa la funció retorna una col·lecció d'elements.

  • getElementById(idelement): Retorna l'element XHTML l'atribut del qual coincideix amb el paràmetre indicat en la funció. Com l'atribut ha de ser únic per a cada element d'una mateixa pàgina, la funció retorna únicament el node desitjat.
var cabecera = document.getElementById("cabecera");
 
<div id="cabecera">
  <a href="/" id="logo">...</a>
</div>


  • getElementsByClassName("nomclass"): retorna una col·lecció de tots els elements en el document amb el nom de classe especificat, com un objecte nodelist. L'objecte nodelist representa una col·lecció de nodes. Els nodes poden ser accedits per nombres d'índex. L'índex comença en 0.
<div class="exemple">Primer Element amb class="exemple".</div>
<div class="exemple">Segon Element amb class="exemple".</div>

var x = document.getElementsByClassName("exemple");


  • document.querySelector() :Retorna el primer element que compleixi amb el criteri donat. Pot ser invocada sobre el document o sobre algun element. En cas d'usar-se sobre un element, les cerca es limita als fills d'aquest element.

Si la cerca no troba res, retorna null.

document.querySelector()

<h2 class="example">A heading with class="example"</h2>  <!--retorna la primera aparació-->
<p class="example">A paragraph with class="example".</p>   

document.querySelector(".example").style.backgroundColor = "red";
  • document.querySelectorAll() Retorna tots els elements que compleixin amb el criteri donat. A l'igual que querySelector pot ser invocada sobre el document o sobre algun element. Sempre retorna 1 nodelist.
/*Selecciona tots els elements i retorna un NodeList, després per cada iteració afeig un 'border'*/
var tags = document.querySelectorAll('h1,h2,h3,h4,h5,h6,div,p');
for (var i = tags.length - 1; i >= 0; i--) {
  tags[i].style.outline = "1px solid green";
}



Accedir als atributs d'un node

Els atributs XHTML dels elements de la pàgina es transformen automàticament en propietats dels nodes. Per accedir al seu valor, simplement s'indica el nom de l'atribut XHTML darrere del nom del node.

var enlace = document.getElementById("enlace");
alert(enlace.href); // muestra http://www...com
 
<a id="enlace" href="http://www...com">Enlace</a>

Per obtenir el valor de qualsevol propietat CSS del node, s'ha d'utilitzar l'atribut style. El següent exemple obté el valor de la propietat margin de la imatge:

var imagen = document.getElementById("imagen");
alert(imagen.style.margin);
 
<img id="imagen" style="margin:0; border:0;" src="logo.png" />

Creació i eliminació nodes de l'arbre

Creació de nodes XHTML simples

crear i afegir a la pàgina un nou element XHTML senzill consta de quatre passos diferents:

  • Creació d'un node de tipus Element que representi a l'element.
  • Creació d'un node de tipus Text que representi el contingut de l'element.
  • Afegir el node Text com a node fill del node Element.
  • Afegir el node Element a la pàgina, en forma de node fill del node corresponent al lloc en el qual es vol inserir l'element.

D'aquesta manera, si es vol afegir un paràgraf simple al final d'una pàgina XHTML, és necessari incloure el següent codi Javascript:

// Crear nodo de tipo Element
var parrafo = document.createElement("p");
 
// Crear nodo de tipo Text
var contenido = document.createTextNode("Hola Mundo!");
 
// Añadir el nodo Text como hijo del nodo Element
parrafo.appendChild(contenido);
 
// Añadir el nodo Element como hijo de la pagina
document.body.appendChild(parrafo);

Funcions utilitzades per a la creació del node:

  • createElement(etiqueta): Crea un node de tipus element que representa l'element XHTML.
  • createTextNode(contingut): crea un node de tipus text que emmagatzema el contingut textual (innerHTML).
  • nodepare.appendChild(nodefill): afegeix el nodefill com a fill de nodepare.

Eliminació de nodes XHTML

Per eliminar un node és molt senzill, només s'ha d'utilitzar la funció removeChild(nodeAeliminar). Exemple:

var parrafo = document.getElementById("provisional");
parrafo.parentNode.removeChild(parrafo);
 
<p id="provisional">...</p>

Per eliminar un node d'una pàgina XHTML s'invoca a la funció removeChild() des del valor parentNode del node que es vol eliminar. Quan s'elimina un node, també s'eliminen automàticament tots els nodes fills que tingui, per la qual cosa no és necessari esborrar manualment cada node fill.


Esdeveniments dinàmics

var btn = document.createElement("p");
    var contenido = document.createTextNode("Hola Mundo!");
    btn.appendChild(contenido);
    btn.addEventListener('click', function(){alert("hola mundo");}, false);
    document.body.appendChild(btn);


opció 2

var i = 1;
document.getElementById('creator').addEventListener('click',function(){
  var div = document.createElement('div');
  var text = document.createTextNode('New Div ' + i);
  div.appendChild(text);
  document.body.appendChild(div);
  i++;
});

document.addEventListener('click',function(e){
    // Fixed
    if(e.target.tagName.toLowerCase() === 'div'){
        console.log(e.target);
    }
 })

<div>
  Div actual
</div>
<button id='creator'>Crear</button>

Exercicis

Exercici Enllaços DOM

Crea un document HTML amb diferents enllaços i paràgrafs i digues:

  • Nombre d'enllaços de la pàgina
  • Direcció a la qual enllaça el penúltim enllaç
  • Nombre d'enllaços del tercer paràgraf


Exercicis

Bibliografia

https://www.w3schools.com/jsref/dom_obj_document.asp