2
votes

Is it possible to make it so I can navigate through a set of radio buttons with the arrow keys without automatically selecting them? I currently have a popup that I want to close when the user selects the radio button and I'm using .click(), but when you navigate the radiobuttons in the popup with arrowkeys, each navigation leads to the popup closing and the user having to reopen it.
Suggestions?
Thanks!

Edit: This is my live demo: jsfiddle.net/TKWzH/4
The real thing has a lot more than the open and close function, so is there a way to combine the keydown enter and mousedown into one? Like

$("#popup2 input:radio").bind('keydown keyCode == 13', 'mousedown' function () {
$('#popup2').css('display', 'none'); });

Something like this? Though I realize this is incorrect and probably makes no sense.

2
Why would you want to override the default behavior? Sounds more like you should want to fix your code.TheZ
And what html and JavaScript are you working with? Can you post a live demo, at JS Fiddle, or similar?David Thomas
This is my fiddle: jsfiddle.net/TKWzH/4 Notice when navigating via keyboard, hitting the arrow key to the radio button closes the dialogue. I would like to be able to navigate to the radio button and on enter (or mouse click) close it. The correct behavior is in "Test Pop2", but the actual script contains a lot more than the function to open and close the dialogue. Is there a way to combine the enter key and also the mousedown function into one?teeth

2 Answers

3
votes

This behavior is specific to certain browsers. IE appears to select radios based on arrow keys, whereas, Chrome does not.

That said, you can disable this behavior by preventing the keydown event via jQuery. I recommend doing this on a DIV (or some other element that wraps your radio buttons), so that it doesn't apply to the entire document:

$('div.wrap').keydown(function(e) {

    if (e.which > 36 && e.which < 41) {
        e.preventDefault();
    }

    var $checkedRadio = $('input[type=radio]:checked');
    if ($checkedRadio.size() > 0) {
        $checkedRadio.removeAttr('checked');
        if (e.which == 38 || e.which == 39) {
            var $nextRadio = $checkedRadio.next('input[type=radio]');
            if ($nextRadio.size() > 0) {
                $nextRadio.attr('checked', 'checked');
            } else {
                $('input[type=radio]:first').attr('checked', 'checked');
            }
        }
        else if (e.which == 37 || e.which == 40) {
            var $prevRadio = $checkedRadio.prev('input[type=radio]');
            if ($prevRadio.size() > 0) {
                $prevRadio.attr('checked', 'checked');
            }
            else {
                $('input[type=radio]:last').attr('checked', 'checked');
            }
        }
    }

});​

There's another way to achieve this, and that is to track what key is pressed, and check that in your click() event:

var keyPressed;

$('input').click(function(e) {
    if (keyPressed && keyPressed > 36 && keyPressed  < 41) {
        e.preventDefault();
        e.stopPropagation();
        // key pressed during click
    }
    else{
        // normal click
    }
});

$(document).keydown(function(e) {
    keyPressed = e.which;
});

$(document).keyup(function(e) {
    keyPressed = null;
});
0
votes

Here is a more generalized cross browser solution that works off the event level, similar to the second example given by @derek-hunziker

$(function() {
    var navKey, getCheck;
    $('input[type=radio]').keydown(function(e) {
        navKey = (e.which >= 37 && e.which <= 40);
        if (navKey) {
            getCheck = $("input:radio[name='" + e.target.name + "']:checked")[0];
        } else if (e.which == 13) {$(e.target).click();}
    }).keyup(function(e) {
        navKey = null;
        getCheck = null;
    }).click(function(e) {
        if (navKey) {
            e.preventDefault();
            e.stopPropagation();
            if (getCheck) {getCheck.checked = true;}
            else {e.target.checked = false;}
        } else {
            // Perform intended click/space/enter action here
        }
    });
});

The changes deal with an issue in Chrome that causes the first navigation move to select an element when there is no default value, and another issue in Internet Explorer that causes navigation to blank out the current selection on every move. It also allows for the click event to be triggered by the enter key, though this functionality can be disabled by removing the "else if" statement in the keydown event.

While more complex than the author's question requires, it offers a more reliable experience across multiple browsers for general usage.