Issue #1174938 by ericduran, aspilicious, voxpelli, David_Rothstein, effulgentsia: Added Natively support the HTML5 #required FAPI property.

8.0.x
catch 2012-03-27 15:23:35 +09:00
parent 97674b9f05
commit d672bcc401
4 changed files with 84 additions and 3 deletions

View File

@ -3104,6 +3104,19 @@ function form_pre_render_conditional_form_element($element) {
return $element;
}
/**
* Processes a form button element.
*/
function form_process_button($element, $form_state) {
// If this is a button intentionally allowing incomplete form submission
// (e.g., a "Previous" or "Add another item" button), then also skip
// client-side validation.
if (isset($element['#limit_validation_errors']) && $element['#limit_validation_errors'] !== FALSE) {
$element['#attributes']['formnovalidate'] = 'formnovalidate';
}
return $element;
}
/**
* Sets the #checked property of a checkbox element.
*/
@ -4312,6 +4325,10 @@ function _form_set_class(&$element, $class = array()) {
// form_builder().
if (!empty($element['#required'])) {
$element['#attributes']['class'][] = 'required';
// @todo Rename the _form_set_class() function to reflect that we're setting
// non-class attributes too.
$element['#attributes']['required'] = 'required';
$element['#attributes']['aria-required'] = 'true';
}
if (isset($element['#parents']) && form_get_error($element)) {
$element['#attributes']['class'][] = 'error';

View File

@ -451,6 +451,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('The textarea has the proper required attribute.'));
}
}
/**
@ -633,6 +656,25 @@ class FormValidationTestCase extends DrupalWebTestCase {
);
$path = 'form-test/limit-validation-errors';
// Render the form, and verify that the buttons with limited server-side
// validation have the proper 'formnovalidate' attribute (to prevent
// client-side validation by the browser).
$this->drupalGet($path);
$expected = 'formnovalidate';
foreach (array('partial', 'partial-numeric-index', 'substring') as $type) {
$element = $this->xpath('//input[@id=:id and @formnovalidate=:expected]', array(
':id' => 'edit-' . $type,
':expected' => $expected,
));
$this->assertTrue(!empty($element), t('The @type button has the proper formnovalidate attribute.', array('@type' => $type)));
}
// The button with full server-side validation should not have the
// 'formnovalidate' attribute.
$element = $this->xpath('//input[@id=:id and not(@formnovalidate)]', array(
':id' => 'edit-full',
));
$this->assertTrue(!empty($element), t('The button with full server-side validation does not have the formnovalidate attribute.'));
// Submit the form by pressing the 'Partial validate' button (uses
// #limit_validation_errors) and ensure that the title field is not
// validated, but the #element_validate handler for the 'test' field

View File

@ -229,6 +229,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;
}
@ -1830,3 +1837,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 required 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;
}

View File

@ -333,7 +333,7 @@ function system_element_info() {
'#button_type' => 'submit',
'#executes_submit_callback' => TRUE,
'#limit_validation_errors' => FALSE,
'#process' => array('ajax_process_form'),
'#process' => array('form_process_button', 'ajax_process_form'),
'#theme_wrappers' => array('button'),
);
$types['button'] = array(
@ -342,7 +342,7 @@ function system_element_info() {
'#button_type' => 'submit',
'#executes_submit_callback' => FALSE,
'#limit_validation_errors' => FALSE,
'#process' => array('ajax_process_form'),
'#process' => array('form_process_button', 'ajax_process_form'),
'#theme_wrappers' => array('button'),
);
$types['image_button'] = array(
@ -350,7 +350,7 @@ function system_element_info() {
'#button_type' => 'submit',
'#executes_submit_callback' => TRUE,
'#limit_validation_errors' => FALSE,
'#process' => array('ajax_process_form'),
'#process' => array('form_process_button', 'ajax_process_form'),
'#return_value' => TRUE,
'#has_garbage_value' => TRUE,
'#src' => NULL,