开发者

Handling Keyboard in Drop Down List

开发者 https://www.devze.com 2023-01-30 14:59 出处:网络
I am converting values based on units (km to m, lb to g, etc). I have it working, except for one bug that I can\'t seem to resolve.

I am converting values based on units (km to m, lb to g, etc). I have it working, except for one bug that I can't seem to resolve.

Here is the function that handles the events (conversion is happening in a jQuery plug-in):

function unitConversion() {
    var from;

    // Remember which unit was sele开发者_如何学Pythoncted 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
            }));
        });
    });
}

This works great (although, if you have any improvements to this code, I'm always wiling to learn). However, the original problem I had was that I had to remember the previous selected unit in the drop down list. Hence, the 'click' event that I'm doing.

This solution works great...as long as the individual uses the mouse. However, if I tab onto the drop down list with the keyboard, and press the up/down arrow keys, nothing happens. I have tried the various key* events, and those do not seem to work, either. What should I be doing here to handle keyboard AND mouse input?

(My hope was that the change event would allow me to access the previously selected item, but that doesn't appear to be the case.)

Update: I wanted to provide some additional clarification.

If I use the focus event, then the conversions get kind of weird. The reason is because I only set the "from" value the first time I get focus. If I want to the conversion to happen correctly every time, I have to lose focus on the drop down list, and then do the process over. Not very useful.

In addition, for whatever reason, when I tab into the field and then click the up and down arrows, the change event does not fire. I really have no idea why that is...


I'd make two changes to your code.

First make sure your options have both text and value:

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

Then instead of doing $('select.unit').find('option:selected').text(); You can just write:

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

This is also more correct as you can show different text to the value, for example show "kilometres" to the user, but still have the value as "km" to work with the plugin.

Now, onto the real problem...

The simplest way to "remember" previous state is to attach data to the element itself. The best way to do this, while avoid memory leaks and all sorts of other problems, is to use jQuery's data(). Just give it a name and a value, and it'll remember it on the select element of your choosing.

// 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
        }));
    });
});

Use the same method to set the from value on document load (if needed):

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


Instead of listening for a click you should just watch for a focus. That should work for both the mouse and the keyboard.


No need in additional event.. you can add global variable (outside the function) called _from, initialize it with the selected value in the document ready event then set _from to be equal to to after you finish processing it.

This way _from will always hold the previously selected value of the drop down list.

Code sample:

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();
        });
    });
});

Test case: http://jsfiddle.net/TuHnB/

0

精彩评论

暂无评论...
验证码 换一张
取 消