Skip to content
This repository has been archived by the owner on May 29, 2019. It is now read-only.

MODAL: Keyboard focus fail with dynamic content #5421

Closed
dsuriano opened this issue Feb 5, 2016 · 0 comments
Closed

MODAL: Keyboard focus fail with dynamic content #5421

dsuriano opened this issue Feb 5, 2016 · 0 comments

Comments

@dsuriano
Copy link

dsuriano commented Feb 5, 2016

The problem:

When the modal opens, it fires clearFocusListCache and as soon as a user presses the tab key, it calls loadFocusElementList to create a cache of all the potential tabbable elements. The problem arises when the modal contains dynamic content that wasn't initially available for the cacheing (ie: using ng-if).

http://plnkr.co/18B9eYZK94Wmq1l8cl8w

Steps to reproduce:

  1. Open a modal and tab or shift-tab around. Everything works as expected.
  2. Toggle the hidden content button.
  3. Repeat step 1. You can now shift-tab focus behind modal window.

Proposed fix:

Add a couple more definitions to the keydownListener for the spacebar and enter / return keys, and when they're pressed, re-run clearFocusListCache and then loadFocusElementList.

Here's my working example of the new keydownListener (there's probably a cleaner way to do it, but it gets the job done):

function keydownListener(evt) {
  if (evt.isDefaultPrevented()) {
    return evt;
  }

  var modal = openedWindows.top();
  if (modal) {
    switch (evt.which) {
      case 27:
        {
          if (modal.value.keyboard) {
            evt.preventDefault();
            $rootScope.$apply(function() {
              $modalStack.dismiss(modal.key, 'escape key press');
            });
          }
          break;
        }
      case 9:
        {
          $modalStack.loadFocusElementList(modal);
          var focusChanged = false;
          if (evt.shiftKey) {
            if ($modalStack.isFocusInFirstItem(evt) || $modalStack.isModalFocused(evt, modal)) {
              focusChanged = $modalStack.focusLastFocusableElement();
            }
          } else {
            if ($modalStack.isFocusInLastItem(evt)) {
              focusChanged = $modalStack.focusFirstFocusableElement();
            }
          }

          if (focusChanged) {
            evt.preventDefault();
            evt.stopPropagation();
          }
          break;
        }
      case 13:
        { // keypress: enter/return
          $modalStack.clearFocusListCache();
          $timeout(function() {
            $modalStack.loadFocusElementList(modal);
          }, 200);
          break;
        }
      case 32:
        { // keypress: space
          $modalStack.clearFocusListCache();
          $timeout(function() {
            $modalStack.loadFocusElementList(modal);
          }, 200);
          break;
        }
    }
  }
}
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants