]> source.dussan.org Git - jquery-ui.git/commitdiff
Dialog: Keep focus inside modal dialog, by handling focus events on elements outside...
authorJörn Zaefferer <joern.zaefferer@gmail.com>
Fri, 26 Oct 2012 14:59:41 +0000 (10:59 -0400)
committerJörn Zaefferer <joern.zaefferer@gmail.com>
Mon, 26 Nov 2012 09:26:11 +0000 (10:26 +0100)
ui/jquery.ui.dialog.js

index 892dd72b099721f32d6dda4f988815337b0cbe38..ed1e55bebf4a593bc007665a519471bfab515d7e 100644 (file)
@@ -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() || $( "<div>" ).addClass( "ui-widget-overlay ui-front" ) );