2010-12-13 7 views
0

Je convertis les valeurs en fonction des unités (km à m, lb à g, etc.). Je l'ai fonctionné, à l'exception d'un bug que je n'arrive pas à résoudre.Gestion du clavier dans la liste déroulante

Voici la fonction qui gère les événements (conversion se produit 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 (bien que, si vous avez des améliorations à ce code, je suis toujours vouloir apprendre). Cependant, le problème original que j'avais était que je devais me souvenir de l'unité sélectionnée précédente 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 clique sur 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 différents événements clés *, et ceux-ci ne semblent pas fonctionner non plus. Que devrais-je faire ici pour gérer les entrées clavier et souris?

(Mon espoir était que l'événement de changement me permettra d'accéder à l'élément sélectionné précédemment, 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 plutôt bizarres. La raison en est que je ne définis la valeur "de" que la première fois que je me concentre. Si je veux que la conversion se produise correctement à chaque fois, je dois perdre le focus sur la liste déroulante, puis refaire le processus. Pas très utile.

De plus, pour une raison quelconque, lorsque je clique dans le champ, puis cliquez sur les flèches haut et bas, l'événement change ne se déclenche pas. Je n'ai vraiment aucune idée pourquoi c'est ...

Répondre

1

je voudrais faire deux changements à votre code.

d'abord, assurez-vous que vos options ont à la fois text et value:

<select> 
    <option value="km">KM</option> 
    ... 
</select> 

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

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

Ceci est également plus correct que vous pouvez afficher un texte différent à la valeur, par exemple afficher "kilomètres" à l'utilisateur, mais toujours avoir la valeur "km" pour travailler avec le plugin.

Maintenant, sur le vrai problème ...

La façon la plus simple de « se souvenir » état antérieur consiste à attacher des données à l'élément lui-même. La meilleure façon de le faire, tout en évitant les fuites de mémoire et toutes sortes d'autres problèmes, est d'utiliser le data() de jQuery. Donnez-lui juste un nom et une valeur, et il se souviendra de l'élément 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 de la charge sur le document (le cas échéant):

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

Excellente réponse! Je vous remercie. Je n'ai pas réalisé que les données existaient même. Je suppose qu'il va montrer qu'il y a toujours quelque chose de nouveau à apprendre. Merci beaucoup. – JasCav

0

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

+0

ne fonctionne pas. S'il vous plaît voir la mise à jour de ma question pour plus d'informations. Merci de votre aide. – JasCav

0

Pas besoin dans l'événement supplémentaire .. vous pouvez ajouter une variable globale (en dehors de la fonction) appelée _from, initialiser avec la valeur sélectionnée dans le document d'événement prêt alors mis _from égale à to après avoir terminé son traitement.

De cette façon, _from conservera toujours la valeur sélectionnée précédemment 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/

+0

Bonne idée. Est-ce que cela fonctionnera si j'ai plusieurs listes déroulantes sur une page (en particulier $ ('select.unit'))? – JasCav

+0

@JasCav: dans le cas de plusieurs listes déroulantes, faites un tableau clé/valeur '_from' par exemple. 'from [" ddl1 "] =" last_val ";' et la clé sera l'identifiant de chaque liste déroulante. –

+0

Hmm ... Je ne suis pas sûr de savoir comment faire cette sélection. Si vous pouviez donner un exemple dans votre réponse, ce serait très apprécié. – JasCav

Questions connexes