Gestion du clavier dans la liste déroulante

Je suis en train de convertir des valeurs en unités (km en m, lb en g, etc.). Je le fais fonctionner, sauf pour un bug que je n’arrive pas à résoudre.

Voici la fonction qui gère les événements (la conversion a lieu dans un plug-in jQuery):

function unitConversion() { var from; // Remember which unit was selected in the drop down list. $('select.unit').live('click', function () { from = $(this).find('option:selected').text(); }); // Now handle the conversion. $('select.unit').live('change', function () { // Get the from and to values. // var from = $(this).prev().find('option:selected').text(); var to = $(this).find('option:selected').text(); // Change the text for each field that corresponds with this component. var textBoxes = $(this).closest('div.data-group').find('input:text'); textBoxes.each(function () { var curValue = $(this).val(); $(this).val($(this).unitConvert({ value: curValue, from: from, to: to })); }); }); } 

Cela fonctionne très bien (même si, si vous avez des améliorations à apporter à ce code, je serai toujours prêt à apprendre). Cependant, le problème initial était que je devais me souvenir de l’unité sélectionnée précédemment dans la liste déroulante. Par conséquent, l’événement «clic» que je fais.

Cette solution fonctionne très bien … tant que l’individu utilise la souris. Cependant, si je me place dans la liste déroulante avec le clavier et que j’appuie sur les touches fléchées haut / bas, rien ne se passe. J’ai essayé les divers événements clés *, et ceux-ci ne semblent pas non plus fonctionner. Que dois-je faire ici pour gérer les entrées clavier ET souris?

(J’espérais que l’événement change me permettrait d’accéder à l’élément précédemment sélectionné, mais cela ne semble pas être le cas.)

Mise à jour : je voulais apporter quelques précisions supplémentaires.

Si j’utilise l’événement focus, les conversions deviennent un peu bizarres. La raison en est que je ne règle la valeur “de” que la première fois que je reçois le focus. Si je veux que la conversion se déroule correctement à chaque fois, je dois perdre le focus sur la liste déroulante, puis refaire le processus. Pas très utile.

En outre, pour une raison quelconque, lorsque je passe dans le champ, puis que je clique sur les flèches haut et bas, l’événement de modification ne se déclenche pas. Je ne sais vraiment pas pourquoi c’est …

Je ferais deux changements à votre code.

Tout d’abord, assurez-vous que vos options ont à la fois du text et une value :

  

Ensuite, au lieu de faire $('select.unit').find('option:selected').text(); Vous pouvez simplement écrire:

 $('select.unit').val(); 

Ceci est également plus correct car vous pouvez afficher un texte différent pour la valeur, par exemple afficher “kilomètres” pour l’utilisateur, tout en conservant la valeur “km” pour travailler avec le plugin.

Maintenant, sur le vrai problème …

Le moyen le plus simple de “mémoriser” l’état précédent consiste à attacher des données à l’élément lui-même. La meilleure façon de le faire, tout en évitant les memory leaks et toutes sortes d’autres problèmes, consiste à utiliser data() de jQuery. Donnez-lui simplement un nom et une valeur, et il s’en souviendra sur l’élément sélectionné de votre choix.

 // Now handle the conversion. $('select.unit').live('change', function () { // Get the from and to values. var from = $(this).data("from"); var to = $(this).val(); // Remember the from value for next time $(this).data("from", to); // Change the text for each field that corresponds with this component. var textBoxes = $(this).closest('div.data-group').find('input:text'); textBoxes.each(function () { var curValue = $(this).val(); $(this).val($(this).unitConvert({ value: curValue, from: from, to: to })); }); }); 

Utilisez la même méthode pour définir la valeur à partir du chargement du document (si nécessaire):

 $(function () { $('select.unit').each(function () { $(this).data("from", $(this).val()); }); }); 

Au lieu d’écouter un click vous devriez simplement regarder pour un focus . Cela devrait fonctionner à la fois pour la souris et le clavier.

Pas besoin d’événement supplémentaire .. vous pouvez append une variable globale (en dehors de la fonction) appelée _from , l’initialiser avec la valeur sélectionnée dans l’événement _from puis définir _from sur la valeur égale à to fois le traitement terminé.

De cette façon, _from conservera toujours la valeur précédemment sélectionnée de la liste déroulante.

Exemple de code:

 var _prevSelectedValues = new Array(); $(function() { $("select").each(function(index) { _prevSelectedValues[$(this).attr("id")] = $(this).val(); $(this).change(function() { var id = $(this).attr("id"); alert("prev: " + _prevSelectedValues[id] + ", current: " + $(this).val()); _prevSelectedValues[id] = $(this).val(); }); }); }); 

Cas de test: http://jsfiddle.net/TuHnB/