admin/config/people/profile/add/textarea

  $form['visibility'] = array('#type' => 'radios',
    '#title' => t('Visibility'),
    '#default_value' => isset($edit['visibility']) ? $edit['visibility'] : PROFILE_PUBLIC,
    '#options' => array(PROFILE_HIDDEN => t('Hidden profile field, only accessible by administrators, modules and themes.'), PROFILE_PRIVATE => t('Private field, content only available to privileged users.'), PROFILE_PUBLIC => t('Public field, content shown on profile page but not used on member list pages.'), PROFILE_PUBLIC_LISTINGS => t('Public field, content shown on profile page and on member list pages.')),
  );

This is an instances where the Visibility label is being generated and causing orphaned labels in the html.

<div class="form-item form-type-radios form-item-visibility">
  <label for="edit-visibility">Visibility </label>
 <div id="edit-visibility" class="form-radios"><div class="form-item form-type-radio form-item-visibility">

 <input type="radio" name="visibility" id="edit-visibility-4" value="4" class="form-radio" />  <label class="option" for="edit-visibility-4">Hidden profile field, only accessible by administrators, modules and themes. </label>

</div>
<div class="form-item form-type-radio form-item-visibility">
 <input type="radio" name="visibility" id="edit-visibility-1" value="1" class="form-radio" />  <label class="option" for="edit-visibility-1">Private field, content only available to privileged users. </label>

</div>
<div class="form-item form-type-radio form-item-visibility">
 <input type="radio" name="visibility" id="edit-visibility-2" value="2" checked="checked" class="form-radio" />  <label class="option" for="edit-visibility-2">Public field, content shown on profile page but not used on member list pages. </label>

</div>
<div class="form-item form-type-radio form-item-visibility">
 <input type="radio" name="visibility" id="edit-visibility-3" value="3" class="form-radio" />  <label class="option" for="edit-visibility-3">Public field, content shown on profile page and on member list pages. </label>

</div>
</div>
</div>

I'm not sure if the best solution here is to nix the '#title' => t('Visibility'), & replace it with a text form element or not.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

mgifford’s picture

Issue tags: +Accessibility

tagging.

mgifford’s picture

also see:

#882666: Core form descriptions shouldn't use a label when not associated with a form

It's mostly just bad HTML, but it's also producing errors for some accessibility validation software.

mgifford’s picture

Status: Active » Needs review
FileSize
799 bytes

This is resolved in the same place #884866: Form type item shouldn't be generating a label by default. and is the same problem so I'm going to treat the other one as a duplicate & work on it here.

Status: Needs review » Needs work

The last submitted patch, remove_labels_from_label_function_v1.patch, failed testing.

mgifford’s picture

Status: Needs work » Needs review
FileSize
829 bytes

I think I'll squish the notices here, but am a bit confused as to why the 1 fail is happening. The Required 'checkboxes' field is marked as required text should still be output. FormsTestCase->testRequiredFields() form.test shouldn't pose a problem as it should be exported by '!title !required !error' in this patch, just associated with an H3 rather than a label.

              // Make sure the form element is marked as required.
              $this->assertTrue(preg_match($required_marker_preg, $form_output), "Required '$type' field is marked as required");

The isset() should cut down the notices though.

mgifford’s picture

Title: Orphaned Labels Being Generated for Radios & Checkboxes » Orphaned Labels Being Generated for Radios, Checkboxes & Items

Quick summary: <label> elements should only be used when associated & tied to a single form element. In the current Forms API the theme_label() function also generates them for radios, checkboxes & items which is incorrect HTML & confusing for the user. It may present accessibility issues to some users as well, but certainly does for validators like WebAIM that looks for orphaned labels.

Status: Needs review » Needs work

The last submitted patch, remove_labels_from_label_function_v2.patch, failed testing.

sun’s picture

In that case, we should introduce a new #title_display value, assigned to #type radios, checkboxes, and item by default, which either routes to a different theme function (not a LABEL) in theme_form_element() already, or alternatively, similar to this patch here, conditionally changes the output of theme_form_element_label(). Deciding on this is tough, as both variants could be understood as correct.

Additionally, H3 is a page structure element. I think we should use <span class="form-label"> or similar and extend the corresponding form label styles in all core themes appropriately. This has to be standardized and a unique pattern to be properly themed.

mgifford’s picture

@sun on the LABEL -> H3 thing, worth looking at #882666: Core form descriptions shouldn't use a label when not associated with a form as there is a precedent there now.

I do think that the heading, is a useful navigational aid for screen readers where as <span class="form-label"> doesn't present any support for navigating the stream of content on a page. I did think about applying a class as you have, but as a model I think <h3 class="form-label"> presents a better way to structure the data presented to the user.

Totally agreed to "This has to be standardized and a unique pattern to be properly themed."

I also agree it's a bit funny to have theme_form_element_label() be outputting things that are more than just labels. I was also looking at the theme_form_element_label() and it seems like there is a lot more in there than stuff than most themers should be modifying.

So, what about something like this:

function _form_element_label($variables) {
  $element = $variables['element'];
  // This is also used in the installer, pre-database setup.
  $t = get_t();

  // If title and required marker are both empty, output no label.
  if (empty($element['#title']) && empty($element['#required'])) {
    return '';

  // If the element is required, a required marker is appended to the label.
  $required = !empty($element['#required']) ? theme('form_required_marker', array('element' => $element)) : '';

  // If the element has an error, append the themeable marker to the label.
  $error = theme('form_error_marker', array('element' => $element));

  $title = filter_xss_admin($element['#title']);

  $attributes = array();
  // Style the label as class option to display inline with the element.
  if ($element['#title_display'] == 'after') {
    $attributes['class'] = 'option';
  }
  // Show label only to screen readers to avoid disruption in visual flows.
  elseif ($element['#title_display'] == 'invisible') {
    $attributes['class'] = 'element-invisible';
  }

  if (!empty($element['#id'])) {
    $attributes['for'] = $element['#id'];
  }

  $var = array('attributes' => $attributes, 'title' => $title, 'required' => $required, 'error' => $error);
  if (isset($element['#type']) && ($element['#type'] == 'item' || $element['#type'] == 'radios' || $element['#type'] == 'checkboxes')) {
    return theme_form_element_not_label($var);
  } else
  { 
    return theme_form_element_label($var);
  }
}

function theme_form_element_label($var) {
  // The leading whitespace helps visually separate fields from inline labels.
  $output = ' <label' . drupal_attributes($var['attributes']) . '>';
  $output .= $t('!title !required !error', array('!title' => $var['title'], '!required' => $var['required'], '!error' => $var['error']));
  $output .= "</label>\n";
  return $output;
}

function theme_form_element_not_label($var) {
  // The leading whitespace helps visually separate fields from inline headers.
  $output = ' <h3' . drupal_attributes($var['attributes']) . '>';
  $output .= $t('!title !required !error', array('!title' => $var['title'], '!required' => $var['required'], '!error' => $var['error']));
  $output .= "</h3>\n";
  return $output;
}

It's really rough, and don't think it's worth it at this stage of drafting up a patch until there's more agreement about where it is going

sun’s picture

1) While this is certainly also an accessibility decision, I'm mainly scared by the machine-readable "importance" a <h3 class="form-label"> would get. Considering there's H1 to H6, if H3 is used for unimportant labels, what's important then? Note that I also considered whether we could use a LEGEND -- not sure whether that is allowed outside of fieldsets though. If all fails, perhaps it should just be a <strong class="form-label"> to KISS?

2) When going with a separate theme function, then you don't need to invent a new arbitrator, theme_form_element() already contains that arbitrator. All we need is a new #title_display value of, say, "heading" or similar, that's applied to those #types in system_element_info() by default.

mgifford’s picture

In the case of checkboxes and radios I don't see this as being a big deal. You either want text above a list or you don't. If don't want the text then the element-invisible should still be passed through. Otherwise you've got a clump of data that really should be grouped together in some logical fashion. If we're not going to be able to do it with fieldsets & legends then headings the next best thing. Maybe there is a way to do this in D7 however...

#504962: Provide a compound form element with accessible labels

Maybe with a few small changes to theme_checkboxes & theme_radios we'd be set? I'm up for drafting something if there's a hope of getting it into core.

I don't know how much of a concern <h3>'s are for machine-readability. I haven't read anything that points to this as a problem. These links are geared to page content, but I think that they would still apply to form data if we aren't able to group it in a fieldset.
http://www.raymondselda.com/importance-of-html-headings-for-accessibility/
http://webaim.org/techniques/semanticstructure/

For #title_display, we have presently lists for before, after, invisible & attribute (I do hope that attribute is extended in D8 so that it is able to insert the title in as an attribute for any form element, however at the moment this isn't the case). Adding a Heading element could be done here, but that's a bit of a deviation from the others which are primarily tied to visibility.

I think the main issue of concern is how to deal with the item #type. The only thing I'm certain about is that there is no instance that this should be a <label>. Stylistically changing it to <h3> makes some sense in Seven, however not in other themes and it needs to be consistent. Maybe the best we can do with items is <strong class="form-label">. However, I'm not exactly sure how it's has been used. How do people want to be able to use this type of form element?

sun’s picture

I think I bumped that fieldset idea to D8 already. Far too late for D7.

My concern with H3 is rather not machine-readability, but the importance a H3 element has within the entire page structure. Whereas the original label was just a small label in front of a couple of elements.

When using #title_display, we don't need a list of #types, because each #type that needs or want this kind of label can simply define #title_display.

Lastly, we may take into account that http://api.drupal.org/api/function/form_pre_render_conditional_form_elem... already exists, too. This #pre_render is invoked for #type radios and checkboxes to conditionally render a wrapping form element. In other words: if your checkboxes/radios do not have a #title or #description, then you won't get that wrapping DIV.form-item container and also no LABEL. --- However, thinking about it, then we need to leave this function alone, as we don't care for the conditional form element, but for that inner #title LABEL only.

As of now, I'd prefer

- A new #title_display value "heading" or similar, which invokes theme_form_element_heading() instead of theme_form_element_label(). Mainly means to copy+paste the "before" switch case in theme_form_element() into a new "heading" case.

- theme_form_element_heading() just outputs a STRONG.form-label or DIV.form-label, possibly with required marker, but no ID or anything else.

- In system_element_info(), the #types item, checkboxes, radios get '#title_display' => 'heading'

sun’s picture

Status: Needs work » Needs review
FileSize
3.91 KB

I realized it takes longer to describe this than to create a patch.

Status: Needs review » Needs work

The last submitted patch, drupal.form-title-heading.13.patch, failed testing.

mgifford’s picture

Well, that works well to address the main issues, thanks @sun.

We'd have to add CSS to ensure that this is bold and styled like the label is:

  <div class="form-label">Content types </div>

That's not a big deal though. I tested:
- checkboxes - admin/config/development/generate/content
- radios - admin/config/regional/settings
- items - admin/structure/block/manage/system/help/configure

None of the previous errors were there. I like using headings, but it's not a deal breaker if they aren't there.

So how do we move this ahead? This patch removes a lot of warnings.

sun’s picture

Status: Needs work » Needs review
FileSize
4.84 KB

well, we make the tests pass and be done with it.

mgifford’s picture

The theming needed to be applied so that there wasn't a change in the visual appearance due to this patch. I've added the css now to this patch & included screen shots of examples of the 3 places where there are changes.

Other than that it seems to be ready to go!

sun’s picture

Status: Needs review » Needs work
+++ modules/system/system.css	19 Aug 2010 14:55:02 -0000
@@ -120,6 +120,10 @@ tr.merge-up th {
+.form-label {

Aren't there selector + styles for "label" already? We just have to add ", .form-label" there.

Lastly, we also have to adjust all core themes accordingly.

Powered by Dreditor.

mgifford’s picture

Status: Needs work » Needs review
FileSize
6.36 KB

Yup. Sorry, got that now.

Also, found relevant code in Bartik & Seven to add it to. Garland doesn't do much to this type of label in my review.

sun’s picture

Issue tags: +Needs screenshots

Looks RTBC to me. At this point in the release cycle, we need screenshots of all themes (bartik/garland/seven) to confirm.

mgifford’s picture

We're going to need a mass file uploading module.... Anyways, here they are. All changes have been captured here.

And no, there should be no visible differences. from before the patch is applied as it is being applied with the same style.

sun’s picture

Status: Needs review » Reviewed & tested by the community

Thank you!

Some of these screenshots look really odd, but in areas unrelated to this patch.

mgifford’s picture

Ya, I noticed this too. Not sure why. But was focusing on the patch.

mgifford’s picture

#19: drupal.form-title-heading.19.patch queued for re-testing.

mgifford’s picture

Issue tags: -Needs screenshots

#21 has lots of screenshots so I'm removing that tag.

sun’s picture

Status: Reviewed & tested by the community » Needs work

As discussed in #882666-17: Core form descriptions shouldn't use a label when not associated with a form, we want to use DIV.label (i.e., not .form-label), as it doesn't matter whether these kind of labels appear within forms or not. We merely want an equivalent to LABEL, which does not imply (or even break) a hierarchical document structure and is valid markup for screen readers.

The previously introduced .form-label styles need to be adjusted accordingly. It doesn't matter in which patch that is done, but that patch needs to get in first. That said, perhaps it would be a good idea to merge both issues/patches.

bowersox’s picture

sub

mgifford’s picture

Status: Needs work » Needs review
FileSize
5.84 KB

Ok, here's a re-rolled version using div.label's.

Status: Needs review » Needs work

The last submitted patch, drupal.form-title-heading.20.patch, failed testing.

sun’s picture

The tests are failing, because DrupalRenderTestCase uses an xpath expression to verify that a #type item is properly rendered outside of a Form API context. That xpath needs to be adjusted for this patch (should be easy).

mgifford’s picture

Ok, so I can try to follow http://tiger-fish.com/blog/drupal-6-using-xpath-your-simpletest-tests

I still find SimpleTests awkward to walk through.. Hopefully my mind will be clearer tomorrow & I can take this on.. I hab a cod.

mgifford’s picture

My laptop bust & everything's been delayed. I don't think I'm going to be able to redo this test any time soon. I'm hoping things will resume to normalish next week after Canadian Thanksgiving.

mgifford’s picture

Status: Needs work » Needs review
FileSize
7.26 KB

I updated common.test & changed a patch to bartik's css & uploaded the tests for the bots.

Status: Needs review » Needs work

The last submitted patch, drupal.form-title-heading.21.patch, failed testing.

mgifford’s picture

Status: Needs work » Needs review
FileSize
3.65 KB

oops.. cut/paste error.

Status: Needs review » Needs work
Issue tags: -Accessibility

The last submitted patch, drupal.form-title-heading.23.patch, failed testing.

mgifford’s picture

Status: Needs work » Needs review

#35: drupal.form-title-heading.23.patch queued for re-testing.

Status: Needs review » Needs work
Issue tags: +Accessibility

The last submitted patch, drupal.form-title-heading.23.patch, failed testing.

Everett Zufelt’s picture

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

Bumping to D8. This is important to resolve, since it is poor practice to use label in this way, but it has no real impact on users, only on testing tools, so it can wait for D8 to be resolved.

mgifford’s picture

Would it make sense to draw out the model of a form here and describe in html how the various elements should occur for different types of forms? Define a best practice and then worry about how we want to get there?

bowersox’s picture

I believe the proper way to do this is #504962: Provide a compound form element with accessible labels . It looks to me like this particular issue was just a work-around because we didn't have time to get fieldset-legend handling into D7 core. But now that we're talking D8, I'm thinking we should close this issue in favor of doing it the proper way.

Please correct if I'm mis-understanding.

mgifford’s picture

I'd be fine to move the bulk of it over and close this as you suggest.

I was just looking for an instance where labels are used just to give emphasis in forms and was looking for additions like .form-item label, div.label

To help set up a practice for maintaining the existing labeling without spawning orphan labels all over the place in contrib modules.

Everett Zufelt’s picture

Status: Needs work » Closed (duplicate)

Marking as duplicate of #504962: Provide a compound form element with accessible labels . Once that issue is fixed we will need to go through and resolve any of these problems in core.