diff --git a/core/includes/form.inc b/core/includes/form.inc index 969e60aed20edbaa9459c578d8bdd76cf3105b02..dcb5e6cd37304b059d55c72ee886d0effe8f09c0 100644 --- a/core/includes/form.inc +++ b/core/includes/form.inc @@ -1942,6 +1942,15 @@ function _form_builder_handle_input_element($form_id, &$element, &$form_state) { } } + // The 'required' attribute should only be printed when #required is true. + // The presence of a boolean attribute on an element represents the true + // value, and the absence of the attribute represents the false value. + // http://www.w3.org/TR/html5/common-microsyntaxes.html#boolean-attribute. + if (!empty($element['#required'])) { + $element['#attributes']['required'] = 'required'; + $element['#attributes']['aria-required'] = 'true'; + } + // With JavaScript or other easy hacking, input can be submitted even for // elements with #access=FALSE or #disabled=TRUE. For security, these must // not be processed. Forms that set #disabled=TRUE on an element do not diff --git a/core/modules/simpletest/tests/form.test b/core/modules/simpletest/tests/form.test index 94dfa8749e16f0a5fa510f3292fde0965035bd2c..c2185e8600a0e38ba2d077c0f3cbb6f119a56491 100644 --- a/core/modules/simpletest/tests/form.test +++ b/core/modules/simpletest/tests/form.test @@ -366,6 +366,29 @@ class FormsTestCase extends DrupalWebTestCase { $this->drupalPost(NULL, array('checkboxes[one]' => TRUE, 'checkboxes[two]' => TRUE), t('Submit')); $this->assertText('An illegal choice has been detected.', t('Input forgery was detected.')); } + + /** + * Tests required attribute. + */ + function testRequiredAttribute() { + $this->drupalGet('form-test/required-attribute'); + $expected = 'required'; + // Test to make sure the elements have the proper required attribute. + foreach (array('textfield', 'password') as $type) { + $element = $this->xpath('//input[@id=:id and @required=:expected]', array( + ':id' => 'edit-' . $type, + ':expected' => $expected, + )); + $this->assertTrue(!empty($element), t('The @type has the proper required attribute.', array('@type' => $type))); + } + + // Test to make sure textarea has the proper required attribute. + $element = $this->xpath('//textarea[@id=:id and @required=:expected]', array( + ':id' => 'edit-textarea', + ':expected' => $expected, + )); + $this->assertTrue(!empty($element), t('Placeholder text placed in textarea.')); + } } /** diff --git a/core/modules/simpletest/tests/form_test.module b/core/modules/simpletest/tests/form_test.module index 5e3fb173ed9b28aae53c47fd315e7a7f2440b564..ed52b8fd4bda4ac72cb011f1d0bffa73c286f571 100644 --- a/core/modules/simpletest/tests/form_test.module +++ b/core/modules/simpletest/tests/form_test.module @@ -210,6 +210,13 @@ function form_test_menu() { 'type' => MENU_CALLBACK, ); + $items['form-test/required-attribute'] = array( + 'title' => 'Required', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('form_test_required_attribute'), + 'access callback' => TRUE, + ); + return $items; } @@ -1683,3 +1690,18 @@ function form_test_checkboxes_zero($form, &$form_state, $json = TRUE) { function _form_test_checkboxes_zero_no_redirect($form, &$form_state) { $form_state['redirect'] = FALSE; } + +/** + * Builds a form to test the placeholder attribute. + */ +function form_test_required_attribute($form, &$form_state) { + foreach (array('textfield', 'textarea', 'password') as $type) { + $form[$type] = array( + '#type' => $type, + '#required' => TRUE, + '#title' => $type, + ); + } + + return $form; +}