diff --git a/core/includes/form.inc b/core/includes/form.inc index a12fb34..2b40109 100644 --- a/core/includes/form.inc +++ b/core/includes/form.inc @@ -1727,6 +1727,7 @@ function form_builder($form_id, &$element, &$form_state) { '#required' => FALSE, '#attributes' => array(), '#title_display' => 'before', + '#description_position' => 'after', ); // Special handling if we're on the top level form element. @@ -3837,7 +3838,9 @@ function theme_file($variables) { * - form-disabled: Only set if the form element is #disabled. * * In addition to the element itself, the DIV contains a label for the element - * based on the optional #title_display property, and an optional #description. + * based on the optional #title_display property, and an optional #description, + * that can be output before or after the field depending on the + * #description_position property. * * The optional #title_display property can have these values: * - before: The label is output before the element. This is the default. @@ -3863,11 +3866,19 @@ function theme_file($variables) { * but the parent element should have neither. Use this carefully because a * field without an associated label can cause accessibility challenges. * + * The optional #description_position property can have these values: + * - before: The description is output before the element. + * - after: The description is output after the element. + * + * If the #description property is not set, the description will not be output, + * regardless of the #description_position value. + * The default value of #description_position is 'after'. + * * @param $variables * An associative array containing: * - element: An associative array containing the properties of the element. - * Properties used: #title, #title_display, #description, #id, #required, - * #children, #type, #name. + * Properties used: #title, #title_display, #description, #description_position, + * #id, #required, #children, #type, #name. * * @ingroup themeable */ @@ -3880,6 +3891,7 @@ function theme_form_element($variables) { // may not necessarily have been processed by form_builder(). $element += array( '#title_display' => 'before', + '#description_position' => 'after', ); // Add element #id for #type 'item'. @@ -3911,10 +3923,16 @@ function theme_form_element($variables) { case 'before': case 'invisible': $output .= ' ' . theme('form_element_label', $variables); + if (!empty($element['#description']) && $element['#description_position'] == 'before') { + $output .= '
' . $element['#description'] . "
\n"; + } $output .= ' ' . $prefix . $element['#children'] . $suffix . "\n"; break; case 'after': + if (!empty($element['#description']) && $element['#description_position'] == 'before') { + $output .= '
' . $element['#description'] . "
\n"; + } $output .= ' ' . $prefix . $element['#children'] . $suffix; $output .= ' ' . theme('form_element_label', $variables) . "\n"; break; @@ -3926,7 +3944,7 @@ function theme_form_element($variables) { break; } - if (!empty($element['#description'])) { + if (!empty($element['#description']) && $element['#description_position'] == 'after') { $output .= '
' . $element['#description'] . "
\n"; } diff --git a/core/modules/simpletest/tests/form.test b/core/modules/simpletest/tests/form.test index 70ebf86..ff3b6d8 100644 --- a/core/modules/simpletest/tests/form.test +++ b/core/modules/simpletest/tests/form.test @@ -653,6 +653,13 @@ class FormsElementsLabelsTestCase extends DrupalWebTestCase { $elements = $this->xpath('//div[@id="form-test-textfield-title-suffix"]/preceding-sibling::div[contains(@class, \'form-item-form-textfield-test-title\')]'); $this->assertTrue(isset($elements[0]), t("Properly places the #suffix element before the form item.")); + + // Check #description placement depending on the #description_position value. + $elements = $this->xpath('//div[@class="form-item form-type-textfield form-item-form-textfield-test-description-after"]/input[@id="edit-form-textfield-test-description-after"]/following-sibling::div[@class="description"]'); + $this->assertTrue(isset($elements[0]), t("Properly places the #description element after the form item.")); + + $elements = $this->xpath('//div[@class="form-item form-type-textfield form-item-form-textfield-test-description-before"]/input[@id="edit-form-textfield-test-description-before"]/preceding-sibling::div[@class="description"]'); + $this->assertTrue(isset($elements[0]), t("Properly places the #description element before the form item.")); } } diff --git a/core/modules/simpletest/tests/form_test.module b/core/modules/simpletest/tests/form_test.module index 0393b18..17dbe58 100644 --- a/core/modules/simpletest/tests/form_test.module +++ b/core/modules/simpletest/tests/form_test.module @@ -755,6 +755,20 @@ function form_label_test_form() { '#type' => 'textfield', ); + $form['form_textfield_test_description_before'] = array( + '#type' =>'textfield', + '#title' => t('Textfield test for description before element'), + '#description' => t('Textfield test for description before element'), + '#description_position' => 'before' + ); + + $form['form_textfield_test_description_after'] = array( + '#type' =>'textfield', + '#title' => t('Textfield test for description after element'), + '#description' => t('Textfield test for description after element'), + '#description_position' => 'after' + ); + return $form; } diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php index 0684f26..5a6469d 100644 --- a/core/modules/system/system.api.php +++ b/core/modules/system/system.api.php @@ -226,6 +226,8 @@ function hook_cron_queue_info_alter(&$queues) { * - "#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(). + * - "#description_position": optional string indicating how the #description should + * be displayed, see theme_form_element(). * * @see hook_element_info_alter() * @see system_element_info()