;(function ($, window, document, undefined) { $.widget("ui.dialog", $.ui.dialog, { _createWrapper: function () { this.uiDialog = $("
") .addClass("ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " + this.options.dialogClass) .hide() .attr({ // Setting tabIndex makes the div focusable tabIndex: -1, role: this.options.role || 'dialog' }) .appendTo(this._appendTo()); this._on(this.uiDialog, { keydown: function (event) { if (this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && event.keyCode === $.ui.keyCode.ESCAPE) { event.preventDefault(); this.close(event); return; } // prevent tabbing out of dialogs if (event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented()) { return; } var tabbables = this.uiDialog.find(":tabbable"), first = tabbables.filter(":first"), last = tabbables.filter(":last"); if (( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey) { this._delay(function () { first.focus(); }); event.preventDefault(); } else if (( event.target === first[0] || event.target === this.uiDialog[0] ) && event.shiftKey) { this._delay(function () { last.focus(); }); event.preventDefault(); } }, mousedown: function (event) { if (this._moveToTop(event)) { this._focusTabbable(); } } }); // We assume that any existing aria-describedby attribute means // that the dialog content is marked up properly // otherwise we brute force the content as the description if (!this.element.find("[aria-describedby]").length) { this.uiDialog.attr({ "aria-describedby": this.element.uniqueId().attr("id") }); } }, /** * The open function has been rewritten to improve the accessibility of modal dialogs. * It does so by taking otherwise focusable elements and removing them from the tab order. * It also "hides" them from screen readers by adding aria-hidden to them. * @returns {*} */ open: function () { var modal = this.options.modal; // do this stuff *only* if the dialog is modal if (modal === true) { this._setOption('dialogClass', 'a11y-ui-dialog-open'); // select the focusable things that are not in the dialog var couldFocus = $('a[href], area, input:not(input[type=hidden]), button, select, textarea, *[tabindex=0]').filter(':visible').not('.a11y-ui-dialog-open *'); couldFocus.attr({ 'tabindex': '-1', 'aria-hidden': 'true' }).addClass('ui-dialog-hidden-by-modal'); } // do all the other stuff this function would normally do return this._super(); }, /** * The close function undoes all of the above * @returns {*} */ close: function () { var modal = this.options.modal; if (modal === true) { $('.ui-dialog-hidden-by-modal').attr({ 'tabindex': '0' }).removeAttr('aria-hidden').removeClass('ui-dialog-hidden-by-modal'); } return this._super(); } }); })(jQuery, window, document);