Problem Description
When creating a table_select element using the form api, the added column with the checkboxes does not have a valid control labels. A title is added to the input for the "select all" by JS, but is not added to the inputs for each individual row. This causes screen readers such as NVDA to repeat the same "select all rows" title for each row, causing confusion. Ideally the input for each of these rows would be titled with something like 'select row #'.
For instance consider a form like follows:
public function buildForm(array $form, FormStateInterface $form_state): array {
$form['message'] = [
'#type' => 'tableselect',
'#title' => $this->t('Test Table Select'),
'#required' => TRUE,
'#header' => ['1','2','3'],
'#options' => [
'1' => ['a','b','c'],
'2' => ['d','e','f'],
'3' => ['g','h','i'],
],
'#multiple' => TRUE,
];
$form['actions'] = [
'#type' => 'actions',
'submit' => [
'#type' => 'submit',
'#value' => $this->t('Send'),
],
];
return $form;
}
If you examine the resultant form using a tool like the drupal editoria11y module (https://www.drupal.org/project/editoria11y) or the industry standard axe dev tools, it reports an accessibility error.
Image from axe dev-tools:
Comment | File | Size | Author |
---|---|---|---|
#45 | Guided Search Axe Dev Tools Error 1.png | 199.12 KB | kwfinken |
#40 | interdiff.txt | 16.84 KB | alansaviolobo |
#40 | tableselect_select-851164-40.patch | 361 bytes | alansaviolobo |
#35 | interdiff-17-34.txt | 18.59 KB | mgifford |
#34 | core-js-selectall-check-851164-34.patch | 17.69 KB | mgifford |
Comments
Comment #1
mgiffordIt did work for me in VoiceOver. I've attached an inaccessible screen capture of the process here - http://screenr.com/6DR
This was before the patch in #851174: Update options checkbox doesn't include labels was applied/developed.
Comment #2
rfayI assume that javascript is the right component for this.
Comment #3
mgiffordYes, thanks!
Comment #4
mgiffordbump
Comment #5
Everett Zufelt CreditAttribution: Everett Zufelt commentedI haven't taken a look at the code, but I'm not sure how we correct this. Screen-readers are typically non-standard when it comes to tables.
1. we can make sure that the cell isn't a header for the column. But, some AT will implicitly treat it as such.
Comment #6
mgiffordOk, so I've got it up here:
http://drupal7.dev.openconcept.ca/admin/content
The HTML looks like:
But that's injected with jQuery in misc/tableselect.js.
So, I've attached a screenshot with the view with firebug.
However, Everett, if you're not hearing "'Select all rows in this table' and this gets read as the associated header for every checkbox in that column, no matter the row." maybe this was just an issue with @jasonkiss' version or configuration.
Can you get that result? If not we can postpone this issue until it can be repeated.
Comment #7
Everett Zufelt CreditAttribution: Everett Zufelt commentedThe title is being read as the column header. I don't really know how we fix it though. Screen-readers don't really respect any predictable rules re: headers for tables.
See:
http://tink.co.uk/2010/08/screen-reader-support-for-html-tables/
Comment #8
jasonkiss CreditAttribution: jasonkiss commentedHere are some screen reader results from the current Content Admin table at http://drupal7.dev.openconcept.ca/admin/content when navigating through a row into the first column's checkbox cells. All screen readers were set with their default out-of-the-box preferences, except where noted otherwise.
JAWS 9.0.2191
IE8: prefaces checkboxes with "Select all rows in this table"
FF3.6: does *not* preface checkboxes with "Select all rows in this table"; but no column headers are read for any cell
JAWS 10.0.1178
IE8: does *not* preface checkboxes with "Select all rows in this table"
FF3.6: prefaces checkboxes with "Select all rows in this table"
JAWS 11.0.1447
IE8 and FF3.6: prefaces checkboxes with "Select all rows in this table"
Window-Eyes 7.2 (when set to read column headers using the CTRL-SHIFT-H rotor)
IE8 and FF3.6: prefaces checkboxes with "Select all rows in this table"
NVDA 2010.2beta1
IE8: does *not* preface checkboxes with "Select all rows in this table", but no column headers are read for any cell
FF3.6: does *not* preface checkboxes with "Select all rows in this table", but does read other column headers
VoiceOver3
Safari5: prefaces checkboxes with "Select all rows in this table"
Incidentally, Mike, the reason you don't find an issue in your screencast is because when you are just using the TAB key to get from focussable element to focussable element in the table, column headers are not announced. If you navigate using VoiceOver's table navigation commands, you'll hear the problem. Press ctrl-option-command-T to set focus to the table. Then press ctrl-option-shift-downarrow to start interacting with the table, at which point you can use ctrl-option and the arrow keys to navigate cell to cell.
My proposed solution is to remove the "Select all rows in this table" checkbox from the table, and place it outside and before the table. CSS can be used to visually position the checkbox over the first cell in the first column in the header row. I've put up a temporary demo page with some additional comments at http://www.kisser.ca/testing/drupal-table-select-all.html. I've also attached it to this comment as a zip file.
You'll note on that demo page that I make these other two suggestions:
th
elements withscope="row"
to act as row headers for supporting screen readers like JAWS 11 and NVDA 2010.2beta1, as well as Window-Eyes in IE8. Window-Eyes in FF3.6 does not respect row headers unless they're in the first column. If configured to read row headers, Window-Eyes in FF3.6 will default to using the first cell in the row, whatever it is, in this case, the checkbox. Unfortunately, VoiceOver doesn't do row headers at all. Still, it does no harm to use header cells here, and it should help users of some screen readers.And while we're on the topic of the admin tables and table headers, I'd be interested to know how real screen reader users feel about table column headers that are also links for sorting the table. In the current implementation, they are just simple links, with no indication, other than their title attributes, that they are for sorting. Some, but not all assistive technologies will get this. Also, I'm not sure that it is clear to a visually impaired user what column and direction the table contents are currently sorted on. Would love to hear your thoughts on this, Everett. Maybe screen reader users who are administering a Drupal install will be familiar enough with this use of table headers as links to sort the table. Otherwise, it is possible, I think, to make things even clearer in this regard by doing one or more of the following:
Like I said, this may be overkill for what a screen reader user who is also a Drupal administrator may require, but just thought I'd put it out there.
Comment #9
Everett Zufelt CreditAttribution: Everett Zufelt commented@jkiss
Thanks for the testing.
You write:
prefaces checkboxes with "Select all rows in this table"
No, it * never * does this, it does not preface the checkbox, it reads a column header and then reads the checkbox. We should make the top left cell not a th though, which may help things for some screen-readers.
that individual row checkboxes have explicit, but visually hidden label text, "Select this row". This label text could also be the same as the Title cell's
content, or a combination, for example, "Select the row for Roto Facilisis Blandit".
Agree completely.
As for the headers, I am comfortable with a linked column header being a design pattern that implies sorting the column. Definitely not a d7 issue.
Thanks again
Comment #10
jasonkiss CreditAttribution: jasonkiss commentedThanks, Everett.
Reading the column header before reading a data cell is what I mean by "prefaces", as in says or reads before by way of introduction. Based on my tests, screen readers almost *always* do this, or can be configured to :)
I did test to see if there was any difference when using a td instead of th, and there is not. JAWS, Window-Eyes, NVDA, and VoiceOver all behave the same, whether it is a td or a th.
What is your view on moving the "Select all rows in this table" checkbox out of the table and placing it before the table? For mouse and sighted keyboard-only users, CSS can be applied so that the "select all" checkbox appears over the top left cell, so they would essentially never know the difference. The benefit is that the individual row checkbox cells would never be introduced by screen readers with the words "Select all rows in the this table".
Cheers
Comment #11
Everett Zufelt CreditAttribution: Everett Zufelt commented@jkiss
My view is that it would be nice to see in D8, but not D7 territory anymore. But, getting titls or labels on the checkboxes definitely is.
Do we have an open issue for that?
Comment #12
mgiffordUltimately, this is about changing the output of the function node_admin_nodes().
I don't think that there is a way to make this function themable, least not in D7, so not sure the best approach to try different structures out for the HTML in a real world environment.
I do wonder if some of this could be brought into D7 using the Accessible Helper Module.
Comment #13
mgiffordOh ya, the related issue we're looking at for the checkboxes is #851174: Update options checkbox doesn't include labels
It's sadly still failing the simpletests.
Comment #14
Everett Zufelt CreditAttribution: Everett Zufelt commentedComment #15
Everett Zufelt CreditAttribution: Everett Zufelt commentedComment #16
mgiffordOk, so the we need a patch here to bring the select all checkbox outside of the table, but via css position it inside the table.
This is the crux of the html that Jason sent in #8 & that Everett has agreed would be useful.
Comment #17
nod_First try it's a little bit different than what it was doing previously. Is is possible to have several checkall checkboxes for one table? If no, there is no problem.
Comment #18
mgiffordI don't think I've ever seen the pattern were there are two checkall checkbox columns in a table before. It would be confusing, but I also could see someone trying to do it. Checkall on visible page vs Check all on all pages for instance. Still it's not a pattern that is often used.
Comment #19
nod_Last time I seen that in drupal was with VBO and they added a link underneath the table header, not a checkbox. I'm still curious to know if the two select-all checkboxes pattern exists somewhere. I'd like it if it wasn't the case but that's not for me to say :)
Comment #20
mgifford#17: core-js-selectall-check-851164.patch queued for re-testing.
Comment #21
mgiffordSo what do we need to bring this to RTBC?
1) Test patch #17 against the latest core
2) Provide a screenshot
3) Review the code changes (all Javascript)
4) Decide to mark it RTBC.
Anything else?
Comment #22
mgifford#17: core-js-selectall-check-851164.patch queued for re-testing.
Comment #23
seutje CreditAttribution: seutje commented1) applies fine
2) see attachment
3) Looks fine to me
4) not sure,
doesn't seem to be implemented, and seems fragile to implement, is this still a requirement?
also: the first TH is empty, is that acceptable?
Comment #24
mgifford#17: core-js-selectall-check-851164.patch queued for re-testing.
Comment #25
mgiffordThe first column TH shouldn't be blank. It should say something about the checkboxes that are in that column. It's a heading & has a semantic value so it shouldn't be blank.
Comment #26
mgifford#17: core-js-selectall-check-851164.patch queued for re-testing.
Comment #27
mgiffordHaving a blank column isn't great, but in the scheme of things it's more annoying than it is a real barrier as far as I am aware.
Comment #29
mgiffordtagging.
Comment #30
mgiffordJust a re-roll. No cleanup.
Comment #31
mgifford#30: core-js-selectall-check-851164-30.patch queued for re-testing.
Comment #32
mgifford#30: core-js-selectall-check-851164-30.patch queued for re-testing.
Comment #34
mgiffordre-roll.
Comment #35
mgiffordProviding an interdiff between #17 & #34. I'd done an earlier patch but it was just a re-roll of what @nod_ did earlier.
Comment #36
mgifford#34: core-js-selectall-check-851164-34.patch queued for re-testing.
Comment #38
mgiffordThis should go in after #675446: Use jQuery UI Autocomplete
Comment #39
mgiffordComment #40
alansaviolobo CreditAttribution: alansaviolobo commentedit appears to be a case where the patch has effectively been reduced to css changes.
Comment #41
mgifford@alansaviolobo - I don't understand how the patch addresses this issue.
Did you do any testing with screen readers?
This needs to be tested again, particularly with NVDA, JAWS & WindowsEyes. Also with VoiceOver. I couldn't replicate the problem in VoiceOver, although the description in #8 is very good. That was over 4 years ago now.
Comment #42
alansaviolobo CreditAttribution: alansaviolobo commentedall the changes in the earlier patch have already found their way into the codebase. the only remaining change is contained in the new patch.
Comment #43
mgiffordOk, then lets just close this for now. I don't think that the removal of
input.form-autocomplete,
does anything for accessibility in this context.We can re-open it if we find that we can replicate this problem. It may well be fixed rather than cannot reproduce, but would like to have a JAWS user validate that first before doing so.
Comment #44
Liam MorlandThis issue is followed-up in #2766853: Add label to Tableselect select all checkbox.
Comment #45
kwfinken CreditAttribution: kwfinken as a volunteer and at Michigan State University for Michigan State University commentedComment #46
Liam Morland@kwfinken Is this not covered by #2766853: Add label to Tableselect select all checkbox?
Comment #47
kwfinken CreditAttribution: kwfinken as a volunteer and at Michigan State University for Michigan State University commentedNo, there is an accessible title (not label) on the select all, but not on the individual rows. Slightly different emphasis that seems to go with the earlier discussion on this ticket before it was originally closed. That is why I reopened with better specificity.