Skip to content

Commit 99056e2

Browse files
committed
Dialog: Keep focus inside modal dialog, by handling focus events on elements outside of it
1 parent 1d0d50a commit 99056e2

File tree

1 file changed

+30
-11
lines changed

1 file changed

+30
-11
lines changed

ui/jquery.ui.dialog.js

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -282,8 +282,7 @@ $.widget("ui.dialog", {
282282
return;
283283
}
284284

285-
var hasFocus,
286-
options = this.options,
285+
var options = this.options,
287286
uiDialog = this.uiDialog;
288287

289288
this.opener = $( this.document[ 0 ].activeElement );
@@ -294,22 +293,26 @@ $.widget("ui.dialog", {
294293
this.moveToTop( null, true );
295294
this._show( uiDialog, options.show );
296295

296+
this._focusTabbable();
297+
298+
this._isOpen = true;
299+
this._trigger( "open" );
300+
this._trigger( "focus" );
301+
302+
return this;
303+
},
304+
305+
_focusTabbable: function() {
297306
// set focus to the first tabbable element in the content area or the first button
298307
// if there are no tabbable elements, set focus on the dialog itself
299-
hasFocus = this.element.find( ":tabbable" );
308+
var hasFocus = this.element.find( ":tabbable" );
300309
if ( !hasFocus.length ) {
301310
hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
302311
if ( !hasFocus.length ) {
303-
hasFocus = uiDialog;
312+
hasFocus = this.uiDialog;
304313
}
305314
}
306315
hasFocus.eq( 0 ).focus();
307-
308-
this._isOpen = true;
309-
this._trigger( "open" );
310-
this._trigger( "focus" );
311-
312-
return this;
313316
},
314317

315318
_keepFocus: function( event ) {
@@ -318,7 +321,7 @@ $.widget("ui.dialog", {
318321
isActive = this.uiDialog[ 0 ] === activeElement ||
319322
$.contains( this.uiDialog[ 0 ], activeElement );
320323
if ( !isActive ) {
321-
this.uiDialog.focus();
324+
this._focusTabbable();
322325
}
323326
}
324327
event.preventDefault();
@@ -656,6 +659,22 @@ $.extend( $.ui.dialog.overlay, {
656659
// reuse old instances due to IE memory leak with alpha transparency (see #5185)
657660
oldInstances: [],
658661
create: function( dialog ) {
662+
if ( this.instances.length === 0 ) {
663+
// prevent use of anchors and inputs
664+
// we use a setTimeout in case the overlay is created from an
665+
// event that we're going to be cancelling (see #2804)
666+
setTimeout(function() {
667+
// handle $(el).dialog().dialog('close') (see #4065)
668+
if ( $.ui.dialog.overlay.instances.length ) {
669+
$( document ).bind( "focusin.dialog-overlay", function( event ) {
670+
if ( !$( event.target ).closest( ".ui-dialog").length ) {
671+
event.preventDefault();
672+
$( ".ui-dialog:visible:last .ui-dialog-content" ).data( "ui-dialog" )._focusTabbable();
673+
}
674+
});
675+
}
676+
}, 1 );
677+
}
659678

660679
var $el = ( this.oldInstances.pop() || $( "<div>" ).addClass( "ui-widget-overlay ui-front" ) );
661680

0 commit comments

Comments
 (0)