NF2 - Model d'objectes del document

De wikiserver
La revisió el 20:12, 7 març 2023 per Jcomas (Discussió | contribucions) (Exercici Carta Restaurant - continuació)
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 curs 2022/2023

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
solucio_enllaços

Exercici mostrar/ocultar nodes DOM

Afegeix a l'exercici anterior un combo box (<select>) amb els valors 1, 2 i 3 de text amb l'etiqueta "paràgraf" i dos botons amb el text "mostrar" i "ocultar".

  • Quan es faci click al botó mostrar, es mostrarà (estil "display:block;") el paràgraf indicat pel valor seleccionat al combo box.
  • Quan es faci click al botó ocultar, s'ocultarà (estil "display:none;") el paràgraf indicat pel valor seleccionat al combo box.

Exercici Carta Restaurant

La carta d'un restaurant té 5 primers plats, 5 segons plats i 5 postres/cafè. Cada plat tindrà un preu associat. Fes una pàgina que permeti prendre una comanda al cambrer. Primer es mostraran els primers plats seleccionats, a continuació els segons plats seleccionats, a continuació els postres/cafè seleccionats i finalment el preu total de la comanda.

  • Inicialment la comanda estarà en blanc i el preu serà de 0,00 €.
  • Al peu de pàgina hi haurà tres botons amb els texts "afegir primer", "afegir segon" i "afegir postre/cafè" respectivament.
  • Quan es premi el botó "afegir primer" s'afegirà un combo box (<select>) amb els possibles primers plats a la secció de primers plats de la pàgina.
  • Els botons "afegir segon" i "afegir postre/cafè" tindran un comportament equivalent pels segons i postres/cafès respectivament.
  • Sempre que es canvii el valor seleccionat a un dels combos es recalcularà el preu total de la comanda.

Exercici Carta Restaurant - continuació

Afegeix al peu de pàgina tres botons amb els texts "Borrar primer", "Borrar segon" i "Borrar postre/cafè".

  • El botó "Borrar primer" eliminarà l'ultim dels combos de primers plats.
  • Els botons "Borrar segon" i "Borrar postre/cafè" tindran un comportament equivalent pels segons plats i pels postres/cafès respectivament.

Exercicis cursos passats

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
solucio_enllaços

Exercici llista

Utilitzar les funcions DOM per crear nous nodes i afegir-los a una llista ordenada existent.

solucio_llista_dom

Exercici Mostra Direcció

Crea aquesta llista d'enllaços, en passar el ratolí per la llista, mostra la direcció a la qual apunten a l'editor de text (dins un input)

solucio_mostra_direccio

Exercici Canvi Fons

Crea una pàgina amb tres botons que ens permetin seleccionar la imatge de fons del document.

solucio_boto_fons

Exercici llista afegir Altre

Realitzar un script que quan premem en l'opció d'uns dels radiobutton (Html, Css, Altre) en el cas de ser l'opció 'Altre' es mostri l'editor de text (input)

solucio_afegir_altre

Ejercicio Añadir Diversos Elementos

Se dispondrá de 5 botones:

"Crear Párrafo", "Crear Imagen", "Borrar último", "Borrar Primero", "sustituir primer párrafo por vacio"

Para poder Crear un párrafo deberá existir un textArea donde introduciremos un texto que irá añadiéndose cada vez que cliquemos y de color rojo.

El botón crear Imagen nos pedirá un prompt de una url o dirección de una imagen y después su atributo "alt" para darle una descripción.

Borrar último, borrará el último elemento creado.

Borrar primero, borrará el primer elemento creado

El último botón se tratará de sustituir el primer párrafo por otro que tenga como texto "vacio". (replaceChild)

solucio_Anadir_diversos_elementos

Exercici Web Dinámica

a) Crea un HTML amb els següents camps: Input text1 : Que demani la etiqueta que es vol crear Input text2 : Que demani On es vol crear (una altre etiqueta que ja hauria d'existir) Boto crear: Crea el node del input text1 com a fill de input text2.

solucio_crea_html

b)Creació automática: Crea automàticament una Web via DOM que contingui: Tants paràgrafs com text trobis a la web http://www.lipsum.com/ Cada paràgraf ha de tenir un botó per tal de poder-lo eliminar.

solucio_web_dom

Exercici Botons Celestials

Crea una pàgina web amb dos botons amb el text:

  • Text boto 1: 'Angelet'
  • Text boto 2: 'Diablet'

El comportament ha de ser el següent: Cada vegada que es clica sobre un botó 'Angelet' es creen n botons més, on n és un número aleatori entre 1 i 10 i aquests botons poden ser 'Angelets o Diablets'. Cada vegada que es clica sobre un botó 'Diablet' s'eliminen n botons, on n és un número aleatori entre 1 i 20.

solucio_botons_celestials

Bibliografia

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