Handlers dblclick test

Handlers

Descripción

Motor declarativo de alta abstracción orientado a la gestión, orquestación e interconexión de flujos de lógica (handlers) desacoplados a nivel de interfaz. Permite mapear elementos del DOM directamente con lógica de JavaScript a través de atributos descriptivos de datos, proporcionando flujos de ejecución secuenciales, encadenamiento mediante middlewares, control dinámico de estados de éxito/error mediante asignaciones reactivas, control declarativo estricto de propagación de eventos, gestión centralizada de consola/errores y un sistema integrado de ciclo de vida de componentes (montaje, desmontaje y destrucción).

Librería: estructura.handlers.js

Dependencias obligatorias: estructura.events.js (Events, documentación). Extensión requerida junto con su objeto global accesible (_events) para inyectar escuchadores de eventos del DOM. Debe estar disponible en el entorno antes de inicializar _handlers; de lo contrario, el proceso se interrumpirá emitiendo una excepción en consola.

Documentación

1. Inicialización, Métodos de Control y Configuración Global

El motor expone globalmente la interfaz _handlers. Esta extensión coordina la lógica declarativa y se apoya directamente en _events para la vinculación física de los disparadores del DOM.


Sintaxis de Registro:

_handlers(...handlersMapsOrStrings).start(startNode?);

Argumentos del Constructor:

  • handlersMapsOrStrings (Object / String): Uno o varios argumentos secuenciales. Pueden ser colecciones de funciones de JavaScript (donde cada clave representa un identificador de handler) o cadenas de texto (String) que hagan referencia a configuraciones registradas previamente de manera pública. El motor fusionará todos los parámetros suministrados de izquierda a derecha.

Métodos de la Interfaz de Retorno e Instancia:

Al invocar la función _handlers(...) se obtiene un objeto de control. Además, la interfaz global _handlers expone métodos de configuración de trazabilidad:

  • .start(startNode?): Inicializa el motor. Escanea el DOM buscando elementos con el atributo data-e-handler. El parámetro opcional startNode (objeto Node o selector String CSS) permite restringir la búsqueda a un subárbol específico. Si se pasa un nodo raíz o un selector de texto, dicho elemento raíz también será evaluado de forma consistente junto con sus descendientes. Si se omite, se procesa de forma segura el documento completo.

    Nota de integración: Debido al patrón de envoltura de métodos de Estructura (adjust_method), los argumentos del despachador inicial se inyectan en primer lugar, por lo que la firma interna del método de arranque es start(args, start_node).

  • .end(startNode?): Realiza el proceso inverso a .start(). Desmantela de manera controlada los listeners vinculados mediante _events (tanto delegados como locales) de los elementos identificados bajo el ámbito de búsqueda (global o delimitado por startNode), destruye los estados lógicos activos en memoria y elimina sus referencias de instancia en los diccionarios internos para liberar la memoria de forma rigurosa.

  • .public(args, name): Registra la colección de handlers actualmente instanciada en un repositorio global bajo el identificador name. Requiere que name sea un String de entre 1 y 128 caracteres. El motor validará estrictamente que no exista una colisión con un identificador público registrado previamente; de ocurrir, interrumpirá el proceso emitiendo una excepción. Permite que llamadas posteriores a _handlers importen y reutilicen esta lógica compartida pasando simplemente el nombre como argumento de tipo cadena de texto.

  • _handlers.console(on): Configura globalmente la emisión de salidas por consola (log, info, warn, error). Acepta un booleano (true para activar todos los canales, false para silenciarlos mediante funciones noop) o cadenas de texto individuales especificando los canales a habilitar. Habilitado por defecto (true).

  • _handlers.errors(on): Habilita (true) o deshabilita (false) la emisión de excepciones internas lanzadas por el motor. Habilitado por defecto (true). Si se establece en false, las excepciones se reemplazan por ejecuciones neutras silenciosas.

2. Sintaxis Declarativa en HTML (Atributos Dataset)

El comportamiento lógico se asocia a los elementos del HTML a través de atributos de datos específicos (data-*):


  • data-e-handler (String): Lista de controladores lógicos (o atajos) separados por comas o espacios. Admite sub-identificadores mediante puntos (.) o barras (|) para una gestión de instancias granular (ej. peticion.idInstancia).

  • data-e-handler-id (String): Requerido. Identificador único de instancia del elemento. El sistema remueve de forma automática todos los espacios en blanco (ej. "btn - registro" se convierte internamente en "btn-registro"). Permite mantener un contexto de estado aislado en memoria para ese nodo sin colisiones.

  • data-e-handler-event (String): Opcional. Evento o eventos del DOM que dispararán el flujo lógico (ej. "click", "submit", "focusout", "dblclick.test").

  • data-e-handler-middleware (Boolean): Opcional. Si está presente, indica que la secuencia principal de ejecución para este elemento operará bajo el modo de middleware (paso de acumulador de datos y callback de continuación).

  • data-e-handler-propagation (Boolean): Opcional. Controla el flujo de burbujeo simulado. Por defecto, los eventos que burbujean detienen su propagación inmediatamente tras ejecutar el handler del elemento receptor. Si se incluye este atributo en el marcado, el motor permitirá que el evento continúe ascendiendo hacia los elementos contenedores superiores (padres). Regla de diseño: La propagación es estrictamente declarativa; el marcado HTML es la única autoridad de control y las mutaciones programáticas sobre el evento en JS no alteran esta regla.

  • data-e-handler-ignore (Boolean): Opcional. Si está presente, el elemento es ignorado durante la inicialización inicial en el DOM activo, forzando de inmediato su desmontaje (remoción física del nodo y reemplazo por un comentario placeholder).

  • data-e-handler-start (String): Opcional. Lista de handlers específicos que se registrarán y ejecutarán inmediatamente con un objeto de payload limpio durante la fase de carga de este elemento. Si se declara vacío, se ejecutan todos los declarados en data-e-handler.

  • data-e-handler-end-start (String): Opcional. Lista de handlers que se registrarán y ejecutarán al final de todo el proceso de inicialización, una vez que el motor ha terminado de procesar e instanciar todos los nodos del DOM identificados por el arranque del .start().

Enlaces Dinámicos Específicos por Handler:

Para cada handler declarado, el motor busca y asocia atributos dinámicos construidos dinámicamente a partir de su nombre en formato kebab-case (ej. el handler mi-peticion se asociará con los atributos de marcado correspondientes en el DOM, resolviéndose mediante lecturas directas del nodo):


  • data-e-[nombre-handler]-middleware: Opcional. Si está presente, determina que los flujos de éxito, error o conexión correspondientes a este handler se procesen mediante la arquitectura de middlewares.

  • data-e-[nombre-handler]-connect: Lista de handlers adicionales que se conectarán e instanciarán en la carga.

  • data-e-[nombre-handler]-success: Flujo de handlers que se ejecutarán automáticamente al establecer un estado de éxito.

  • data-e-[nombre-handler]-error: Flujo de handlers que se ejecutarán automáticamente al establecer un estado de error.

3. El Contexto de Ejecución (this) y Ciclo de Vida

Al invocarse un handler, su contexto (this) apunta a un objeto de estado seguro creado con herencia limpia (Object.create(null)). Este entorno provee acceso a propiedades dinámicas y operaciones de flujo de ciclo de vida:


  • this.liveElement (Node): Referencia directa al elemento activo en el árbol del DOM.

  • this.initialElement (Node): Clon inmutable (cloneNode) del elemento en su estado original de registro. Mantiene la configuración y atributos originales intactos frente a mutaciones del flujo.

  • this.ready (Boolean): Rastreador de inicialización. Indica si la instancia está lista para recibir conexiones lógicas.

  • this.mounted (Boolean): Propiedad de Solo Lectura. Devuelve un booleano que indica de manera dinámica si el elemento está actualmente integrado y conectado dentro del DOM activo o si se encuentra desmontado. Asignar un valor directamente a esta propiedad emitirá una advertencia en consola y no alterará el estado.

  • this.mount() (Function): Reinserta el elemento en el DOM activo en su ubicación original, reemplazando el nodo de comentario placeholder que se generó al desmontarlo. Devuelve la referencia al nodo reinsertado.

  • this.unmount() (Function): Remueve físicamente el elemento del DOM activo de manera segura, insertando en su lugar un comentario placeholder (etiquetado con el `id` de la instancia) y preservando el nodo original dentro de un fragmento de documento (DocumentFragment). Devuelve la referencia al fragmento.

  • this.success (Cualquier tipo): Setter Reactivo. Al asignarle un valor, dispara automáticamente la cadena de handlers especificada en el atributo de éxito (-success) correspondiente, propagando el valor asignado.

  • this.error (Cualquier tipo): Setter Reactivo. Al asignarle un valor, dispara automáticamente la cadena de handlers especificada en el atributo de error (-error) correspondiente.

  • this.connect(state, data, ids?) (Function): Permite propagar estados y datos estructurados hacia los handlers indicados en la declaración de conexión. El destino ids puede ser un string único o un arreglo de strings identificadores de instancias.

    Restricción de seguridad: No está permitido alterar estados que coincidan con nombres de claves reservadas del motor. Si el argumento state coincide con "liveElement", "initialElement", "connect", "ready", "mount", "unmount" o "mounted", la operación se omitirá de inmediato emitiendo una advertencia en la consola.

4. Modos de Ejecución y Firmas de Argumentos

Las firmas de los argumentos de los controladores lógicos se unifican según el modo de operación activo:


A. Modo Secuencial (Estándar)

Los controladores se llaman directamente de forma sucesiva e independiente. Cada función se ejecuta de forma aislada.


  • Manejadores de Evento DOM: Reciben el evento nativo capturado por el motor o el desencadenante de arranque.
    function miHandler(event) {
    	// event: Objeto Event del DOM o trigger de activación
    	console.log("Elemento emisor:", this.liveElement);
    }

  • Manejadores de Éxito / Error: Reciben el payload asignado al descriptor de acceso reactivo.
    function miHandlerExito(data) {
    	// data: El valor asignado a this.success o this.error
    	console.log("Datos de éxito recibidos:", data);
    }

B. Modo Middleware

Activado mediante la bandera data-e-handler-middleware o mediante configuraciones de handler específicas. Organiza el flujo como una cadena secuencial asíncrona donde cada eslabón puede interactuar, modificar o abortar el proceso. El acumulador de datos compartidos (data) se inicializa como un objeto limpio sin prototipo (Object.create(null)).


  • Middlewares de Evento DOM: Reciben el evento, el acumulador de datos y la función de llamada de continuación (next).
    function miMiddleware(event, data, next) {
    	data.timestamp = Date.now();
    	return next(data); // Propaga la continuación del flujo
    }

  • Middlewares de Éxito o Error: Reciben el valor asignado al setter reactivo (payload), el acumulador y la función de continuación.
    function miMiddlewareExito(payload, data, next) {
    	data.resultado = payload;
    	return next(data);
    }

Si alguna de las funciones interceptoras en la tubería de middlewares omite llamar o retornar la ejecución de next(data), la ejecución de los handlers posteriores en la secuencia se cancela por completo.


5. Ejemplos Prácticos de Implementación

Estructuración de Compartición Pública e Inicialización Diferida:

<!-- El botón 'validador' se inicializará al final del arranque global -->
<button id="accion"
	data-e-handler="comun.logger, validador"
	data-e-handler-id="btn-enviar"
	data-e-handler-event="click"
	data-e-handler-end-start="validador"
	data-e-validador-success="moduloOk">
	Procesar Formulario
</button>

Control Declarativo de Propagación Ascendente (Burbujeo):

<!-- El contenedor padre responderá al click únicamente porque el hijo declara 'data-e-handler-propagation' -->
<div data-e-handler="padreLogger" data-e-handler-id="box-padre" data-e-handler-event="click">
	<button data-e-handler="hijoAccion" data-e-handler-id="btn-hijo" data-e-handler-event="click" data-e-handler-propagation>
		Ejecutar y Propagar al Padre
	</button>
</div>

Registro de Handlers Públicos, Reutilización y Control de Flujo:

// 1. Definición y registro de un grupo de handlers de utilidad común
_handlers({
	logger: function(event) {
		console.log("Acción detectada en el elemento id:", this.liveElement.id);
	}
}).public({}, "comun");

// 2. Importación de los handlers comunes y mezcla con lógica local específica
_handlers("comun", {
	validador: function(event) {
		var datosValidos = true; // Simulación de validación
		if (datosValidos) {
			this.success = { estado: "correcto", timestamp: Date.now() };
		} else {
			this.error = { estado: "erroneo" };
		}
	},
	moduloOk: function(data) {
		console.log("Flujo completado exitosamente con datos:", data);
	}
}).start();

6. Características Técnicas de la Implementación

Delegación Inteligente de Eventos y Desacoplamiento de Estado: El motor optimiza el uso de la memoria clasificando los eventos asignados. Los eventos que no burbujean (tales como focus, blur, scroll, resize, mouseenter o mouseleave) se enlazan localmente sobre cada elemento específico. Los eventos burbujeantes se capturan de forma centralizada mediante un único listener delegado en el nodo raíz (document.documentElement) con fase de captura habilitada. Un almacenamiento desacoplado (_bubbling_cache) mapea los metadatos de los eventos nativos mediante WeakMap/Map, asegurando el rastreo de nodos procesados entre múltiples instancias simultáneas sin mutar ni definir propiedades sobre los objetos Event del navegador.


Autoridad Declarativa Estricta (Single Source of Truth): La propagación de eventos está regida de manera exclusiva por el marcado HTML mediante la presencia del atributo data-e-handler-propagation. Por defecto, el motor frena la propagación simulada al ejecutar el primer nodo receptor. Esta regla prevalece sobre cualquier intento de alteración procedimental en JavaScript, garantizando una trazabilidad del flujo 100% predecible a nivel de plantilla.


Aislamiento de Instancia Seguro: Cada instancia lógica se ejecuta dentro de un contexto de almacenamiento exclusivo mapeado por su identificador único (id), construido de forma limpia con Object.create(null) para erradicar posibles interferencias con propiedades heredadas del prototipo de JavaScript.


Ciclo de Vida de Componente Reutilizable (Placeholder): Mediante los métodos mount y unmount, el motor permite retirar físicamente nodos del DOM y reemplazarlos por comentarios de marcado (comentarios placeholder) de forma reactiva, salvaguardando la estructura original del elemento en memoria en un fragmento de documento (DocumentFragment) para su posterior restitución en el lugar exacto que ocupaban.


Control Reactivo mediante Descriptores de Acceso: Las propiedades clave de estado y flujo (ready, success, error, mounted) se gestionan mediante descriptores dinámicos (Object.defineProperty), permitiendo que la simple asignación de un valor a estas variables actúe como disparador inmediato para ejecutar secuencias completas de callbacks.


Protección de Referencias Circulares en Atajos: El motor implementa una rutina de rastreo de recursividad durante la resolución de atajos de handlers. Si se detecta que dos o más atajos se referencian mutuamente en un bucle circular infinito, el sistema aborta de inmediato la ejecución lanzando una excepción controlada, asegurando la estabilidad del hilo de ejecución.


Auditoría de Configuración Persistente: A través de la propiedad initialElement, que resguarda una copia inalterada del nodo (cloneNode) obtenida al momento del arranque, los desarrolladores mantienen la capacidad de auditar la parametrización de atributos data-e-handler-* original, sin importar las mutaciones o cambios dinámicos sufridos por el nodo activo de la interfaz (liveElement).


Normalización Automatizada de Nombres: El motor procesa internamente el identificador de cada handler aplicando un formateo kebab-case optimizado para resolver atributos en el marcado DOM (ej. asociando un handler "miHandler" con selectores de tipo "data-e-mi-handler-*"). Las lecturas dinámicas se evalúan directamente sobre los atributos del nodo para prescindir del mapeo nativo camelCase del objeto dataset y agilizar las comprobaciones.


Gestión Global de Trazabilidad y Excepciones: Los métodos globales _handlers.console() y _handlers.errors() permiten controlar de forma quirúrgica la visibilidad de los avisos por consola y la interrupción del hilo por excepciones, permitiendo alternar de forma transparente entre un entorno de desarrollo ruidoso e informativo y un entorno de producción optimizado y silencioso.


Limpieza de Memoria Rigurosa: El método .end() asegura el desmontaje absoluto de los recursos, desvinculando de forma programática las escuchas de eventos del DOM (utilizando .off() de la extensión _events) y liberando los diccionarios de estados lógicos y de caché creados durante el ciclo de vida.