¡Locura de eventos de JavaScript! Capturar * todos * los eventos sin interferencias | Programar Plus

La siguiente es una publicación invitada de Matthias Christen y Florian Müller de Ghostlab. Ghostlab es un software de prueba entre navegadores y dispositivos para Mac y PC. Una de las cosas que estoy muy impresionado de que Ghostlab pueda hacer es sincronizar los eventos de un navegador con todos los demás. Desplácese por una página, las otras que está probando se desplazan. Haga clic en algún lugar de una página, el mismo clic ocurre en las demás. Les pregunté cómo diablos hace eso cuando hay tanto que podría interferir. Matthias y Florian explican:

Hemos estado desarrollando Ghostlab, una herramienta para probar sus sitios web entre dispositivos y navegadores. En esencia, sincroniza cualquier número de clientes que ven un sitio web y facilita la navegación por ese sitio y se asegura de que funcione bien y se vea bien en todas las ventanas y plataformas. Un componente central es la replicación de eventos entre clientes: cuando el usuario hace clic en un botón, se desplaza o ingresa texto en un campo de formulario en un cliente, debemos asegurarnos de que suceda exactamente lo mismo en todos los demás.

Captura de eventos perdidos

El componente de script del lado del cliente de Ghostlab está escuchando todo tipo de eventos que suceden, intenta capturarlos y replicarlos en todos los demás clientes. En algún momento, notamos que no captamos todos los eventos. Tuvimos que averiguar cuál era el problema y se nos ocurrió una solución que le permite detectar cualquier evento que suceda en su sitio, sin importar cómo lo maneje cualquier JavaScript personalizado.

¿Cómo puede ser que esté escuchando un evento, pero no lo capte? Eso es porque cualquier controlador de eventos tiene la opción de hacer varias cosas con un evento. Conocerá la capacidad de evitar la acción predeterminada que suele realizar el navegador (preventDefault()). Te permite, por ejemplo, tener un enlace (<a>) por lo que el usuario no acude a su href en un click evento.

Además de decirle al navegador que no realice la acción predeterminada siempre que ocurra el evento, un controlador de eventos también puede detener la propagación de un evento. Cuando se activa un evento en un elemento, digamos un enlace, cualquier controlador de eventos que esté adjunto a este elemento específico podrá manejar el evento primero. Una vez hecho, el evento burbujeará hasta que alcance el document nivel. Cada oyente de este evento en cualquier padre del elemento original podrá reaccionar al evento, es decir, a menos que un controlador de eventos inferior decida detener la propagación, en cuyo caso el evento ya no irá más arriba en el DOM.

Nuestra Ejemplo 1 demuestra esto. Cuando hace clic en el div interno (Nivel 3), el controlador de clic para este elemento manejará el evento primero. A menos que evite la propagación, los elementos padres (Nivel 2, Nivel 1) podrán luego reaccionar al evento en orden. En caso de que marque la casilla de verificación “Detener propagación”, el controlador de eventos evitará una mayor propagación; por lo tanto, los eventos de clic en el Nivel 3 ya no alcanzarán los Niveles 1 y 2, y los eventos de clic en el Nivel 2 ya no alcanzarán el Nivel 1.

Vea el Ejemplo I de propagación de eventos de pluma de Florian Mueller (@ mueflo00) en CodePen.

En ejemplo 2, demostramos el efecto de detener la propagación inmediata. Este método detiene implícitamente la propagación del evento, por lo que si hubiera algún elemento padre, observaríamos el mismo comportamiento que en el ejemplo 1. Además, también evita que se ejecuten controladores adicionales del mismo evento en el mismo elemento. . En nuestro ejemplo, tenemos que hacer clic en los controladores de eventos registrados en nuestro elemento. Si elegimos detener la propagación inmediata, solo el primer respondedor podrá manejar el evento, y después de llamar a stopImmediatePropagation, no se llamará a ningún otro controlador.

Vea el Ejemplo II de propagación de eventos de pluma de Florian Mueller (@ mueflo00) en CodePen.

Entonces, si desea escuchar todos los eventos que suceden en el DOM, eso es bastante difícil. Para evitar que falten eventos debido al burbujeo cancelado, tendría que registrar todos los controladores de eventos en cada elemento del DOM. E incluso entonces, en caso de que un desarrollador elija detener la propagación inmediata, esto solo funcionaría si usted fuera el primero en registrarse para el evento.

Si queremos estar absolutamente seguros de que estamos informados de cualquier evento, sin importar lo que hagan sus controladores con él, tenemos que estar al tanto desde el comienzo del registro del evento. Para ese propósito, anulamos el addEventListener función de la EventTarget objeto. La idea básica es simple: cada registro de controlador de eventos, al final, llamará a este método. Si lo anulamos, tenemos control total de lo que sucede cuando se registra cualquier controlador de eventos.

El original addEventListener La función toma una función de controlador de eventos (el “controlador de eventos original”) como su segundo argumento. Si no anulamos la función addEventListener, se llamará a la función del controlador de eventos original siempre que ocurra el evento especificado. Ahora, en nuestra costumbre addEventListener función, simplemente envolvemos el controlador de eventos original en nuestro propio controlador de eventos (la “función contenedora”). La función contenedora contiene cualquier lógica que necesitemos y, en última instancia, puede llamar al controlador de eventos original, si así lo deseamos.

Ejemplo 3 demuestra esto. Los tres eventos de clic adjuntos a los elementos “Nivel” se registran a través de nuestro addEventListener , por lo que cada vez que se produce un evento de clic en estos elementos, se llama a nuestra función contenedora. Allí, observamos el estado de la casilla de verificación: si está marcada, simplemente no llamamos al controlador de eventos original, evitando así que cualquier evento de clic active cualquier controlador de eventos original. Una pequeña nota al margen: si desea asegurarse de tomar el control de todos los eventos, debe asegurarse de anular la addEventListener funcionar antes de que se registre cualquier evento.

Vea el ejemplo de anulación de evento de lápiz por Florian Mueller (@ mueflo00) en CodePen.

Si bien esta solución nos ha ayudado a mejorar Ghostlab, puede preguntarse para qué podría ser bueno. Bueno, hay varias posibilidades. Hemos bosquejado dos posibles casos de uso a continuación: si puede encontrar otro, ¡compártalo!

Posible aplicación 1: Visualizador de eventos

Existen herramientas para ayudarlo a visualizar eventos en su sitio web (nos encanta, por ejemplo, VisualEvent Allan Jardine). Usando nuestra técnica, podemos implementar rápidamente una herramienta de este tipo nosotros mismos. En nuestro ejemplo, para cada evento registrado, simplemente dibujamos un pequeño cuadrado encima del elemento para el cual se registró el evento. Al pasar el mouse, mostramos el código fuente de la función de controlador de eventos registrada (original).

Vea el Visualizador de eventos de lápiz de Florian Mueller (@ mueflo00) en CodePen.

Posible aplicación 2: Estadísticas de eventos

En lugar de dibujar indicadores de eventos en la pantalla, también puede mostrar esa información de otra manera. Este ejemplo le muestra una descripción general tabular de los eventos registrados en cualquier página (dado que inyecta el código en ella) y actualiza los eventos activados en tiempo real. Esto puede ser útil, por ejemplo, cuando tiene problemas de rendimiento y sospecha que podría deberse a que hay demasiados controladores de eventos.

Consulte la Anulación del evento de lápiz: estadísticas de Florian Mueller (@ mueflo00) en CodePen.

Los eventos son solo una pequeña parte del enorme y complejo mundo del desarrollo front-end. En Vanamco, nos complace ofrecerle herramientas que lo ayudarán a simplificar y optimizar sus procesos mientras lo mantienen actualizado con las mejores prácticas.

(Visited 3 times, 1 visits today)