El DOM
Tabla de contenidos
Qué es el DOM
El DOM es una API para XML1, lo que sin siglas quiere decir que es una capa de programación intermedia que representa un documento y que nos permite modificarlo. Por decirlo de otra manera, es una serie de funciones y procedimientos que nos permiten trabajar sobre un modelo abstracto de un documento, que sirve como medio de comunicación entre nuestro lenguaje de programación —en este caso JavaScript— y los contenidos del documento.
El DOM es una interfaz independiente de cualquier lenguaje de programación, pero aquí voy a centrarme en su uso por medio de JavaScript.
Pongamos un ejemplo. Tenemos un documento como el siguiente:
y por medio de JavaScript queremos modificar la lista. ¿Cómo lo hacemos? Necesitamos que haya alguna manera de indicarle al agente de usuario —por ejemplo, nuestro navegador— que de todos los caracteres que componen ese documento nos interesa seleccionar los que componen el que es un elemento
ul
. Ahí es donde entra en juego el DOM, que permite que el navegador se represente el documento como un árbol jerárquico, algo así:- El código anterior, representado gráficamente como un árbol jerárquico
Ahora sí, el navegador no interpreta simplemente el documento como una serie de caracteres, sino que «comprende» que existen una serie de elementos con sus propiedades, y que la relación entre todos ellos es una relación estructural. Así, por ejemplo, se puede pedir al navegador que devuelva una lista de los hijos del elemento
ul
.
Una ventaja de esta interfaz es que la manera de trabajar con ella es análoga a la forma de emplear selectores de CSSbasados en el árbol de parentesco que ya vimos.
El modelo resultante del documento original es un árbol, y una vez creado es este árbol lo que representa el navegador, y también lo que modificamos con nuestros scripts.
Los nodos del árbol
Como se ve, el DOM es un modelo jerárquico. En la representación que he ofrecido antes, todo aquello situado en el origen o el final de una rama del árbol es un nodo, y los nodos establecen entre sí relaciones de parentesco. Por ejemplo, el elemento
ul
es hijo de body
, padre de dos li
, hermano de h1
y los tres p
, descendiente de html
y ascendente del texto de cualquiera de los li
.
Así, todo documento puede representarse como un conjunto de nodos relacionados entre sí. Además, existe un número limitado de tipos de nodos que son suficientes para representar cualquier documento, y que han sido definidos por el W3C:
Nodo | Descripción | ¿Hijos? |
---|---|---|
Document | Este nodo es único, y representa el documento en sí. | Sí |
DocumentType | Este nodo también es único, y representa la referencia a la DTD del documento, es decir, la línea del <!DOCTYPE> . | No |
DocumentFragment | Representa un fragmento del modelo total del árbol del documento. | Sí |
Element | Representa un elemento. | Sí2 |
Attr | Representa un atributo de un elemento, en combinación con su valor. | No |
Text | Representa un texto dentro de un elemento, o de una sección CData. | No |
CDataSection | Representa una sección <[!CDATA[]]> . | Sí3 |
Entity | Representa la definición de una entidad en la DTD. | No |
EntityReference | Representa una referencia de entidad. | No |
ProcessingInstruction | Representa una instrucción de proceso. | No |
Comment | Representa un comentario en el código XML. | No |
Notation | Representa una notación definida en la DTD. | No |
Así, cuando el agente de usuario mapea un documento, lo que hace es asignar a cada nodo una constante que lo identifica. Dependiendo del tipo de nodo, éste aceptará una serie de propiedades y métodos, y podrá tener hijos o no.
PROPIEDADES GENERALES DE LOS NODOS
Independientemente del tipo de nodo, hay una serie de propiedades generales que comparten, y que recojo en la tabla siguiente:
Propiedad | Descripción | Devuelve |
---|---|---|
nodeName | El nombre del nodo, que se define dependiendo del tipo de nodo. | Una cadena literal |
nodeValue | El valor del nodo, que se define dependiendo del tipo de nodo. | Una cadena literal |
nodeType | Un número que representa el tipo de nodo del que se trata. | Un número del 1 al 12 |
ownerDocument | El documento al que pertenece el nodo. | El documento |
firstChild | El primer hijo del nodo. | Un nodo |
lastChild | El último hijo del nodo. | Un nodo |
childNodes | Una lista de los hijos de un nodo. | Una matriz de nodos |
previousSibling | El hermano anterior al nodo. | Un nodo, o null si el nodo es el primer hijo |
nextSibling | El hermano siguiente al nodo. | Un nodo, o null si el nodo es el último hijo |
hasChildNodes | Indica si el nodo tiene hijos o no. | Un booleano |
attributes | Una lista con los atributos del nodo. | Una matriz con los atributos |
La sintaxis para acceder a estas propiedades es la misma que vimos para los objetos nativos de JavaScript, por lo que no voy a detenerme a explicarla aquí. No obstante, vamos a emplear muchas de ellas en los ejemplos de las secciones siguientes.
En cuanto a los métodos comunes, les dedico su propia sección:
appendChild
, insertBefore
, replaceChild
,removeChild
y cloneNode
.IDENTIFICAR EL TIPO DE NODO
En algún momento podemos necesitar identificar el tipo de un nodo, y para eso contamos con la propiedad
nodeType
, que devuelve un número. A continuación recojo el tipo de nodo que corresponde a cada número:Tipo de nodo | Constante4 | Número |
---|---|---|
Element | Node.ELEMENT_NODE | 1 |
Attr | Node.ATTRIBUTE_NODE | 2 |
Text | Node.TEXT_NODE | 3 |
CDataSection | Node.CDATA_SECTION_NODE | 4 |
EntityReference | Node.ENTITY_REFERENCE_NODE | 5 |
Entity | Node.ENTITY_NODE | 6 |
ProcessingInstruction | Node.PROCESSING_INSTRUCTION_NODE | 7 |
Comment | Node.COMMENT_NODE | 8 |
Document | Node.DOCUMENT_NODE | 9 |
DocumentType | Node.DOCUMENT_TYPE_NODE | 10 |
DocumentFragment | Node.DOCUMENT_FRAGMENT_NODE | 11 |
Notation | Node.NOTATION_NODE | 12 |
VALORES Y NOMBRES DE LOS NODOS
Además, dos de las propiedades listadas anteriormente nos proporcionan datos sobre un nodo:
nodeName
y nodeValue
. Sin embargo, a diferencia de nodeType
, su valor no es una constante, sino que dependiendo del tipo de nodo el valor que devuelven difiere:Tipo de nodo | nodeName | nodeValue |
---|---|---|
Element | El nombre del elemento, en mayúsculas | null |
Attr | El nombre del atributo, en minúsculas | El valor del atributo como una cadena literal |
Text | #text | El contenido del nodo como una cadena literal |
CDataSection | #cdata-section | El contenido del nodo como una cadena literal |
EntityReference | El nombre de la entidad de referencia | null |
Entity | El nombre de la entidad | null |
ProcessingInstruction | El nombre del destino de la instrucción | El contenido del nodo como una cadena literal |
Comment | #comment | El texto del comentario como una cadena literal |
Document | #document | null |
DocumentType | El nombre del tipo de documento | null |
DocumentFragment | #document-fragment | null |
Notation | El nombre de la notación | null |
Con esto, hemos dado el primer paso para conocer el DOM, aunque lo visto no es más que un ápice del nivel más bajo y básico de esta interfaz. No obstante, esta información es necesaria si se quiere trabajar con ella, y avanzar en el estudio de los siguientes niveles.
Niveles del DOM
Dejo fuera de esta sección tanto el DOM 0 como el DHTML5. Si alguien tiene curiosidad, remito a Level 0 DOM (inglés) e Intermediate DOMs (inglés) en quirksmode.org (inglés).
A diferencia de otras recomendaciones como pueda ser la de XHTML 1.0, el DOM no se recoge en un único documento, sino que consiste en tres niveles —a día de hoy—, y cada uno de ellos está a su vez compuesto por varias recomendaciones referidas a distintos aspectos de la interfaz:
- DOM 1:
- DOM Core (inglés): Define el conjunto mínimo de objetos e interfaces con los que manipular la estructura de un documento, ya se trate de un documento HTML o XML, o cualquier lenguaje basado en éste.
- DOM HTML (inglés): Define una serie objetos y métodos específicos de un documento HTML, y que por extensión también pueden aplicarse a un XHTML. Es importante conocerlo bien porque en muchas ocasiones hay que emplearlo en un script como alternativa para Internet Explorer de métodos del DOM Core 1, como por ejemplo
getAtribute
ysetAttribute
.Sobre la inconsistencia del soporte de Explorer para estos dos métodos, ver «Una nota sobre el soporte de getAttribute y setAttribute en Internet Explorer 6».
- DOM 2:
- DOM Core (inglés): Extiende las interfaces definidas en el DOM Core 1, por ejemplo añadiendo soporte para espacios de nombre, y permitiendo así poder manipular secciones del documento asociadas a uno de ellos.
- DOM Views (inglés): Define lo que es una «vista» de un documento, es decir, el documento cuando es representado en un agente de usuario —por ejemplo cuando se le aplica una hoja de estilo en un navegador—, en contraposición a la «vista abstracta» del documento en sí. Sí, es casi metafísica.
- DOM Events (inglés): Especifica qué es un evento, sus tipos, y qué son los procesos de burbuja, captura y cancelación6. Además, entre otras muchas cosas, define un método maravilloso:
addEventListener
(inglés). - DOM Style (inglés): Define una interfaz para poder extraer información y manipular la/s hojas/s de estilo de un documento.
- DOM Traversal and Range (inglés): Define la interfaz avanzada y los métodos con los que desplazarse por el árbol del documento, y para seleccionar partes del mismo.
- DOM HTML (inglés): Amplía el DOM HTML 1, e indica explícitamente que vuelve el anterior obsoleto.
- DOM 3:
- DOM Core (inglés): Amplía aún más el contenido de DOM Core 2.
- DOM Load and Save (inglés): Define una interfaz con la que cargar documentos XML que puedan integrarse en el árbol de otro documento.
- DOM Validation (inglés): Define una interfaz que permite asegurar que la estructura de un documento modificado dinámicamente sigue siendo válida.
Para el nivel 3 del DOM hay muchos más documentos que tratan otros aspectos de esta interfaz (inglés), pero no tienen todavía la categoría de Recomendaciones.
En las siguientes secciones sólo veremos una ínfima parte de lo que contiene la especificación del DOM Core 1.
Notas
- Existen otras API para XML, como SAX.
- Éste es el único tipo de nodo que puede tener como hijo uno del tipo
attr
. - Sólo acepta como hijos nodos de tipo
Text
. - El número devuelto por
nodeType
es una referencia; estrictamente, al mapear el árbol del documento es una constante la que se asigna a cada nodo para identificarlo. En realidad la mayor parte de las veces para trabajar basta con el número, pero saber algo más no hace daño nunca. - A pesar de que pueda parecerlo, DHTML no es ninguna especificación de un lenguaje, sólo un nombre comercial para englobar las propiedades de los modelos de capas y los métodos con los que operar con ellas en las versiones 4 de Explorer y Netscape. Cosa del pasado, vamos.
- Veremos estos conceptos al tratar
addEventListener
.
0 comentarios:
Publicar un comentario