Hi All,

It's Really nice to have Chosen in our sites but ..
But we do have this issue with Accessibility to Chosen.
http://wave.webaim.org/report?url=http%3A%2F%2Fharvesthq.github.com%2Fch...

I think we need to find a way to add a aria-label to the Field label or Exposed internal Filters.. and External Blocks too.
WAVE Test for Chosen

Errors
Missing form label
What It Means
A form control does not have a corresponding label.
Why It Matters
If a form control does not have a properly associated text label, the function or purpose of that form control may not be presented to screen reader users. Form labels also provide visible descriptions and larger clickable targets for form controls.
How to Fix It
If a text label for a form control is visible, use the element to associate it with its respective form control. If there is no visible label, either provide an associated label, add a descriptive title attribute to the form control, or reference the label(s) using aria-labelledby. Labels are not required for image, submit, reset, button, or hidden form controls.
The Algorithm... in English
An (except types of image, submit, reset, button, or hidden),
, or does not have a properly associated label text. A properly associated label is:
a element with a for attribute value that is equal to the id of a unique form control
a element that surrounds the form control, does not surround any other form controls, and does not reference another element with its for attribute
a non-empty title attribute, or
a non-empty aria-labelledby attribute.

Thanks.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Rajab Natshah’s picture

Issue summary: View changes
Rajab Natshah’s picture

http://www.w3.org/TR/2010/WD-wai-aria-20100916/states_and_properties#ari...


aria-label (property)

Defines a string value that labels the current element. Also see aria-labelledby.

The purpose of aria-label is the same as that of aria-labelledby. It provides the user with a recognizable name of the object. The most common accessibility API mapping for a label is the accessible name property.

If the label text is visible on screen, authors SHOULD use aria-labelledby and SHOULD NOT use aria-label. There may be instances where the name of an element cannot be determined programmatically from the content of the element, and there are cases where providing a visible label is not the desired user experience. Most host languages provide an attribute that could be used to name the element (e.g. the title attribute in HTML [HTML]), yet this may present a browser tooltip. In the cases where a visible label or visible tooltip is undesirable, authors MAY set the accessible name of the element using aria-label. User agents give precedence to aria-labelledby over aria-label when computing the accessible name property.

Characteristics of aria-label
Characteristic Value
Related Concepts: A related concept is title in HTML [HTML].
Used in Roles: All elements of the base markup
Value: string

aria-labelledby (property)

Identifies the element (or elements) that labels the current element. Also see aria-label and aria-describedby.

The purpose of aria-labelledby is the same as that of aria-label. It provides the user with a recognizable name of the object. The most common accessibility API mapping for a label is the accessible name property.

If the label text is visible on screen, authors SHOULD use aria-labelledby and SHOULD NOT use aria-label. Use aria-label only if the interface is such that it is not possible to have a visible label on the screen. User agents give precedence to aria-labelledby over aria-label when computing the accessible name property.

The aria-labelledby attribute is very similar to describing an object with aria-describedby, where a description is intended to provide additional information that some users might need.

Rajab Natshah’s picture

If we try to have a Chosen Accessibility options
chosen accessibility options

as in this code :

   $form['accessibility'] = array(
     '#type' => 'fieldset',
     '#title' => t('Chosen Accessibility options'),
   );
   $form['accessibility']['chosen_accessibility_use_aria_label'] = array(
     '#type' => 'checkbox',
     '#title' => t('Use aria-label'),
     '#default_value' => variable_get('chosen_accessibility_use_aria_label', FALSE),
     '#description' => t('To let Chosen add the accessibility attribute <b>aria-label</b>
       <p>The purpose of aria-label is the same as that of aria-labelledby. It provides the user with a recognizable name of the object. The most common accessibility API mapping for a label is the accessible name property.<a href="http://www.w3.org/TR/2010/WD-wai-aria-20100916/states_and_properties#aria-label">Read more ...</a></p>'),
   );
   $form['accessibility']['chosen_accessibility_use_aria_labelledby'] = array(
     '#type' => 'checkbox',
     '#title' => t('Use aria-labelledby'),
     '#default_value' => variable_get('chosen_accessibility_use_aria_labelledby', FALSE),
     '#description' => t('To let Chosen add the accessibility attribute <b>aria-labelledby</b>
       <p>If the label text is visible on screen, authors SHOULD use aria-labelledby and SHOULD NOT use aria-label. There may be instances where the name of an element cannot be determined programmatically from the content of the element, and there are cases where providing a visible label is not the desired user experience.<a href="http://www.w3.org/TR/2010/WD-wai-aria-20100916/states_and_properties#aria-labelledby">Read more ...</a></p>'),
   );

Then do more of this code :

   //  Add the accessibility use aria-labelledby attribute.
   if(variable_get('chosen_accessibility_use_aria_labelledby', FALSE)) {
     $element['#attributes']['aria-labelledby'][]= "The field label or title";
   }

   // Add the accessibility use aria-label attribute.
   if(variable_get('chosen_accessibility_use_aria_label', FALSE)) {
     $element['#attributes']['aria-label'][]= "The field label or title";
   }

But We still can not do that to the Custom input Chosen add .. as in this code

      if (this.is_multiple) {
        this.container.html('<ul class="chosen-choices"><li class="search-field"><input type="text" value="' + this.default_text + '" class="default" autocomplete="off" style="width:25px;" /></li></ul><div class="chosen-drop"><ul class="chosen-results"></ul></div>');
      } else {
        this.container.html('<a class="chosen-single chosen-default" tabindex="-1"><span>' + this.default_text + '</span><div><b></b></div></a><div class="chosen-drop"><div class="chosen-search"><input type="text" autocomplete="off" /></div><ul class="chosen-results"></ul></div>');
      }

So We need a JavaScript Fix not a PHP fix. or this should come from the Library directly.

Thanks

Rewarding :)

Rajab Natshah’s picture

Hi All,

The way I will go with in my project to do this for each Chosen Wrapper div or container.

In this Case Filters in exposed Filters:

        $(".views-exposed-widget").each(function( index, element ) {
           $(this).find('.form-type-select .chosen-container input').attr("aria-label" ,$.trim($(this).find('label').text()));
        });

Thanks.

Rewarding :)

Dave Reid’s picture

I would think if at all possible, this should be fixed upstream in the Chosen library itself, unless there's some reason it has to be fixed here at the Drupal integration layer.

mgifford’s picture

Always better to fix upstream if possible for sure.

Rajab Natshah’s picture

Yes. That what should be as something as in the following code.

      if (this.is_multiple) {
        this.container.html('<ul class="chosen-choices"><li class="search-field"><input type="text" aria-label="' + this.form_field_jq.parents("label") +'" value="' + this.default_text + '" class="default" autocomplete="off" style="width:25px;" /></li></ul><div class="chosen-drop"><ul class="chosen-results"></ul></div>');
      } else {
        this.container.html('<a class="chosen-single chosen-default" tabindex="-1"><span>' + this.default_text + '</span><div><b></b></div></a><div class="chosen-drop"><div class="chosen-search"><input type="text" aria-label="' + this.form_field_jq.parents("label") +'"  autocomplete="off" /></div><ul class="chosen-results"></ul></div>');
      }

But We can use this code :

  $(".views-exposed-widget").each(function( index, element ) {
           $(this).find('.form-type-select .chosen-container input').attr("aria-label" ,$.trim($(this).find('label').text()));
  });

Thanks.

Rewarding :)

Rajab Natshah’s picture

Status: Needs work » Needs review
imperator_99’s picture

@RajabNatshah your JavaScript code was excellent, I was able to implement it in Drupal 8. I did have to wrap it in a chosen:ready event block, however, to make sure the input element was available:

Drupal.behaviors.dtagovauChosenAccessibilityFix = {
    attach: function(context, settings) {
      $('body').on('chosen:ready', function(evt, params) {
        $('.js-form-item.js-form-type-select', context).once('chosenAccessibilityFix').each(function(index, element) {
          $(this).find('.chosen-container-multi input.chosen-search-input').attr('aria-label', $.trim($(this).find('label').text()));
        });
      });
    }
  }

Cheers,
Jesse.

kaicyee’s picture

Hi, @imperator_99 and @RajabNatshah, I'm experiencing the same issue in regards to the exposed filters for Chosen on Drupal 8. Forgive me for being dense but where should you put in this fix? Is this a patch?

Thank you,
Kai

kaicyee’s picture

OK, with the help of our JavaScript goddess Vijaya we got your code to work with some edits and additions. For the edification of other people who may be equally as confused, for Drupal 8, you need to put this in your-theme/assets/js/chosen_patch.js. You also need to update your-theme.libraries.yml and your-theme.info files.

Drupal.behaviors.dtagovauChosenAccessibilityFix = {
    attach: function(context, settings) {
      jQuery('body').on('chosen:ready', function(evt, params) {
        jQuery('.js-form-item.js-form-type-select', context).each(function(index, element) {
          jQuery(this).find('.chosen-container-multi input.chosen-search-input').attr('aria-label', jQuery.trim(jQuery(this).find('label').text()));
        });
      });
    }
  }

Thank you very much for the original legwork!
Kai C. Yee
Drupal developer
Department of Commerce

joshua.boltz’s picture

While this seems to help for field provides via the admin interface, in cases where you use the Chosen widget on a front-end theme, I found the patch in this issue solved the issue for those cases.
https://www.drupal.org/project/chosen/issues/2834096