Commit 772edb3b authored by xjm's avatar xjm

Issue #1918994 by Tim Bozeman, mgifford, mpdonadio, vprocessor, sun, xjm,...

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
parent 0b45cbb7
......@@ -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;
......
......@@ -35,6 +35,9 @@ public static function defaultSettings() {
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') {
......
......@@ -59,6 +59,16 @@ public static function create(ContainerInterface $container, array $configuratio
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:
......
......@@ -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,
......
......@@ -120,6 +120,7 @@ protected function createField() {
$this->field = FieldConfig::create([
'field_storage' => $this->fieldStorage,
'bundle' => 'entity_test',
'description' => 'Description for ' . $field_name,
'required' => TRUE,
]);
$this->field->save();
......
......@@ -48,8 +48,10 @@ function testDateField() {
// 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 @@ function testDatetimeField() {
$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 @@ function testDatelistWidget() {
// 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.');
......
......@@ -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');
......
......@@ -61,9 +61,12 @@ public function testDateRangeField() {
$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 @@ public function testDatetimeRangeField() {
$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 @@ public function testAlldayRangeField() {
$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 @@ public function testDatelistWidget() {
// 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.');
......
......@@ -30,4 +30,8 @@
{{ errors }}
</div>
{% endif %}
{{ description }}
{% if description %}
<div{{ description_attributes }}>
{{ description }}
</div>
{% endif %}
......@@ -30,5 +30,7 @@
</div>
{% endif %}
{% if description %}
<div class="description">{{ description }}</div>
<div{{ description_attributes.addClass('description') }}>
{{ description }}
</div>
{% endif %}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment