From: Jörn Zaefferer Date: Fri, 26 Oct 2012 14:59:41 +0000 (-0400) Subject: Dialog: Keep focus inside modal dialog, by handling focus events on elements outside... X-Git-Tag: 1.10.0-beta.1~130 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=8ee8046c029354501bc6d1690b3ac84edf23efd7;p=jquery-ui.git Dialog: Keep focus inside modal dialog, by handling focus events on elements outside of it --- diff --git a/ui/jquery.ui.dialog.js b/ui/jquery.ui.dialog.js index 892dd72b0..ed1e55beb 100644 --- a/ui/jquery.ui.dialog.js +++ b/ui/jquery.ui.dialog.js @@ -282,8 +282,7 @@ $.widget("ui.dialog", { return; } - var hasFocus, - options = this.options, + var options = this.options, uiDialog = this.uiDialog; this.opener = $( this.document[ 0 ].activeElement ); @@ -294,22 +293,26 @@ $.widget("ui.dialog", { this.moveToTop( null, true ); this._show( uiDialog, options.show ); + this._focusTabbable(); + + this._isOpen = true; + this._trigger( "open" ); + this._trigger( "focus" ); + + return this; + }, + + _focusTabbable: function() { // set focus to the first tabbable element in the content area or the first button // if there are no tabbable elements, set focus on the dialog itself - hasFocus = this.element.find( ":tabbable" ); + var hasFocus = this.element.find( ":tabbable" ); if ( !hasFocus.length ) { hasFocus = this.uiDialogButtonPane.find( ":tabbable" ); if ( !hasFocus.length ) { - hasFocus = uiDialog; + hasFocus = this.uiDialog; } } hasFocus.eq( 0 ).focus(); - - this._isOpen = true; - this._trigger( "open" ); - this._trigger( "focus" ); - - return this; }, _keepFocus: function( event ) { @@ -318,7 +321,7 @@ $.widget("ui.dialog", { isActive = this.uiDialog[ 0 ] === activeElement || $.contains( this.uiDialog[ 0 ], activeElement ); if ( !isActive ) { - this.uiDialog.focus(); + this._focusTabbable(); } } event.preventDefault(); @@ -659,6 +662,22 @@ $.extend( $.ui.dialog.overlay, { // reuse old instances due to IE memory leak with alpha transparency (see #5185) oldInstances: [], create: function( dialog ) { + if ( this.instances.length === 0 ) { + // prevent use of anchors and inputs + // we use a setTimeout in case the overlay is created from an + // event that we're going to be cancelling (see #2804) + setTimeout(function() { + // handle $(el).dialog().dialog('close') (see #4065) + if ( $.ui.dialog.overlay.instances.length ) { + $( document ).bind( "focusin.dialog-overlay", function( event ) { + if ( !$( event.target ).closest( ".ui-dialog").length ) { + event.preventDefault(); + $( ".ui-dialog:visible:last .ui-dialog-content" ).data( "ui-dialog" )._focusTabbable(); + } + }); + } + }, 1 ); + } var $el = ( this.oldInstances.pop() || $( "
" ).addClass( "ui-widget-overlay ui-front" ) );