ACTUALIZACIÓN:(recapitular, el violín y la abundancia)JavaScript: Cómo simular evento de cambio en Internet Explorer (delegación)
Esta pregunta no ha estado recibiendo mucha atención, así que voy a gasta un representante en eso. Sé que tiendo a ser demasiado detallado en mis respuestas y preguntas. Es por eso que continué y configuré this fiddle, que es, en mi opinión, una representación decente del tipo de código que estoy teniendo que usar para acercarme a un evento burbujeante change
. Un par de cuestiones que estoy tratando de resolver:
- El evento
pseudo-change
no se activa en un elemento seleccionado, a menos que pierda el foco. En algunos casos, el cliente debe ser redirigido al seleccionar un nuevo valor. ¿Cómo logro esto? - El controlador se llama tanto cuando se hace clic en las etiquetas como en las casillas de verificación. En sí mismo es lo que esperarías, pero debido al burbujeo del evento es imposible determinar en qué elemento se hizo clic (AFAIK). El objeto de evento de IE no tiene una propiedad
realTarget
. - Al cambiar el
checked
-estado de una casilla en IE haciendo clic en la etiqueta, todo está bien (aunque requiere algunas soluciones desagradables), pero al hacer clic en la casilla de verificación directamente, se llama al controlador, pero el estado comprobado permanece sin cambios, hasta que haga clic por segunda vez. Entonces el valor cambia, pero no se llama al controlador. - Cuando cambio a una pestaña diferente y viceversa, se llama al controlador varias veces. Tres veces si el estado comprobado realmente cambió, dos veces si hice clic directamente en el checbox solo una vez.
Cualquier información que pueda ayudarme a resolver uno o más de los problemas anteriores sería muy apreciada. Por favor, no me olvidé de agregar una etiqueta jQuery, me gusta JS puro, así que estoy buscando una respuesta JS pura.
Tengo una página web con más de 250 elementos seleccionados y 20 ~ 30 casillas de verificación. También tengo que rastrear las acciones de los usuarios y tomar las medidas adecuadas. Por lo tanto, es bastante natural para mí delegar el evento de cambio, en lugar de agregar cientos de oyentes, en mi humilde opinión.
Por supuesto, política de la empresa IE: IE8 tiene que ser compatible, no activa el evento onchange cuando lo necesito. Así que estoy tratando de falsificar un evento onchange. Lo que tengo hasta ahora es trabajar razonablemente bien aparte de 1 cosa que realmente me molesta.
Estoy usando onfocusin
y onfocusout
para registrar los eventos. En algunos casos, cuando el usuario selecciona un nuevo valor del elemento a select, el script debe responder de inmediato. Sin embargo, mientras el selector no haya perdido el foco, esto no sucederá.
Esto es lo que se me ocurrió hasta el momento:
i = document.getElementById('content');
if (!i.addEventListener)
{
i.attachEvent('onfocusin',(function(self)
{
return function(e)
{
e = e || window.event;
var target = e.target || e.srcElement;
switch (target.tagName.toLowerCase())
{
case 'input':
if (target.getAttribute('type') !== 'checkbox')
{
return true;
}
return changeDelegator.apply(self,[e]);//(as is
case 'select':
self.attachEvent('onfocusout',(function(self,current)
{
return function(e)
{
e = e || window.event;
var target = e.target || e.srcElement;
if (target !== current)
{
return;
}
self.detachEvent('onfocusout',arguments.callee);//(remove closure
return changeDelegator.apply(self,[e]);
}
})(self,target));
default: return;
}
}
})(i));//(fake change event, buggy
}
else
{//(to put things into perspective: all major browsers:
i.addEventListener('change',changeDelegator,false);
}
He intentado fijar otro detector de eventos dentro del manejador onfocusin
, con destino al evento onclick
. Disparó el evento onfocusout
de cualquier selección que tenga foco ATM. El único problema es que el 99.9% de los usuarios harán clic en una selección, por lo que el evento focusin
también activa un clic.
Para evitarlo, creé el cierre y pasé el actual en foco y su valor original como argumentos.Pero algunos usuarios hacen utilizan su teclado, y estos usuarios a menudo tabulan en el siguiente cuadro de selección sin cambiar el valor. Cada vez que vincula un nuevo oyente onclick ... creo que hay HAS que sea una manera más fácil que verificar todos los e.type
y tratarlos por separado.
Sólo como ejemplo: el código con un onclick
oyente adicional: todo el código es el mismo que el primer fragmento, así que sólo estoy pegando el bloque
case 'select':
self.attachEvent('onfocusout',(function(self,current)
{
return function(e)
{
e = e || window.event;//(IE...
var target = e.target || e.srcElement;
if (!(target === current))
{
return;
}
self.detachEvent('onfocusout',arguments.callee);//(remove closure
return changeDelegator.apply(self,[e]);
};
})(self,target));
self.attachEvent('onclick',(function(self,current,oldVal)
{
return function(e)
{
e = e || window.event;
var target = e.target || e.srcElement;
if (target.tagName.toLowerCase() === 'option')
{
while(target.tagName.toLowerCase() !== 'select')
{
target = target.parentNode;
}
}
if (target !== current)
{//focus lost, onfocusout triggered anyway:
self.detachEvent('onclick',arguments.callee);
return;
}
var val = target.options[target.selectedIndex].innerHTML;//works best in all browsers
if (oldVal !== target.options[target.selectedIndex].innerHTML)
{
self.detachEvent('onclick',arguments.callee);
return target.fireEvent('onfocusout');
}
};
})(self,target,target.options[target.selectedIndex].innerHTML));
default: return;
1. Sí, estoy seguro de eso: el evento de cambio se activa en IE8, pero no se dispara. Es [un problema conocido] (http://stackoverflow.com/questions/5146784/make-form-elements-onchange-bubble-in-internet-explorer) 2. se llama al controlador de cambios en ambos casos, ese no es el problema. Sin embargo, al hacer clic en la etiqueta, se llama al controlador después de que el estado verificado ha cambiado, mientras que el estado verificado está a punto de cambiar cuando se hace clic directamente en la casilla de verificación. Entonces, si 'target.checked === true', ¿se acaba de verificar o se va a desmarcar? No hay forma de decirlo. Se están quedando sin los caracteres –
3. Agregar desenfoque y enfoque hace que el IE se cuelgue: tenga en cuenta que, debido a que 'onchange' no burbujea, estoy usando los eventos' onfocusin' y 'onfocusout'. Si el manejador se desenfoca y se enfoca, seguirá llamándose infinitamente 4. Y manejando quiero decir ambos: estrictamente hablando 'changeDelegator' es solo una función, pero a la que llamo en el contexto de los manejadores (' changeDelegator. aplicar (esto, [e]); '), así que lo considero una extensión/continuación del controlador real. Sé que el 'focusin' se dispara cuando se renueva la pestaña_, pero se activa para cada evento tratado por la función del delegador. chars .... –
Lo que quiero decir con lo último es simplemente: hago clic en una casilla de verificación (¡el controlador se activa, pero el estado verificado no cambia!), si hago clic en esa casilla una segunda vez, el controlador no está 't llamado, pero el estado verificado cambia de todos modos. Si no hago clic por segunda vez, sino que cambio de pestaña y viceversa, el evento 'focusin' aparece _no_ para ser llamado para esa casilla de verificación en la que hice clic una vez. Muy raro. En el frente de rendimiento: hay una gran diferencia, especialmente cuando _no_ se ejecuta en V8. adjuntarlo a cada elemento en toda la página agregaría hasta 333 (solo los conté todos) elems! chars ... –