diff --git a/core/includes/form.inc b/core/includes/form.inc
index 853990b..1349c17 100644
--- a/core/includes/form.inc
+++ b/core/includes/form.inc
@@ -3986,36 +3986,69 @@ function theme_form_element($variables) {
}
$output = '
' . "\n";
+ // Composite elements consist of more than one HTML form control. These must
+ // be grouped by a fieldset.
+ $composite = FALSE;
+ if (isset($element['#composite']) && $element['#composite'] === TRUE) {
+ $composite = TRUE;
+ }
+
+ if ($composite) {
+ $output .= '
'fieldset-invisible')) . '>';
+ }
+
// 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'] . ' ' : '';
+ $children = ' ' . $prefix . $element['#children'] . $suffix;
+
+ // Generate the title, either a legend or a label, only if the title will be
+ // used.
+ if (!in_array($element['#title_display'], array('none', 'attribute'))) {
+ if ($composite) {
+ $attributes = array();
+ if ($element['#title_display'] == 'invisible') {
+ $attributes['class'] = 'element-invisible';
+ }
+ $title = '' . $element['#title'];
+ if (!empty($element['#required'])) {
+ $title .= theme('form_required_marker', array('element' => $element));
+ }
+ $title .= ' ';
+ } else {
+ $title = ' ' . theme('form_element_label', $variables);
+ }
+ }
switch ($element['#title_display']) {
case 'before':
case 'invisible':
- $output .= ' ' . theme('form_element_label', $variables);
- $output .= ' ' . $prefix . $element['#children'] . $suffix . "\n";
+ $output .= $title . $children;
break;
case 'after':
- $output .= ' ' . $prefix . $element['#children'] . $suffix;
- $output .= ' ' . theme('form_element_label', $variables) . "\n";
+ $output .= $children . $title;
break;
case 'none':
case 'attribute':
// Output no label and no required marker, only the children.
- $output .= ' ' . $prefix . $element['#children'] . $suffix . "\n";
+ $output .= $children;
break;
}
+ $output .= "\n";
if (!empty($element['#description'])) {
$output .= '' . $element['#description'] . "
\n";
}
+ if ($composite) {
+ $output .= ' ';
+ }
+
$output .= "
\n";
return $output;
diff --git a/core/modules/simpletest/tests/form.test b/core/modules/simpletest/tests/form.test
index 784da88..cf395c7 100644
--- a/core/modules/simpletest/tests/form.test
+++ b/core/modules/simpletest/tests/form.test
@@ -68,7 +68,7 @@ class FormsTestCase extends DrupalWebTestCase {
$elements['file']['empty_values'] = $empty_strings;
// Regular expression to find the expected marker on required elements.
- $required_marker_preg = '@\*@';
+ $required_marker_preg = '@<(label|legend).*\* \1>@';
// 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 38c3f55..75d0181 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -411,6 +411,7 @@ function system_element_info() {
$types['radios'] = array(
'#input' => TRUE,
'#process' => array('form_process_radios'),
+ '#composite' => TRUE,
'#theme_wrappers' => array('radios'),
'#pre_render' => array('form_pre_render_conditional_form_element'),
);
@@ -425,6 +426,7 @@ function system_element_info() {
$types['checkboxes'] = array(
'#input' => TRUE,
'#process' => array('form_process_checkboxes'),
+ '#composite' => TRUE,
'#theme_wrappers' => array('checkboxes'),
'#pre_render' => array('form_pre_render_conditional_form_element'),
);
@@ -453,6 +455,7 @@ function system_element_info() {
'#input' => TRUE,
'#element_validate' => array('date_validate'),
'#process' => array('form_process_date'),
+ '#composite' => TRUE,
'#theme' => 'date',
'#theme_wrappers' => array('form_element'),
);
diff --git a/core/modules/system/system.theme.css b/core/modules/system/system.theme.css
index c3913c1..7788c1c 100644
--- a/core/modules/system/system.theme.css
+++ b/core/modules/system/system.theme.css
@@ -188,6 +188,48 @@ abbr.form-required, abbr.tabledrag-changed, abbr.ajax-changed {
}
/**
+ * Invisible fieldsets.
+ *
+ * @see theme_form_element()
+ */
+fieldset.fieldset-invisible {
+ margin: 0;
+ padding: 0;
+ border: none;
+ display: inherit;
+}
+fieldset.fieldset-invisible > legend {
+ margin: 0;
+ padding: 0;
+ border: none;
+ outline: 0;
+ font-style: inherit;
+ font-size: 100%;
+ font-family: inherit;
+ vertical-align: baseline;
+
+ border-radius: 0;
+ color: inherit;
+ background-color: transparent;
+ background-image: none;
+
+ display: block;
+ font-weight: bold;
+
+ position: static;
+ left: 0;
+ right: 0;
+ top: 0;
+ bottom: 0;
+
+ text-indent: 0;
+ text-shadow: none;
+ line-height: normal;
+ width: auto;
+ height: auto;
+}
+
+/**
* TableDrag behavior.
*
* @see tabledrag.js