From 51d4cd99e1e00b1e4da98f21764f85a6b617881f Mon Sep 17 00:00:00 2001 From: Dave Reid Date: Wed, 1 Jun 2011 08:39:48 -0500 Subject: [PATCH] Issue #1174630: Added the HTML5 url form element. --- includes/common.inc | 3 + includes/form.inc | 57 +++++++++++++++++++++++++-- modules/aggregator/aggregator.admin.inc | 14 +----- modules/aggregator/aggregator.test | 3 +- modules/comment/comment.module | 3 - modules/profile/profile.module | 22 +++++++--- modules/simpletest/drupal_web_test_case.php | 1 + modules/system/system.module | 9 ++++ modules/update/update.manager.inc | 8 +--- 9 files changed, 86 insertions(+), 34 deletions(-) diff --git a/includes/common.inc b/includes/common.inc index 4ec37dc..6c318f6 100644 --- a/includes/common.inc +++ b/includes/common.inc @@ -6558,6 +6558,9 @@ function drupal_common_theme() { 'textfield' => array( 'render element' => 'element', ), + 'url' => array( + 'render element' => 'element', + ), 'form' => array( 'render element' => 'element', ), diff --git a/includes/form.inc b/includes/form.inc index 8f2ee26..8be2fe5 100644 --- a/includes/form.inc +++ b/includes/form.inc @@ -3635,8 +3635,59 @@ function theme_textfield($variables) { element_set_attributes($element, array('id', 'name', 'value', 'size', 'maxlength')); _form_set_class($element, array('form-text')); + $extra = form_add_autocomplete($element); + $output = ''; + + return $output . $extra; +} + +/** + * Returns HTML for an url form element. + * + * @param $variables + * An associative array containing: + * - element: An associative array containing the properties of the element. + * Properties used: #title, #value, #description, #size, #maxlength, + * #placeholder, #required, #attributes, #autocomplete_path. + * + * @ingroup themeable + */ +function theme_url($variables) { + $element = $variables['element']; + element_set_attributes($element, array('type', 'id', 'name', 'value', 'size', 'maxlength', 'placeholder')); + _form_set_class($element, array('form-text', 'form-url')); + + $extra = form_add_autocomplete($element); + $output = ''; + + return $output . $extra; +} + +/** + * Form element validation handler for #type 'url'. + * + * Note that #maxlength and #required is validated by _form_validate() already. + */ +function form_validate_url(&$element, &$form_state) { + if ($element['#value'] && !valid_url($element['#value'], TRUE)) { + form_error($element, t('The URL %url is not valid.', array('%url' => $element['#value']))); + } +} + +/** + * Return the autocompletion HTML for a form element. + * + * @param $element + * The renderable element to process for autocompletion. + * + * @return + * The rendered autocompletion element HTML, or an empty string if the field + * has no autocompletion enabled. + */ +function form_add_autocomplete(&$element) { $extra = ''; - if ($element['#autocomplete_path'] && drupal_valid_path($element['#autocomplete_path'])) { + + if (!empty($element['#autocomplete_path']) && drupal_valid_path($element['#autocomplete_path'])) { drupal_add_library('system', 'drupal.autocomplete'); $element['#attributes']['class'][] = 'form-autocomplete'; @@ -3649,9 +3700,7 @@ function theme_textfield($variables) { $extra = ''; } - $output = ''; - - return $output . $extra; + return $extra; } /** diff --git a/modules/aggregator/aggregator.admin.inc b/modules/aggregator/aggregator.admin.inc index d9039e0..f10d384 100644 --- a/modules/aggregator/aggregator.admin.inc +++ b/modules/aggregator/aggregator.admin.inc @@ -70,7 +70,8 @@ function aggregator_form_feed($form, &$form_state, stdClass $feed = NULL) { '#description' => t('The name of the feed (or the name of the website providing the feed).'), '#required' => TRUE, ); - $form['url'] = array('#type' => 'textfield', + $form['url'] = array( + '#type' => 'url', '#title' => t('URL'), '#default_value' => isset($feed->url) ? $feed->url : '', '#maxlength' => 255, @@ -133,10 +134,6 @@ function aggregator_form_feed($form, &$form_state, stdClass $feed = NULL) { */ function aggregator_form_feed_validate($form, &$form_state) { if ($form_state['values']['op'] == t('Save')) { - // Ensure URL is valid. - if (!valid_url($form_state['values']['url'], TRUE)) { - form_set_error('url', t('The URL %url is invalid. Enter a fully-qualified URL, such as http://www.example.com/feed.xml.', array('%url' => $form_state['values']['url']))); - } // Check for duplicate titles. if (isset($form_state['values']['fid'])) { $result = db_query("SELECT title, url FROM {aggregator_feed} WHERE (title = :title OR url = :url) AND fid <> :fid", array(':title' => $form_state['values']['title'], ':url' => $form_state['values']['url'], ':fid' => $form_state['values']['fid'])); @@ -241,7 +238,7 @@ function aggregator_form_opml($form, &$form_state) { '#description' => t('Upload an OPML file containing a list of feeds to be imported.'), ); $form['remote'] = array( - '#type' => 'textfield', + '#type' => 'url', '#title' => t('OPML Remote URL'), '#maxlength' => 1024, '#description' => t('Enter the URL of an OPML file. This file will be downloaded and processed only once on submission of the form.'), @@ -287,11 +284,6 @@ function aggregator_form_opml_validate($form, &$form_state) { if (empty($form_state['values']['remote']) == empty($_FILES['files']['name']['upload'])) { form_set_error('remote', t('You must either upload a file or enter a URL.')); } - - // Validate the URL, if one was entered. - if (!empty($form_state['values']['remote']) && !valid_url($form_state['values']['remote'], TRUE)) { - form_set_error('remote', t('This URL is not valid.')); - } } /** diff --git a/modules/aggregator/aggregator.test b/modules/aggregator/aggregator.test index 1ab12dc..0b4c019 100644 --- a/modules/aggregator/aggregator.test +++ b/modules/aggregator/aggregator.test @@ -629,7 +629,7 @@ class ImportOPMLTestCase extends AggregatorTestCase { $edit = array('remote' => 'invalidUrl://empty'); $this->drupalPost('admin/config/services/aggregator/add/opml', $edit, t('Import')); - $this->assertText(t('This URL is not valid.'), t('Error if the URL is invalid.')); + $this->assertText(t('This URL invalidUrl://empty is not valid.'), t('Error if the URL is invalid.')); $after = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField(); $this->assertEqual($before, $after, t('No feeds were added during the three last form submissions.')); @@ -856,4 +856,3 @@ class FeedParserTestCase extends AggregatorTestCase { $this->assertEqual('urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a', db_query('SELECT guid FROM {aggregator_item} WHERE link = :link', array(':link' => 'http://example.org/2003/12/13/atom03'))->fetchField(), 'Atom entry id element is parsed correctly.'); } } - diff --git a/modules/comment/comment.module b/modules/comment/comment.module index 60a9ca4..25d56b6 100644 --- a/modules/comment/comment.module +++ b/modules/comment/comment.module @@ -2120,9 +2120,6 @@ function comment_form_validate($form, &$form_state) { if ($form_state['values']['mail'] && !valid_email_address($form_state['values']['mail'])) { form_set_error('mail', t('The e-mail address you specified is not valid.')); } - if ($form_state['values']['homepage'] && !valid_url($form_state['values']['homepage'], TRUE)) { - form_set_error('homepage', t('The URL of your homepage is not valid. Remember that it must be fully qualified, i.e. of the form http://example.com/directory.')); - } } /** diff --git a/modules/profile/profile.module b/modules/profile/profile.module index 2374fe8..4d2beec 100644 --- a/modules/profile/profile.module +++ b/modules/profile/profile.module @@ -390,7 +390,6 @@ function profile_form_alter(&$form, &$form_state, $form_id) { } switch ($field->type) { case 'textfield': - case 'url': $form[$category][$field->name] = array( '#type' => 'textfield', '#title' => check_plain($field->title), @@ -404,6 +403,20 @@ function profile_form_alter(&$form, &$form_state, $form_id) { } break; + case 'url': + $form[$category][$field->name] = array( + '#type' => 'url', + '#title' => check_plain($field->title), + '#default_value' => isset($account->{$field->name}) ? $account->{$field->name} : '', + '#maxlength' => 255, + '#description' => _profile_form_explanation($field), + '#required' => $field->required, + ); + if ($field->autocomplete) { + $form[$category][$field->name]['#autocomplete_path'] = "profile/autocomplete/" . $field->fid; + } + break; + case 'textarea': $form[$category][$field->name] = array( '#type' => 'textarea', @@ -483,12 +496,7 @@ function _profile_update_user_fields($fields, $account) { function profile_user_form_validate($form, &$form_state) { $result = _profile_get_fields($form['#user_category'], $form['#user_category'] == 'register'); foreach ($result as $field) { - if (!empty($form_state['values'][$field->name])) { - if ($field->type == 'url' && !valid_url($form_state['values'][$field->name], TRUE)) { - form_set_error($field->name, t('The value provided for %field is not a valid URL.', array('%field' => $field->title))); - } - } - elseif ($field->required && !user_access('administer users')) { + if (empty($form_state['values'][$field->name]) && $field->required && !user_access('administer users')) { form_set_error($field->name, t('The field %field is required.', array('%field' => $field->title))); } } diff --git a/modules/simpletest/drupal_web_test_case.php b/modules/simpletest/drupal_web_test_case.php index b60c682..8e4f60b 100644 --- a/modules/simpletest/drupal_web_test_case.php +++ b/modules/simpletest/drupal_web_test_case.php @@ -2144,6 +2144,7 @@ class DrupalWebTestCase extends DrupalTestCase { case 'textarea': case 'hidden': case 'password': + case 'url': $post[$name] = $edit[$name]; unset($edit[$name]); break; diff --git a/modules/system/system.module b/modules/system/system.module index 3ebc657..f8fe223 100644 --- a/modules/system/system.module +++ b/modules/system/system.module @@ -355,6 +355,15 @@ function system_element_info() { '#theme' => 'textfield', '#theme_wrappers' => array('form_element'), ); + $types['url'] = array( + '#input' => TRUE, + '#size' => 60, + '#maxlength' => 128, + '#autocomplete_path' => FALSE, + '#process' => array('ajax_process_form'), + '#theme' => 'url', + '#theme_wrappers' => array('form_element'), + ); $types['machine_name'] = array( '#input' => TRUE, '#default_value' => NULL, diff --git a/modules/update/update.manager.inc b/modules/update/update.manager.inc index 35b2929..bde1673 100644 --- a/modules/update/update.manager.inc +++ b/modules/update/update.manager.inc @@ -486,7 +486,7 @@ function update_manager_install_form($form, &$form_state, $context) { ); $form['project_url'] = array( - '#type' => 'textfield', + '#type' => 'url', '#title' => t('Install from a URL'), '#description' => t('For example: %url', array('%url' => 'http://ftp.drupal.org/files/projects/name.tar.gz')), ); @@ -586,12 +586,6 @@ function update_manager_install_form_validate($form, &$form_state) { if (!($form_state['values']['project_url'] XOR !empty($_FILES['files']['name']['project_upload']))) { form_set_error('project_url', t('You must either provide a URL or upload an archive file to install.')); } - - if ($form_state['values']['project_url']) { - if (!valid_url($form_state['values']['project_url'], TRUE)) { - form_set_error('project_url', t('The provided URL is invalid.')); - } - } } /** -- 1.7.1