7 days of WordPress plugins, themes & templates - for free!* Unlimited asset downloads! Start 7-Day Free Trial
Advertisement
  1. Code
  2. Web Development

Javascript y DOM: Lección 2

Scroll to top
Read Time: 20 mins

Spanish (Español) translation by Valentino (you can also view the original English article)

Hola y bienvenido de nuevo a la serie "JavaScript y DOM". La última vez cubrimos algunos conceptos básicos de JavaScript y tocamos varios aspectos del Modelo de objetos de documento, incluido cómo acceder a los nodos y atravesar el DOM.  Hoy cubriremos cómo manipular elementos dentro del DOM y discutiremos el modelo de eventos del navegador.

Elementos manipuladores

En la última lección, cubrimos los pasos necesarios para acceder a una colección de nodos DOM o un nodo DOM singular. La verdadera magia ocurre cuando luego manipulas ciertas propiedades que resultan en lo que se conoce ampliamente como "comportamiento".

Cada nodo DOM tiene una colección de propiedades; la mayoría de estas propiedades proporcionan abstracciones para determinadas funciones. Por ejemplo, si tienes un elemento de párrafo con un ID de 'intro', podrías cambiar fácilmente el color de ese elemento a través de la API DOM:

Para ilustrar la naturaleza de objeto/propiedad de esta API, podría ser más fácil de entender si la dividimos asignando cada objeto a una variable:

Ahora que tenemos una referencia al objeto 'estilo' del párrafo, podemos agregar otros estilos CSS:

Aquí solo estamos usando nombres de propiedades CSS básicos. La única diferencia es que donde normalmente se encuentra un guión ('-'), el texto está en formato camel.  Entonces, en lugar de 'margin-top' usamos 'marginTop'. Lo siguiente, por ejemplo, no funcionaría y produciría un error de sintaxis:

Se puede acceder a las propiedades en forma de matriz. Entonces, con este conocimiento podríamos crear una pequeña función para cambiar cualquier estilo de un elemento dado:

Este es solo un ejemplo; para ser honesto, probablemente no sea una función muy útil ya que, sintácticamente, es más rápido usar los medios convencionales mostrados anteriormente (por ejemplo, elem.style.color = 'red').

Además de la propiedad 'estilo', hay muchas otras que puedes usar para manipular ciertos aspectos de un nodo/elemento. De hecho, si tienes Firebug instalado, debes intentar "inspeccionar un elemento", luego haz clic en la pestaña "DOM" (normalmente a la derecha o debajo del panel de visualización del elemento) para ver todas sus propiedades:

DOM Element properties, in the Firebug addon for FirefoxDOM Element properties, in the Firebug addon for FirefoxDOM Element properties, in the Firebug addon for Firefox Propiedades del elemento DOM, en Firebug

Se puede acceder a todas las propiedades utilizando la notación de puntos convencional (por ejemplo, Element.tabIndex).  No todas las propiedades son tipos de datos primitivos (cadenas, números, booleanos, etc.); la propiedad 'estilo', por ejemplo, que discutimos anteriormente, es un objeto que contiene sus propias propiedades.  Muchas de las propiedades de un elemento solo serán legibles; lo que quiero decir con esto es que no se puede cambiar su valor. Por ejemplo, no puedes cambiar directamente la propiedad 'parentNode' de un nodo.  El navegador generalmente arrojará un error si intentas cambiar una de estas propiedades de solo lectura: p. Ej. ERROR: "configurando una propiedad que solo tiene un getter". Es algo a tener en cuenta ...

Un requisito común es cambiar el contenido de un elemento. Hay algunas formas diferentes de hacer esto. De lejos, la forma más fácil es usar la propiedad 'innerHTML', así:

El único problema con este método es que no está especificado en ningún estándar y no está en la especificación DOM.  Si no te molesta eso, continúa y utilízalo. De todos modos, normalmente es mucho más rápido que los métodos DOM convencionales, que trataremos a continuación.

Nodos

Al crear contenido a través de la API DOM, debes tener en cuenta dos tipos diferentes de nodos, un nodo de elemento y un nodo de texto. Hay muchos otros tipos de nodos, pero estos dos son los únicos importantes por ahora.

Para crear un elemento usa el método 'createElement' y para crear un nodo de texto usa el método 'createTextNode', ambos se muestran a continuación:

Aquí estamos usando el método 'appendChild' para agregar nuestro nuevo nodo de texto al párrafo.  Hacerlo de esta manera lleva un poco más de tiempo que el método innerHTML no estándar, pero aún es importante conocer ambas formas para que puedas tomar la decisión correcta. Aquí hay un ejemplo más avanzado usando métodos DOM:

También hay un método DOM 'insertBefore' que se explica por sí mismo. Usando estos dos métodos ('insertBefore' y 'appendChild') podemos crear nuestra propia función 'insertAfter':

La función anterior verifica la existencia del próximo hermano del objetivo dentro del DOM, si existe, insertará el nodo 'viñeta' antes del próximo hermano del objetivo; de lo contrario, asumirá que el objetivo es el último hijo de un elemento y así está bien agregar la viñeta como hijo del padre.  La API DOM no nos proporciona el método 'insertAfter' porque no es necesario, podemos crearlo nosotros mismos.

Hay bastante más que aprender sobre la manipulación de elementos dentro del DOM, pero lo anterior debería ser una base suficiente sobre la que puedes construir.

Eventos

Los eventos del navegador son el núcleo de cualquier aplicación web y la mayoría de las mejoras de JavaScript. Es a través de estos eventos que definimos cuándo sucederá algo.  Si tienes un botón en tu documento y necesitas que se realice alguna validación del formulario cuando se hace clic en él, entonces usarías el evento 'clic'. A continuación se muestra una descripción general de la mayoría de los eventos de navegador estándar:

Nota: Como discutimos la última vez, DOM y el lenguaje JavaScript son dos entidades separadas. Los eventos del navegador son parte de la API DOM, no son parte de JavaScript.

Eventos de mouse

  • 'mousedown': el evento mousedown se activa cuando el dispositivo señalador (generalmente un mouse) se presiona hacia abajo sobre un elemento.
  • 'mouseup': el evento mouseup se activa cuando el dispositivo señalador (generalmente un mouse) se suelta sobre un elemento.
  • 'click': el evento de clic se define como un mousedown seguido de un mouseup en exactamente la misma posición.
  • 'dblclick': este evento se activa cuando se hace clic dos veces en un elemento en rápida sucesión en la misma posición.
  • 'mouseover': el evento mouseover se activa cuando el dispositivo señalador se mueve sobre un elemento.
  • 'mouseout': el evento mouseout se activa cuando el dispositivo señalador se mueve fuera de un elemento. (lejos de un elemento)
  • 'mousemove': el evento mousemove se activa cuando el dispositivo señalador se mueve mientras se coloca el cursor sobre un elemento.

Eventos de teclado

  • 'keypress': este evento se activa cada vez que se presiona una tecla del teclado.
  • 'keydown': este evento también se activa cada vez que se presiona una tecla, se ejecuta antes del evento 'keypress'.
  • 'keyup': este evento se activa cuando se suelta una tecla, después de los eventos de 'keydown' y 'keypress'.

Eventos de formulario

  • 'select': este evento se activa cuando se selecciona texto dentro de un campo de texto (entrada, área de texto, etc.).
  • 'change': este evento se activa cuando un control pierde el foco de entrada y / o el valor se ha modificado desde que ganó el foco.
  • 'submit': este evento se activa cuando se envía un formulario.
  • 'reset': este evento se activa cuando se restablece un formulario.
  • 'focus': este evento se activa cuando un elemento recibe el foco, normalmente desde un dispositivo señalador.
  • 'blur': este evento se activa cuando un elemento pierde el foco, generalmente desde un dispositivo señalador.

Otros eventos

  • 'load': este evento se activa cuando el agente de usuario termina de cargar todo el contenido de un documento, incluidos el contenido, las imágenes, los marcos y los objetos. Para elementos, como 'IMG', se activa cuando el contenido en cuestión ha terminado de cargarse.
  • 'resize': este evento se activa cuando se cambia el tamaño de la vista del documento. (es decir, cuando se cambia el tamaño del navegador).
  • 'scroll': este evento se activa cuando se desplaza el documento.
  • 'unload': este evento se activa cuando el agente de usuario elimina todo el contenido de una ventana o marco, es decir, cuando abandona una página.

Hay muchos más eventos para elegir. Los que se muestran arriba son los principales con los que te encontrarás con frecuencia en el código JavaScript. Ten en cuenta que algunos de ellos tienen diferencias sutiles entre navegadores. Además, ten en cuenta que muchos navegadores implementan eventos propietarios, por ejemplo, hay bastantes eventos específicos de Gecko, como 'DOMContentLoaded' o 'DOMMouseScroll'; puedes leer más sobre estos aquí: https://developer.mozilla.org / es / Gecko-Specific_DOM_Events

Manejo de eventos

Hemos cubierto los eventos reales, pero aún tenemos que discutir el proceso de adjuntar una función a un evento. Aquí es donde ocurre la magia.  Todos los eventos enumerados anteriormente ocurrirán independientemente de si has escrito o no JavaScript, por lo que para aprovechar su poder, debes registrar "controladores de eventos", este es un término elegante para describir una función que se usa para manejar un evento.  A continuación, se muestra un ejemplo sencillo que utiliza el modelo básico de registro de eventos (también conocido como "registro de eventos tradicional"):

Registro básico de eventos:

Tenemos un botón HTML con un ID de 'my-button' y hemos accedido a él usando el comando 'document.getElementById'. Luego, estamos creando una nueva función que luego se asigna a la propiedad DOM 'onclick' del botón. ¡Eso es todo al respecto!

El modelo de "registro básico de eventos" es tan simple como parece. Prefija el evento que está buscando con 'on' y accede a él como una propiedad de cualquier elemento con el que esté trabajando.  Esta es esencialmente la versión discreta de hacer algo como esto (que no recomiendo):

El manejo de eventos en línea (usando atributos HTML) es muy molesto y hace que tu sitio web sea mucho más difícil de mantener.  Es mejor usar JavaScript discreto y tenerlo todo contenido dentro de los respectivos archivos '.js' que se pueden incluir en el documento cuando sea necesario.  Ya que estamos en el tema de JavaScript discreto, me gustaría corregir la idea errónea de que las bibliotecas como jQuery hacen "posible codificar discretamente"; esto no es cierto.  Cuando usas jQuery, es igual de fácil hacer las cosas de manera incorrecta. La razón por la que no debe utilizar el manejo de eventos en línea es exactamente la misma que la razón por la que no debes aplicar estilos CSS en línea (usando style = "").

Registro avanzado de eventos:

No dejes que este nombre te engañe, solo porque se llame "avanzado" no significa que sea mejor de usar; de hecho, la técnica que discutimos anteriormente ("registro básico de eventos") es perfectamente adecuada la mayor parte del tiempo. Sin embargo, el uso de la técnica básica tiene una limitación clave; no puedes vincular más de una función a un evento.  En realidad, esto no es tan malo, porque puedes llamar a cualquier número de otras funciones desde esa única función, pero si necesitas más control, entonces hay otra forma de registrar controladores, ingresa el "modelo avanzado de registro de eventos".

Este modelo te permite vincular varios controladores a un solo evento, lo que significa que se ejecutarán múltiples funciones cuando ocurra un evento. Además, este modelo te permite eliminar fácilmente cualquiera de los controladores de eventos vinculados.

Estrictamente hablando, hay dos modelos diferentes en esta categoría; del W3C y de Microsoft. El modelo W3C es compatible con todos los navegadores modernos, excepto IE, y el modelo de Microsoft solo es compatible con IE. Así es como usaría el modelo de W3C:

Y aquí está lo mismo, pero para IE (modelo de Microsoft):

Y aquí está la función 'introClick':

Debido al hecho de que ninguno de los modelos funciona en todos los navegadores, es una buena idea combinarlos en una función personalizada. Aquí hay una función 'addEvent' muy básica, que funciona en varios navegadores:

La función busca las propiedades 'attachEvent' y 'addEventListener' y luego usa uno de los modelos que dependen de esa prueba. Ambos modelos también permiten eliminar controladores de eventos, como se muestra en esta función 'removeEvent':

Usarías las funciones como esta:

Observa que pasamos una función sin nombre como tercer parámetro. JavaScript nos permite definir y ejecutar funciones sin nombrarlas; Las funciones de este tipo se denominan "funciones anónimas" y pueden resultar muy útiles, especialmente cuando se necesita pasar una función como parámetro a otra función.  Podríamos haber puesto nuestra función 'introClick' (definida anteriormente) como el tercer parámetro, pero a veces es más conveniente hacerlo con una función anónima.

Si deseas que se produzca una acción en un evento solo la primera vez que se hace clic en él, puedes hacer algo como esto:

Eliminaremos el controlador tan pronto como se active el evento por primera vez. No hemos podido usar una función anónima en el ejemplo anterior porque necesitábamos retener una referencia a la función ('oneClickOnly') para poder eliminarla más tarde.  Dicho esto, en realidad es posible lograrlo con una función sin nombre (anónima):

Estamos siendo bastante descarados aquí al hacer referencia a la propiedad 'callee' del objeto 'argumentos'. El objeto 'argumentos' contiene todos los parámetros pasados ​​de CUALQUIER función y también contiene una referencia a la función en sí ('callee').  Al hacer esto, eliminamos por completo la necesidad de definir una función con nombre (por ejemplo, la función 'oneClickOnly' que se mostró anteriormente).

Aparte de las obvias diferencias sintácticas entre la implementación del W3C y la de Microsoft, hay algunas otras discrepancias que vale la pena señalar. Cuando vincula una función a un evento, la función debe ejecutarse dentro del contexto del elemento, por lo que la palabra clave 'this' dentro de la función debe hacer referencia al elemento; utilizando el modelo básico de registro de eventos o el modelo avanzado de W3C, esto funciona sin fallas, pero la implementación de Microsoft falla.  Aquí hay un ejemplo de lo que deberías poder hacer dentro de las funciones de manejo de eventos:

Hay algunas formas diferentes de evitar/solucionar este problema. Con mucho, la opción más fácil es usar el modelo básico; casi no hay inconsistencias entre navegadores cuando se usa este modelo. Sin embargo, si deseaw utilizar el modelo avanzado y necesitas la palabra clave 'this' para hacer referencia al elemento correctamente, deberías echar un vistazo a algunas de las funciones 'addEvent' más ampliamente adoptadas, específicamente las de John Resig o Dean Edward (su no Ni siquiera utilices el modelo avanzado, ¡magnífico!).

El objeto de evento

Un aspecto importante del manejo de eventos que todavía tenemos que discutir es algo llamado "Objeto de evento". Siempre que vincule una función a un evento, es decir, cada vez que crees un controlador de eventos, a la función se le pasará un objeto.  Esto sucede de forma nativa, por lo que no es necesario realizar ninguna acción para inducirlo. Este objeto de evento contiene una variedad de información sobre el evento que acaba de ocurrir; también contiene métodos ejecutables que tienen varios efectos de comportamiento en el evento.  Pero, como era de esperar, Microsoft eligió su propia forma de implementar esta "característica"; Los navegadores IE no pasan este objeto de evento, sino que debes acceder a él como una propiedad del objeto de ventana global; esto no es realmente un problema, es solo una molestia:

Para verificar la existencia del objeto 'e' (el "Objeto de evento") usamos un operador OR (lógico) que básicamente dicta lo siguiente: si 'e' es un valor "falso" (nulo, indefinido, 0 etc.) luego asigna 'window.event' a 'e'; de lo contrario, usa 'e'.  Esta es una forma rápida y sencilla de obtener el objeto de evento real en un entorno de varios navegadores. Si no te sientes cómodo con el uso de operadores lógicos fuera de una declaración IF, esta construcción podría ser más adecuada para tú:

Desafortunadamente, algunos de los comandos y propiedades más útiles de este objeto de evento se implementan de manera inconsistente en todos los navegadores (es decir, IE frente a todos los demás). Por ejemplo, la cancelación de la acción predeterminada de un evento se puede lograr usando el método 'preventDefault ()' del objeto Event, pero en IE solo se puede lograr usando la propiedad 'returnValue' del objeto.  Entonces, nuevamente, tenemos que usar ambos para adaptarse a todos los navegadores:

La acción predeterminada de un evento es lo que ocurre normalmente como resultado de la activación de ese evento.  Cuando haces clic en un enlace de anclaje, la acción predeterminada es que el navegador navegue a la ubicación especificada en el atributo 'href' de ese enlace. Pero a veces querrás deshabilitar esta acción predeterminada.

La molestia 'returnValue' / 'preventDefault' no es por sí sola; muchas otras propiedades del objeto Event se implementan de manera inconsistente, por lo que este modelo de verificación if / else / o es una tarea requerida.

Muchas de las bibliotecas de JavaScript actuales normalizan el objeto de evento, lo que significa que comandos como 'e.preventDefault' estarán disponibles en IE, aunque debes tener en cuenta que, detrás de escena, la propiedad 'returnValue' todavía se utiliza.

Evento burbujeante

El evento burbujeante, también conocido como "propagación de eventos", es cuando se activa un evento y luego ese evento "burbujea" a través del DOM. Lo primero que hay que tener en cuenta es que no todos los eventos burbujean, pero para aquellos que sí lo hacen, así es como funciona:

El evento se dispara en el elemento de destino. Luego, el evento se dispara en todos y cada uno de los antepasados ​​de ese elemento: el evento fluye a través del DOM hasta que alcanza el elemento superior:

Event bubbling graphicEvent bubbling graphicEvent bubbling graphic Evento burbujeante, ilustrado

Como se muestra en el gráfico anterior, si se hace clic en un ancla dentro de un párrafo, el evento de clic del ancla se activará primero y luego, después de eso, se activará el evento de clic de párrafos, etc.hasta que se alcance el elemento del cuerpo (el cuerpo es el elemento DOM más alto que tiene un evento de clic).

Estos eventos se activarán en ese orden, no todos ocurren al mismo tiempo.

La idea del burbujeo de eventos puede no tener mucho sentido al principio, pero finalmente queda claro que es una parte fundamental de lo que consideramos "comportamiento normal". Cuando vincula un controlador al evento de clic del párrafo, esperas que se active cada vez que se hace clic en el párrafo, ¿verdad?  Bueno, eso es exactamente lo que garantiza la "propagación de eventos": si el párrafo tiene varios elementos secundarios ( s, s, s), incluso cuando se haga clic en el evento, aparecerá el párrafo .

Este comportamiento de burbujeo se puede detener en CUALQUIER momento durante el proceso. Entonces, si solo deseas que el evento suba al párrafo pero no más (no al nodo del cuerpo), puedes usar otro método útil que se encuentra en el objeto Event, "stopPropagation":

Delegación de eventos

Digamos, por ejemplo, que tienes una tabla enorme con muchas filas de datos. Vincular un controlador de eventos de clic a cada <tr> puede ser una tarea peligrosa, principalmente debido al efecto negativo que tiene en el rendimiento. Una forma habitual de combatir este problema es utilizar la "delegación de eventos". La delegación de eventos describe el proceso de aplicar un controlador de eventos a un elemento contenedor y luego usarlo como base para todos los elementos secundarios.  Al probar la propiedad 'target' ('srcElement' en IE) del objeto de evento, podemos determinar el elemento real en el que se hizo clic.

La delegación de eventos se basa en la propagación de eventos. El código anterior no funcionaría si se detuviera el burbujeo antes de llegar al nodo 'tabla'.

¡Es todo por hoy!

Hemos cubierto cómo manipular elementos DOM y hemos discutido, con bastante profundidad, el modelo de eventos del navegador. ¡Espero que hayas aprendido algo hoy! Como de costumbre, si tienes alguna pregunta, no dudes en preguntar.

  • Suscríbete a la fuente RSS de NETTUTS para obtener más información y artículos sobre desarrollo web diarios.
Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.