aria-dialog.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. 'use strict';
  2. exports.__esModule = true;
  3. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
  4. var _ariaUtils = require('./aria-utils');
  5. var _ariaUtils2 = _interopRequireDefault(_ariaUtils);
  6. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  7. /**
  8. * @constructor
  9. * @desc Dialog object providing modal focus management.
  10. *
  11. * Assumptions: The element serving as the dialog container is present in the
  12. * DOM and hidden. The dialog container has role='dialog'.
  13. *
  14. * @param dialogId
  15. * The ID of the element serving as the dialog container.
  16. * @param focusAfterClosed
  17. * Either the DOM node or the ID of the DOM node to focus when the
  18. * dialog closes.
  19. * @param focusFirst
  20. * Optional parameter containing either the DOM node or the ID of the
  21. * DOM node to focus when the dialog opens. If not specified, the
  22. * first focusable element in the dialog will receive focus.
  23. */
  24. var aria = aria || {};
  25. var tabEvent;
  26. aria.Dialog = function (dialog, focusAfterClosed, focusFirst) {
  27. var _this = this;
  28. this.dialogNode = dialog;
  29. if (this.dialogNode === null || this.dialogNode.getAttribute('role') !== 'dialog') {
  30. throw new Error('Dialog() requires a DOM element with ARIA role of dialog.');
  31. }
  32. if (typeof focusAfterClosed === 'string') {
  33. this.focusAfterClosed = document.getElementById(focusAfterClosed);
  34. } else if ((typeof focusAfterClosed === 'undefined' ? 'undefined' : _typeof(focusAfterClosed)) === 'object') {
  35. this.focusAfterClosed = focusAfterClosed;
  36. } else {
  37. this.focusAfterClosed = null;
  38. }
  39. if (typeof focusFirst === 'string') {
  40. this.focusFirst = document.getElementById(focusFirst);
  41. } else if ((typeof focusFirst === 'undefined' ? 'undefined' : _typeof(focusFirst)) === 'object') {
  42. this.focusFirst = focusFirst;
  43. } else {
  44. this.focusFirst = null;
  45. }
  46. if (this.focusFirst) {
  47. this.focusFirst.focus();
  48. } else {
  49. _ariaUtils2.default.focusFirstDescendant(this.dialogNode);
  50. }
  51. this.lastFocus = document.activeElement;
  52. tabEvent = function tabEvent(e) {
  53. _this.trapFocus(e);
  54. };
  55. this.addListeners();
  56. };
  57. aria.Dialog.prototype.addListeners = function () {
  58. document.addEventListener('focus', tabEvent, true);
  59. };
  60. aria.Dialog.prototype.removeListeners = function () {
  61. document.removeEventListener('focus', tabEvent, true);
  62. };
  63. aria.Dialog.prototype.closeDialog = function () {
  64. var _this2 = this;
  65. this.removeListeners();
  66. if (this.focusAfterClosed) {
  67. setTimeout(function () {
  68. _this2.focusAfterClosed.focus();
  69. });
  70. }
  71. };
  72. aria.Dialog.prototype.trapFocus = function (event) {
  73. if (_ariaUtils2.default.IgnoreUtilFocusChanges) {
  74. return;
  75. }
  76. if (this.dialogNode.contains(event.target)) {
  77. this.lastFocus = event.target;
  78. } else {
  79. _ariaUtils2.default.focusFirstDescendant(this.dialogNode);
  80. if (this.lastFocus === document.activeElement) {
  81. _ariaUtils2.default.focusLastDescendant(this.dialogNode);
  82. }
  83. this.lastFocus = document.activeElement;
  84. }
  85. };
  86. exports.default = aria.Dialog;