Updated: Comment #28

Problem/Motivation

Parts of this issue are already committed to D8 (see #6)

This is similar to a problem that occurs in the Link module (See http://drupal.org/node/1309768#comment-6320382).

The "for" attributes in the labels are not matching the id or name attributes in the input boxes, which causes failures for Section 508 accessibility. Here is an example of how this fails:

<label for="edit-field-workapp-resume-und-0">Resume <span class="form-required" title="This field is required.">*</span></label>

<input id="edit-field-workapp-resume-und-0-upload" name="files[field_workapp_resume_und_0]" size="22" class="form-file" type="file">

Just like the "Link" module problem, the id in the file input area has an appended string '-upload'. The "display" and "description" fields were not enabled when configuring the File field here and used the progress bar instead of the throbber.

Proposed resolution

Patch from #6: This patch is using process, possibly not ideal (see #11 and #16). It's because the label is on the parent element, the actual field is $element['upload'], ie a child. But that is a file upload field so the title is used for a different purpose. This patch updates the id of the field so that the parent label is given to the child, there is no other markup output for the parent so we don't get duplicate ids. (source: #12)

Issues raised and new proposal, #21 and #22: this ID gets added as a JavaScript setting and therefore breaks the JavaScript validation for allowed file extensions i.e. as set up later on in the same function.

A better way to fix this might be to change the label's "for" attribute to match the desired ID, rather than the other way around. This would probably just involve making some changes to theme_form_element_label() to be smart enough to allow elements to set an explicit "for" attribute for the label and not overwrite it if it's already set...

Remaining tasks

The regression is in Drupal 7 & 8 (the JavaScript-based validation of allowed file extensions doesn't work)... Can we find the code that's adding the -upload in the first place?
Would removing the concatenation of -upload from the js setting break things downstream after applying the patch?

Needs thorough going through and new patch (+ D7 backport)

User interface changes

N/A

API changes

N/A

http://drupal.org/node/1309768#comment-6320382

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Everett Zufelt’s picture

Title: File field labeling does not pass 508 accessibility tests » File field form lable has incorrect id in @for attribute
Version: 7.9 » 8.x-dev
Component: file system » file.module
Priority: Normal » Major

This should be relatively easy to solve. Changed to 8.x as this is where all new work is done.

tim.plunkett’s picture

Tagging.

larowlan’s picture

Status: Active » Needs review
FileSize
1.76 KB
larowlan’s picture

This is tests only patch, should fail.

Status: Needs review » Needs work

The last submitted patch, file-label-508-1734716-4.test-only.patch, failed testing.

larowlan’s picture

Status: Needs work » Needs review
FileSize
1.76 KB

Test only fails as expected
And again with the patch + tests

larowlan’s picture

Title: File field form lable has incorrect id in @for attribute » File field form label has incorrect id in @for attribute
BarisW’s picture

Status: Needs review » Reviewed & tested by the community

Patch works as expected. When clicking the label, the file upload window opens and the 'for' value is correct.

<div class="form-item form-type-managed-file form-item-field-resume-und-0">
  <label for="edit-field-resume-und-0-upload">Resume </label>
 <div class="file-widget form-managed-file clearfix"><input type="file" id="edit-field-resume-und-0-upload" name="files[field_resume_und_0]" size="22" class="form-file"><input formnovalidate="formnovalidate" type="submit" id="edit-field-resume-und-0-upload-button" name="field_resume_und_0_upload_button" value="Upload" class="form-submit drupal-ajax-processed"><input type="hidden" name="field_resume[und][0][fid]" value="0">
<input type="hidden" name="field_resume[und][0][display]" value="1">
</div>
<div class="description" id="edit-field-resume-und-0-upload--description">Files must be less than <strong>128 MB</strong>.<br>Allowed file types: <strong>pdf</strong>.</div>
</div>
Everett Zufelt’s picture

Agreed, applies and works.

Seems like a good candidate to backport to d7

conniemh’s picture

Thank you so much larowlan, BarisW, and Everett for giving this your attention and effort!

Backporting the patch to D7 would be great if possible; I have been sidetracked by other projects and have not made the updated function for my template.php file yet. Patching core file module would be preferable.

Thanks again!
Connie

catch’s picture

Status: Reviewed & tested by the community » Needs review

Doing this in preprocess doesn't feel right to me, can't it happen when building the form somewhere? Or can we find the code that's adding the -upload in the first place?

larowlan’s picture

Hi catch, it's not using preprocess, it's using process - do you have the same objection to that?
It's because the label is on the parent element, the actual field is $element['upload'], ie a child. But that is a file upload field so the title is used for a different purpose. This patch updates the id of the field so that the parent label is given to the child, there is no other markup output for the parent so we don't get duplicate ids.
/me cheekily sets status back.

larowlan’s picture

Status: Needs review » Reviewed & tested by the community

Forgot to switch status back

catch’s picture

Version: 8.x-dev » 7.x-dev
Status: Reviewed & tested by the community » Patch (to be ported)

OK I spoke to chx and he didn't have a good reason not to do this here, so I've gone ahead and committed/pushed this to 8.x.

This would be a markup change so it'll need some consideration as to how backportable it is, but will leave that for David to decide.

dcam’s picture

dcam’s picture

Status: Patch (to be ported) » Needs review
xjm’s picture

#17: file-label-508-d7-1734716-17.patch queued for re-testing.

Gábor Hojtsy’s picture

Status: Needs review » Reviewed & tested by the community

Looks like a good backport, thanks for the proof of fail with the test only.

David_Rothstein’s picture

Status: Reviewed & tested by the community » Needs work

In general changing IDs is OK to fix accessibility issues (outside code should not be relying on specific IDs anyway), but if you look at how $element['#id'] is used later on in this function, the patch is changing a lot more of them than necessary.

More to the point, this ID gets added as a JavaScript setting, so it totally breaks the JavaScript validation for allowed file extensions, i.e. as set up by this code later on in the same function

  // Add the extension list to the page as JavaScript settings.
  if (isset($element['#upload_validators']['file_validate_extensions'][0])) {
    $extension_list = implode(',', array_filter(explode(' ', $element['#upload_validators']['file_validate_extensions'][0])));
    $element['upload']['#attached']['js'] = array(
      array(
        'type' => 'setting',
        'data' => array('file' => array('elements' => array('#' . $element['#id'] . '-upload' => $extension_list)))
      )
    );
  }

and as used by Drupal.behaviors.fileValidateAutoAttach() later on.

David_Rothstein’s picture

Title: File field form label has incorrect id in @for attribute » File field form label has incorrect id in @for attribute (regression: JavaScript allowed extensions validation is broken)
Version: 7.x-dev » 8.x-dev

I just checked that the regression is in Drupal 8 also (the JavaScript-based validation of allowed file extensions doesn't work).

Not sure if it makes sense to split that off to a different issue at this point, but rolling this patch back fixes it and it's clear we need a different fix here anyway, so I'm leaving it as part of this issue for now...

Anyway, wouldn't a better way to fix this be to change the label's "for" attribute to match the desired ID, rather than the other way around? I think this would just involve making some changes to theme_form_element_label() to be smart enough to allow elements to set an explicit "for" attribute for the label and not overwrite it if it's already set... (I actually even thought there was an issue for that in the queue already, but I can't find it at the moment.)

nod_’s picture

Issue tags: +JavaScript

tag even if not really a JS issue.

larowlan’s picture

Issue tags: +#pnx-sprint

Tagging

scottshipman’s picture

If you remove the concatenation of -upload from the js setting, would that break things downstream, after applying the patch?

dcam’s picture

http://drupal.org/node/1427826 contains instructions for updating the issue summary with the summary template.

The summary may need to be updated with information from comments.

mgifford’s picture

Issue tags: +Accessibility

Just wanted to chime in to say that Section 508 isn't the goal that Drupal is working towards. The global standard for accessibility is still WCAG 2.0 and the Drupal community is working to ensure that it is AA compliant. That being said, it's a real challenge and there are sometimes issues like this that slip through.

@larowlan or @dcam any suggestions on how to deal with the downstream issues that @David_Rothstein & @scottshipman raised?

larowlan’s picture

@mgifford I'll see if I can prod someone at work to have a look at this

ekl1773’s picture

Updated issue summary using comments.

ekl1773’s picture

Issue summary: View changes

Updated issue summary using template. -ekl1773

mgifford’s picture

mgifford’s picture

Issue summary: View changes

Updated issue summary.

mgifford’s picture

Issue tags: +Needs reroll
mgifford’s picture

Version: 8.x-dev » 7.x-dev
Status: Needs work » Needs review
Issue tags: -Needs reroll
FileSize
1.54 KB

Testing the patch again (just a re-roll) in D7. Then will set it back to D8 so that we can look at @David_Rothstein's concerns in #22.

mgifford’s picture

Version: 7.x-dev » 8.x-dev

Ok, that passed but as @David_Rothstein said

wouldn't a better way to fix this be to change the label's "for" attribute to match the desired ID, rather than the other way around?

by making theme_form_element_label() allow elements to set an explicit "for" attribute for the label and not overwrite it if it's already set.

mgifford’s picture

Version: 8.x-dev » 7.x-dev

This is in Core now in D8 core/modules/file/file.module

function file_managed_file_process($element, &$form_state, $form) {
  // Append the '-upload' to the #id so the field label's 'for' attribute
  // corresponds with the file element.
  $element['#id'] .= '-upload';

I don't know if this presents a problem for the Javascript wrapper:

  $ajax_settings = array(
    'path' => 'file/ajax',
    'options' => array(
      'query' => array(
        'element_parents' => implode('/', $element['#array_parents']),
        'form_build_id' => $form['form_build_id']['#value'],
      ),
    ),
    'wrapper' => $element['#id'] . '-ajax-wrapper',
    'effect' => 'fade',
    'progress' => array(
      'type' => $element['#progress_indicator'],
      'message' => $element['#progress_message'],
    ),
  );

At the moment it just produces <div id="edit-field-image-0-upload-ajax-wrapper">

I don't see where the commit message was for this code, but perhaps it was added elsewhere.

In anycase, the accessibility problem is fixed in D8 now. So it should be fine to move this back to D7.

larowlan’s picture

mgifford’s picture

Status: Needs review » Reviewed & tested by the community

I confirmed that this is still an issue in D7 Core and that this patch fixes the problem which is visible here /node#overlay=node/add/article

maikeru’s picture

The patch seems to work ok for the first filefield, but not sure the patch fixes it for multiple filefields on the same page.

Heres what I get on my second one:

for="edit-field-comment-attachment-und-0--2-upload"

id="edit-field-comment-attachment-und-0-upload--2"
mgifford’s picture

Status: Reviewed & tested by the community » Needs work

Ok, so it's a bit better, but we should figure out why it doesn't work for the second filefield.

Also, this should be tested for D8 as well.

mgifford’s picture

Status: Needs work » Reviewed & tested by the community
FileSize
229.43 KB

Actually, just tested it and it seems to be working fine so setting this back to RTBC:

Need more information to be able to replicate issue in #37.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 35: file_field_form_label-1734716-35.patch, failed testing.

David_Rothstein’s picture

Status: Needs work » Reviewed & tested by the community

That was a bogus test failure, so back to RTBC for now. (I didn't review the patch myself.)

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 35: file_field_form_label-1734716-35.patch, failed testing.

dcam’s picture

Status: Needs work » Reviewed & tested by the community
David_Rothstein’s picture

Title: File field form label has incorrect id in @for attribute (regression: JavaScript allowed extensions validation is broken) » File field form label has incorrect id in @for attribute
Status: Reviewed & tested by the community » Fixed
Issue tags: +7.36 release notes

This looks and works great. And the regression in Drupal 8 indeed appears to have been fixed elsewhere, so I'm removing that from the title.

Committed to 7.x - thanks!

  • David_Rothstein committed fc31045 on 7.x
    Issue #1734716 by larowlan, dcam, mgifford: Managed file form label has...
Chris Burge’s picture

Status: Fixed » Needs review
FileSize
1.3 KB

The 7.x commit from this issue has caused a regression, which causes AJAX file uploads to fail. I discovered this issue after updating from Drupal 7.35 to Drupal 7.36 when Plupload ceased to upload files over AJAX.

Preserving the original element ID for use in $form['form_build_id']['#value']['wrapper'] and $element['#prefix'] appears to be unnecessary. The $original_id variable first appeared in patch #35.

Patch attached that eliminates the use of the original element ID.

  • Drupal 7.36 (Standard install profile)
  • FileField Sources 7.x-1.9
  • FileField Sources Plupload 7.x-1.1
  • Plupload 7.x-1.7
  • Plupload external library (v 1.5.8)
David_Rothstein’s picture

Looks like we have these two issue so far:
#2466247: Drupal core 7.36 broke Filefield Sources Ajax upload previews (FileField Sources)
#2466475: Drupal core 7.36 broke IMCE for FileField Ajax upload previews (IMCE for FileField)

Is Plupload broken specifically? It didn't look to me like it would be.

The original goal was to change as little HTML as possible, and I'm not sure we want to go back on that and start changing wrapper IDs (we could break even more if we do that)...

We could consider just rolling this back, or something like #22.

But at this point we also have the problem that it's already out there so rolling it back could re-break things.

I guess what we missed here is that some modules are expecting a particular relationship between $element['#id'] and the Ajax wrapper ID, and that relationship is no longer true after this issue? I'm not sure that's a great assumption to make but perhaps they have no choice...

David_Rothstein’s picture

I just posted patches on both the above issues that fix this by making those modules use the actual Ajax wrapper ID rather than assuming a particular structure for it. It seems like a clean way to fix this, and the patches appear to work correctly.

I also added a note about these issues to the release notes (https://www.drupal.org/drupal-7.36-release-notes) - thanks!

David_Rothstein’s picture

Is Plupload broken specifically? It didn't look to me like it would be.

Looks like FileField Sources Plupload was the culprit actually: #2466505: Drupal core 7.36 broke FileField Sources Plupload Ajax upload previews

Chris Burge’s picture

I agree that patching the affected modules is better than reverting the core commit from this issue. Patches for two of the affected modules tested successfully for me: #2466505: Drupal core 7.36 broke FileField Sources Plupload Ajax upload previews and #2466505: Drupal core 7.36 broke FileField Sources Plupload Ajax upload previews. @David_Rothstein - Thanks for working through this issue so quickly. I think we're OK to change the status of this issue back to Fixed.

David_Rothstein’s picture

Status: Needs review » Fixed

Thanks for testing those! Yeah, let's close this again for now.

I did take a look through some other FileField Sources-related modules and found 4 others that look like they might be affected (I just added them all to the list at https://www.drupal.org/drupal-7.36-release-notes now). I didn't test any of them myself, but did put up patches for each for people to test, if anyone is using those modules - since the code for the patch looked like it would be a completely straightforward extension of the code used to fix the other modules.

Status: Fixed » Closed (fixed)

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

David_Rothstein’s picture

Note that we're probably going to have to roll this back and fix it differently after all. See discussion/analysis in #2594955: [D7] Duplicate HTML IDs are created for file_managed_file fields

alexdoma’s picture

After using patch #35 label starts works correct for first time. But with ajax we still get wrong for attribute.

  // Append the '-upload' to the #id so the field label's 'for' attribute
  // corresponds with the file element.
  $original_id = $element['#id'];
  $element['#id'] .= '-upload';

  // Get actual id.
  $element['#id'] = str_replace($original_id, $element['#id'], drupal_html_id($original_id));

Maybe it will helps to somebody.