Ticket #9101 (closed feature: fixed)

Opened 20 months ago

Last modified 11 months ago

Dialog: Track last focused element instead of always focusing the first tabbable element

Reported by: KopiasCsaba Owned by:
Priority: minor Milestone: 1.11.0
Component: ui.dialog Version: 1.10.0
Keywords: Cc:
Blocking: Blocked by:

Description

Hello!

This problem for some reason is only comes up in Firefox.

Here is an example:  http://jsbin.com/irovuj/1/edit

Steps to reproduce:

  • Click on the second text input in the dialog
  • Ctrl+TAB (switch to the next tab, open one before if you don't have)
  • Ctrl+SHIFT+TAB (switch back to the previous tab)
  • The result: the first text input will be selected.

If you turn off the "modal" parameter, then this behaviour stops. The problem is with the _focusTabbable call:

_createOverlay: function() { 
[...]
$(".ui-dialog:visible:last .ui-dialog-content").data("ui-dialog")._focusTabbable();
[...]
}

Without that the bug disappears. I don't know why thats there, it might have a reason, but please check this out.

Thank you!

Change History

comment:2 Changed 20 months ago by KopiasCsaba

Tested in Firefox 18.0.2 linux version

comment:3 Changed 20 months ago by tj.vantoll

  • Status changed from new to open
  • Summary changed from Dialog focuses to the first input element when changing tabs (in Firefox) to Dialog: focus moved to first focusable element when changing tabs in modal (Firefox)

Confirmed on Firefox 18 on OS X. Reduced -  http://jsbin.com/irovuj/4/edit. The issue does not occur in Chrome. Haven't gotten around to testing the other browsers yet.

comment:4 follow-up: ↓ 10 Changed 20 months ago by scott.gonzalez

  • Type changed from bug to feature
  • Summary changed from Dialog: focus moved to first focusable element when changing tabs in modal (Firefox) to Dialog: Track last focused element instead of always focusing the first tabbable element

This happens because Firefox focuses the document when showing the page. We need to shift focus back to the dialog, so the only option is either put focus back on the first element or the element that had focus when the page was hidden. We can probably track which element had focus to make this better, but this is working as intended based on what Firefox is doing.


Proposed solution:

  • Create a property to store which element currently has focus.
  • Set this to null on create.
  • When determining which element to focus, first check if we have a stored element.
  • On close, reset the property to null

This should give us consistent behavior whenever the dialog loses focus (regardless of how that happens).

comment:5 Changed 17 months ago by scott.gonzalez

#9302 is a duplicate of this ticket.

comment:6 follow-up: ↓ 7 Changed 17 months ago by incutonez2

Happens with anchor tags as well ( JS Bin), because I believe they're considered "tabbable." Is there a quick fix for this? Like, can we unbind the focusing event somehow?

Last edited 17 months ago by incutonez2 (previous) (diff)

comment:7 in reply to: ↑ 6 ; follow-up: ↓ 8 Changed 17 months ago by tj.vantoll

Replying to incutonez2:

Happens with anchor tags as well ( JS Bin), because I believe they're considered "tabbable." Is there a quick fix for this? Like, can we unbind the focusing event somehow?

If you *must*, you can override  _focusTabbable.

Just make sure if you go down this route you do move focus to something for a11y purposes. This example gives it to the close icon, which will avoid scrolling the dialog:  http://jsbin.com/icuguz/2/edit.

comment:8 in reply to: ↑ 7 Changed 17 months ago by incutonez2

Replying to tj.vantoll:

If you *must*, you can override  _focusTabbable.

Just make sure if you go down this route you do move focus to something for a11y purposes. This example gives it to the close icon, which will avoid scrolling the dialog:  http://jsbin.com/icuguz/2/edit.

Interesting... I'm going to use your fix. I was setting _focusTabbable to $.noop, but I guess that causes accessibility issues. Thanks for the help!

Last edited 17 months ago by incutonez2 (previous) (diff)

comment:9 Changed 13 months ago by tj.vantoll

#9513 is a duplicate of this ticket.

comment:10 in reply to: ↑ 4 ; follow-up: ↓ 11 Changed 12 months ago by joern.zaefferer

Replying to scott.gonzalez:

Proposed solution:

  • Create a property to store which element currently has focus.
  • Set this to null on create.
  • When determining which element to focus, first check if we have a stored element.
  • On close, reset the property to null

This should give us consistent behavior whenever the dialog loses focus (regardless of how that happens).

Is this still correct? I can work on putting that together.

comment:11 in reply to: ↑ 10 Changed 12 months ago by scott.gonzalez

Replying to joern.zaefferer:

Is this still correct? I can work on putting that together.

Yes.

comment:12 Changed 12 months ago by joern.zaefferer

At which point do we set that property to something other then null? The obvious one is "at the end of _focusTabbable", but what we probably really need is to bind a focusin event and store the event.target to that property.

comment:13 Changed 12 months ago by scott.gonzalez

Yes, a focusin event handler which stores the target is what we need. We just set that up on create and we don't need to do anything special in _focusTabbable().

comment:14 Changed 11 months ago by Jörn Zaefferer

  • Status changed from open to closed
  • Resolution set to fixed

Dialog: Restore focus to the previously focused element when window regains focus. Fixes #9101 - Dialog: Track last focused element instead of always focusing the first tabbable element

Changeset: 0e5a2e126ab4179f1ec83e1e4e773058b49e336d

comment:15 Changed 11 months ago by joern.zaefferer

  • Milestone changed from none to 1.11.0
Note: See TracTickets for help on using tickets.