Keyboard users who attempt to use the Panels IPE (or Page Manager, although it has even more problems) to add or configure panes will get caught in a keyboard trap that prevents them from accessing the links and fields in the CTools modal.

The trap is mitigated by the fact that the Esc key closes the modal, but it doesn't look like there's any way to add or configure panes without using the mouse. This is also an issue for screenreader users, but the screenreader functions that allow searching for text strings or links and navigating within the page from the location of the matching text are a big help (although, how could you possible know what to search for?). I was not able to find a similar workaround using only the keyboard on Firefox/Mac.

While this issue is focused primarily on fixing the Panels IPE use-case, these problems affect any use of the CTools modal! By fixing the modal itself, we'll automatically make everything that uses the CTools modal a little more accessible (although, that's not to say that they couldn't to something else that hurts accessibility).

System setup and configuration:

  • Drupal 7.34
  • CTools 1.x-dev (revision fb6c216)
  • Panels 3.x-dev (revision cd0ded6)
  • Panelizer 3.1
  • Panels In-Place Editor 1.4
  • Bartik 7.34 set as front-end theme
  • Seven 7.34 set as admin theme
  • Node view page enabled in Page Manager
  • Panelizer configured for the Basic Page content type - full page override, provide default panel, render with IPE, single-column default layout
  • One node of type Basic Page created and saved

To reproduce:

  1. On the Basic Page node, tab to and activate the Customize this page button
  2. Tab to and activate the Add new pane button
  3. Note that a modal overlay appears with a Close link and a set of vertical tabs and links
  4. Without tabbing or mousing anywhere, hit the Enter key
  5. Note that the modal overlay disappears and then appears again, implying that keyboard focus is still on the button that activated the overlay
  6. Using the Tab key, try to navigate to the first vertical tab
  7. Note that no matter how many times you hit Tab, focus does not appear to change (I tried about 50 tabs)
  8. Use the Esc key to exit the modal overlay
  9. Repeat the above process and try Shift+Tab to navigate backwards
  10. Note that no matter how many times you hit Shift+Tab, focus does not appear to change (also tried about 50 tabs)

This problem occurs with the Add pane functions, the Settings functions, and the Style functions.

Here is a link to simplytest.me that you can use to launch a test site to verify the problem:

http://simplytest.me/project/ctools?add[]=panels&add[]=panelizer

Solution:

When the user activates the CTools modal, move the keyboard focus to the Close Window link. Constrain tabbing to within the modal, so tabbing forward after the last focusable element will return to the beginning of the modal.

To fully fix this in the Panels IPE and Page Manager use cases, this Panels patch is also necessary: #2390803: Keyboard focus should be on the first element in the selected category tab in the "Add content" model (accessibility problem)

Unfortunately, since two patches on two different projects (CTools and Panels) are required to test the solution, we can't make a simplytest.me link for that. :-/

Comments

cboyden’s picture

Issue summary: View changes
mgifford’s picture

Issue tags: +keyboard

Nice description.

cboyden’s picture

Title: Keyboard trap when using Panels IPE » Keyboard trap when using ctools modal
Project: Panels » Chaos Tool Suite (ctools)
Version: 7.x-3.4 » 7.x-1.x-dev
Component: In-Place Editor (IPE) » User interface

Looks like this might be caused by the ctools modal.js function - moving to ctools.

js/modal.js, line 403-428:

    // Keyboard and focus event handler ensures focus stays on modal elements only
    modalEventHandler = function( event ) {
      target = null;
      if ( event ) { //Mozilla
        target = event.target;
      } else { //IE
        event = window.event;
        target = event.srcElement;
      }

      var parents = $(target).parents().get();
      for (var i = 0; i < parents.length; ++i) {
        var position = $(parents[i]).css('position');
        if (position == 'absolute' || position == 'fixed') {
          return true;
        }
      }
      if( $(target).filter('*:visible').parents('#modalContent').size()) {
        // allow the event only if target is a visible child node of #modalContent
        return true;
      }
      if ( $('#modalContent')) $('#modalContent').get(0).focus();
      return false;
    };
    $('body').bind( 'focus', modalEventHandler );
    $('body').bind( 'keypress', modalEventHandler );

Since keyboard focus is still on the button that opens the modal (see steps 4 and 5), the keyboard focus target is not within the modal and thus all keypresses except Esc, which is bound to the Close button, are getting discarded.

cboyden’s picture

As a proof of concept, I added

$('.close').focus();

to modal.js just before the lines that bind focus and keypress events to the modalEventHandler function. With this in place, I was able to tab forward through the links on the Add Content modal in the Panels IPE. When I activated one of the links, I was caught in the keyboard trap again.

mgifford’s picture

Issue tags: +JavaScript, +modal
cboyden’s picture

This trap is an issue on Firefox (Windows, Mac, and Linux) but not on Chrome (W/M/L), Safari (M), or IE 11 (W).

For Safari, Chrome and IE, usability would improve if focus was set to the Close button when the modal opened. Otherwise there are a ton of keystrokes involved.

mgifford’s picture

Was any of the code responsible ported over to D8 Core? I know not all of Ctools was but believe some code has been brought over with Views into Core.

dsnopek’s picture

Status: Active » Needs work
StatusFileSize
new3.92 KB

Here is a first pass at a patch for this. It still needs lots of work and TONS of testing, but it's a start. :-)

cboyden’s picture

I tested this patch on Chrome/Mac on a vanilla install of the latest Panopoly dev. It's looking pretty good there. One thing that I found was that it was possible to tab forwards out of the modal settings dialog in some cases, but not backwards.

To reproduce on a clean install of Panopoly with demo content:

  1. Log in as an administrator. You should be on the home page.
  2. Tab backward (shift+tab) to the Customize this page button and hit Enter to activate it.
  3. Tab a bunch of times until you are on the Settings button for the first pane in the Content section. Hit Enter to activate.
  4. Note that the red X in the upper right corner is in the hover/focused state (this is right).
  5. Tab to the Content Settings radio button group.
  6. Arrow up to change the view mode from Featured to Teaser.
  7. Tab forward. Note that focus is now in the browser address bar (no longer within the modal).
  8. Tab backward a bunch of times. Note that you loop through the modal without escaping.
  9. Tab backward to the Content Settings radio button group again.
  10. Arrow down to change the view mode back to Featured.
  11. Tab forward. Note you are focused on the red X (tab order is not good, but that's a separate issue).
  12. Tab forward a bunch of times and note that you loop through the modal.

Firefox/Mac will still need some work. With or without the patch, I can't tab to anything except the navbar menu and the Customize/Save etc. IPE options at the bottom of the page.

dsnopek’s picture

Here is a related patch to Panels that allows the "Add content" dialog to work with this (for me) under Chrome, using straight Panels (not Panopoly): #2356449: Content type buttons not focusable under Chrome (accessibility problem)

dsnopek’s picture

@cboyden: I'm able to reproduce the issue you found under Panopoly, however, I haven't come up with a way to do it in straight Panels. I'm not sure what the problem is exactly - it could be some CSS or template changes that Panopoly is making OR something specific to radio buttons in Firefox. I originally thought it might have to do with the live previews, but I disabled that and could still reproduce.

Anyway, unless we can reproduce this on straight Panels, it should be become a follow-up Panopoly issue after this one is finished.

cboyden’s picture

I found another tabbing bug where it's possible to tab backwards out of the modal. This is in plain Panels.

Code:

  • Core 7.31
  • ctools 7.x-1.4+9-dev
  • Panels 7.x-3.4+7-dev
  • Panelizer 7.x-3.1+84-dev

Modules enabled:

  • ctools
  • page_manager
  • panels
  • panels_ipe
  • panelizer

Patches:

Config

  • Node view page enabled in Page Manager
  • Panelizer configured for the Basic Page content type: full page override, provide default panel, render with IPE, single-column default layout
  • One node of type Basic Page created and saved

This is on Mac OS X 10.9.5 with Firefox 32.

Tabbing backward once you've selected a vertical tab will send you out of the modal. To reproduce:

  1. On the Basic Page node, tab to and activate the Customize this page button
  2. Tab to and activate the Add new pane button
  3. Note that the Close Window link is in the focused/hovered state
  4. Tab forward to the Comment item in the vertical tabs and hit Enter to activate it
  5. Note that the Comment tab is highlighted and the Comment links are in the main area of the modal
  6. Note that nothing appears to have keyboard focus
  7. Tab backward once
  8. Note that nothing appears to have keyboard focus
  9. Keep tabbing backward
  10. Note that repeated backwards tabs don't appear to do anything - keyboard input is trapped.
  11. Tab forward once
  12. Note that the Activity vertical tab is now in its focused/hovered state
  13. Tab forward or backward as much as you want
  14. Note that you are now constrained to tabbing within the modal.

There's also a conflict with Admin Menu/Toolbar Style. To reproduce:

  1. Download and enable Admin Menu and Admin Menu Toolbar. Disable core Toolbar.
  2. Do steps 1-7 as above (up to tabbing backward after activating the Comment link)
  3. Note that the "Hello [username]" link in the Toolbar appears to be focused
  4. Continue tabbing backward a few stops
  5. Note that you continue to tab through the Toolbar
  6. Tab forward the same number of stops
  7. Note you have tabbed back to the Close Window link
  8. Tab forward and backward as much as you want
  9. Note that you are now constrained to tabbing within the modal.

Expected behavior in both cases:
Once you've activated a vertical tab, tabbing backward should focus you on the previous tab. If there are no previous vertical tabs, focus should be on whichever focusable element is before the vertical tabs. In this case, that's the Close Window link.

cboyden’s picture

Related to the above: Once you've activated a vertical tab, when you tab forward once, you always focus on the first vertical tab (Activity in this case).

To reproduce:

  1. Do steps 1-6 as in the previous comment (up to where you've activated the Comment link)
  2. Tab forward once
  3. Note that the Activity vertical tab is now in its focused/hovered state

Expected behavior:
Focus should be on the first link in the Comment section (preferred), or on the next vertical tab. If there are no further vertical tabs, focus should be on the next link after the vertical tabs.

cboyden’s picture

The previous issues also apply to Safari 7.0.6, Firefox 33, and Chrome 38 on Mac OSX 10.9.5, and the same Chrome and Firefox versions on Windows 7.

The problem with tabbing backward doesn't happen on the first load of the ctools modal, but once you've activated a link, it will happen on any state of the modal.

cboyden’s picture

When using IE 11 on Windows 7:

  1. On the Basic Page node, tab to and activate the Customize this page button
  2. Tab to and activate the Add new pane button
  3. Note that the Close Window link is not in the focused/hovered state
  4. Tab backward once
  5. Note that nothing appears to have keyboard focus
  6. Keep tabbing backward
  7. Note that repeated backwards tabs don't appear to do anything - keyboard input is trapped
  8. Tab forward once
  9. Note that the Activity vertical tab is now in its focused/hovered state
  10. Tab forward and backward as much as you want
  11. Note that you are now constrained to tabbing within the modal.

So for IE 11, the backward tabbing issue happens even on the initial state of the modal.

Also, the issues are different after you've activated a link in the modal. To reproduce:

  1. Do steps 1-9 as above (until you've tabbed forward to hit the Activity vertical tab)
  2. Tab forward to the Comment vertical tab and hit Enter to activate it
  3. Tab forward once
  4. Note that nothing appears to be in focus. If you keep an eye on the tooltip that tells you the destination of the focused link, you will see you are on #main-content (the skip link)
  5. Keep tabbing forward. Watch the tooltip and see that you are tabbing through the toolbar and the page behind the modal - you can also see the toolbar links get highlighted dimly through the overlay.
  6. You will eventually tab back into the modal, but the Close Window link doesn't receive focus the first time you get to where it should be in the tab order
  7. Tab forward and backward as much as you want
  8. Note that you are now constrained to tabbing within the modal.

However, if you tab backward after activating a link, tab focus moves back to the last focusable element in the modal. To reproduce:

  1. Do steps 1-9 in the first sequence (until you've tabbed forward to hit the Activity vertical tab)
  2. Tab forward to the Comment vertical tab and hit Enter to activate it
  3. Tab backward once
  4. Note you are focused on the last link in the modal, which is the Comment Reply Form link

It appears that IE 11 has the opposite problem from FF and Chrome: it handles backward tabbing OK after you've activated a link, but not forward tabbing.

cboyden’s picture

What's probably happening is that when you click a link in the modal, it's changing the state and losing where it should be focused. Focus then tries to go back to the Close button like it does on first load, but something is interfering so it doesn't look or behave like Close is actually focused. Then different browsers interpret where it's actually focused differently, which creates the differing behavior when you tab forward or back.

dsnopek’s picture

So, first let's just start by focusing on problems on Chrome (we can do the other browsers after - it'd just be nice to have one browser working to start with).

  1. From #13:

    Once you've activated a vertical tab, when you tab forward once, you always focus on the first vertical tab (Activity in this case).

    This is because clicking a tab reloads the entire content of the modal - not just the area on the right. So, the DOM element it was previously focusing on is no longer on the page! I'm not sure we can fix this in CTools - it might need to be fixed in Panels, by either changing how much of the modal is reloaded or by explicitly focusing on the selected category after the reload has happened. I'll try and find a solution to this...

  2. If I activate one of the vertical tabs and then tab backwards then focus leaves the modal and I can no longer tab backwards! But if I tab forward, focus jumps back into the dialog. This appears to be the same as #12 steps 10-12 (in the first set of steps)
  3. Conflict with admin_menu from #12 (the second set of steps). I've been able to reproduce this both with and without admin_menu_toolbar. I suspect it's related to the issue above as it also has tabbing backwards put us outside the modal.

I think these are all the problems reported that affect Chrome! @cboyden: Please let me know if I missed any!

All my testing was on Chrome 39.

dsnopek’s picture

Status: Needs work » Needs review
Related issues: +#2390803: Keyboard focus should be on the first element in the selected category tab in the "Add content" model (accessibility problem)
StatusFileSize
new4.04 KB

Alright! I created a Panels issue to fix #17.1:

#2390803: Keyboard focus should be on the first element in the selected category tab in the "Add content" model (accessibility problem)

And here is an updated patch for this issue which should fix #17.2 and .3.

Please let me know what you think!

cboyden’s picture

Very nice. I tested on Mac OSX 10.9.5 with Chrome 39.0.2171.95, Firefox 34.0.5 and Safari 7.1 and have so far been unable to break anything or get myself into a keyboard trap. I added, configured, and deleted panes using the IPE successfully on those three browsers.

However, I ran into these same issues when adding panes using the Page Manager interface instead of the IPE (trapped in Firefox; able to tab out of the modal in Chrome and Safari). Hopefully it's not too hard to add these fixes to the content modals in Page Manager.

Code and patch status for my testing:

Code:

  • Core 7.34
  • ctools 7.x-1.5
  • Panels 7.x-3.4+7-dev
  • Panelizer 7.x-3.1+90-dev

Modules enabled:

  • ctools
  • page_manager
  • panels
  • panels_ipe
  • panelizer

Patches:

Config:

  • Node view page enabled in Page Manager
  • Panelizer configured for the Basic Page content type: full page override, provide default panel, render with IPE, single-column default layout
  • One node of type Basic Page created and saved
  • One Page Manager page created
mgifford’s picture

Ok, so with SimplyTest.me we can capture this all this with the following.

That gave me a - Error message: An error occurred while patching the project.

cboyden’s picture

How do you specify the dev version of a contrib project on simplytest.me? The patches might only apply correctly using the dev version of Panels.

cboyden’s picture

Or, does simplytest.me attempt to apply all patches to the main project you choose? Since patches are not explicitly associated with the projects you can add, this is probably what's happening. So it doesn't sound like you can apply patches to more than one project, which makes this not a good candidate for simplytest.

Unless you generated the patch(es) from the Drupal site root. Then as long as simplytest puts the modules where you expect them, you could have it patch the whole shebang. That would clutter up the issue queue with patches that were doomed to fail, so they'd have to be uploaded elsewhere.

dsnopek’s picture

StatusFileSize
new5.7 KB

Here is an updated patch that fixes the issue that @cboyden found on Panopoly in comment #9. It's not actually Panopoly-specific, the issue will happen any time the last focusable element on the page is a group of radio buttons, and any radio button other than the last one is selected (if the last one is selected, everything works fine).

The cause is jQuery's :tabbable psuedo selector returning all radio buttons, when in fact, only the selected radio button in a group is tabbable, and if no radio buttons in a group are selected, then only the first is tabbable. So, I've added a function (getTabbableElements()) that will filter out the un-tabbable radio buttons.

This should now resolve all the problems discovered on this issue so far! Please let me know what you think.

cboyden’s picture

The latest patch fixes the issue with radio buttons in the modal.

cboyden’s picture

Status: Needs review » Needs work

This is looking great in the IPE. Using the Page Manager interface, somehow the fix isn't working. After activating one of the links for a type of content, the symptoms are the same as before the patch. I can't tell if the problem is in this JS or in the fix for #2390803: Keyboard focus should be on the first element in the selected category tab in the "Add content" model (accessibility problem).

dsnopek’s picture

Copying @cboyden's comment from #2390803-7: Keyboard focus should be on the first element in the selected category tab in the "Add content" model (accessibility problem) for the bits that mainly relate to this issue:

This is working when using the IPE on Firefox, Chrome, and Safari (Mac). Unfortunately it's not working when I run this from the Page Manager page editing interface. Keyboard focus is lost entirely (Firefox) or outside the modal (Chrome, Safari). In Chrome and Safari, I can tab in and out of the modal, backward and forward.

  1. From the page manager at admin/structure/pages, choose an existing page and follow the Edit link.
  2. Follow the "Content" link in the vertical tabs.
  3. Activate the gear icon link for a content region.
  4. A popup menu will appear.
  5. Tab to and activate the Add Content link.
  6. The ctools modal will appear.
  7. Tab to one of the content type links in the vertical tabs in the modal. For example, Widgets.
  8. Activate the link.
  9. Note that nothing appears to be focused.
  10. Tab forward.
  11. Note that keyboard focus is outside the modal (Chrome, Safari) or lost (Firefox).

Step #9 pertains to #2390803: Keyboard focus should be on the first element in the selected category tab in the "Add content" model (accessibility problem) which we'll address there.

But step #10 and #11 represent issues that this patch should address.

dsnopek’s picture

Status: Needs work » Needs review

I'm testing with a vanilla Drupal 7.34 site, CTools 1.x (fb6c216) + this patch and Panels 3.x (cd0ded6) + the latest patch from #2390803: Keyboard focus should be on the first element in the selected category tab in the "Add content" model (accessibility problem).

Following the steps in #25, testing on Chrome 40.0.2214.91 and Firefox 34.0 (both under Linux), I'm unable to reproduce: the keyboard focus is correctly restricted to the modal. Unfortunately, I don't have Safari to test.

So, setting back to "Needs review". Could you give it a try with the more recent Git revisions and the latest patch from #2390803: Keyboard focus should be on the first element in the selected category tab in the "Add content" model (accessibility problem) and see if you're still seeing the same problems? Thanks!

cboyden’s picture

Status: Needs review » Needs work

Tested on Firefox 35.0.1 on Mac. I've narrowed down the problem to jQuery errors which are interfering with the tab constraints code (this ticket) and the focus on the first element (linked ticket #2390803: Keyboard focus should be on the first element in the selected category tab in the "Add content" model (accessibility problem)). The errors are:

Error: Syntax error, unrecognized expression: tabbable
Error: Syntax error, unrecognized expression: focusable

This is using the standard jQuery version that comes with vanilla Drupal, 1.4.4. I tried updating to jQuery 1.7.1 and got the same errors.

Since the exact same code runs without a hitch when using the IPE, I'm guessing the error is actually somewhere further up the stack?

Here is a stack trace from Firebug:

uncaught exception: Syntax error, unrecognized expression: Syntax error, unrecognized expression: tabbable

k.error()jquery.js?v=1.4.4 (line 85)
g = "Syntax error, unrecognized expression: tabbable"

k.selectors.filter.PSEUDO()jquery.js?v=1.4.4 (line 93)
g = div.ctools-modal-content
i = [":tabbable", "tabbable", undefined, undefined]
n = 0
m = HTMLCollection[div.ctools-modal-content, div.modal-header, a.close #, 21 more...]

k.filter()jquery.js?v=1.4.4 (line 84)
g = ":tabbable"
i = HTMLCollection[div.ctools-modal-content, div.modal-header, a.close #, 21 more...]
n = undefined
m = undefined

k()jquery.js?v=1.4.4 (line 81)
g = "#modalContent :tabbable"
i = div#modalContent
n = Object[]
m = undefined

k()jquery.js?v=1.4.4 (line 102)
m = "#modalContent :tabbable"
p = Document content
q = Object[]
u = undefined

.find()jquery.js?v=1.4.4 (line 105)
a = "#modalContent :tabbable"

c</b.prototype.init()jquery.js?v=1.4.4 (line 26)
j = "#modalContent :tabbable"
s = undefined

$.fn.init()drupal.js?nj4lpj (line 26)
selector = "#modalContent :tabbable"
context = undefined
rootjQuery = undefined

c</b()jquery.js?v=1.4.4 (line 23)
j = "#modalContent :tabbable"
s = undefined

Drupal.CTools.Modal.modalContent/getTabbableElements()modal.js?nj4lpj (line 441)

Drupal.CTools.Modal.modalContent/modalTabTrapHandler()modal.js?nj4lpj (line 495)
evt = Object { originalEvent=Event keydown, type="keydown", timeStamp=1422849539184, more...}

c.event.handle()jquery.js?v=1.4.4 (line 64)
a = Object { originalEvent=Event keydown, type="keydown", timeStamp=1422849539184, more...}

c.event.add/o()jquery.js?v=1.4.4 (line 57)

...{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,N...

jquery.js?v=1.4.4 (line 85)

And from the Chrome dev tools:

Uncaught Syntax error, unrecognized expression: Syntax error, unrecognized expression: tabbablejquery.js?v=1.4.4:85 
k.errorjquery.js?v=1.4.4:93 
k.selectors.filter.PSEUDOjquery.js?v=1.4.4:84 
k.filterjquery.js?v=1.4.4:82 
kjquery.js?v=1.4.4:102 
t.querySelectorAll.kjquery.js?v=1.4.4:105 
c.fn.extend.findjquery.js?v=1.4.4:26 
b.fn.b.initdrupal.js?nj4lpj:26 
$.fn.initjquery.js?v=1.4.4:23 
bmodal.js?nj4lpj:441 
Drupal.CTools.Modal.modalContent.getTabbableElementsmodal.js?nj4lpj:495
Drupal.CTools.Modal.modalContent.modalTabTrapHandlerjquery.js?v=1.4.4:64 
c.event.handlejquery.js?v=1.4.4:57 c.event.add.h.handle.o
cboyden’s picture

This may be it: When the core Overlay is disabled, I get the jQuery error. When it's enabled, I don't, and the code works as intended. @dsnopek can you try disabling Overlay on your test site and see what you get? I also updated the referenced ticket #2390803: Keyboard focus should be on the first element in the selected category tab in the "Add content" model (accessibility problem).

dsnopek’s picture

Status: Needs work » Needs review
StatusFileSize
new6.12 KB

Great catch! I explained what this is about over in #2390803-13: Keyboard focus should be on the first element in the selected category tab in the "Add content" model (accessibility problem).

Here is a new patch that should fix it!

cboyden’s picture

StatusFileSize
new6.12 KB
new558 bytes

I think this is finally it! The only issue with the patch in #31 is that IE 8 does not support the indexOf function on arrays. Using the jQuery $.inArray function is working for me, as tested using IE 11's developer tools set to IE 8 mode. Patch and interdiff are attached.

cboyden’s picture

Status: Needs review » Needs work

I have one more problem when using IE/Windows: Focus is not always corralled properly or does not appear where I expect it. Issues are similar between Windows 7/8.1 and IE 8 thru 11. They happen both on the Panelized/IPE node and on the Page Manager page.

Here's what happens using Win7/IE11 on the Panelized/IPE node:

  1. Go to the panelized node.
  2. Tab to and activate the Customize This Page button.
  3. Tab to and activate the Add Content button.
  4. The Close Window link is not focused, as I expect it to be.
  5. Tab backwards once.
  6. Focus is on the Existing Node link (the 2nd to last item in the modal), not on the New custom content link (the last item). (When I tab forward directly after activating the Add Content modal, I end up on Activity, the first item after Close Window.)
  7. Tab backwards to Activity and activate the link.
  8. Focus is now on the first item in the set (Recent comments), as expected.
  9. Tab to Who's Online and activate it.
  10. The modal changes to the Configure screen.
  11. Tab forward once.
  12. I am not constrained to the modal, and I appear to be focused on the Skip to Main Content link on the underlying page.
  13. Tab backwards a few times.
  14. Eventually focus appears in the modal.
  15. Once back in the modal, focus is constrained there. (When I initially tab backward in the Configure modal, I end up on the Cancel button, which is within the modal, and focus stays constrained.)
dsnopek’s picture

Status: Needs work » Needs review
StatusFileSize
new7.82 KB
new4.28 KB

I was able to reproduce this on IE11.

The issue with the the "Close Window" link not getting focus (steps #1-4), was from a left over line of code that gave focus to #modalContent which came after my new line of code giving focus to the close button. I have no idea why this didn't happen on other browsers! Possibly only IE actually allows that div to be focused? In any case, I've removed that line.

This also had the side effect of fixing the issue where tabbing backwards would select the second to last item (steps #5-6).

The remaining issue where focus escaped the modal was much more complicated. It appears that IE acts differently than Chrome and Firefox when focus is lost entirely. It will put focus on nothing, so pressing TAB will move to the first tabbable element on the page (which is the "Skip to main content link") and it also won't fire events registered on the body. So, our event handler has no chance to catch this TAB and force us back to the modal. (And, also, when "Skip to main content link" is focused, it matches our heuristic for detecting if another dialog is in use, so we don't do our magic then either - that's why you have to TAB a couple of times to get back to the modal).

This means that the only way to fix this in IE, is to try and make sure that focus ISN'T lost entirely.

So, I added some code to the AJAX responder for the modal_display command, to put focus on the first tabbable element in the dialog, when we are replace existing contents of an already visible modal. This will catch the case where we switch to the settings form when adding a new Pane, and I think it's a good improvement for accessibility on its own, we just haven't gotten there yet. :-)

New patch is attached! Please let me know what you think.

cboyden’s picture

Status: Needs review » Needs work

The functionality is working as expected. Tested on Win7/IE11 plus emulation of IE 8, 9, and 10 using the IE developer tools.

However, the script is now throwing Javascript errors on all browsers/platforms I tested (Mac: Chrome and FF; Windows: IE) in specific circumstances. Here's what happened:

  1. Go to the panelized page
  2. Tab to and activate the Customize button
  3. Tab to and activate the Add Content button
  4. Tab to and activate the Node link
  5. Tab to and activate Node author
  6. Tab to and activate Finish to add the Node author element
  7. Tab to and activate the Save button
  8. Start tabbing backward through the Change layout and Customize buttons into the rest of the page
  9. As soon as I started tabbing through the page content, I got one of these two errors on every tab:
TypeError: lastTabbableElement is undefined
http://dev-a11y.pantheon.berkeley.edu/sites/all/modules/ctools/js/modal.js?njiltt
Line 541
lastTabbableElement.focus();

or

TypeError: firstTabbableElement is undefined
http://dev-a11y.pantheon.berkeley.edu/sites/all/modules/ctools/js/modal.js?njiltt
Line 544
firstTabbableElement.focus();

The errors also occur after any operation that involves saving something in the Add/Configure modal.

I did not see the errors under these conditions:

  • Only deleted an item from the page before saving
  • Opened the Add Content modal, then closed it without adding and saved
  • Opened the Configure modal, then closed it without clicking Finish and saved

Tabbing through the admin toolbar menu did not generate errors. Errors disappeared after reloading the page and did not recur until I did something that involved saving pane settings in the Add/Configure modals.

cboyden’s picture

Assigned: Unassigned » cboyden

Looks like maybe the tab trap handler isn't getting unbound like it should? I'll take a shot at fixing this.

cboyden’s picture

Status: Needs work » Needs review
StatusFileSize
new8.32 KB
new1010 bytes

OK, maybe this is IT it. The tab trap handler was not getting unbound when the modal closed other than by the explicit Close Window link - i.e., when the modal disappeared after you clicked Finish. In order to allow it to unbind, I had to change the scope of the modalTabTrapHandler by removing 'var'. I also added an explicit unbinding of the Escape handler. New patch and interdiff are attached.

cboyden’s picture

Assigned: cboyden » Unassigned
dsnopek’s picture

Issue summary: View changes
Issue tags: +panopoly

I'm able to reproduce the Javascript errors that @cboyden found by following the steps in #37. And I can confirm that her updated version of the patch fixes them!

At this point we've tested all major browsers and got everything working in very many cases, however, I'm not sure that review by either @cboyden or myself is really enough to RTBC this. I cleaned up the issue summary a bit and I'm going to see if I can find some other people to test and review the patch.

dsnopek’s picture

Something I noticed when updating the issue summary: it originally said we should use the ARIA role of "dialog" on the modal overlay. This patch doesn't do that - is it something we should still do?

dsnopek’s picture

Issue summary: View changes

Added a link to simplytest.me to verify the problem:

http://simplytest.me/project/ctools?add[]=panels&add[]=panelizer

Unfortunately, since two patches on two different projects are required to test the solution, we can't make a simplytest.me link for that. :-/ Maybe if we can get the Panels patch committed, this will possible: #2390803: Keyboard focus should be on the first element in the selected category tab in the "Add content" model (accessibility problem)

klu’s picture

Thanks @dsnopek and @cboyden! I have done additional BrowserStack testing in Windows XP, 7, and 8 with IE 8, 10, 11, and can confirm that keyboard behavior is working properly.

dsnopek’s picture

Issue summary: View changes

Discussed with @cboyden and decided save the ARIA stuff for a dedicated issue to ARIA things up! Removing that from the issue summary.

japerry’s picture

Added to my list of stuff to review for 1.7 (maybe 1.8)

damienmckenna’s picture

micnap’s picture

Status: Needs review » Reviewed & tested by the community

I'm on Mac OS X and tested in Chrome 41, FF 36.0.4, and Safari 7.0.3 with and without overlay enabled.

Tested using latest core and contrib modules:
Core 7.35
CTools 7.x-1.7+1-dev
Page manager 7.x-1.7+1-dev
Panelizer 7.x-3.2-beta1+21-dev
Panels In-Place Editor 7.x-3.5+0-dev
Panels 7.x-3.5+0-dev

Patch from #37
Patch from https://www.drupal.org/node/2390803#comment-9585245
Patch from https://www.drupal.org/files/issues/panels-chrome-a11y-2356449-1.patch was committed so I didn't have to apply.

Used the config from #19:
Node view page enabled in Page Manager
Panelizer configured for the Basic Page content type: full page override, provide default panel, render with IPE, single-column default layout
One node of type Basic Page created and saved
One Page Manager page created

All worked beautifully! When the modal opened, the focus was immediately on the Close Window link in the modal. Tabbing took me through the categories. I entered a category and tabbed through the category's items. All tabbing stayed within the modal. When I closed the modal without adding content, focus returned to the Add New Pane button. When I added content, the focus returned to the top of the page when the modal closed. This worked when adding content to both panelizer and page manager.

This is a great step forward in the accessibility of Drupal!

dsnopek’s picture

@micnap: Thanks so much for testing!

japerry’s picture

Status: Reviewed & tested by the community » Fixed

Thanks everyone for the hard work here! Committed!

  • japerry committed b4548de on 7.x-1.x authored by cboyden
    Issue #2280853 by dsnopek, cboyden: Keyboard trap when using ctools...
dsnopek’s picture

Woohoo! It's great to see this EPIC issue finally get finished. :-)

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.