Skip to content

Commit

Permalink
Dialog: Extend autofocus, starting with [autofocus], then :tabbable c…
Browse files Browse the repository at this point in the history
…ontent, then buttonpane, then close button, then dialog. Fixes #4731 - Dialog: Add option to set which element gains focus on open
  • Loading branch information
jzaefferer committed Nov 26, 2012
1 parent 299681e commit b27db7e
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 8 deletions.
42 changes: 42 additions & 0 deletions tests/unit/dialog/dialog_core.js
Expand Up @@ -17,6 +17,8 @@ test("title id", function() {
el.remove();
});

// TODO test for aria-describedby
// add only when the attribute isn't anywhere yet
test("ARIA", function() {
expect(4);

Expand All @@ -42,4 +44,44 @@ test("widget method", function() {
deepEqual(dialog.parent()[0], dialog.dialog("widget")[0]);
});

test( "focus tabbable", function() {
expect( 5 );
var el,
options = {
buttons: [{
text: "Ok",
click: $.noop
}]
};

// 1. first element inside the dialog matching [autofocus]
el = $( "<div><input><input autofocus></div>" ).dialog( options );
equal( document.activeElement, el.find( "input" )[ 1 ] );
el.remove();

// 2. tabbable element inside the content element
el = $( "<div><input><input></div>" ).dialog( options );
equal( document.activeElement, el.find( "input" )[ 0 ] );
el.remove();

// 3. tabbable element inside the buttonpane
el = $( "<div>text</div>" ).dialog( options );
equal( document.activeElement, el.dialog( "widget" ).find( ".ui-dialog-buttonpane button" )[ 0 ] );
el.remove();

// 4. the close button
el = $( "<div>text</div>" ).dialog();
equal( document.activeElement, el.dialog( "widget" ).find( ".ui-dialog-titlebar .ui-dialog-titlebar-close" )[ 0 ] );
el.remove();

// 5. the dialog itself
el = $( "<div>text</div>" ).dialog({
autoOpen: false
});
el.dialog( "widget" ).find( ".ui-dialog-titlebar-close" ).hide();
el.dialog( "open" );
equal( document.activeElement, el.parent()[ 0 ] );
el.remove();
});

})(jQuery);
2 changes: 1 addition & 1 deletion tests/visual/dialog/complex-dialogs.html
Expand Up @@ -107,7 +107,7 @@

<div id="dialog-datepicker" title="A dialog with a datepicker">
<p>Date: <input id="datepicker"></p>
<p><button id="open-autocomplete">Open another window with an autocomplete and a tooltip.</button></p>
<p><button id="open-autocomplete" autofocus>Open another window with an autocomplete and a tooltip.</button></p>
</div>

<div id="dialog-autocomplete">
Expand Down
22 changes: 15 additions & 7 deletions ui/jquery.ui.dialog.js
Expand Up @@ -224,15 +224,24 @@ $.widget("ui.dialog", {
return this;
},

// TODO check if dialog already has focus, merge with _keepFocus
_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
var hasFocus = this.element.find( ":tabbable" );
// 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.uiDialogButtonPane.find( ":tabbable" );
hasFocus = this.element.find( ":tabbable" );
if ( !hasFocus.length ) {
hasFocus = this.uiDialog;
hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
if ( !hasFocus.length ) {
hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" );
if ( !hasFocus.length ) {
hasFocus = this.uiDialog;
}
}
}
}
hasFocus.eq( 0 ).focus();
Expand Down Expand Up @@ -316,7 +325,6 @@ $.widget("ui.dialog", {
.prependTo( this.uiDialog );
this._on( this.uiDialogTitlebar, {
mousedown: function() {
// TODO call _focusTabbable or _keepFocus
// Dialog isn't getting focus when dragging (#8063)
this.uiDialog.focus();
}
Expand Down

0 comments on commit b27db7e

Please sign in to comment.