I'd like to add a semantic relationship between a form's description and the input it is describing.

I thought I should be able to do that by adding the appropriate text to theme_webform_element, however unfortunately it isn't working.

However the aria-described by element keeps getting stripped out of the input form.

By adding the attribute to the element:

$element['#attributes']['aria-describedby'] = $element['#id'] . '-description';

And attaching the ID to the description:

  if (!empty($element['#description'])) {                                                                                                                                    
    $describedby = (!empty($element['#id'])) ? ' id=' . $element['#id'] . '-description' : '';                                                                               
    $output .= ' <div class="description"' . $describedby . '>' . $element['#description'] . "</div>\n";                                                                     
  } 

This should work, but it isn't coming through to the webform. I wonder if the aria-describedby is getting filtered out or if I'm just doing something wrong.

It would be really nice though if this were done by default so that people who are filling in complex forms especially get more semantic descriptions.

Comments

acrazyanimal’s picture

The trick here is to do the following in theme_webform_element and theme_element:

if (!empty($element['#description'])) {
    $decription_attributes = array('class' => array('description'));
    if ($element['#id']) {
      $decription_attributes['id'] = $element['#id'] . '-description';
    }
    $output .= '<div' . drupal_attributes($decription_attributes) . '>' . $element['#description'] . "</div>\n";
  }

But then you also need to use preprocess functions in your theme/module to add in the aria-describedby attribute to the form elements. There are lots, some are webform specific theme functions and others are core:

/**
 * Preprocess textareas to add in aria attributes.
 */
function yourtheme_preprocess_textarea(&$variables) {
  yourtheme_add_aria_attributes($variables);
}

/**
 * Preprocess textfield to add in aria attributes.
 */
function yourtheme_preprocess_textfield(&$variables) {
  yourtheme_add_aria_attributes($variables);
}

/**
 * Preprocess radios to add in aria attributes.
 */
function yourtheme_preprocess_radios(&$variables) {
  yourtheme_add_aria_attributes($variables);
}

/**
 * Preprocess checkboxes to add in aria attributes.
 */
function yourtheme_preprocess_checkboxes(&$variables) {
  yourtheme_add_aria_attributes($variables);
}

/**
 * Preprocess select to add in aria attributes.
 */
function yourtheme_preprocess_select(&$variables) {
  yourtheme_add_aria_attributes($variables);
}

/**
 * Preprocess date to add in aria attributes.
 */
function yourtheme_preprocess_date(&$variables) {
  yourtheme_add_aria_attributes($variables);
}

/**
 * Preprocess webform_email to add in aria attributes.
 */
function yourtheme_preprocess_webform_email(&$variables) {
  yourtheme_add_aria_attributes($variables);
}

/**
 * Preprocess webform_number to add in aria attributes.
 */
function yourtheme_preprocess_webform_number(&$variables) {
  yourtheme_add_aria_attributes($variables);
}

function yourtheme_add_aria_attributes(&$variables) {
  if (!empty($variables['element']['#description'])) {
    $variables['element']['#attributes']['aria-describedby'] = $variables['element']['#id'] . '-description';
  }
}

.... and I'm sure there are plenty more.

acrazyanimal’s picture

An example of the output would be the following:

<input id="edit-submitted-email-address" class="email form-text form-email required" type="email" size="60" name="submitted[email_address]" aria-describedby="edit-submitted-email-address-description">
<div id="edit-submitted-email-address-description" class="description">This will only be used to follow-up with you if there are additional questions.</div>
mgifford’s picture

Very good, thanks for that detail! It's definitely worth having in a handbook on Drupal.org or on our blog. This just comes out of the box with D8, but this is the first description of how to do it in Drupal 7.

mgifford’s picture

@quicksketch - what do you think of bringing this into the 4.x branch?

maki3000’s picture

it also would be cool to integrate following ARIA-Features in the webform module:
- aria-reqired for requred fields
- aria-labelledby for errors

There is an attempt to do that here:
https://www.drupal.org/project/webform_aria

Should i make an own ticket for that?

danchadwick’s picture

@mgifford, @maki3000 -- I support someone writing a patch for ARIA support, provided people test it and mark it RTBC.

liam morland’s picture

Status: Active » Needs review
StatusFileSize
new1.39 KB

Here is a patch that has the desired effect. However, I really don't like the way that it does it. I don't like how I had to use the "--WEBFORM-PLACEHOLDER--", however, I couldn't find a place where the component had an #id, but had not yet been rendered into #children. Perhaps this happens inside Drupal core. I would appreciate any suggestions for making this better.

If the "--WEBFORM-PLACEHOLDER--" approach is to be used, a regex could allow it to deal with other elements setting @aria-describedby.

liam morland’s picture

@maki3000, the other ARIA-related things you mention should each get their own tickets.

danchadwick’s picture

Version: 7.x-4.x-dev » 8.x-4.x-dev
Status: Needs review » Postponed

The maintainers have decided to defer all aria issues to D8. They are marked postponed because they will be looked at after the D8 port is functional.

fenstrat’s picture

Status: Postponed » Closed (outdated)

Closing to clear out the old Webform 8.x-4.x branch. See #2827845: [roadmap] YAML Form 8.x-1.x to Webform 8.x-5.x.