Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent default event for jQuery keydown in Firefox

I have jQuery code which makes an array of focusable elements and binds .keydown for the left and right arrows to tab through them. In Chrome, IE, and Safari beginning with preventDefault() or ending with a return false (which technically I don't want to use because I have no need to stopPropagation()) prevents the default event of the arrows, but in Firefox it does not.

How can I prevent the default action in Firefox as well?

Here is the code, which works as expected, except in Firefox where the default event fires in addition to my callback.

$(function () {
    var focusables = $(":focusable");
    focusables.eq(0).focus();
    focusables.eq(0).select();
    focusables.each(function () {
        $(this).keydown(function (e) {
            if (e.which == '37') { // left-arrow
                e.preventDefault();
                var current = focusables.index(this),
                    next = focusables.eq(current - 1).length ? focusables.eq(current - 1) : focusables.eq(0);
                next.focus();
                next.select();
            }
            if (e.which == '39') { // right-arrow
                e.preventDefault();
                var current = focusables.index(this),
                    next = focusables.eq(current + 1).length ? focusables.eq(current + 1) : focusables.eq(0);
                next.focus();
                next.select();
            }
        });
    });
});
like image 216
Brandon Avatar asked May 23 '11 20:05

Brandon


1 Answers

The keypress event is the one which would need to be canceled, but Firefox ignores preventDefault() in this scenario. So the solution is to blur the current dropdown, let the keypress event fire on the document and set the focus to the new dropdown via timeout.

var focusables = $(":focusable");
focusables.eq(0).focus().select();
focusables.each(function () {
    $(this).keydown(function (e) {
        if (e.which == '37') { // left-arrow
            e.preventDefault();
            var current = focusables.index(this),
                next = focusables.eq(current - 1).length ? focusables.eq(current - 1) : focusables.eq(0);
            this.blur();
            setTimeout(function() { next.focus().select(); }, 50);
        }
        if (e.which == '39') { // right-arrow
            e.preventDefault();
            var current = focusables.index(this),
                next = focusables.eq(current + 1).length ? focusables.eq(current + 1) : focusables.eq(0);
            this.blur();
            setTimeout(function() { next.focus().select(); }, 50);
        }
    });
});

Demo at http://jsfiddle.net/roberkules/3vA53/

like image 190
roberkules Avatar answered Sep 28 '22 17:09

roberkules