Several months ago, after using Drupal sites for some time, I was surprised to find that some fields provide autocomplete functionality. I am an assistive technology user, and primarily use the JAWS screen-reader.
I noticed today that not only does autocomplete not function (e.g. free tagging), but that it can sometimes return undesirable results, as the unintentional Issue Tag "variable_get" at http://drupal.org/node/515236 shows.
Yahoo and Google have both implemented search suggestions accessible to screen-reader users (my only testing is with JAWS 10). Google's approach does not use ARIA, as it works in IE6. Yahoo's approach does use ARIA.
Suggestions:
1. Resolve the issue where screen reader users may unintentionally select an inappropriate item in an autocomplete field.
2. Improve the markup of autocomplete fields to make autocomplete functionality accessible to screen-reader users. This will likely be best accomplished by using ARIA.
Comments
Comment #1
Everett Zufelt CreditAttribution: Everett Zufelt commentedCorrected component.
Comment #2
drewish CreditAttribution: drewish commentedI'd never heard of ARIA before but a quick Google turned up: http://www.w3.org/WAI/intro/aria and that had http://www.w3.org/TR/wai-aria-primer/ which makes for a nice introduction to their approach.
Comment #3
drewish CreditAttribution: drewish commentedBest quote from the primer—and one of my gripes with the current autocomplete:
Comment #4
Everett Zufelt CreditAttribution: Everett Zufelt commentedResources:
JQuery Autocomplete static test - http://code.google.com/p/jquery-ui/source/browse/branches/dev/autocomple...
Using ARIA to Implement Auto Complete - jQuery Accessibility - http://groups.google.com/group/jquery-a11y/browse_thread/thread/600b37f3...
CodeTalks (Dojo autocomplete) - http://wiki.codetalks.org/wiki/index.php/Set_of_ARIA_Test_Cases#autocomp...
Comment #5
lilou CreditAttribution: lilou commentedAdd tag.
Comment #6
Everett Zufelt CreditAttribution: Everett Zufelt commentedAutocomplete returning incorrect values for screen-reader users is a duplicate of #159762: Autocomplete errors on whitespace only.
To provide autocomplete functionality for screen-reader users we will need to add ARIA support to the autocomplete JS. Tagging and changing title.
Comment #7
mgiffordAgain I'm assuming it's mostly a matter of inserting the aria attribute 'aria-live="polite"' in the right place.
Looking at and extending the model for autocomplete listed here - http://www.mit.edu/~rjc/completionList.html
I also added 'aria-relevant="all"' as I think that the entire list would be potentially useful in terms of how it could be used.
This is mostly an example, but think it may do the trick. Needs testing.
Comment #9
mgiffordtesting if the bot was bust.
Comment #10
mgiffordI ran the CSS Unit Tests locally after applying the patches without problem.
Comment #11
mgiffordRan into the same problem here - http://drupal.org/node/521904
Maybe simpletest doesn't like ARIA
Comment #14
bowersox CreditAttribution: bowersox commented+1 for adding ARIA markup to autocomplete. The code here looks simple and okay to me.
I have not tested in a screenreader so I hope someone will do that to verify it works as expected.
Also, it looks like we could use JS to add the
aria-autocomplete="list"
attribute onto the the input element so screenreaders would announce that the input field supports autocomplete. (See aria-autocomplete values).Comment #15
bowersox CreditAttribution: bowersox commentedNow that we're past the UX/string freeze, what is the policy on issues like this one?
So should we proceed with it? Or should we be marking these as drupal 8.x-dev?
Comment #16
mgiffordI'd like to think that any accessibility enhancements that we can make that don't change the functionality or display of D7 should still be possible to bring in.
With this and other ARIA issues I'd like to have some testing in popular screen readers but would expect we'd be able to bring them in (as heck accessibility enhancements for D6 were backported into releases D6 earlier this year).
It's a simple change if it will make a difference to the users. There are some questions about the impacts for validation, but ARIA adoption is becoming more widespread.
Comment #18
Everett Zufelt CreditAttribution: Everett Zufelt commentedLooked at aria-autocomplete="list". This is only part of the solution. This tells AT that there is a list of values, but aria is also required to tell AT which of the list of suggestions is currently selected. At this time I believe that aria should be injected with jQuery, as it will break document validation.
Would be happy to provide support if someone wants to try to get this in before 7.x RC.
Comment #19
mgiffordCan this be brought into D7 using the Accessible Helper Module?
Comment #20
Everett Zufelt CreditAttribution: Everett Zufelt commentedThe attached patch is a partial solution and is primarily to get something out there to use for testing. I could really use the assistance (likely briefly) of a jQuery guru to answer the question about the context for 'this' mentioned in the first todo in the patch.
1. Adds role="application" to container div for autocomplete widget.
2. Appends a span role="alert" class="element-invisible" to the end of the container.
Todo:
Add behavior to add / remove the selected item from the autocomplete list to the span. AT that supports ARIA live regions should read the content of the span.
Note: This is not a perfect solution, which would involve completely rebuilding the widget to be a semantic UI component using ARIA. However, this will work, is relatively clean and unobtrusive.
Comment #21
Everett Zufelt CreditAttribution: Everett Zufelt commentedI noticed #675446: Use jQuery UI Autocomplete. I tested out the jQuery UI autocomplete widget, which is no more accessible than our own. I think that this reinforces the argument of geting something built that works, if not a full ARIA implementation, for our custom autocomplete, and then to focus effort on assisting with improving the accessibility of the jQuery UI widget so that we can eventually switch to using it instead of our own.
Comment #22
mgiffordYour patch applies nicely. It doesn't interfere with autocomplete's use for sighted folks either.
Just gotta get your jQuery question answered.
Comment #23
merlinofchaos CreditAttribution: merlinofchaos commentedTo answer the TODOs, from skimming through the code, 'this' in the select, selectUp and selectDown functions will be the textfield
<input>
form widget.Comment #24
merlinofchaos CreditAttribution: merlinofchaos commentedTo get the span you added, I believe you want this:
Comment #25
merlinofchaos CreditAttribution: merlinofchaos commentedSorry, I was wrong. 'this' will be the jsAC object. So 'this.input' should contain the input textfield.
Comment #26
Everett Zufelt CreditAttribution: Everett Zufelt commented@merlinofchaos
Thanks, this.input makes sense now.
@all
A couple further problems.
1. Autocomplete in beta1 w/o the patch doesn't appear to be working, testing with the tags field on articles. Can someone please confirm?
2. I can't install head since it now requires PHP 5.2.4 and my dev server doesn't support that. And there are a series of events that I do not have full control over that need to take place before I upgrade. If someone has access to a place that I can test the patch against head I'd appreciate it.
Comment #27
Everett Zufelt CreditAttribution: Everett Zufelt commentedAttached a new partial patch.
1. Fixed added span, so that it actually gets the correct id.
2. Added an alert to the highlight function for testing. It * should * display the id of the span, it is displaying Undefined.
+alert($($(this.input).attr('id') + '-autocomplete-aria-live').attr('id'));
I thought the above line would work to get the id of the span, I was incorrect.
Comment #29
Everett Zufelt CreditAttribution: Everett Zufelt commentedOk, @jacine helped me remember I need a '#' for an id selector. I am happy to report that the selected list item is currently being read to me in JAWS 11 / FF 3.6.
$('#' + $(this.input).attr('id') + '-autocomplete-aria-live').html($(this.selected).html());
The above line is what I am using to put the selected item into the invisible span to be read automatically by screen-readers that support ARIA live.
I will do a bit more tweaking and reroll a patch for testing tomorrow.
Comment #30
Everett Zufelt CreditAttribution: Everett Zufelt commentedThis patch:
1. Sets role = application for the div containing the autocomplete element.
2. Sets aria-autocomplete = list on the text input element (Testing with NVDA 2010.1 and JAWS 11 neither reported this, but it is worth having)
3. Adds a span to the end of the div with aria-live = assertive (once we are done testing this can have class = element-invisible set
4. Adds behavior to add 'Autocomplete popup' to the span when the popup appears
5. As items are selected in the popup they are added to the span so that AT that supports aria live regions will announce them.
Other than tweaking / code cleanup I think this is good.
Comment #31
Everett Zufelt CreditAttribution: Everett Zufelt commentedI realized that the 'Autocomplete popup' message needs to be translatable. Can someone please point me to the docs to use t() in JS?
Comment #32
mgiffordIt works. I've got it up on my sandbox http://drupal7.dev.openconcept.ca/
I did notice that some additional descriptive text is actually visible - "Autocomplete popup" is visible in some situations.
Screenshot is attached. I don't think it's a bad thing, just worth mentioning.
Comment #33
Everett Zufelt CreditAttribution: Everett Zufelt commented@Mike
Yep, the span is exposed for testing, once we are ready to RTBC we can add class="element-invisible"
Comment #34
Everett Zufelt CreditAttribution: Everett Zufelt commentedAdded class="element-invisible" to the aria live region span.
Added Drupal.t() to wrap the 'Autocomplete popup' string.
Tagging with string freeze
Comment #35
Everett Zufelt CreditAttribution: Everett Zufelt commentedTesting:
Pass = Autocomplete worked as expected
Fail = Same results as before patch, user can enter tags, but is unaware of autocomplete functionality
FF 3.6
JAWS 11.0.1467 = Pass
NVDA 2010.1 = Pass
IE 8
JAWS 11.0.1467 = PASS
NVDA 2010.1 = Fail (poor IE support)
System Access To Go = Pass ( http://satogo.com )
Safari 5
VoiceOver (10.6.3) = Fail (no live region support)
Comment #36
sun1) The appended element should be assigned and made available to all other methods in this.$heading.
2) .html('') == .empty()
Powered by Dreditor.
Comment #37
Everett Zufelt CreditAttribution: Everett Zufelt commented@Sun
1) The appended element should be assigned and made available to all other methods in this.$heading.
Can you point to an example where I can look to learn to do this? This seems a bit over my head, but I will give it a shot.
2. Will switch .html('') to .empty()
Thanks
Comment #38
Everett Zufelt CreditAttribution: Everett Zufelt commented1. Sets role = application for the div containing the autocomplete element.
2. Sets aria-autocomplete = list on the text input element (Testing with NVDA 2010.1 and JAWS 11 neither reported this, but it is worth having)
3. Adds a span to the end of the div with aria-live = assertive and class = element-invisible
4. Adds behavior to add Drupal.t('Autocomplete popup') to the span when the popup appears
5. As items are selected in the popup they are added to the span so that AT that supports aria live regions will announce them.
6. Addresses both of @Sun's points in #36.
Comment #39
casey CreditAttribution: casey commentedCan't we follow jquery ui's approach on aria on autocomplete elements?
Comment #40
Everett Zufelt CreditAttribution: Everett Zufelt commented@Casey
Thanks for the comment.
1. I tested http://jqueryui.com/demos/autocomplete/multiple.html and it was not accessible with a screen-reader, perhaps it is not using the most recent code?
2. We are considering replacing our autocomplete with jQuery UI, so I am not inclined to do much work at all on our custom solution. See #675446: Use jQuery UI Autocomplete.
3. I think it far more likely for this small change to get committed in D7 than a larger solution, which is what the jQuery UI code that you pointed me to looks to be doing.
Comment #41
bowersox CreditAttribution: bowersox commentedThe patch in #38 looks great! The javascript code all looks good and it appears coding standards are met. The behavior appears to work as desired (I agree with Everett that VoiceOver doesn't handle it right but maybe a future version will support live regions).
@sun or anyone else ready to give a last review? I think this is RTBC material.
As far as future use of jQuery UI (#675446) we should work to make that accessible before switching to it. It makes good sense for us to include this patch here as a light-weight solution for D7, and make jQuery UI our longer-term strategy.
Comment #42
Everett Zufelt CreditAttribution: Everett Zufelt commentedThis patch adds to #38 a message announced only to screen-reader users Drupal.t('Searching for matches.'), when the throbbing class is added.
Comment #43
bowersox CreditAttribution: bowersox commentedI tested again and things work well. JAWS 10 on IE 7 announced the "Searching for matches" message as soon as the autocomplete started searching. After that it announced the "Autocomplete popup" and it read out the selections as I navigated through them.
One question: Should the t() string have a period at the end (eg "Searching for matches.")?
Otherwise, this looks good to me. I think we're ready for RTBC.
Comment #44
Everett Zufelt CreditAttribution: Everett Zufelt commented@Brandon
Looking back at the patch I notice that I put a period on 'Searching for matches.' but not 'Autocomplete popup'. I am happy to reroll w/ or w/o the period if someone can point me to directions.
My reasoning, I believe, at the time was that 'Searching for matches.' is a sentence, whereas 'Autocomplete popup' is more of a label / announcement. But, I really don't know where to find guidance for string punctuation.
Comment #45
bowersox CreditAttribution: bowersox commentedIt's probably good as-is. I just grep'ed around core. When there is a complete sentence, we end the string with the period included. When we just have a title ("Warning message") we don't include the period. So it looks like the patch is consistent with that.
Comment #46
bowersox CreditAttribution: bowersox commentedCan anyone give a second review so this can be RTBC?
@sun?
Comment #47
mgiffordShould I expect to hear 'Searching for matches' using VoiceOver in Mac OS X 10.6.5? I applied the patch, cleared the patches, but I don't get an alert that says that. I just get the text that is listed in the form.
I'm not familiar enough with what it should sound like to mark this RTBC. It certainly doesn't break functionality for sighted users. I'd be happy to mark it rtbc if it's a matter that it's doing no harm.
Has anyone else tested this with VoiceOver?
Comment #48
Everett Zufelt CreditAttribution: Everett Zufelt commented@mgifford
From comment #35 "VoiceOver (10.6.3) = Fail (no live region support)" So, you shouldn't hear anything ever with voiceover.
Comment #49
mgiffordThat's what I was hoping to hear. With that I'm willing to mark it RTBC.
Comment #50
sunPlease try again with this one.
Comment #51
mgifford@sun - I can't test this with JAWS or NVDA, but it looks just fine when applied to my local sandbox. The autocomplete functionality works well.
Thanks for the patch. Hopefully someone else will RTBC it after reviewing it with a screen reader.
Comment #52
Everett Zufelt CreditAttribution: Everett Zufelt commented@Sun's patch in #50 looks to just be a code cleanup. Tested and working properly.
1. Sets role = application for the div containing the autocomplete element. This is to allow screen-reader users to be able to use arrow keys in the text field without them being trapped by the screen-reader.
2. Sets aria-autocomplete = list on the text input element (Testing with NVDA 2010.1 and JAWS 11 neither reported this, but it is worth having)
3. Adds a span to the end of the div with aria-live = assertive and class = element-invisible
4. Adds behavior to add Drupal.t('Searching for matches...') to the span, when the throbbing class is added.
5. Adds behavior to add Drupal.t('Autocomplete popup') to the span when the popup appears
6. As items are selected in the popup they are added to the span.
This will make autocomplete functionality usable by users of AT that supports the ARIA application role and aria-live.
Comment #53
webchickThis seems like a small patch that improves the UX for screen readers, and doesn't seem to have any impact for visual users.
Committed to HEAD. Thanks!