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 @@ 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') { 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 @@ 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: 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 @@ protected function createField() { $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 @@ 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.'); 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 @@ 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.'); diff --git a/core/modules/system/templates/datetime-wrapper.html.twig b/core/modules/system/templates/datetime-wrapper.html.twig index 8430baa..27dfa4e 100644 --- a/core/modules/system/templates/datetime-wrapper.html.twig +++ b/core/modules/system/templates/datetime-wrapper.html.twig @@ -30,4 +30,8 @@ {{ errors }} {% endif %} -{{ description }} +{% if description %} + + {{ description }} + +{% 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 @@ {% endif %} {% if description %} -
{{ description }}
+ + {{ description }} + {% endif %} diff --git a/core/themes/stable/templates/form/datetime-wrapper.html.twig b/core/themes/stable/templates/form/datetime-wrapper.html.twig index 3c37ffd..8e04751 100644 --- a/core/themes/stable/templates/form/datetime-wrapper.html.twig +++ b/core/themes/stable/templates/form/datetime-wrapper.html.twig @@ -28,4 +28,8 @@ {{ errors }} {% endif %} -{{ description }} +{% if description %} + + {{ description }} + +{% endif %}