diff --git a/core/includes/theme.inc b/core/includes/theme.inc index d8f3136..9082884 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -507,8 +507,8 @@ function template_preprocess_datetime_wrapper(&$variables) { } $variables['required'] = FALSE; - // For required datetime fields a 'form-required' class is appended to the - // label attributes. + // For required datetime fields 'form-required' & 'js-form-required' classes + // are appended to the label attributes. if (!empty($element['#required'])) { $variables['required'] = TRUE; } @@ -1606,6 +1606,7 @@ function template_preprocess_field_multiple_value_form(&$variables) { $order_class = $element['#field_name'] . '-delta-order'; $header_attributes = new Attribute(array('class' => array('label'))); if (!empty($element['#required'])) { + $header_attributes['class'][] = 'js-form-required'; $header_attributes['class'][] = 'form-required'; } $header = array( diff --git a/core/misc/states.js b/core/misc/states.js index b969da7..1c9e5e6 100644 --- a/core/misc/states.js +++ b/core/misc/states.js @@ -526,12 +526,12 @@ if (e.value) { var $label = $(e.target).attr({'required': 'required', 'aria-required': 'aria-required'}).closest('.form-item, .form-wrapper').find('label'); // Avoids duplicate required markers on initialization. - if (!$label.hasClass('form-required').length) { - $label.addClass('form-required'); + if (!$label.hasClass('js-form-required').length) { + $label.addClass('js-form-required form-required'); } } else { - $(e.target).removeAttr('required aria-required').closest('.form-item, .form-wrapper').find('label.form-required').removeClass('form-required'); + $(e.target).removeAttr('required aria-required').closest('.form-item, .form-wrapper').find('label.js-form-required').removeClass('js-form-required form-required'); } } }); diff --git a/core/modules/datetime/src/Tests/DateTimeFieldTest.php b/core/modules/datetime/src/Tests/DateTimeFieldTest.php index f3fcae1..d07a244 100644 --- a/core/modules/datetime/src/Tests/DateTimeFieldTest.php +++ b/core/modules/datetime/src/Tests/DateTimeFieldTest.php @@ -100,7 +100,7 @@ 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, "form-required")]', TRUE, 'Required markup found'); + $this->assertFieldByXPath('//*[@id="edit-' . $field_name . '-wrapper"]/h4[contains(@class, "js-form-required")]', TRUE, 'Required markup found'); $this->assertNoFieldByName("{$field_name}[0][value][time]", '', 'Time element not found.'); // Submit a valid date and ensure it is accepted. diff --git a/core/modules/field/src/Tests/FormTest.php b/core/modules/field/src/Tests/FormTest.php index 748d2ac..4b21bc4 100644 --- a/core/modules/field/src/Tests/FormTest.php +++ b/core/modules/field/src/Tests/FormTest.php @@ -334,12 +334,12 @@ public function testFieldFormUnlimitedRequired() { // Display creation form -> 1 widget. $this->drupalGet('entity_test/add'); // Check that the Required symbol is present for the multifield label. - $this->assertRaw(SafeMarkup::format('

@label

', array('@label' => $this->field['label'])), - 'Required symbol added field label.'); + $element = $this->xpath('//h4[contains(@class, "label") and contains(@class, "js-form-required") and contains(text(), :value)]', array(':value' => $this->field['label'])); + $this->assertTrue(isset($element[0]), 'Required symbol added field label.'); // Check that the label of the field input is visually hidden and contains // the field title and an indication of the delta for a11y. - $this->assertRaw(SafeMarkup::format('', array('@label' => $this->field['label'])), - 'Required symbol not added for field input.'); + $element = $this->xpath('//label[@for=:for and contains(@class, "js-form-required") and contains(text(), :value)]', array(':for' => 'edit-field-unlimited-0-value', ':value' => $this->field['label'] . ' (value 1)')); + $this->assertTrue(isset($element[0]), 'Required symbol not added for field input.'); } /** diff --git a/core/modules/field_ui/field_ui.js b/core/modules/field_ui/field_ui.js index 9bdbe50..0056904 100644 --- a/core/modules/field_ui/field_ui.js +++ b/core/modules/field_ui/field_ui.js @@ -11,15 +11,16 @@ attach: function (context) { var $form = $(context).find('#field-ui-field-storage-add-form').once('field_ui_add'); if ($form.length) { - // Add a few 'form-required' css classes here. We can not use the Form API - // '#required' property because both label elements for "add new" and - // "re-use existing" can never be filled and submitted at the same time. + // Add a few 'js-form-required' and 'form-required' CSS classes here. We + // can not use the Form API '#required' property because both label + // elements for "add new" and "re-use existing" can never be filled and + // submitted at the same time. // The actual validation will happen server-side. $form.find( '.form-item-label label,' + '.form-item-field-name label,' + '.form-item-existing-storage-label label') - .addClass('form-required'); + .addClass('js-form-required form-required'); var $newFieldType = $form.find('select[name="new_storage_type"]'); var $existingStorageName = $form.find('select[name="existing_storage_name"]'); diff --git a/core/modules/image/src/Tests/ImageFieldValidateTest.php b/core/modules/image/src/Tests/ImageFieldValidateTest.php index 938176a..ee76462 100644 --- a/core/modules/image/src/Tests/ImageFieldValidateTest.php +++ b/core/modules/image/src/Tests/ImageFieldValidateTest.php @@ -69,11 +69,11 @@ function testRequiredAttributes() { $this->uploadNodeImage($image, $field_name, 'article'); // Look for form-required for the alt text. - $elements = $this->xpath('//label[@for="edit-' . $field_name . '-0-alt" and @class="form-required"]/following-sibling::input[@id="edit-' . $field_name . '-0-alt"]'); + $elements = $this->xpath('//label[@for="edit-' . $field_name . '-0-alt" and @class="js-form-required form-required"]/following-sibling::input[@id="edit-' . $field_name . '-0-alt"]'); $this->assertTrue(isset($elements[0]),'Required marker is shown for the required alt text.'); - $elements = $this->xpath('//label[@for="edit-' . $field_name . '-0-title" and @class="form-required"]/following-sibling::input[@id="edit-' . $field_name . '-0-title"]'); + $elements = $this->xpath('//label[@for="edit-' . $field_name . '-0-title" and @class="js-form-required form-required"]/following-sibling::input[@id="edit-' . $field_name . '-0-title"]'); $this->assertTrue(isset($elements[0]), 'Required marker is shown for the required title text.'); diff --git a/core/modules/system/src/Tests/Form/ElementsLabelsTest.php b/core/modules/system/src/Tests/Form/ElementsLabelsTest.php index db5dbee..cc3ce30 100644 --- a/core/modules/system/src/Tests/Form/ElementsLabelsTest.php +++ b/core/modules/system/src/Tests/Form/ElementsLabelsTest.php @@ -53,16 +53,16 @@ function testFormLabels() { // Exercise various defaults for textboxes and modifications to ensure // appropriate override and correct behavior. - $elements = $this->xpath('//label[@for="edit-form-textfield-test-title-and-required" and @class="form-required"]/following-sibling::input[@id="edit-form-textfield-test-title-and-required"]'); + $elements = $this->xpath('//label[@for="edit-form-textfield-test-title-and-required" and @class="js-form-required form-required"]/following-sibling::input[@id="edit-form-textfield-test-title-and-required"]'); $this->assertTrue(isset($elements[0]), 'Label precedes textfield, with required marker inside label.'); - $elements = $this->xpath('//input[@id="edit-form-textfield-test-no-title-required"]/preceding-sibling::label[@for="edit-form-textfield-test-no-title-required" and @class="form-required"]'); + $elements = $this->xpath('//input[@id="edit-form-textfield-test-no-title-required"]/preceding-sibling::label[@for="edit-form-textfield-test-no-title-required" and @class="js-form-required form-required"]'); $this->assertTrue(isset($elements[0]), 'Label tag with required marker precedes required textfield with no title.'); $elements = $this->xpath('//input[@id="edit-form-textfield-test-title-invisible"]/preceding-sibling::label[@for="edit-form-textfield-test-title-invisible" and @class="visually-hidden"]'); $this->assertTrue(isset($elements[0]), 'Label preceding field and label class is visually-hidden.'); - $elements = $this->xpath('//input[@id="edit-form-textfield-test-title"]/preceding-sibling::span[@class="form-required"]'); + $elements = $this->xpath('//input[@id="edit-form-textfield-test-title"]/preceding-sibling::span[@class="js-form-required form-required"]'); $this->assertFalse(isset($elements[0]), 'No required marker on non-required field.'); $elements = $this->xpath('//input[@id="edit-form-textfield-test-title-after"]/following-sibling::label[@for="edit-form-textfield-test-title-after" and @class="option"]'); diff --git a/core/modules/system/src/Tests/Form/FormTest.php b/core/modules/system/src/Tests/Form/FormTest.php index 321502d..0bca2cb 100644 --- a/core/modules/system/src/Tests/Form/FormTest.php +++ b/core/modules/system/src/Tests/Form/FormTest.php @@ -97,7 +97,7 @@ function testRequiredFields() { $elements['file']['empty_values'] = $empty_strings; // Regular expression to find the expected marker on required elements. - $required_marker_preg = '@<.*?class=".*?form-required.*?">@'; + $required_marker_preg = '@<.*?class=".*?js-form-required.*form-required.*?">@'; // Go through all the elements and all the empty values for them. foreach ($elements as $type => $data) { foreach ($data['empty_values'] as $key => $empty) { diff --git a/core/modules/system/templates/datetime-wrapper.html.twig b/core/modules/system/templates/datetime-wrapper.html.twig index 443b5b3..62a4b9d 100644 --- a/core/modules/system/templates/datetime-wrapper.html.twig +++ b/core/modules/system/templates/datetime-wrapper.html.twig @@ -17,7 +17,7 @@ #} {% set title_classes = [ - required ? 'form-required', + required ? 'js-form-required', ] %} {% if title %} diff --git a/core/modules/system/templates/fieldset.html.twig b/core/modules/system/templates/fieldset.html.twig index ab6796c..f7af6fa 100644 --- a/core/modules/system/templates/fieldset.html.twig +++ b/core/modules/system/templates/fieldset.html.twig @@ -25,7 +25,7 @@ {% set legend_span_classes = [ 'fieldset-legend', - required ? 'form-required', + required ? 'js-form-required', ] %} {# Always wrap fieldset legends in a SPAN for CSS positioning. #} diff --git a/core/modules/system/templates/form-element-label.html.twig b/core/modules/system/templates/form-element-label.html.twig index 6ececd9..644b4bd 100644 --- a/core/modules/system/templates/form-element-label.html.twig +++ b/core/modules/system/templates/form-element-label.html.twig @@ -18,7 +18,7 @@ set classes = [ title_display == 'after' ? 'option', title_display == 'invisible' ? 'visually-hidden', - required ? 'form-required', + required ? 'js-form-required', ] %} {% if title is not empty or required -%} diff --git a/core/themes/classy/templates/form/datetime-wrapper.html.twig b/core/themes/classy/templates/form/datetime-wrapper.html.twig index 399dea2..e3f504b 100644 --- a/core/themes/classy/templates/form/datetime-wrapper.html.twig +++ b/core/themes/classy/templates/form/datetime-wrapper.html.twig @@ -16,6 +16,7 @@ {% set title_classes = [ 'label', + required ? 'js-form-required', required ? 'form-required', ] %} diff --git a/core/themes/classy/templates/form/fieldset.html.twig b/core/themes/classy/templates/form/fieldset.html.twig index f7460cf..7eb65f9 100644 --- a/core/themes/classy/templates/form/fieldset.html.twig +++ b/core/themes/classy/templates/form/fieldset.html.twig @@ -23,6 +23,7 @@ {% set legend_span_classes = [ 'fieldset-legend', + required ? 'js-form-required', required ? 'form-required', ] %} diff --git a/core/themes/classy/templates/form/form-element-label.html.twig b/core/themes/classy/templates/form/form-element-label.html.twig index 70ed96c..7c2f8f2 100644 --- a/core/themes/classy/templates/form/form-element-label.html.twig +++ b/core/themes/classy/templates/form/form-element-label.html.twig @@ -16,6 +16,7 @@ set classes = [ title_display == 'after' ? 'option', title_display == 'invisible' ? 'visually-hidden', + required ? 'js-form-required', required ? 'form-required', ] %}