2010-02-20 8 views
11

Cela me rend fou. C'est difficile à expliquer mais je vais essayer.J'ai des problèmes avec l'événement keydown et autocomplete dans Firefox sur mac

J'ai un champ de saisie sur la première page de mon site. J'ai codé un observateur d'événement de keydown qui vérifie le keyCode et si son ENTRER (ou equiv), il vérifie la valeur d'entrée (email). Si l'e-mail est valide et unique dans la base de données, le formulaire sera envoyé. Des trucs basiques, ou alors tu penserais.

Si je tape mon adresse e-mail dans le champ et appuyez sur Entrée, cela fonctionne très bien dans tous les navigateurs. Toutefois, si je tape les premières lettres, puis utilisez les touches fléchées pour sélectionner l'email dans la liste déroulante de l'historique (j'espère que vous savez ce que je veux dire ici), puis appuyez sur Entrée, le résultat est différent. La valeur du champ de formulaire est capturée comme le couple de lettres que j'ai tapé, et donc la validation échoue. Il semble que lorsque j'appuie sur la touche Entrée pour "sélectionner" l'email de la liste déroulante de l'historique, le navigateur interrompt cela comme si je tapais.

Dans Chrome et Safari, cela fonctionne comme il se doit. Comme cela devrait signifier que lorsque vous appuyez sur Entrée pour "sélectionner" l'email de la liste déroulante de l'historique, tout ce qu'il fait est de mettre cette adresse e-mail dans la zone de texte. Ce n'est que sur la deuxième touche ENTER que l'on déclenche l'observateur d'événement et que l'e-mail est validé. J'espère que quelqu'un pourra faire la lumière sur les raisons de cette situation ... Mon instinct est un truc de navigateur et je ne peux rien y changer.

Merci Lee

EDIT: Pour ajouter des éclaircissements à ma question je voudrais ajouter que Im en utilisant l'événement « keydown » pour saisir le moment où la touche Entrée. J'ai essayé le "keyup" événement et ceci a résolu mon problème ci-dessus, mais alors je ne peux pas sembler arrêter le formulaire soumettant par lui-même. L'événement "keyup" se déclenche APRÈS le comportement par défaut, donc ce n'est pas le bon choix pour cela.

EDIT DE PLUS:

Merci encore, et d'ailleurs, votre anglais est excellent (en réponse à vos commentaires sur un mauvais anglais).

J'ai changé mon gestionnaire d'événements de ce:

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

à ceci:

$("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; 
} 

semble fonctionner, mais le problème est maintenant que le navigateur est autorisé à effectuer l'action par défaut avant d'exécuter le submitViaEnter fonction qui signifie que le formulaire est soumis lorsque j'appuie sur ENTRÉE.

Répondre

6

réponse à la question initiale

Ouais, c'est un bug Gecko (non spécifique Mac bien).

The last part of this comment contient la description de la solution de contournement: utilisez le délai d'expiration.

[modifier] depuis que vous avez demandé la clarification du bug

Lorsque vous appuyez sur Entrée et le remplissage automatique est le premier actif, Firefox (par erreur) déclenche gestionnaire clé de la page, puis sur la touche interne du navigateur gestionnaire qui ferme la fenêtre contextuelle de saisie semi-automatique et met à jour la valeur de la zone de texte, alors qu'il devrait sans doute se déclencher dans la fenêtre de saisie semi-automatique et laisser la page connaître uniquement la valeur de la zone de texte modifiée. Cela signifie que lorsque votre gestionnaire de clé est appelé, le gestionnaire de saisie semi-automatique n'a pas encore été exécuté - la fenêtre de saisie semi-automatique est toujours ouverte et la valeur de la zone de texte est identique à celle précédant l'achèvement automatique. Lorsque vous ajoutez un appel setTimeout à votre gestionnaire de clés, vous dites au navigateur "hé, exécutez cette fonction juste après avoir fini de faire des choses déjà dans votre liste de tâches P1". Ainsi, le gestionnaire de saisie semi-automatique s'exécute, puisqu'il est déjà dans la liste des tâches, puis le code que vous mettez dans un délai expire - lorsque la fenêtre contextuelle de saisie semi-automatique est déjà fermée et la valeur de la zone de texte mise à jour.

[modifier] répondre à la question "De plus modifier"

droit. Vous devez annuler l'action par défaut dans le gestionnaire d'événements, pas dans le délai d'attente, si vous voulez que cela fonctionne:

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 vous vouliez encore soumettre le formulaire Entrez, ce serait un exercice plus intéressant, mais il ne semble pas que vous le fassiez.

+0

Merci! Ive travaillé autour de lui en désactivant la fonctionnalité de saisie semi-automatique pour le formulaire, mais je ne l'aime pas. Savez-vous ce que "le temps-mort" est, et si oui, pouvez-vous élaborer s'il vous plaît? Merci encore. –

+0

@LeeRM: dans le gestionnaire de touches, appelez setTimeout (handler2, 0) et déplacez votre code de validation dans | function handler2() {} |. – Nickolay

+0

oh je vois. Je suis désolé si je suis épais ici. Juste quand je pense que je deviens bon dans ce genre de choses ... Quel est le résultat? Je sais que ça résout le problème que j'ai mais comment? J'aime comprendre ce qui se passe. Merci de votre aide! –

2

ok trié. Merci beaucoup pour votre aide. C'était la fonction curry qui me manquait avant. J'essayais de travailler sur l'événement dans le cadre de la fonction setTimeout.

Cela fonctionne ci-dessous. Le submitViaEnter est appelé à partir du eventobserver et répond à l'événement 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; 
} 

Arrêter l'action par défaut à l'intérieur du eventObserver signifie qu'aucun caractère pourrait être tapées. Donc je suis resté à l'intérieur de la clause de clé d'entrée si.