]> source.dussan.org Git - jquery-ui.git/commitdiff
Dialog: Restore focus to the previously focused element when window regains focus... 1108/head
authorJörn Zaefferer <joern.zaefferer@gmail.com>
Wed, 2 Oct 2013 15:27:43 +0000 (17:27 +0200)
committerJörn Zaefferer <joern.zaefferer@gmail.com>
Fri, 15 Nov 2013 07:16:24 +0000 (08:16 +0100)
tests/unit/dialog/dialog_core.js
ui/jquery.ui.dialog.js

index e85759dc9ad66f97fe3c06d294d6ee875ad8499c..062d4457625268d1597546df96465f9c907d0ffd 100644 (file)
@@ -40,7 +40,7 @@ test("widget method", function() {
 });
 
 asyncTest( "focus tabbable", function() {
-       expect( 5 );
+       expect( 6 );
        var element,
                options = {
                        buttons: [{
@@ -50,6 +50,12 @@ asyncTest( "focus tabbable", function() {
                };
 
        function checkFocus( markup, options, testFn, next ) {
+
+               // Support: IE8
+               // For some reason the focus doesn't get set properly if we don't
+               // focus the body first.
+               $( "body" ).focus();
+
                element = $( markup ).dialog( options );
                setTimeout(function() {
                        testFn();
@@ -59,43 +65,57 @@ asyncTest( "focus tabbable", function() {
        }
 
        function step1() {
+               element = $( "<div><input><input></div>" ).dialog( options );
+               setTimeout(function() {
+                       var input = element.find( "input:last" ).focus().blur();
+                       element.dialog( "instance" )._focusTabbable();
+                       setTimeout(function() {
+                               equal( document.activeElement, input[ 0 ],
+                                       "1. an element that was focused previously." );
+                               element.remove();
+                               setTimeout( step2 );
+                       });
+               });
+       }
+
+       function step2() {
                checkFocus( "<div><input><input autofocus></div>", options, function() {
                        equal( document.activeElement, element.find( "input" )[ 1 ],
-                               "1. first element inside the dialog matching [autofocus]" );
-               }, step2 );
+                               "2. first element inside the dialog matching [autofocus]" );
+               }, step3 );
        }
 
-       function step2() {
+       function step3() {
                checkFocus( "<div><input><input></div>", options, function() {
                        equal( document.activeElement, element.find( "input" )[ 0 ],
-                               "2. tabbable element inside the content element" );
-               }, step3 );
+                               "3. tabbable element inside the content element" );
+               }, step4 );
        }
 
-       function step3() {
+       function step4() {
                checkFocus( "<div>text</div>", options, function() {
                        equal( document.activeElement,
                                element.dialog( "widget" ).find( ".ui-dialog-buttonpane button" )[ 0 ],
-                               "3. tabbable element inside the buttonpane" );
-               }, step4 );
+                               "4. tabbable element inside the buttonpane" );
+               }, step5 );
        }
 
-       function step4() {
+       function step5() {
                checkFocus( "<div>text</div>", {}, function() {
                        equal( document.activeElement,
                                element.dialog( "widget" ).find( ".ui-dialog-titlebar .ui-dialog-titlebar-close" )[ 0 ],
-                               "4. the close button" );
-               }, step5 );
+                               "5. the close button" );
+               }, step6 );
        }
 
-       function step5() {
+       function step6() {
                element = $( "<div>text</div>" ).dialog({
                        autoOpen: false
                });
                element.dialog( "widget" ).find( ".ui-dialog-titlebar-close" ).hide();
                element.dialog( "open" );
                setTimeout(function() {
-                       equal( document.activeElement, element.parent()[ 0 ], "5. the dialog itself" );
+                       equal( document.activeElement, element.parent()[ 0 ], "6. the dialog itself" );
                        element.remove();
                        start();
                });
index c5bd42ab5a8a56839c827564e9365031f6ccc3e4..2684b7615fd13955f08d3e725292b2348cdf61fb 100644 (file)
@@ -118,6 +118,8 @@ $.widget( "ui.dialog", {
                }
 
                this._isOpen = false;
+
+               this._trackFocus();
        },
 
        _init: function() {
@@ -178,6 +180,7 @@ $.widget( "ui.dialog", {
                }
 
                this._isOpen = false;
+               this._focusedElement = null;
                this._destroyOverlay();
 
                if ( !this.opener.filter(":focusable").focus().length ) {
@@ -256,20 +259,24 @@ $.widget( "ui.dialog", {
 
        _focusTabbable: function() {
                // Set focus to the first match:
-               // 1. First element inside the dialog matching [autofocus]
-               // 2. Tabbable element inside the content element
-               // 3. Tabbable element inside the buttonpane
-               // 4. The close button
-               // 5. The dialog itself
-               var hasFocus = this.element.find("[autofocus]");
+               // 1. An element that was focused previously
+               // 2. First element inside the dialog matching [autofocus]
+               // 3. Tabbable element inside the content element
+               // 4. Tabbable element inside the buttonpane
+               // 5. The close button
+               // 6. The dialog itself
+               var hasFocus = this._focusedElement;
+               if ( !hasFocus ) {
+                       hasFocus = this.element.find( "[autofocus]" );
+               }
                if ( !hasFocus.length ) {
-                       hasFocus = this.element.find(":tabbable");
+                       hasFocus = this.element.find( ":tabbable" );
                }
                if ( !hasFocus.length ) {
-                       hasFocus = this.uiDialogButtonPane.find(":tabbable");
+                       hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
                }
                if ( !hasFocus.length ) {
-                       hasFocus = this.uiDialogTitlebarClose.filter(":tabbable");
+                       hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" );
                }
                if ( !hasFocus.length ) {
                        hasFocus = this.uiDialog;
@@ -552,6 +559,14 @@ $.widget( "ui.dialog", {
                .css( "position", position );
        },
 
+       _trackFocus: function() {
+               this._on( this.widget(), {
+                       "focusin": function( event ) {
+                               this._focusedElement = $( event.target );
+                       }
+               });
+       },
+
        _minHeight: function() {
                var options = this.options;