From c6aa47f1c3cdf96e069dec5d1d38319d8699be7a Mon Sep 17 00:00:00 2001
From: Dave Reid <dave@davereid.net>
Date: Tue, 31 May 2011 16:25:00 -0500
Subject: [PATCH] Issue #1174620: Added the new HTML5 emailfield element.

---
 includes/common.inc               |    3 ++
 includes/form.inc                 |   55 +++++++++++++++++++++++++++++++++++--
 includes/install.core.inc         |   11 ++-----
 modules/comment/comment.module    |    5 +---
 modules/contact/contact.pages.inc |   18 +-----------
 modules/system/system.admin.inc   |    6 +---
 modules/system/system.module      |    9 ++++++
 modules/user/user.module          |   29 +------------------
 8 files changed, 73 insertions(+), 63 deletions(-)

diff --git a/includes/common.inc b/includes/common.inc
index fbad974..2861532 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -6558,6 +6558,9 @@ function drupal_common_theme() {
     'textfield' => array(
       'render element' => 'element',
     ),
+    'email' => array(
+      'render element' => 'element',
+    ),
     'form' => array(
       'render element' => 'element',
     ),
diff --git a/includes/form.inc b/includes/form.inc
index c0e2ec7..15891ff 100644
--- a/includes/form.inc
+++ b/includes/form.inc
@@ -3635,8 +3635,48 @@ 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 = '<input' . drupal_attributes($element['#attributes']) . ' />';
+
+  return $output . $extra;
+}
+
+/**
+ * Returns HTML for an email 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_email($variables) {
+  $element = $variables['element'];
+  element_set_attributes($element, array('type', 'id', 'name', 'value', 'size', 'maxlength', 'placeholder'));
+  _form_set_class($element, array('form-text', 'form-email'));
+
+  $extra = form_add_autocomplete($element);
+  $output = '<input' . drupal_attributes($element['#attributes']) . ' />';
+
+  return $output . $extra;
+}
+
+/**
+ * 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 +3689,18 @@ function theme_textfield($variables) {
     $extra = '<input' . drupal_attributes($attributes) . ' />';
   }
 
-  $output = '<input' . drupal_attributes($element['#attributes']) . ' />';
+  return $extra;
+}
 
-  return $output . $extra;
+/**
+ * Form element validation handler for #type 'email'.
+ *
+ * Note that #maxlength and #required is validated by _form_validate() already.
+ */
+function form_validate_email(&$element, &$form_state) {
+  if ($element['#value'] && !valid_email_address($element['#value'])) {
+    form_error($element, t('The e-mail address %mail is not valid.', array('%mail' => $element['#value'])));
+  }
 }
 
 /**
diff --git a/includes/install.core.inc b/includes/install.core.inc
index a74dfdf..f838800 100644
--- a/includes/install.core.inc
+++ b/includes/install.core.inc
@@ -1682,7 +1682,7 @@ function _install_configure_form($form, &$form_state, &$install_state) {
     '#weight' => -20,
   );
   $form['site_information']['site_mail'] = array(
-    '#type' => 'textfield',
+    '#type' => 'email',
     '#title' => st('Site e-mail address'),
     '#default_value' => ini_get('sendmail_from'),
     '#description' => st("Automated e-mails, such as registration information, will be sent from this address. Use an address ending in your site's domain to help prevent these e-mails from being flagged as spam."),
@@ -1705,7 +1705,8 @@ function _install_configure_form($form, &$form_state, &$install_state) {
     '#attributes' => array('class' => array('username')),
   );
 
-  $form['admin_account']['account']['mail'] = array('#type' => 'textfield',
+  $form['admin_account']['account']['mail'] = array(
+    '#type' => 'email',
     '#title' => st('E-mail address'),
     '#maxlength' => EMAIL_MAX_LENGTH,
     '#required' => TRUE,
@@ -1784,12 +1785,6 @@ function install_configure_form_validate($form, &$form_state) {
   if ($error = user_validate_name($form_state['values']['account']['name'])) {
     form_error($form['admin_account']['account']['name'], $error);
   }
-  if ($error = user_validate_mail($form_state['values']['account']['mail'])) {
-    form_error($form['admin_account']['account']['mail'], $error);
-  }
-  if ($error = user_validate_mail($form_state['values']['site_mail'])) {
-    form_error($form['site_information']['site_mail'], $error);
-  }
 }
 
 /**
diff --git a/modules/comment/comment.module b/modules/comment/comment.module
index 60a9ca4..43b9649 100644
--- a/modules/comment/comment.module
+++ b/modules/comment/comment.module
@@ -1934,7 +1934,7 @@ function comment_form($form, &$form_state, $comment) {
 
   // Add author e-mail and homepage fields depending on the current user.
   $form['author']['mail'] = array(
-    '#type' => 'textfield',
+    '#type' => 'email',
     '#title' => t('E-mail'),
     '#default_value' => $comment->mail,
     '#required' => (!$user->uid && $anonymous_contact == COMMENT_ANONYMOUS_MUST_CONTACT),
@@ -2117,9 +2117,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 <code>http://example.com/directory</code>.'));
   }
diff --git a/modules/contact/contact.pages.inc b/modules/contact/contact.pages.inc
index 30b2825..d35e56c 100644
--- a/modules/contact/contact.pages.inc
+++ b/modules/contact/contact.pages.inc
@@ -69,7 +69,7 @@ function contact_site_form($form, &$form_state) {
     '#required' => TRUE,
   );
   $form['mail'] = array(
-    '#type' => 'textfield',
+    '#type' => 'email',
     '#title' => t('Your e-mail address'),
     '#maxlength' => 255,
     '#default_value' => $user->uid ? $user->mail : '',
@@ -117,9 +117,6 @@ function contact_site_form_validate($form, &$form_state) {
   if (!$form_state['values']['cid']) {
     form_set_error('cid', t('You must select a valid category.'));
   }
-  if (!valid_email_address($form_state['values']['mail'])) {
-    form_set_error('mail', t('You must enter a valid e-mail address.'));
-  }
 }
 
 /**
@@ -203,7 +200,7 @@ function contact_personal_form($form, &$form_state, $recipient) {
     '#required' => TRUE,
   );
   $form['mail'] = array(
-    '#type' => 'textfield',
+    '#type' => 'email',
     '#title' => t('Your e-mail address'),
     '#maxlength' => 255,
     '#default_value' => $user->uid ? $user->mail : '',
@@ -242,17 +239,6 @@ function contact_personal_form($form, &$form_state, $recipient) {
 }
 
 /**
- * Form validation handler for contact_personal_form().
- *
- * @see contact_personal_form()
- */
-function contact_personal_form_validate($form, &$form_state) {
-  if (!valid_email_address($form_state['values']['mail'])) {
-    form_set_error('mail', t('You must enter a valid e-mail address.'));
-  }
-}
-
-/**
  * Form submission handler for contact_personal_form().
  *
  * @see contact_personal_form()
diff --git a/modules/system/system.admin.inc b/modules/system/system.admin.inc
index 9e7d69d..4d0accd 100644
--- a/modules/system/system.admin.inc
+++ b/modules/system/system.admin.inc
@@ -1465,7 +1465,7 @@ function system_site_information_settings() {
     '#description' => t("How this is used depends on your site's theme."),
   );
   $form['site_information']['site_mail'] = array(
-    '#type' => 'textfield',
+    '#type' => 'email',
     '#title' => t('E-mail address'),
     '#default_value' => variable_get('site_mail', ini_get('sendmail_from')),
     '#description' => t("The <em>From</em> address in automated e-mails sent during registration and new password requests, and other notifications. (Use an address ending in your site's domain to help prevent this e-mail being flagged as spam.)"),
@@ -1519,10 +1519,6 @@ function system_site_information_settings() {
  * Validates the submitted site-information form.
  */
 function system_site_information_settings_validate($form, &$form_state) {
-  // Validate the e-mail address.
-  if ($error = user_validate_mail($form_state['values']['site_mail'])) {
-    form_set_error('site_mail', $error);
-  }
   // Check for empty front page path.
   if (empty($form_state['values']['site_frontpage'])) {
     // Set to default "node".
diff --git a/modules/system/system.module b/modules/system/system.module
index 3ebc657..8c88843 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['email'] = array(
+    '#input' => TRUE,
+    '#size' => 60,
+    '#maxlength' => 128,
+    '#autocomplete_path' => FALSE,
+    '#process' => array('ajax_process_form'),
+    '#theme' => 'email',
+    '#theme_wrappers' => array('form_element'),
+  );
   $types['machine_name'] = array(
     '#input' => TRUE,
     '#default_value' => NULL,
diff --git a/modules/user/user.module b/modules/user/user.module
index ffd170c..c61bfc0 100644
--- a/modules/user/user.module
+++ b/modules/user/user.module
@@ -631,28 +631,6 @@ function user_validate_name($name) {
 }
 
 /**
- * Validates a user's email address.
- *
- * Checks that a user's email address exists and follows all standard
- * validation rules. Returns error messages when the address is invalid.
- *
- * @param $mail
- *   A user's email address.
- *
- * @return
- *   If the address is invalid, a human-readable error message is returned.
- *   If the address is valid, nothing is returned.
- */
-function user_validate_mail($mail) {
-  if (!$mail) {
-    return t('You must enter an e-mail address.');
-  }
-  if (!valid_email_address($mail)) {
-    return t('The e-mail address %mail is not valid.', array('%mail' => $mail));
-  }
-}
-
-/**
  * Validates an image uploaded by a user.
  *
  * @see user_account_form()
@@ -1007,7 +985,7 @@ function user_account_form(&$form, &$form_state) {
   );
 
   $form['account']['mail'] = array(
-    '#type' => 'textfield',
+    '#type' => 'email',
     '#title' => t('E-mail address'),
     '#maxlength' => EMAIL_MAX_LENGTH,
     '#description' => t('A valid e-mail address. All e-mails from the system will be sent to this address. The e-mail address is not made public and will only be used if you wish to receive a new password or wish to receive certain news or notifications by e-mail.'),
@@ -1197,10 +1175,7 @@ function user_account_form_validate($form, &$form_state) {
     form_set_value($form['account']['mail'], $mail, $form_state);
 
     // Validate the e-mail address, and check if it is taken by an existing user.
-    if ($error = user_validate_mail($form_state['values']['mail'])) {
-      form_set_error('mail', $error);
-    }
-    elseif ((bool) db_select('users')->fields('users', array('uid'))->condition('uid', $account->uid, '<>')->condition('mail', db_like($form_state['values']['mail']), 'LIKE')->range(0, 1)->execute()->fetchField()) {
+    if ((bool) db_select('users')->fields('users', array('uid'))->condition('uid', $account->uid, '<>')->condition('mail', db_like($form_state['values']['mail']), 'LIKE')->range(0, 1)->execute()->fetchField()) {
       // Format error message dependent on whether the user is logged in or not.
       if ($GLOBALS['user']->uid) {
         form_set_error('mail', t('The e-mail address %email is already taken.', array('%email' => $form_state['values']['mail'])));
-- 
1.7.1

