diff --git a/tests/unit/dialog/dialog_core.js b/tests/unit/dialog/dialog_core.js
index e85759dc9..062d44576 100644
--- a/tests/unit/dialog/dialog_core.js
+++ b/tests/unit/dialog/dialog_core.js
@@ -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() {
- checkFocus( "
", options, function() {
- equal( document.activeElement, element.find( "input" )[ 1 ],
- "1. first element inside the dialog matching [autofocus]" );
- }, step2 );
+ element = $( "" ).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( "", options, function() {
- equal( document.activeElement, element.find( "input" )[ 0 ],
- "2. tabbable element inside the content element" );
+ checkFocus( "", options, function() {
+ equal( document.activeElement, element.find( "input" )[ 1 ],
+ "2. first element inside the dialog matching [autofocus]" );
}, step3 );
}
function step3() {
- checkFocus( "text
", options, function() {
- equal( document.activeElement,
- element.dialog( "widget" ).find( ".ui-dialog-buttonpane button" )[ 0 ],
- "3. tabbable element inside the buttonpane" );
+ checkFocus( "", options, function() {
+ equal( document.activeElement, element.find( "input" )[ 0 ],
+ "3. tabbable element inside the content element" );
}, step4 );
}
function step4() {
- checkFocus( "text
", {}, function() {
+ checkFocus( "text
", options, function() {
equal( document.activeElement,
- element.dialog( "widget" ).find( ".ui-dialog-titlebar .ui-dialog-titlebar-close" )[ 0 ],
- "4. the close button" );
+ element.dialog( "widget" ).find( ".ui-dialog-buttonpane button" )[ 0 ],
+ "4. tabbable element inside the buttonpane" );
}, step5 );
}
function step5() {
+ checkFocus( "text
", {}, function() {
+ equal( document.activeElement,
+ element.dialog( "widget" ).find( ".ui-dialog-titlebar .ui-dialog-titlebar-close" )[ 0 ],
+ "5. the close button" );
+ }, step6 );
+ }
+
+ function step6() {
element = $( "text
" ).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();
});
diff --git a/ui/jquery.ui.dialog.js b/ui/jquery.ui.dialog.js
index c5bd42ab5..2684b7615 100644
--- a/ui/jquery.ui.dialog.js
+++ b/ui/jquery.ui.dialog.js
@@ -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]");
- if ( !hasFocus.length ) {
- hasFocus = this.element.find(":tabbable");
+ // 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.uiDialogButtonPane.find(":tabbable");
+ hasFocus = this.element.find( ":tabbable" );
}
if ( !hasFocus.length ) {
- hasFocus = this.uiDialogTitlebarClose.filter(":tabbable");
+ hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
+ }
+ if ( !hasFocus.length ) {
+ 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;