While working on a site for blind users I noticed the address field widget on the checkout form loses your focus due to the AJAX refresh when selecting a country.

I whipped up a quick fix specifically for just this widget, but perhaps there is a better, more generic way to fix this?

#3 address_form_tab_2.patch687 bytesinolen
address_form_tab.patch835 bytesinolen
Members fund testing for the Drupal project. Drupal Association Learn more


rszrama’s picture

Issue tags: +1.1 blocker

Ahh, interesting. Will review this in time for the 1.1 release.

inolen’s picture

Status: Needs review » Needs work

Doh, I was in a hurry to fix this and while I told myself there was an addressfield module this belongs to, I somehow forgot and stuffed it into commerce_checkout as it was my immediate problem.

inolen’s picture

Project: Drupal Commerce » Address Field
Component: Checkout » Code
Status: Needs work » Needs review
687 bytes

So, the first patch here turned out to be a terrible idea.

Consider that there are two separate ways that the AJAX event would fire that should provide a different experience:
- The user picks a specific value with by clicking with the mouse or the user picks a specific value with the keyboard and presses enter. Both of these would mean the focus should remain on the select box.
- The user picks a specific value with the keyboard and presses tab. This would mean that we'd want to be focused on the next field on refresh.

I tried to solve both of these cases a variety of ways in JS by using document.activeElement. The idea would be to store off the name of the focused element before the AJAX event occurs, and re-select it after the dust settles.

However, that proves to be problematic for a cross-browser solution as document.activeElement is not at all consistent. For example:
- When the AJAX framework disables the select element in beforeSubmit() this sets document.activeElement to document.body in IE, but it remains the select element in FF, meaning you can't implement a solution after the AJAX framework processes the event.
- If you then trap the beforeSubmit() event and store document.activeElement before the element is disabled, it works in IE, but in FF document.activeElement is set to document.body at that specific time (perhaps because you're in the middle of tabbing to a new element?).

In the end, I decided to just re-focus on the new select element after the refresh. It solves case 1, and for case 2 it adds an extra tab and perhaps a split second of confusion. Also, we can do it in a very obvious fashion inside the widget AJAX callback without the need to introduce a javascript file into the addressfield module. However, it does feel a little weird forcing focus from the server.

rszrama’s picture

Status: Needs review » Fixed

Finally committed this. I did change it from ajax_command_insert() to ajax_command_replace(), though, and at the same time removed some incorrect "replace" #ajax methods in the code. This will ensure we always get the replaceWith functionality when the form is rebuilt.

Automatically closed -- issue fixed for 2 weeks with no activity.

Anonymous’s picture

Issue summary: View changes