Upgrade Your Drupal Skills

We trained 1,000+ Drupal Developers over the last decade.

See Advanced Courses NAH, I know Enough

Section 508: Better Accessibility in Drupal 6 Form API

Parent Feed: 

Posted Sep 19, 2012 // 0 comments

When it comes to making websites Section 508 compliant, there are a variety of things to remember to do. Ensuring images and image maps have alt links, links have titles, the skip links… What about forms?

While Drupal 7 has taken great strides forward in the realm of accessibility there are still an awful lot of sites on Drupal 6 that may need to come up to standards. I wanted to talk a bit about Form API and helping make it more accessible. To most people this means just two things: Tab order and labels. Yes, a user should be able to tab through the form naturally and each label should have a for attribute with the value being the id of its input field. These both come easy with FAPI and Form Builder.

Great, that’s all we need to do! But is it really? Take a minute to use a screen reader and you can find the forms confusing. It jumps from label to entry and then to a description if the field has one. This doesn’t present a very clear form now. Does the description apply to what comes next? It’s poor design and sadly it is the default FAPI render.

When I was first tasked to change the form to change from Label->Input Field->Description to Label->Description->Input Field I took a look at the form.inc file, form builder module code and our own custom code that plugged into that. I also searched Google to see if others have tackled this in Drupal 6. The Google endeavor was pretty fruitless as it brought up a lot of Drupal 7 accessibility pages. So digging into the forms a bit, I found a fairly easy solution (but not one I liked).

I could simply use the hook_form_alter to add to the elements data, callbacks to the [’#post_render’] and [’#pre_render’]. The pre render callbacks would essentially remove the description and add it to a new temporary entry in the field array. At the post render function, the function would alter the rendered html content and inject the description data. The method felt too hacky and a bit dirty. But it worked, we now had the form rendering as Label->Description->Input Field. I wasn’t terribly comfortable using this method and wanted to find something more ‘Drupal-ish’.

A coworker and I were talking about accessibility and how to work around issues like this when the mention of theme_element came up. While I was familiar with the core code that rendered the form elements, I wasn’t aware of the theme_element functionality. So after using core theme function to find the proper element name (form_element) I added a new theme_form_element function. Simply copying the core functionality of the theme_form_element function in form.inc (line 2208) and then altering the couple lines I needed resulted in a win. A quick one at that.

So if you need to make the form more accessible, just plug this into your template.php file:

/**
* override theme_form_element
* used to override placement of description field.
/
function theme_name_form_element($element, $value) {
// This is also used in the installer, pre-database setup.
  $t = get_t();  $output = '<div class="form-item"';
  if (!empty($element['#id'])) {
    $output .= ' id="' . $element['#id'] . '-wrapper"';
  }
  $output .= ">\n";
  $required = !empty($element['#required']) ? '<span class="form-required" title="' . $t('This field is required.') . '">
</span>' : '';

  if (!empty($element['#title'])) {
    $title = $element['#title'];
    if (!empty($element['#id'])) {
      $output .= ' <label for="' . $element['#id'] . '">' . $t('!title: !required', array('!title' => filter_xss_admin($title), '!required' => $required)) . "</label>\n";
    }
    else {
      $output .= ' <label>' . $t('!title: !required', array('!title' => filter_xss_admin($title), '!required' => $required)) . "</label>\n";
    }
  }
  //new location for printing description before input field ($value)
  if (!empty($element['#description'])) {
    $output .= ' <div class="description">' . $element['#description'] . "</div>\n";
  }

  $output .= " $value\n";

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

  return $output;
}

And voila, the form elements will now be more accessible. Navigating and filing out forms using a screen reader are now much easier and more coherent.

It does bring to mind that perhaps FAPI should have better ways to reorder the way elements are being rendered. I’d also be curious as to other solutions community members may have found to solve this particular issue.

As a web developer for Phase2 Brian Nash works to create an effective and structured solution to provide a great experience for the client.

Before joining us, Brian worked for Ruby on Rails that specialized in a large-scale healthcare ...

Author: 
Original Post: 

About Drupal Sun

Drupal Sun is an Evolving Web project. It allows you to:

  • Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
  • Facet based on tags, author, or feed
  • Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
  • View the entire article text inline, or in the context of the site where it was created

See the blog post at Evolving Web

Evolving Web