Browse files

Dialog: Keep track of instances to focus when elements outside the di…

…alog get focus. Works with inheritance. Adds tests for both. Fixes #9241 - Dialog: UI dialog inheritance causes undefined property '_focusTabbable' in IE9
  • Loading branch information...
1 parent 32a0060 commit 1096f19f37d6075328509d62a4c2c6d6a53d4b37 @jzaefferer jzaefferer committed Nov 16, 2013
Showing with 69 additions and 2 deletions.
  1. +48 −0 tests/unit/dialog/dialog_core.js
  2. +21 −2 ui/jquery.ui.dialog.js
View
48 tests/unit/dialog/dialog_core.js
@@ -4,6 +4,7 @@
(function($) {
+// TODO add teardown callback to remove dialogs
module("dialog: core");
test("title id", function() {
@@ -180,4 +181,51 @@ asyncTest( "#9048: multiple modal dialogs opened and closed in different order",
start();
});
});
+
+asyncTest( "interaction between overlay and other dialogs", function() {
+ $.widget( "ui.testWidget", $.ui.dialog, {
+ options: {
+ modal: true,
+ autoOpen: false
+ }
+ });
+ expect( 2 );
+ var first = $( "<div><input id='input-1'></div>" ).dialog({
+ modal: true
+ }),
+ firstInput = first.find( "input" ),
+ second = $( "<div><input id='input-2'></div>" ).testWidget(),
+ secondInput = second.find( "input" );
+
+ // Support: IE8
+ // For some reason the focus doesn't get set properly if we don't
+ // focus the body first.
+ $( "body" ).focus();
+
+ // Wait for the modal to init
+ setTimeout(function() {
+ second.testWidget( "open" );
+
+ // Simulate user tabbing from address bar to an element outside the dialog
+ $( "#favorite-animal" ).focus();
+ setTimeout(function() {
+ equal( document.activeElement, secondInput[ 0 ] );
+
+ // Last active dialog must receive focus
+ firstInput.focus();
+ $( "#favorite-animal" ).focus();
+ setTimeout(function() {
+ equal( document.activeElement, firstInput[ 0 ] );
+
+ // Cleanup
+ first.remove();
+ second.remove();
+ delete $.ui.testWidget;
+ delete $.fn.testWidget;
+ start();
+ });
+ });
+ });
+});
+
})(jQuery);
View
23 ui/jquery.ui.dialog.js
@@ -182,6 +182,7 @@ $.widget( "ui.dialog", {
this._isOpen = false;
this._focusedElement = null;
this._destroyOverlay();
+ this._untrackInstance();
if ( !this.opener.filter( ":focusable" ).focus().length ) {
@@ -562,11 +563,30 @@ $.widget( "ui.dialog", {
_trackFocus: function() {
this._on( this.widget(), {
"focusin": function( event ) {
+ this._untrackInstance();
+ this._trackingInstances().unshift( this );
this._focusedElement = $( event.target );
}
});
},
+ _untrackInstance: function() {
+ var instances = this._trackingInstances(),
+ exists = $.inArray( this, instances );
+ if ( exists !== -1 ) {
+ instances.splice( exists, 1 );
+ }
+ },
+
+ _trackingInstances: function() {
+ var instances = this.document.data( "ui-dialog-instances" );
+ if ( !instances ) {
+ instances = [];
+ this.document.data( "ui-dialog-instances", instances );
+ }
+ return instances;
+ },
+
_minHeight: function() {
var options = this.options;
@@ -783,8 +803,7 @@ $.widget( "ui.dialog", {
if ( !this._allowInteraction( event ) ) {
event.preventDefault();
- this.document.find( ".ui-dialog:visible:last .ui-dialog-content" )
- .data( this.widgetFullName )._focusTabbable();
+ this._trackingInstances()[ 0 ]._focusTabbable();
}
}
});

0 comments on commit 1096f19

Please sign in to comment.