2010-02-20 17 views
11

Esto me está volviendo loco. Es difícil de explicar, pero voy a intentarlo.Tengo problemas con el evento de selección de teclas y autocompletado en Firefox en mac

Tengo un campo de texto de entrada en la página principal de mi sitio. He codificado un observador de evento keydown que verifica el código de clave y si está ENTER (o equiv), verificará el valor de entrada (correo electrónico). Si el correo electrónico es válido y único en el DB, deberá enviar el formulario. Cosas básicas, o eso pensarías.

Si escribo mi dirección de correo electrónico en el campo y pulso enter, funciona bien en todos los navegadores. Sin embargo, si escribo el primer par de letras, y luego uso las teclas de flecha para seleccionar el correo electrónico del cuadro desplegable del historial (espero que sepas lo que quiero decir aquí), y luego presionar enter, el resultado es diferente. El valor del campo de formulario se captura como solo el par de letras que escribí y, por lo tanto, la validación está fallando. Parece que cuando presiono la tecla enter para "seleccionar" el correo electrónico del menú desplegable del historial, el navegador lo interrumpe como si estuviera escribiendo.

En Chrome y Safari funciona como debería. Como debería, significa que cuando presiona ingresar para "seleccionar" el correo electrónico del menú desplegable de historial, todo lo que hace es poner esa dirección de correo electrónico en el cuadro de texto. Solo en la segunda tecla ENTER presionar activa el observador del evento y se valida el correo electrónico.

Espero que alguien pueda arrojar algo de luz sobre por qué sucede esto ... Mi instinto es que es algo de navegador y será algo que no puedo solucionar.

Gracias Lee

EDIT: Para añadir una aclaración a mi pregunta permítanme añadir que estoy usando el evento "keydown" para capturar el momento en que se pulsa la tecla Intro. He intentado el evento "keyup" y esto resolvió mi problema anterior, pero parece que no puedo detener el envío del formulario por sí mismo. El evento "keyup" se desencadena DESPUÉS del comportamiento predeterminado, por lo tanto, no es la elección correcta para esto.

hacer otras modificaciones:

Gracias de nuevo, y por cierto, el Inglés es excelente (en respuesta a su comentario sobre la mala Inglés).

he cambiado de controlador de eventos de esta:

$("emailInputBox").observe("keydown", function(event) { 
    return submitViaEnter(event, submitSignupFormOne); 
}); 

a esto:

$("emailInputBox").observe("keydown", function(event) { 
    setTimeout(submitViaEnter.curry(event, submitSignupFormOne),0); 
}); 

submitViaEnter:

function submitViaEnter(event, callback) { 
var code = event.keyCode; 
if (code == Event.KEY_RETURN) { 
    event.stop(); 
    return callback(event); 
} 
return true; 
} 

parece funcionar, pero el problema ahora es que el navegador está permitido llevar a cabo la acción predeterminada antes de ejecutar submitViaEnter función que significa que el formulario se envía cuando presiono ENTRAR.

Respuesta

6

respuesta a la pregunta original

Sí, es un error Gecko (no específicos de Mac sin embargo).

The last part of this comment contiene la descripción de la solución: use el tiempo de espera.

[editar] ya que pidió la aclaración del fallo

Al pulsar Intro y el relleno automático está activo, Firefox (erróneamente) primeros fuegos manejador clave de la página, a continuación, clave interna del navegador manejador que cierra la ventana emergente de autocompletar y actualiza el valor del área de texto, mientras que podría dispararse en la ventana emergente de autocompletar y solo dejar que la página sepa el valor del cuadro de texto cambiado.

Esto significa que cuando se llama al controlador de teclas, el controlador de autocompletar no se ha ejecutado todavía: la ventana emergente de autocompletar todavía está abierta y el valor del cuadro de texto es justo antes de que se completara la autocompletación.

Cuando agrega una llamada setTimeout a su controlador de teclas le está diciendo al navegador "hey, ejecute esta función inmediatamente después de haber terminado de hacer cosas que ya están en su lista de tareas P1". Por lo tanto, se ejecuta el controlador de autocompletar, ya que ya está en la lista de tareas pendientes, luego se ejecuta el código que ejecuta en tiempo de espera, cuando la ventana emergente de autocompletar ya está cerrada y el valor del cuadro de texto actualizado.

[editar] responder a la pregunta de "hacer otras modificaciones"

derecho. Es necesario para cancelar la acción predeterminada en el controlador de eventos, no en el tiempo de espera, si se quiere que funcione:

function onKeyPress(ev) { 
    if (... enter pressed ...) { 
    setTimeout(function() { 
     ... check the new textbox value after letting autocomplete work ... 
    }, 0); 
    // but cancel the default behavior (submitting the form) directly in the event listener 
    ev.preventDefault(); 
    return false; 
    } 
} 

Si todavía quería enviar el formulario de Enter, sería un ejercicio más interesante, pero parece que no.

+0

Gracias! He solucionado el problema desactivando la funcionalidad de autocompletar para el formulario, pero no me gusta. ¿Sabes qué es "el tiempo de espera"? Si es así, ¿puedes explicarlo? Gracias de nuevo. –

+0

@LeeRM: en el manejador de teclas llama a setTimeout (handler2, 0) y mueve tu código de validación a | function handler2() {} |. – Nickolay

+0

oh ya veo. Lo siento si estoy gruesa aquí. Justo cuando creo que me estoy volviendo bueno en esto ... ¿Cuál es el resultado de esto? Sé que soluciona el problema que tengo pero ¿cómo? Me gusta entender qué está pasando. ¡Gracias por tu ayuda! –

2

bien ordenado. Muchas gracias por su ayuda. Era la función de curry que me faltaba antes. Estaba tratando de trabajar en el evento dentro del alcance de la función setTimeout.

Esto funciona a continuación. El submitViaEnter se llama desde el eventobserver y responde al evento keyDown:

function submitViaEnter(event, callback) { 
var code = event.keyCode; 
if (code == Event.KEY_RETURN) { 
    event.stop(); 
    setTimeout(callback.curry(event),0);   
    // return callback(event); 
    // return false;  
} 
return true; 
} 

Detener la acción predeterminada en el interior del eventObserver significa que no hay personajes podrían ser escritos. Así que me quedé dentro de la cláusula de la tecla ENTER.

Cuestiones relacionadas