Document Object Model (DOM)

DOM

Objetivos:

  • Entender el DOM y herencia de los nodes
  • Trabajar con varios node types


Javascript & DOM

Javascript & DOM (codepen)



- En páginas  HTML,  "document element" es siempre  "<html> element"

- Cada pieza está representada por un "node" de hasta 12 tipos diferentes.

Node Type:  someNode.nodeType

    • Node.ELEMENT_NODE (1)
    • Node.ATTRIBUTE_NODE (2)
    • Node.TEXT_NODE (3)
    • Node.CDATA_SECTION_NODE (4)
    • Node.ENTITY_REFERENCE_NODE (5)
    • Node.ENTITY_NODE (6)
    • Node.PROCESSING_INSTRUCTION_NODE (7)
    • Node.COMMENT_NODE (8)
    • Node.DOCUMENT_NODE (9)
    • Node.DOCUMENT_TYPE_NODE (10)
    • Node.DOCUMENT_FRAGMENT_NODE (11)
    • Node.NOTATION_NODE (12)
  • if (someNode.nodeType == 1) { value = someNode.nodeName}  // será el nombre del TAG
  • if (someNode.nodeType == 1) {var tipoNode = someNode.attributes[0].nodeType} // tipoNode = 2

Node Relationships

  • Todos los nodos en un documento tienen relaciones sobre otros nodos.
  • Cada nodo tiene la propiedad childNodes que contiene una NodeList.
    • es un array-like object, es decir, una colección de nodos como los devueltos por someNode.childNodes ó document.querySelectorAll () ...
    • Aunque no es un array soporta NodeList.foreach
    • var firstChild = someNode.childNodes [0] ;
    • var secondChild = nodeNode.childNodes.item(1) ;  // otro tipo de acceso
    • var count = someNode.childNodes.length; 
    • someNode.lastChild  ==  someNode.childNodes[someNode.childNodes.length-1 ]. // true
    • someNode.hasChildNodes() : indica si el nodo tiene uno o más hijos
    • No todos los node Types pueden tener childNodes  (ej: Node.ATTRIBUTE_NODE)



Manipulating Nodes

  • let returnedNode = someNode.appendChild( newNode ) ;
    • alert( returnedNode == newNode ) ; // true
    • alert( someNode.lastChild == newNode ) ; // true
  • let returnedNode = someNode.appendChild( someNode.firstChild ) ; Asumimos varios hijos de someNode
    • alert( returnedNode  ==  someNode.firstChild ) ;  // false
    • alert( returnedNode  ==  someNode.lastChild)  ;  // true
  • let returnedNode = someNode.insertBefore( newNode, null ) ;   insert como last child
    • alert( newNode == someNode.lastChild ) ;  // true
  • let returnedNode = someNode.insertBefore( newNode, someNode.firstChild) ;   insert com new first child
    • alert( returnedNode == newNode) ;  / true
    • alert( newNode == someNode.firstChild) ;  // true
  • let returnedNode = someNode.insertBefore( newNode, someNode.lastChild) ;
    • alert( newNode == someNode.childNodes[ someNode.childNodes.length -2 ])  ;     // true
  • let returnedNode = someNode.replaceChild( newNode, someNode.firstChild);  // replace first child. El nodo reemplazado sigue pertenciendo al document, pero sin ninguna referencia hacia él.
  • let returnedNode = someNode.replaceChild( newNode, someNode.lastChild);  // replace last child
  • let formerFirstChild = someNode.removeChild(  someNode.firstChild ) ;  // remove first child.  El nodo eliminado sigue pertenciendo al document, pero sin ninguna referencia hacia él.
  • let deepList = someNode.cloneNode( true ) ; clona el árbol entero someNode. El nodo clonado sigue pertenciendo al document, pero sin ningún padre asignado.
    • alert( deepList.childNodes.length) ;  //  > 0 
  • let shallowList = someNode.cloneNode( false ) ;  clona solo el nodo inicial, nó sus hijos
    • alert( shallowList.childNodes.length) ;  // = 0 

  •  isEqualNode(): Un nodo A es igual a un nodo B si se cumplen todas las condiciones siguientes: el valor del atributo nodeType de A y B es idéntico. ... Cada hijo de A es igual al hijo de B en el mismo índice.
    • let div1 = document.createElement("div");
    • div1.setAttribute("class", "box");
    • let div2 = document.createElement("div");
    • div2.setAttribute("class", "box");
    • alert( div1.isEqualNode(div2) );   // true
  • Ejemplo:

Document Type

  • Javascript representa document nodes vía Document type.
  • En los navegadores the document object es una instancia de HTMLDocument que a su vez hereda de la clase Document
  • Características
    • document.nodeType es 9
    • document.nodeName es #document
    • document.nodeValue es null
    • document.parentNode es null
    • ownerDocument es null
    • Child nodes puede tener:
      • DocumentType (max 1)
      • Element (max 1)
      • ProcessingInstruction
      • Comment
  • document.childNodes
    • NodeList (2)
      • 0 : <!DOCTYPE html>        [object   DocumentType]
      • 1 : <html ...> ..... </html>     [object   HTMLHtmlElement]     

Document Children

  • document.documentElement === document.childNodes[1] ;  // true
  • document.documentElement === document.firstChild ;  // true
  • document.body ;   // <body ...> ... </body>
  • document.doctype === document.childNodes[0] ;   // true

Document  Information

  • document.title
  • document.URL
  • document.domain
  • document.referrer

Locating Elements

  • document.getElementById("myDiv")
  • document.getElementsByTagName("img") ;  retorna un [object HTMLCollection]
  • document.getElementsByTagName("img").length ;  num. etiquetas img encontradas
  • document.getElementsByTagName("img")[0].src
  • document.getElementsByTagName("img").item(0).src
  • document.getElementsByTagName("img").namedItem("myImage")
  • document.getElementsByTagName("img")["myImage"]
  • document.getElementsByName("color")    retorna un [object HTMLCollection]

Special Collections

  • document.anchors    Contiene todos las <a> elementos con el atributo name
  • document.applets.    deprecated
  • document.forms.      Contiene todos las <form> elementos 
  • document.images.    Contiene todos las <img> elementos 
  • document.links.       Contiene todos las <a> elementos con el atributo href

Element Type

  • Es el elemento más utilizado.
  • Características:
    • nodeType es 1
    • nodeName es el tag name del elemento
    • nodeValue es null
    • parentNode puede ser un documento o elemento
    • Child nodes puede ser: Element, Text, Comment, ProcessingInstruction, CDATASection,o EntityReference.
  • El nombre de un tag del elemento es accesible vía la propiedad nodeName o tagName
    • let div = document.getElementById("myDiv")
    • alert(div.tagName);  // DIV
    • alert(div.tagName == div.nodeName) ;   // true

HTML Elements

  • Todos los HTML elements son representados por el HTMLElement type
  • HTMLElement hereda de Element y añade algunas propiedades.

Getting Attributes

  • Cada elemento puede tener cero o más atributos
  • Un elemento tiene la propiedad attributes que es una colección NamedNodeMaps y cada uno de sus elementos es un nodo tipo atributo Node.ATTRIBUTE_NODE (2)
  • En el apartado anterior hemos visto que hay unas propiedades que pueden recuperarse con: elemento.id, elemento.title, etc... 
  • Custom Attributes no puede recuperarse con elemento.customAttribute. Se hace con getAttribute()
  • Los siguientes métodos trabajan con los atributos
    • getAttribute()
    • setAttribute()
    • removeAttribute()
  • Ej: <div id="myDiv" class="bd" title="Body Text" mySpecialAttribute="enric"></div>
    • var div = document.getElementById("myDiv");
    • alert(div.getAttribute("id")) ;   // "myDiv"
    • alert(div.getAttribute("class")) ;   // "bd"
    • alert(div.getAttribute("title")) ;   // "Body Text"
    • alert(div.getAttribute("mySpecialAttribute")) ;   // "enric" 
  • Dos tipos de atributos tienen la property name que no mapea directamente el mismo valor retornado por getAttribute().
    • style 
      • Si accedemos a style con getAttribute(), el style atributo contiene CSS texto
      • Si accedemos con la style propiedad retorna un objeto.
    • event-handler attributes

Setting Attributes

  • Crea o reemplaza un atributo.
  • Trabaja de la misma manera HTML attributes y Custom attributes
  • Ej: myElement.setAttribute("title", "nuevo titulo")

Remove Attributes

  • myElement.removeAttribute("nombre_atributo")

Attributes property

  • Elment Type es el único tipo de nodo que utiliza attributes property.
  • Attributes property contiene un NameNodeMap que es una "live collection" similar a NodeList.
  • Cada atributo de un elemento es representado por un attr node y almacenado en NameNodeMap object.
  • NameNodeMap object tiene los siguientes métodos:
    • getNamedItem(name)
    • removeNamedItem(name)
      • let  oldAttr = element.attributes.removeNamedItem("id")
    • setNamedItem(node)
      • element.attributes.setNamedItem(newAttr). Poco utilizado.
    • item(pos)
  • Cada nodo de attributes property tiene:
    • nodeName es el nombre del atributo
      • let id = element.attributes.getNamedItem("id").nodeName
    • nodeValue es el valor del atributo
      • let value_id = element.attributes.getNamedItem("id").nodeValue
  • Shorthand notation
    • let id = element.attributes["id"].nodeName
    • let value_id = element.attributes["id"].nodeValue
    • element.attributes["id"].nodeValues = "someOtherId"
  • Por comodidad se utilizan más
    • getAttribute()
    • removeAttribute()
    • setAttribute()
  • Ejemplo iteración sobre los atributos de un elemento 

Creating Elements

  • Nuevos elementos se pueden crear con document.createElement(nomEtiquetaTagElement)
    • let div = document.createElement("div")
    • Al crearlo se actiuliza su ownerDocument property
    • No surge efecto hasta que el element creado se añade con 
      • appendChild()
      • insertBefore()
      • replaceChild()
  • Ejemplo crear elemento

Element Children

  • Los elementos pueden tener hijos
  • childNodes property contiene todos los hijos
  • Al iterar la propiedad childNodes es conveniente tratar solo los elementos tipo Node.ELEMENT_NODE (1)

Text Type

  • Text nodes son representados por Text type y contiene texto plano que es interpretado literalmente y puede contener escaped HTML caracteres pero no HTML code.
  • Características:
    • nodeType es 3
    • nodeName es "#text"
    • nodeValue es el texto del nodo
    • parentNode es un elemento
    • Child nodes no está soportado
  • El texto contenido puede se accedido por:
    • nodeValue property
    • data property 
  • Métodos para text nodes
    • appendData(text)  Añade texto al final del nodo
    • deleteData(offset, count)  Elimina count number caracteres a partir de la posición offset
    • insertData(offset, text)  Inserta text a partir de la posición offset
    • replaceData(offset, count, text)  Reemplaza el texto a partir de la posición offset
    • splitText(offset)  Divide el texto del nodo en dos text nodes separados por la posición de offset
    • substringData(offset, count)  Extrae un string del texto a partir de offset hasta offset + count
    • nodeValues.lenght
    • data.length
    • Ejemplo-1
    • Ejemplo-2

Creating Text Nodes 

Normalizing Text Nodes

  • Text nodes hermanos pueden llevar a confusión en el DOM
  • El método normalize() fusiona los text nodes en uno.
  • Ejemplo:

Splitting Text Nodes

  • splitText() es el método opuesto a normalize()
  • Ejemplo

Comment Type

  • Comment Type representa los comentarios en el DOM
  • Características del comment node
    • nodeType es 8
    • nodeName es "#comment"
    • nodeValue es el contenido del comentario
    • parentNode es un Document o Element
    • Child nodes no está soportado
  • Ejemplo

CDATASection Type

  • CDATASection es específico para XML y está representado por CDATASection type que hereda de textType
  • Características
    • nodeType es 4
    • nodeName es "#cdaa-section"
    • nodeValue es el contenido de CDATA section
    • parentNode es un Document o Element
    • Child nodes no está soportado

DocumentType Type

  •  DocumentType object contiene toda la información del document doctype
  • Características:
    • nodeType es 10
    • nodeName es el nombre del doctype
    • nodeValue es null
    • parentNode es un Document
    • Child nodes no está soportado

DocumentFragment Type

  • Son Nodos del DOM que nunca forman parte del DOM tree.
  • Características:
    • nodeType es 11
    • nodeName es "#document-fragment"
    • nodeValue es null
    • parentNode es null
    • Child nodes puede ser: Element, ProcessingInstruction, Comment, Text, CDATASection o EntityReference
  • El caso de uso mas común es crear un document fragment, agregar elementos al document fragment y luego agregar el document fragment al DOM tree.
  • Dado que el document fragment es generado en memoria y no como parte del DOM tree, agregar elementos al mismo no castiga al navegador porque no lo renderiza.
  • document.createDocumentFragment() crea un fragment node
  • Es adecuado para crear listas
  • Ejemplo

Attr Type

  • Element attributes son representados  por el Attr type en el DOM.
  • Técnicamente, attributes son nodos que existen en attributes property de un elemento.
  • Características
    • nodeType es 11
    • nodeName es el attribute name
    • nodeValue es el attribute value
    • parentNode es null
    • Child nodes puede ser Text o EntityReference en XML
  • Aunque son nodos, attributes no son considerados parte del DOM document tree
  • Attributes nodes son raramente reverenciados directamente. 
  • Generalmente se usan más: getAttribute(), setAttribute() y removeAttribute()
  • Hay tres propiedades en un Attr object
    • name: attribute name (igual que nodeName)
    • value: attribute value (igual que nodeValue)
    • specified: es un booleano que indica si el atributo fue especificado en el código o és su valor por defecto
  • document.createAttribute() crea un nuevo node attribute
  • Ejemplo:

Dynamic Scripts

  • Para crear: <script type="text/javascript" src="client.js"></script>
    • let script = document.createElement("script");
    • script.type = "text/javascript";
    • script.src = "client.js";
    • document.body.appendChild(script);
  • Ejemplo-1:
  • Ejemplo-2:

Dynamic Styles

  • Para crear: <link rel=stylesheet" type="text/css" href="styles.css">
    • let link = document.createElement("link");
    • link.rel = "stylesheet";
    • link.type = "text/css";
    • link.href = "styles.css";
    • let head = document.getElementByTagname("head") [0];
    • head.appendChild(link);
  • Ejemplo-1:
  • Ejemplo-2:

Using NodeLists

  • Entender NodeList y sus parientes NamedNodeMap HTMCollection es importante.
  • Si iteramos un NodeList para insertar, debemos ir con cuidado para no crear un infinite loop
  • Ejemplo: Mal, se crea un infinite loop porque length va aumentando a medida que vamos agregando divs. Recordar que NodeList es un live collection y cada vez que se modifica se renderiza todo de nuevo.
    • let divs = document.getElementsByTagName("div");
    • let i;
    • let div;
    • for ( i=0; i < divs.length; i++) {
    • div = document.createElment("div");
    • document.body.appendChild(div);
    • }
  • Ejemplo: Bien, se crea una variable len con el valor
    • let divs = document.getElementsByTagName("div");
    • let I;
    • let len;
    • let div;
    • for ( i=0; len=divs.length; i++) {
    • div = document.createElment("div");
    • document.body.appendChild(div);
    • }

SUMMARY

  •  Document Object Model DOM Se compone de una serie de tipos de nodos.
    • El tipo de nodo base es nodo, que es una representación abstracta de una parte individual de un documento. Todos los otros tipos heredan de Node.
    • Document type  representa un documento completo y es el nodo raíz de una jerarquía.
    • En javascript, Document object es una instancia de Document, que permite la consulta y recuperación de nodos de varias maneras diferentes.
    • Un element node representa todos los elementos HTML o XML en un documento y se puede utilizar para manipular sus contenidos y atributos.
    • Existen otros node types para text contents, comments, document types, sección CDATA y documents fragments.
  • La manipulación del DOM es la mas cara operación en rendimiento que se puede hacer en javascript cuando manipulamos NodeList
  • Por esto es importante limitar al máximo el número de manipulaciones del DOM



Entradas populares de este blog

Angular

Spotify