How does jQuery UI Dialog disable focus on background inputs?
Asked Answered
B

2

9

When you open a modal dialog using jQuery UI, you'll notice that if you use the Tab key, you can focus on the dialog's buttons, but any inputs outside the dialog are ignored. I'm trying to achieve this same behavior with jQuery UI Tools Overlay , but I'm not sure how jQuery UI is doing it. It doesn't seem to be setting the elements' tab index to -1, and besides, doing this would be extremely tedious since it would involve finding all the focusable elements that aren't part of the dialog. This wouldn't be very good if you require automation. Is there a way to disable focus an all of the page's elements except a few?

Blandina answered 17/10, 2012 at 14:44 Comment(0)
S
9

The dialog widget actually handles the keypress event and performs its own Tab key processing. This processing ignores tabbable elements outside of the dialog.

The relevant source code (lines 286 to 305 in the current version at the time of this post) is:

// prevent tabbing out of modal dialogs
if (options.modal) {
    uiDialog.bind('keypress.ui-dialog', function(event) {
        if (event.keyCode !== $.ui.keyCode.TAB) {
            return;
        }

        var tabbables = $(':tabbable', this),
            first = tabbables.filter(':first'),
            last  = tabbables.filter(':last');

        if (event.target === last[0] && !event.shiftKey) {
            first.focus(1);
            return false;
        } else if (event.target === first[0] && event.shiftKey) {
            last.focus(1);
            return false;
        }
    });
}

Note that TrueBlueAussie's comment is right, and that release of the dialog widget used to bind to the wrong event. keydown should be used instead of keypress:

uiDialog.bind('keydown.ui-dialog', function(event) {
    // ...
});
Sonatina answered 17/10, 2012 at 15:4 Comment(4)
Ah yes, it looks a bit hard to emulate, but this is what I was looking for. ThanksBlandina
Note sure if that was a miss-copy, or the source you quoted was different to j08691's answer from the same date, but to do this tab-key handling requires keydown, not keypress. keypress is too late (or does not fire at all for tab).Ferguson
@TrueBlueAussie, that definitely wasn't a miscopy (I tracked down the original source there), but I may have copy-pasted a bug, yes :) I'll fix the link and the bug.Straightout
Just had to implement this code in my own custom MessageBox plugin (aka a dialog without using JQuery UI dialog) and found that the keypress never fires for TAB as the browser eats it during keydown. If you change your code I will be happy to make my DV into an UV (done) :)Ferguson
J
4

Here's the chunk of code that handles this:

// prevent tabbing out of modal dialogs
this._on(uiDialog, {
    keydown: function(event) {
        if (!options.modal || event.keyCode !== $.ui.keyCode.TAB) {
            return;
        }
        var tabbables = $(":tabbable", uiDialog),
            first = tabbables.filter(":first"),
            last = tabbables.filter(":last");
        if (event.target === last[0] && !event.shiftKey) {
            first.focus(1);
            return false;
        } else if (event.target === first[0] && event.shiftKey) {
            last.focus(1);
            return false;
        }
    }
});​

It looks like jQuery UI adds a filter (:tabbable) to the jQuery selector engine and when the dialog is active, it only allows the tab to cycle between the modal's tabbable elments.

Code from: https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.dialog.js

Jasperjaspers answered 17/10, 2012 at 15:4 Comment(1)
As of today keydown is correct. The answer by Frédéric Hamidi uses keypress and does not trigger for the tab key. +1Ferguson

© 2022 - 2024 — McMap. All rights reserved.