diff --git a/core/includes/form.inc b/core/includes/form.inc index 3c88b1e..77a9f5e 100644 --- a/core/includes/form.inc +++ b/core/includes/form.inc @@ -2786,7 +2786,7 @@ function form_get_options($element, $key) { * An associative array containing: * - element: An associative array containing the properties of the element. * Properties used: #attributes, #children, #collapsed, #collapsible, - * #description, #id, #title, #value. + * #description, #id, #title, #title_display, #value. * * @ingroup themeable */ @@ -2795,21 +2795,29 @@ function theme_fieldset($variables) { element_set_attributes($element, array('id')); _form_set_attributes($element, array('form-wrapper')); - if (!empty($element['#description'])) { - $description_id = $element['#attributes']['id'] . '--description'; - $element['#attributes']['aria-describedby'] = $description_id; + // Add the aria-describedby attribute to associate the fieldset with its + // description. + $description_attributes = array( + 'class' => array('fieldset-description'), + ); + if (!empty($element['#description']) && isset($element['#attributes']['id'])) { + $description_attributes['id'] = $element['#attributes']['id'] . '--description'; + $element['#attributes']['aria-describedby'] = $description_attributes['id']; } $output = ''; - if (!empty($element['#title'])) { + $element += array('#title_display' => 'before'); + if (!empty($element['#title']) && !in_array($element['#title_display'], array('none', 'attribute'), TRUE)) { + $attributes = new Attribute(array('class' => array('fieldset-legend'))); + if ($element['#title_display'] === 'invisible') { + $attributes['class'][] = 'element-invisible'; + } // Always wrap fieldset legends in a SPAN for CSS positioning. - $output .= '' . $element['#title'] . ''; + $output .= '' . $element['#title'] . ''; } $output .= '
'; if (!empty($element['#description'])) { - $attributes = array('class' => 'fieldset-description', 'id' => $description_id); - $output .= '' . $element['#description'] . '
'; - + $output .= '' . $element['#description'] . ''; } $output .= $element['#children']; if (isset($element['#value'])) { @@ -4531,14 +4539,29 @@ function theme_form_element($variables) { if (!empty($element['#attributes']['disabled'])) { $attributes['class'][] = 'form-disabled'; } + $prefix = isset($element['#field_prefix']) ? '' . $element['#field_prefix'] . ' ' : ''; + $suffix = isset($element['#field_suffix']) ? ' ' . $element['#field_suffix'] . '' : ''; + + // Composite elements consist of more than one HTML form control. These must + // be grouped by a fieldset. + if (isset($element['#composite']) && $element['#composite'] === TRUE) { + $fieldset_variables = array('element' => array()); + $fieldset_variables['element']['#children'] = $prefix . $element['#children'] . $suffix; + foreach (array('#attributes', '#description', '#id', '#title', '#title_display') as $property) { + if (!empty($element[$property])) { + $fieldset_variables['element'][$property] = $element[$property]; + } + } + unset($fieldset_variables['element']['#attributes']['disabled']); + $fieldset_variables['element']['#title'] .= !empty($element['#required']) ? ' ' . theme('form_required_marker', array('element' => $element)) : ''; + return theme('fieldset', $fieldset_variables); + } $output = '' . "\n"; // If #title is not set, we don't display any label or required marker. if (!isset($element['#title'])) { $element['#title_display'] = 'none'; } - $prefix = isset($element['#field_prefix']) ? '' . $element['#field_prefix'] . ' ' : ''; - $suffix = isset($element['#field_suffix']) ? ' ' . $element['#field_suffix'] . '' : ''; switch ($element['#title_display']) { case 'before': 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 9efe0c3..e0ff73c 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php @@ -95,7 +95,7 @@ function testRequiredFields() { $elements['file']['empty_values'] = $empty_strings; // Regular expression to find the expected marker on required elements. - $required_marker_preg = '@\*@'; + $required_marker_preg = '@<(label|legend).*\*.*@'; // Go through all the elements and all the empty values for them. foreach ($elements as $type => $data) { diff --git a/core/modules/system/system.module b/core/modules/system/system.module index 1492cf0..5063ecd 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -430,6 +430,7 @@ function system_element_info() { '#theme_wrappers' => array('form_element'), ); $types['radios'] = array( + '#composite' => TRUE, '#input' => TRUE, '#process' => array('form_process_radios'), '#theme_wrappers' => array('radios'), @@ -444,6 +445,7 @@ function system_element_info() { '#title_display' => 'after', ); $types['checkboxes'] = array( + '#composite' => TRUE, '#input' => TRUE, '#process' => array('form_process_checkboxes'), '#theme_wrappers' => array('checkboxes'), @@ -475,6 +477,7 @@ function system_element_info() { '#process' => array('form_process_weight', 'ajax_process_form'), ); $types['date'] = array( + '#composite' => TRUE, '#input' => TRUE, '#element_validate' => array('date_validate'), '#process' => array('form_process_date'),