1

I am developping some kind of modal popup using jQuery and I have some problems with the focus.

What happens right now, is that when I press the tab key, the focus goes to the controls hidden behind the popup.

Is there a way to force the focus to remain only on the controls in the popup window ?

asked Oct 17, 2011 at 14:05
8
  • You could could put something like onblur="this.focus()" inside any controls in the popup, though that would lock focus into whatever's currently selected. A bit more code to determine if whatever's gaining focus should be allowed to gain focus would be needed. Commented Oct 17, 2011 at 14:11
  • Thanks, however, this would not work for me because I have to respect the WCAG 2.0 AA guidelines and all controls should be reachable using the keyboard. Commented Oct 17, 2011 at 14:17
  • 2
    Then you're contradicting yourself. "Do not allows controls to be reached, but all controls must be reachable". Commented Oct 17, 2011 at 14:19
  • I want the focus to be contained inside the popup window when the window is opened. When the window is closed, other controls should be accessible using the keyboard. Commented Oct 17, 2011 at 14:24
  • So is it an ACTUAL popup, as in a new browser window? OR is it a jQuery modal popup which is still contained in the original page? Commented Oct 17, 2011 at 14:25

9 Answers 9

1

There is. You basically need to listen for when the tab key is pressed, so that you can respond accordingly. Using jQuery, here's the general structure:

$(window).keydown(function(e){
 if(e.which ===9){ //it's the tab key!
 //do whatever you want here.
 e.preventDefault();
 }
});

You put your custom code where I commented do whatever you want here, and finish up by preventing the default action (such as jumping focus to a hidden control) with e.preventDefault;

answered Oct 17, 2011 at 14:11

2 Comments

It won't work, tabkey still has to work, but only on the popup div.
Right, that's why you "do whatever you want here". So you can check which control currently has focus, and then call "focus()" on the control you want to move to.
1

You could always look into removing the default actions of the tab key, there is a small tutorial on how to do this here.

However, that is for the enter and tab key, but if you also look here, you will see that the tab key is key number 9. So if we alter the code to just remove the default actions of the tab key your line would be something similar to

 if ( key == 9 ) { }

rather than

 if ( key == 3 || key == 9 || key == 13 ) { }

EDIT

Okay, since now you've stated you don't want to prevent the default action of the tab key, but you still wish to stop that key from focusing on elements below the modal window.

The only thing I can think of now is, checking to see if the user is focused on your last field example 1 / example 2 (you would link these to your last input/textarea/checkbox/radio). If so, you could do 1 of 2 things:

1) Use the above code and prevent the default action, thus, stopping the using from focusing on elements below the modal.

OR

2) Focus back on the first field in your modal window, with first_field.focus();

As far as I can see, by sticking with your requirements the second choice is the best option for you.

answered Oct 17, 2011 at 14:12

1 Comment

It won't work, tabkey still has to work, but only on the popup div.
1

Finally, I ended up with the following solution:

When the window is opened, I save the tabindexes for all elements not in the popup window inside jQuery.data and I set the focus to the first element of the window.

Then, for all those elements, I set the tabindex to -1 which prevents them from being accessed with the tab key.

When the window is closed, I restore all tabindexes to their previous values.

answered Oct 17, 2011 at 15:32

2 Comments

I don't get this. When you use tabindex="-1", isn't the element focusable using tab?
No, when tabindex="-1", the element is not focusable.
0

Try here. Just prevent the user from pressing tab, or you'll have to loop through your fields and set tab indexes on them.

answered Oct 17, 2011 at 14:12

2 Comments

It won't work, tabkey still has to work, but only on the popup div.
I'd suggest hiding all the offending inputs with display:none while the window is up, browsers won't tab to inputs that it can't see
0

I use a generic on focus event added to all input tags, when the event gets fired I determine the parent div's z-index if it is above a pre-determined threshold (9950 for example) then I allow the focus, if below I prevent focus. To prevent focus I do this by finding a control within the proper div and calling .focus() on that item.

pseudo code below.

$('input').bind('focus', function() 
{ 
 if ($(this).parents('div:first').css('z-index') < 9950) 
 {
 //prevent focus here
 //usually by finding a suitable target and setting focus
 $('input:first', $('.myModalClass')).focus(); 
 }
}); 

ps. Also set the tabindex on the items so that the items within your "modal" window are right after each other in the tab index. just makes things a little cleaner

answered Oct 17, 2011 at 15:52

Comments

0

I had similar problem and created this tiny jQUeryUI plugin. Use it simply (in multiple places on a page if needed) and this will make TAB or shift+TAB iterate only inside of .someGroup wrapper.

$(".someGroup").tabGuard();

More in here and I hope it will help someone:

http://tomaszegiert.seowebsolutions.com.au/tabguard/index.htm

answered May 24, 2013 at 0:43

Comments

0

I think I might have a better solution to your problem that doesn't involve disabling tab or having to track/disable other elements. It does require jQueryUI though.

<div id="modalBgCover">
 <div onfocus="$(this).next('div').find(':tabbable').last().focus();" tabindex="0"></div>
 <div id="modal">
 <input id="input1">
 <input id="input2">
 </div>
 <div onfocus="$(this).prev('div').find(':tabbable').first().focus();" tabindex="0"></div>
<div>

What this does is creates two tabbable (but without content, so not visible) divs which take and redirect focus.

Tabbing off the last input and into the bottom div will throw focus back to the first tabbable element inside the modal, and likewise shift+tabbing to the top div will throw focus back to the bottom input in the modal.

The modalBgCover overlays the page with a semitransparent layer, preventing clicks from getting through.

answered Jul 24, 2014 at 15:43

Comments

0

I have implemented mini-framework based on gather knowledge including answers in this post.

It uses JQuery UI.

Improvements are welcome.

Here is framework object:

var TabLim = {};
TabLim.activate = function(el) {
 TabLim.deactivate();
 TabLim._el = el;
 $(window).on('keydown', TabLim._handleTab);
 return TabLim;
};
TabLim.deactivate = function() {
 TabLim._el = null;
 // detach old focus events
 TabLim._detachFocusHandlers();
 TabLim._els = null;
 TabLim._currEl = null;
 $(window).off('keydown', TabLim._handleTab);
 return TabLim;
};
TabLim.setFocus = function(prev) {
 // detach old focus events
 TabLim._detachFocusHandlers();
 // scan for new tabbable elements
 var tabbables = TabLim._el.find(':tabbable');
 TabLim._els = [];
 // wrap elements in jquery
 for ( var i = 0; i < tabbables.length; i++) {
 var el = $(tabbables[i]);
 // set focus listener on each element
 el.on('focusin', TabLim._focusHandler);
 TabLim._els.push(el);
 }
 // determine the index of focused element so we will know who is
 // next/previous to be focused
 var currIdx = 0;
 for ( var i = 0; i < TabLim._els.length; i++) {
 var el = TabLim._els[i];
 // if focus is set already on some element
 if (TabLim._currEl) {
 if (TabLim._currEl === el[0]) {
 currIdx = i;
 prev ? currIdx-- : currIdx++;
 break;
 }
 } else {
 // focus is not set yet.
 // let's set it by attribute "autofocus".
 if (el.attr('autofocus') !== undefined) {
 currIdx = i;
 break;
 }
 }
 }
 if (currIdx < 0) {
 currIdx += TabLim._els.length;
 }
 if (TabLim._els.length) {
 TabLim._els[Math.abs(currIdx % TabLim._els.length)].focus();
 }
 return TabLim;
};
TabLim._handleTab = function(e) {
 if (e.which === 9) {
 e.preventDefault();
 TabLim.setFocus(e.shiftKey);
 }
};
TabLim._focusHandler = function(e) {
 TabLim._currEl = e.currentTarget;
};
TabLim._detachFocusHandlers = function() {
 if (TabLim._els) {
 for ( var i = 0; i < TabLim._els.length; i++) {
 TabLim._els[i].off('focusin', TabLim._focusHandler);
 }
 }
};

How to use it:

1) to activate to limit focus on specific div

TabLim.activate($('.yourDic')).setFocus();

2) to deactivate

TabLim.deactivate();
answered Dec 17, 2014 at 16:49

Comments

0

When you open your modal popup window if your trying to just get the focus on the first input when they initially press the "tab" key then a very simple solution would be to put the focus on the first input in your modal popup window then simply apply a .blur() to that same input. Then when you hit "tab" it will begin the focus on that form.

$("#modalTestInput").focus();
$("#modalTestInput").blur();

If you're trying to remove any ability to focus on the inputs behind the modal popup window then your solution to apply a tabindex = "-1" to the inputs outside of your modal popup is definitely the way to go.

Just thought you may be interested in a simpler solution.

Paul Roub
36.5k27 gold badges88 silver badges95 bronze badges
answered Mar 30, 2016 at 19:44

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.