summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorxjm2017-03-03 10:03:40 -0600
committerxjm2017-03-03 10:03:40 -0600
commit772edb3b50ea04bcb9474a92a35b56d6839c9175 (patch)
tree6f9607adfea1f7126de32169730c03e2acd5b21a
parent0b45cbb70fde40978c9012ac8dfbba32aec8f223 (diff)
Issue #1918994 by Tim Bozeman, mgifford, mpdonadio, vprocessor, sun, xjm, falcon03, nabiyllin, rteijeiro, cwarsaw, yoroy, andymartha, jessebeach, lauriii, jhedstrom, andypost, Bojhan, cilefen, aaronbauman, sugaroverflow: Improve Datetime and Daterange Widget accessibility
-rw-r--r--core/includes/theme.inc6
-rw-r--r--core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeDatelistWidget.php3
-rw-r--r--core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeDefaultWidget.php10
-rw-r--r--core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeWidgetBase.php9
-rw-r--r--core/modules/datetime/src/Tests/DateTestBase.php1
-rw-r--r--core/modules/datetime/src/Tests/DateTimeFieldTest.php10
-rw-r--r--core/modules/datetime_range/src/Plugin/Field/FieldWidget/DateRangeWidgetBase.php4
-rw-r--r--core/modules/datetime_range/src/Tests/DateRangeFieldTest.php16
-rw-r--r--core/modules/system/templates/datetime-wrapper.html.twig6
-rw-r--r--core/themes/classy/templates/form/datetime-wrapper.html.twig4
10 files changed, 55 insertions, 14 deletions
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index f180cbd..51d10a7 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -576,8 +576,14 @@ function template_preprocess_datetime_wrapper(&$variables) {
// Suppress error messages.
$variables['errors'] = NULL;
+ $variables['description'] = NULL;
if (!empty($element['#description'])) {
+ $description_attributes = [];
+ if (!empty($element['#id'])) {
+ $description_attributes['id'] = $element['#id'] . '--description';
+ }
$variables['description'] = $element['#description'];
+ $variables['description_attributes'] = new Attribute($description_attributes);
}
$variables['required'] = FALSE;
diff --git a/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeDatelistWidget.php b/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeDatelistWidget.php
index 8cdabf1..06ced05 100644
--- a/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeDatelistWidget.php
+++ b/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeDatelistWidget.php
@@ -35,6 +35,9 @@ class DateTimeDatelistWidget extends DateTimeWidgetBase {
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
$element = parent::formElement($items, $delta, $element, $form, $form_state);
+ // Wrap all of the select elements with a fieldset.
+ $element['#theme_wrappers'][] = 'fieldset';
+
$date_order = $this->getSetting('date_order');
if ($this->getFieldSetting('datetime_type') == 'datetime') {
diff --git a/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeDefaultWidget.php b/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeDefaultWidget.php
index 89381ab..6d03ffd 100644
--- a/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeDefaultWidget.php
+++ b/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeDefaultWidget.php
@@ -59,6 +59,16 @@ class DateTimeDefaultWidget extends DateTimeWidgetBase implements ContainerFacto
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
$element = parent::formElement($items, $delta, $element, $form, $form_state);
+ // If the field is date-only, make sure the title is displayed. Otherwise,
+ // wrap everything in a fieldset, and the title will be shown in the legend.
+ if ($this->getFieldSetting('datetime_type') === DateTimeItem::DATETIME_TYPE_DATE) {
+ $element['value']['#title'] = $this->fieldDefinition->getLabel();
+ $element['value']['#description'] = $this->fieldDefinition->getDescription();
+ }
+ else {
+ $element['#theme_wrappers'][] = 'fieldset';
+ }
+
// Identify the type of date and time elements to use.
switch ($this->getFieldSetting('datetime_type')) {
case DateTimeItem::DATETIME_TYPE_DATE:
diff --git a/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeWidgetBase.php b/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeWidgetBase.php
index aa6175a..b363eed 100644
--- a/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeWidgetBase.php
+++ b/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeWidgetBase.php
@@ -17,15 +17,6 @@ class DateTimeWidgetBase extends WidgetBase {
* {@inheritdoc}
*/
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
- // We are nesting some sub-elements inside the parent, so we need a wrapper.
- // We also need to add another #title attribute at the top level for ease in
- // identifying this item in error messages. We do not want to display this
- // title because the actual title display is handled at a higher level by
- // the Field module.
-
- $element['#theme_wrappers'][] = 'datetime_wrapper';
- $element['#attributes']['class'][] = 'container-inline';
-
$element['value'] = array(
'#type' => 'datetime',
'#default_value' => NULL,
diff --git a/core/modules/datetime/src/Tests/DateTestBase.php b/core/modules/datetime/src/Tests/DateTestBase.php
index 0f1277e..ed8d9b4 100644
--- a/core/modules/datetime/src/Tests/DateTestBase.php
+++ b/core/modules/datetime/src/Tests/DateTestBase.php
@@ -120,6 +120,7 @@ abstract class DateTestBase extends WebTestBase {
$this->field = FieldConfig::create([
'field_storage' => $this->fieldStorage,
'bundle' => 'entity_test',
+ 'description' => 'Description for ' . $field_name,
'required' => TRUE,
]);
$this->field->save();
diff --git a/core/modules/datetime/src/Tests/DateTimeFieldTest.php b/core/modules/datetime/src/Tests/DateTimeFieldTest.php
index 0f2f4ff..67e5183 100644
--- a/core/modules/datetime/src/Tests/DateTimeFieldTest.php
+++ b/core/modules/datetime/src/Tests/DateTimeFieldTest.php
@@ -48,8 +48,10 @@ class DateTimeFieldTest extends DateTestBase {
// Display creation form.
$this->drupalGet('entity_test/add');
$this->assertFieldByName("{$field_name}[0][value][date]", '', 'Date element found.');
- $this->assertFieldByXPath('//*[@id="edit-' . $field_name . '-wrapper"]/h4[contains(@class, "js-form-required")]', TRUE, 'Required markup found');
+ $this->assertFieldByXPath('//*[@id="edit-' . $field_name . '-wrapper"]//label[contains(@class,"js-form-required")]', TRUE, 'Required markup found');
$this->assertNoFieldByName("{$field_name}[0][value][time]", '', 'Time element not found.');
+ $this->assertFieldByXPath('//input[@aria-describedby="edit-' . $field_name . '-0-value--description"]', NULL, 'ARIA described-by found');
+ $this->assertFieldByXPath('//div[@id="edit-' . $field_name . '-0-value--description"]', NULL, 'ARIA description found');
// Build up a date in the UTC timezone. Note that using this will also
// mimic the user in a different timezone simply entering '2012-12-31' via
@@ -213,6 +215,9 @@ class DateTimeFieldTest extends DateTestBase {
$this->drupalGet('entity_test/add');
$this->assertFieldByName("{$field_name}[0][value][date]", '', 'Date element found.');
$this->assertFieldByName("{$field_name}[0][value][time]", '', 'Time element found.');
+ $this->assertFieldByXPath('//fieldset[@id="edit-' . $field_name . '-0"]/legend//text()', $field_name, 'Fieldset and label found');
+ $this->assertFieldByXPath('//fieldset[@aria-describedby="edit-' . $field_name . '-0--description"]', NULL, 'ARIA described-by found');
+ $this->assertFieldByXPath('//div[@id="edit-' . $field_name . '-0--description"]', NULL, 'ARIA description found');
// Build up a date in the UTC timezone.
$value = '2012-12-31 00:00:00';
@@ -363,6 +368,9 @@ class DateTimeFieldTest extends DateTestBase {
// Display creation form.
$this->drupalGet('entity_test/add');
+ $this->assertFieldByXPath('//fieldset[@id="edit-' . $field_name . '-0"]/legend//text()', $field_name, 'Fieldset and label found');
+ $this->assertFieldByXPath('//fieldset[@aria-describedby="edit-' . $field_name . '-0--description"]', NULL, 'ARIA described-by found');
+ $this->assertFieldByXPath('//div[@id="edit-' . $field_name . '-0--description"]', NULL, 'ARIA description found');
// Assert that Hour and Minute Elements do not appear on Date Only
$this->assertNoFieldByXPath("//*[@id=\"edit-$field_name-0-value-hour\"]", NULL, 'Hour element not found on Date Only.');
diff --git a/core/modules/datetime_range/src/Plugin/Field/FieldWidget/DateRangeWidgetBase.php b/core/modules/datetime_range/src/Plugin/Field/FieldWidget/DateRangeWidgetBase.php
index 71309d4..e99374c 100644
--- a/core/modules/datetime_range/src/Plugin/Field/FieldWidget/DateRangeWidgetBase.php
+++ b/core/modules/datetime_range/src/Plugin/Field/FieldWidget/DateRangeWidgetBase.php
@@ -19,6 +19,10 @@ class DateRangeWidgetBase extends DateTimeWidgetBase {
*/
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
$element = parent::formElement($items, $delta, $element, $form, $form_state);
+
+ // Wrap all of the select elements with a fieldset.
+ $element['#theme_wrappers'][] = 'fieldset';
+
$element['#element_validate'][] = [$this, 'validateStartEnd'];
$element['value']['#title'] = $this->t('Start date');
diff --git a/core/modules/datetime_range/src/Tests/DateRangeFieldTest.php b/core/modules/datetime_range/src/Tests/DateRangeFieldTest.php
index 74b8f6a..b2d259a 100644
--- a/core/modules/datetime_range/src/Tests/DateRangeFieldTest.php
+++ b/core/modules/datetime_range/src/Tests/DateRangeFieldTest.php
@@ -61,9 +61,12 @@ class DateRangeFieldTest extends DateTestBase {
$this->drupalGet('entity_test/add');
$this->assertFieldByName("{$field_name}[0][value][date]", '', 'Start date element found.');
$this->assertFieldByName("{$field_name}[0][end_value][date]", '', 'End date element found.');
- $this->assertFieldByXPath('//*[@id="edit-' . $field_name . '-wrapper"]/h4[contains(@class, "js-form-required")]', TRUE, 'Required markup found');
+ $this->assertFieldByXPath('//*[@id="edit-' . $field_name . '-wrapper"]//label[contains(@class, "js-form-required")]', TRUE, 'Required markup found');
$this->assertNoFieldByName("{$field_name}[0][value][time]", '', 'Start time element not found.');
$this->assertNoFieldByName("{$field_name}[0][end_value][time]", '', 'End time element not found.');
+ $this->assertFieldByXPath('//fieldset[@id="edit-' . $field_name . '-0"]/legend//text()', $field_name, 'Fieldset and label found');
+ $this->assertFieldByXPath('//fieldset[@aria-describedby="edit-' . $field_name . '-0--description"]', NULL, 'ARIA described-by found');
+ $this->assertFieldByXPath('//div[@id="edit-' . $field_name . '-0--description"]', NULL, 'ARIA description found');
// Build up dates in the UTC timezone.
$value = '2012-12-31 00:00:00';
@@ -261,6 +264,9 @@ class DateRangeFieldTest extends DateTestBase {
$this->assertFieldByName("{$field_name}[0][value][time]", '', 'Start time element found.');
$this->assertFieldByName("{$field_name}[0][end_value][date]", '', 'End date element found.');
$this->assertFieldByName("{$field_name}[0][end_value][time]", '', 'End time element found.');
+ $this->assertFieldByXPath('//fieldset[@id="edit-' . $field_name . '-0"]/legend//text()', $field_name, 'Fieldset and label found');
+ $this->assertFieldByXPath('//fieldset[@aria-describedby="edit-' . $field_name . '-0--description"]', NULL, 'ARIA described-by found');
+ $this->assertFieldByXPath('//div[@id="edit-' . $field_name . '-0--description"]', NULL, 'ARIA description found');
// Build up dates in the UTC timezone.
$value = '2012-12-31 00:00:00';
@@ -425,9 +431,12 @@ class DateRangeFieldTest extends DateTestBase {
$this->drupalGet('entity_test/add');
$this->assertFieldByName("{$field_name}[0][value][date]", '', 'Start date element found.');
$this->assertFieldByName("{$field_name}[0][end_value][date]", '', 'End date element found.');
- $this->assertFieldByXPath('//*[@id="edit-' . $field_name . '-wrapper"]/h4[contains(@class, "js-form-required")]', TRUE, 'Required markup found');
+ $this->assertFieldByXPath('//*[@id="edit-' . $field_name . '-wrapper"]//label[contains(@class, "js-form-required")]', TRUE, 'Required markup found');
$this->assertNoFieldByName("{$field_name}[0][value][time]", '', 'Start time element not found.');
$this->assertNoFieldByName("{$field_name}[0][end_value][time]", '', 'End time element not found.');
+ $this->assertFieldByXPath('//fieldset[@id="edit-' . $field_name . '-0"]/legend//text()', $field_name, 'Fieldset and label found');
+ $this->assertFieldByXPath('//fieldset[@aria-describedby="edit-' . $field_name . '-0--description"]', NULL, 'ARIA described-by found');
+ $this->assertFieldByXPath('//div[@id="edit-' . $field_name . '-0--description"]', NULL, 'ARIA description found');
// Build up dates in the proper timezone.
$value = '2012-12-31 00:00:00';
@@ -597,6 +606,9 @@ class DateRangeFieldTest extends DateTestBase {
// Display creation form.
$this->drupalGet('entity_test/add');
+ $this->assertFieldByXPath('//fieldset[@id="edit-' . $field_name . '-0"]/legend//text()', $field_name, 'Fieldset and label found');
+ $this->assertFieldByXPath('//fieldset[@aria-describedby="edit-' . $field_name . '-0--description"]', NULL, 'ARIA described-by found');
+ $this->assertFieldByXPath('//div[@id="edit-' . $field_name . '-0--description"]', NULL, 'ARIA description found');
// Assert that Hour and Minute Elements do not appear on Date Only.
$this->assertNoFieldByXPath("//*[@id=\"edit-$field_name-0-value-hour\"]", NULL, 'Hour element not found on Date Only.');
diff --git a/core/modules/system/templates/datetime-wrapper.html.twig b/core/modules/system/templates/datetime-wrapper.html.twig
index 8430baa..a14da89 100644
--- a/core/modules/system/templates/datetime-wrapper.html.twig
+++ b/core/modules/system/templates/datetime-wrapper.html.twig
@@ -30,4 +30,8 @@
{{ errors }}
</div>
{% endif %}
-{{ description }}
+{% if description %}
+ <div{{ description_attributes }}>
+ {{ description }}
+ </div>
+{% endif %}
diff --git a/core/themes/classy/templates/form/datetime-wrapper.html.twig b/core/themes/classy/templates/form/datetime-wrapper.html.twig
index 3f6aa59..5b52f2d 100644
--- a/core/themes/classy/templates/form/datetime-wrapper.html.twig
+++ b/core/themes/classy/templates/form/datetime-wrapper.html.twig
@@ -30,5 +30,7 @@
</div>
{% endif %}
{% if description %}
- <div class="description">{{ description }}</div>
+ <div{{ description_attributes.addClass('description') }}>
+ {{ description }}
+ </div>
{% endif %}