';
+
+ if (isset($element['#field_prefix'])) {
+ $output .= '
' . $element['#field_prefix'] . ' ';
+ }
+ $output .= $element['#children'];
+ if (isset($element['#field_suffix'])) {
+ $output .= '
' . $element['#field_suffix'] . '';
+ }
if (!empty($element['#description'])) {
$description_id = $element['#attributes']['id'] . '--description';
$description_attributes = array(
@@ -2881,7 +2887,7 @@ function template_preprocess_form_element(&$variables) {
$variables['attributes']['class'][] = 'form-disabled';
}
- // If #title is not set, we don't display any label or required marker.
+ // If #title is not set, we don't display any label.
if (!isset($element['#title'])) {
$element['#title_display'] = 'none';
}
@@ -2907,23 +2913,6 @@ function template_preprocess_form_element(&$variables) {
}
/**
- * Returns HTML for a marker for required form elements.
- *
- * @param $variables
- * An associative array containing:
- * - element: An associative array containing the properties of the element.
- *
- * @ingroup themeable
- */
-function theme_form_required_marker($variables) {
- $attributes = array(
- 'class' => 'form-required',
- 'aria-hidden' => 'true',
- );
- return '
*';
-}
-
-/**
* Returns HTML for a form element label and required marker.
*
* Form element labels include the #title and a #required marker. The label is
@@ -2953,26 +2942,16 @@ function theme_form_element_label($variables) {
return '';
}
- // If the element is required, a required marker is appended to the label.
- $required = '';
- if (!empty($element['#required'])) {
- $marker = array(
- '#theme' => 'form_required_marker',
- '#element' => $element,
- );
- $required = drupal_render($marker);
- }
-
$title = filter_xss_admin($element['#title']);
$attributes = array();
// Style the label as class option to display inline with the element.
if ($element['#title_display'] == 'after') {
- $attributes['class'] = 'option';
+ $attributes['class'][] = 'option';
}
// Show label only to screen readers to avoid disruption in visual flows.
elseif ($element['#title_display'] == 'invisible') {
- $attributes['class'] = 'visually-hidden';
+ $attributes['class'][] = 'visually-hidden';
}
// A #for property of a dedicated #type 'label' element as precedence.
@@ -2989,7 +2968,13 @@ function theme_form_element_label($variables) {
$attributes['for'] = $element['#id'];
}
- return '
';
+ // For required elements a 'form-required' class is appended to the
+ // label attributes.
+ if (!empty($element['#required'])) {
+ $attributes['class'][] = 'form-required';
+ }
+
+ return '
';
}
/**
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index f98df80..8119acf 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -2900,9 +2900,6 @@ function drupal_common_theme() {
'render element' => 'element',
'template' => 'form-element',
),
- 'form_required_marker' => array(
- 'render element' => 'element',
- ),
'form_element_label' => array(
'render element' => 'element',
),
diff --git a/core/misc/states.js b/core/misc/states.js
index 701d6fc..530f03e 100644
--- a/core/misc/states.js
+++ b/core/misc/states.js
@@ -522,12 +522,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.find('.form-required').length) {
- $label.append(Drupal.theme('requiredMarker'));
+ if (!$label.hasClass('form-required').length) {
+ $label.addClass('form-required');
}
}
else {
- $(e.target).removeAttr('required aria-required').closest('.form-item, .form-wrapper').find('label .form-required').remove();
+ $(e.target).removeAttr('required aria-required').closest('.form-item, .form-wrapper').find('label.form-required').removeClass('form-required');
}
}
});
@@ -573,10 +573,4 @@
return (a === b) ? (typeof a === 'undefined' ? a : true) : (typeof a === 'undefined' || typeof b === 'undefined');
}
- $.extend(Drupal.theme, {
- requiredMarker: function () {
- return '
*';
- }
- });
-
})(jQuery);
diff --git a/core/modules/datetime/datetime.module b/core/modules/datetime/datetime.module
index 3a016b5..4b37ae2 100644
--- a/core/modules/datetime/datetime.module
+++ b/core/modules/datetime/datetime.module
@@ -225,16 +225,6 @@ function template_preprocess_datetime_form(&$variables) {
*/
function template_preprocess_datetime_wrapper(&$variables) {
$element = $variables['element'];
-
- // If the element is required, a required marker is appended to the label.
- $variables['required'] = NULL;
- if(!empty($element['#required'])) {
- $variables['required'] = array(
- '#theme' => 'form_required_marker',
- '#element' => $element,
- );
- }
-
if (!empty($element['#title'])) {
$variables['title'] = $element['#title'];
}
@@ -243,6 +233,13 @@ function template_preprocess_datetime_wrapper(&$variables) {
$variables['description'] = $element['#description'];
}
+ $title_attributes = array('class' => array('label'));
+ // For required datetime fields a 'form-required' class is appended to the
+ // label attributes.
+ if (!empty($element['#required'])) {
+ $title_attributes['class'][] = 'form-required';
+ }
+ $variables['title_attributes'] = new Attribute($title_attributes);
$variables['content'] = $element['#children'];
}
diff --git a/core/modules/datetime/templates/datetime-wrapper.html.twig b/core/modules/datetime/templates/datetime-wrapper.html.twig
index a4acf70..5660cf5 100644
--- a/core/modules/datetime/templates/datetime-wrapper.html.twig
+++ b/core/modules/datetime/templates/datetime-wrapper.html.twig
@@ -6,8 +6,7 @@
* Available variables:
* - content: The form element to be output, usually a datelist, or datetime.
* - title: The title of the form element.
- * - attributes: HTML attributes for the form wrapper.
- * - required: (optional) A marker indicating that the form element is required.
+ * - title_attributes: HTML attributes for the title wrapper.
* - description: Description text for the form element.
*
* @see template_preprocess_datetime_wrapper()
@@ -16,9 +15,7 @@
*/
#}
{% if title %}
-
- {% trans %}{{ title|passthrough }}{{ required|passthrough }}{% endtrans %}
-
+
{{ title }}
{% endif %}
{{ content }}
{% if description %}
diff --git a/core/modules/system/css/system.theme.css b/core/modules/system/css/system.theme.css
index f397a5a..86638b2 100644
--- a/core/modules/system/css/system.theme.css
+++ b/core/modules/system/css/system.theme.css
@@ -79,11 +79,20 @@ h4.label {
.form-type-checkbox .description {
margin-left: 2.4em;
}
-.marker,
-.form-required {
+.marker {
color: #e00;
}
-abbr.form-required, abbr.tabledrag-changed, abbr.ajax-changed {
+
+.form-required:after {
+ color: #e00;
+ content: "*";
+ speak: none;
+ margin-left: 0.25em;
+ margin-right: 0.25em; /* RTL */
+}
+
+abbr.tabledrag-changed,
+abbr.ajax-changed {
border-bottom: none;
}
.form-item input.error,
diff --git a/core/modules/system/lib/Drupal/system/Tests/Form/ElementsLabelsTest.php b/core/modules/system/lib/Drupal/system/Tests/Form/ElementsLabelsTest.php
index 6c51a04..b002635 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Form/ElementsLabelsTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Form/ElementsLabelsTest.php
@@ -59,10 +59,10 @@ 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"]/child::span[@class="form-required"]/parent::*/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="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"]/span[@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="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"]');
diff --git a/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php b/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php
index e2ef22c..ca047cd 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php
@@ -96,8 +96,7 @@ function testRequiredFields() {
$elements['file']['empty_values'] = $empty_strings;
// Regular expression to find the expected marker on required elements.
- $required_marker_preg = '@<(?:label|legend).*
\*.*(?:label|legend)>@';
-
+ $required_marker_preg = '@<.*?class=".*?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/themes/bartik/css/style.css b/core/themes/bartik/css/style.css
index 663d60c..1e4a411 100644
--- a/core/themes/bartik/css/style.css
+++ b/core/themes/bartik/css/style.css
@@ -430,7 +430,7 @@ h1.site-name {
background: #fff;
background: rgba(255, 255, 255, 0.8);
}
-.region-header .form-required {
+.region-header .form-required:after {
color: #eee;
color: rgba(255, 255, 255, 0.7);
}