diff --git a/core/includes/form.inc b/core/includes/form.inc index 5d4a943..daa17a6 100644 --- a/core/includes/form.inc +++ b/core/includes/form.inc @@ -2687,6 +2687,9 @@ function form_process_file($element) { /** * Returns HTML for a form element. + * Prepares variables for form element templates. + * + * Default template: form-element.html.twig. * * Each form element is wrapped in a DIV container having the following CSS * classes: @@ -2723,7 +2726,7 @@ function form_process_file($element) { * but the parent element should have neither. Use this carefully because a * field without an associated label can cause accessibility challenges. * - * @param $variables + * @param array $variables * An associative array containing: * - element: An associative array containing the properties of the element. * Properties used: #title, #title_display, #description, #id, #required, @@ -2731,7 +2734,7 @@ function form_process_file($element) { * * @ingroup themeable */ -function theme_form_element($variables) { +function template_preprocess_form_element(&$variables) { $element = &$variables['element']; // This function is invoked as theme wrapper, but the rendered form element @@ -2743,64 +2746,57 @@ function theme_form_element($variables) { // Take over any #wrapper_attributes defined by the element. // @todo Temporary hack for #type 'item'. // @see http://drupal.org/node/1829202 + $variables['attributes'] = array(); if (isset($element['#wrapper_attributes'])) { - $attributes = $element['#wrapper_attributes']; + $variables['attributes'] = $element['#wrapper_attributes']; } + // Add element #id for #type 'item'. if (isset($element['#markup']) && !empty($element['#id'])) { - $attributes['id'] = $element['#id']; + $variables['attributes']['id'] = $element['#id']; } + // Add element's #type and #name as class to aid with JS/CSS selectors. - $attributes['class'][] = 'form-item'; + $variables['attributes']['class'][] = 'form-item'; if (!empty($element['#type'])) { - $attributes['class'][] = 'form-type-' . strtr($element['#type'], '_', '-'); + $variables['attributes']['class'][] = 'form-type-' . strtr($element['#type'], '_', '-'); } if (!empty($element['#name'])) { - $attributes['class'][] = 'form-item-' . strtr($element['#name'], array(' ' => '-', '_' => '-', '[' => '-', ']' => '')); + $variables['attributes']['class'][] = 'form-item-' . strtr($element['#name'], array(' ' => '-', '_' => '-', '[' => '-', ']' => '')); } // Add a class for disabled elements to facilitate cross-browser styling. if (!empty($element['#attributes']['disabled'])) { - $attributes['class'][] = 'form-disabled'; + $variables['attributes']['class'][] = 'form-disabled'; } - $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': - case 'invisible': - $output .= ' ' . theme('form_element_label', $variables); - $output .= ' ' . $prefix . $element['#children'] . $suffix . "\n"; - break; - - case 'after': - $output .= ' ' . $prefix . $element['#children'] . $suffix; - $output .= ' ' . theme('form_element_label', $variables) . "\n"; - break; - - case 'none': - case 'attribute': - // Output no label and no required marker, only the children. - $output .= ' ' . $prefix . $element['#children'] . $suffix . "\n"; - break; - } + $variables['prefix'] = isset($element['#field_prefix']) ? $element['#field_prefix'] : NULL; + $variables['suffix'] = isset($element['#field_suffix']) ? $element['#field_suffix'] : NULL; + $variables['description'] = NULL; if (!empty($element['#description'])) { - $attributes = array('class' => 'description'); + $description_attributes = array('class' => 'description'); if (!empty($element['#id'])) { - $attributes['id'] = $element['#id'] . '--description'; + $description_attributes['id'] = $element['#id'] . '--description'; } - $output .= '' . $element['#description'] . "\n"; + $variables['description']['attributes'] = new Attribute($description_attributes); + $variables['description']['content'] = $element['#description']; } - $output .= "\n"; + // Add label_display and label variables to template. + $variables['label_display'] = $element['#title_display']; + $variables['label'] = array( + '#theme' => 'form_element_label', + '#required' => isset($element['#required']) ? $element['#required'] : '', + '#title' => isset($element['#title']) ? $element['#title'] : '', + '#title_display' => isset($element['#title_display']) ? $element['#title_display'] : '', + '#id' => isset($element['#id']) ? $element['#id'] : '', + ); - return $output; + $variables['children'] = $element['#children']; } /** @@ -2845,7 +2841,6 @@ function theme_form_required_marker($variables) { */ function theme_form_element_label($variables) { $element = $variables['element']; - // If title and required marker are both empty, output no label. if ((!isset($element['#title']) || $element['#title'] === '') && empty($element['#required'])) { return ''; diff --git a/core/includes/theme.inc b/core/includes/theme.inc index 96a0466..e464081 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -2732,6 +2732,7 @@ function drupal_common_theme() { ), 'form_element' => array( 'render element' => 'element', + 'template' => 'form-element', ), 'form_required_marker' => array( 'render element' => 'element', diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php index 6c83611..17a9ef5 100644 --- a/core/modules/system/system.api.php +++ b/core/modules/system/system.api.php @@ -233,7 +233,7 @@ function hook_queue_info_alter(&$queues) { * - "#post_render": array of callables taking $children and $element. * - "#submit": array of callback functions taking $form and $form_state. * - "#title_display": optional string indicating if and how #title should be - * displayed, see theme_form_element() and theme_form_element_label(). + * displayed, see the form-element template and theme_form_element_label(). * * @see hook_element_info_alter() * @see system_element_info() diff --git a/core/modules/system/templates/form-element.html.twig b/core/modules/system/templates/form-element.html.twig new file mode 100644 index 0000000..ea4d90f --- /dev/null +++ b/core/modules/system/templates/form-element.html.twig @@ -0,0 +1,58 @@ +{# +/** + * @file + * Default theme implementation for a form element. + * + * Available variables: + * - attributes: HTML attributes for the containing element. + * - prefix: (optional) The form element prefix, may not be set. + * - suffix: (optional) The form element suffix, may not be set. + * - required: The required marker, or empty if the associated form element is + * not required. + * - label: A rendered label element. + * - label_display: Label display setting. It can have these values: + * - before: The label is output before the element. This is the default. + * The label includes the #title and the required marker, if #required. + * - after: The label is output after the element. For example, this is used + * for radio and checkbox #type elements as set in system_element_info(). + * If the #title is empty but the field is #required, the label will + * contain only the required marker. + * - invisible: Labels are critical for screen readers to enable them to + * properly navigate through forms but can be visually distracting. This + * property hides the label for everyone except screen readers. + * - attribute: Set the title attribute on the element to create a tooltip but + * output no label element. This is supported only for checkboxes and radios + * in form_pre_render_conditional_form_element(). It is used where a visual + * label is not needed, such as a table of checkboxes where the row and + * column provide the context. The tooltip will include the title and + * required marker. + * - description: (optional) A list of description properties containing: + * - content: A description of the form element, may not be set. + * - attributes: (optional) A list of HTML attributes to apply to the + * description content wrapper. Will only be set when description is set. + * + * @see template_preprocess_form_element() + * + * @ingroup themeable + */ +#} + + {% if label_display in ['before', 'invisible'] %} + {{ label }} + {% endif %} + {% if prefix is not empty %} + {{ prefix }} + {% endif %} + {{ children }} + {% if suffix is not empty %} + {{ suffix }} + {% endif %} + {% if label_display == 'after' %} + {{ label }} + {% endif %} + {% if description.content %} + + {{ description.content }} + + {% endif %} +