From e0834ecdbf961ac6a19f60dc72588165aa2e8e86 Mon Sep 17 00:00:00 2001 From: Aryeh Gregor Date: Fri, 7 Aug 2009 03:32:20 +0000 Subject: [PATCH] Start using some HTML 5 form features autofocus attribute added in some places; this looks like it's respected by both recent Opera and recent WebKit. Its function is self-explanatory. :) I used this in a few obvious places like Special:UserLogin and Special:ResetPass to focus the first field in the form. Could be used in other places too: Special:Search, etc. required attribute added in some places. This is only supported in recent Opera at the moment. Also self-explanatory: it won't allow form submission if the field is empty. For stuff using HTMLForm (i.e., Special:Preferences), validation will be done for integers and floats. Browsers that support this (recent Opera) will not allow non-integers to be submitted for integer fields, will not allow non-floating-point values to be submitted for float fields, and will enforce any min/max values specified. Opera also gives little up and down arrows to allow the user to increment/decrement the value in addition to letting them edit the field as text. For HTMLForm and account creation, the email input type is used for e-mails. This enforces a sane set of values for e-mails (alphanumerics plus some ASCII punctuation, with an @ in it). Again, this is supported only by recent Opera (yay Opera!). Note that this is actually more restrictive than what we currently check for on the server side; it might be sane to tighten up our server-side checks to forbid e-mail addresses that HTML 5 forbids. In all cases, the extra features aren't added if $wgHtml5 is false, and will be ignored by non-supporting browsers. The major room for further improvement here is use of the pattern attribute. We can have the client refuse to submit the form unless it matches a regex! The HTML 5 spec says that if a title attribute is provided, it should be a message that explains what the valid values are and browsers should provide it to the user if the regex doesn't match, so it's not a usability problem. I didn't bother adding that anywhere at this point because it would require adding new messages, but it should be easy to do. Note of course that HTMLForm should be updated to verify that pattern matches on the server side as well -- this way we have a clean, unified way of ensuring that our client and server checks are the same. --- RELEASE-NOTES | 8 +++++- includes/HTMLForm.php | 40 ++++++++++++++++++++++++-- includes/Preferences.php | 2 +- includes/specials/SpecialResetpass.php | 12 +++++++- includes/templates/Userlogin.php | 30 +++++++++++++++---- 5 files changed, 81 insertions(+), 11 deletions(-) diff --git a/RELEASE-NOTES b/RELEASE-NOTES index f7a37001aa..d4fb8c007e 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -71,7 +71,6 @@ this. Was used when mwEmbed was going to be an extension. interface will not appear in Special:AllMessages. * $wgRegisterInternalExternals can be used to record external links pointing to same server -* $wgHtml5 outputs an HTML 5 doctype instead of XHTML 1.0 Transitional. * $wgSpecialVersionExtended shows the extended version information besides PHP and database version. * $wgSecondaryGoNamespaces allows an arry of namespaces to be checked when the @@ -188,6 +187,13 @@ this. Was used when mwEmbed was going to be an extension. * wgMainPageTitle variable now available to JavaScript code to identify the main page link, so it doesn't have to be extracted from the link URLs. * (bug 16836) Display preview of signature in user preferences and describe its use +* The default output format is now HTML 5 instead of XHTML 1.0 Transitional. + This can be disabled by setting $wgHtml5 = false;. Specific features enabled + if HTML 5 is used: +** New HTML 5 input attributes allow JavaScript-free input validation in some + cutting-edge browsers. E.g., some inputs will be autofocused, users will + not be allowed to submit forms with certain types of invalid values (like + numbers outside the permitted ranges), etc. === Bug fixes in 1.16 === diff --git a/includes/HTMLForm.php b/includes/HTMLForm.php index 619a0695a7..30f85bee01 100644 --- a/includes/HTMLForm.php +++ b/includes/HTMLForm.php @@ -23,6 +23,10 @@ class HTMLForm { 'float' => 'HTMLFloatField', 'info' => 'HTMLInfoField', 'selectorother' => 'HTMLSelectOrOtherField', + # HTMLTextField will output the correct type="" attribute automagically. + # There are about four zillion other HTML 5 input types, like url, but + # we don't use those at the moment, so no point in adding all of them. + 'email' => 'HTMLTextField', ); function __construct( $descriptor, $messagePrefix ) { @@ -512,22 +516,53 @@ abstract class HTMLFormField { } class HTMLTextField extends HTMLFormField { - function getSize() { return isset( $this->mParams['size'] ) ? $this->mParams['size'] : 45; } function getInputHTML( $value ) { + global $wgHtml5; $attribs = array( 'id' => $this->mID ); if ( isset( $this->mParams['maxlength'] ) ) { $attribs['maxlength'] = $this->mParams['maxlength']; } - if( !empty( $this->mParams['disabled'] ) ) { + if ( !empty( $this->mParams['disabled'] ) ) { $attribs['disabled'] = 'disabled'; } + if ( $wgHtml5 ) { + # TODO: Enforce pattern, step, required, readonly on the server + # side as well + foreach ( array( 'min', 'max', 'pattern', 'title', 'step', + 'placeholder' ) as $param ) { + if ( isset( $this->mParams[$param] ) ) { + $attribs[$param] = $this->mParams[$param]; + } + } + foreach ( array( 'required', 'autofocus', 'multiple', 'readonly' ) + as $param ) { + if ( isset( $this->mParams[$param] ) ) { + $attribs[$param] = ''; + } + } + if ( isset( $this->mParams['type'] ) ) { + switch ( $this->mParams['type'] ) { + case 'email': + $attribs['type'] = 'email'; + break; + case 'int': + $attribs['type'] = 'number'; + break; + case 'float': + $attribs['type'] = 'number'; + $attribs['step'] = 'any'; + break; + } + } + } + return Xml::input( $this->mName, $this->getSize(), @@ -535,7 +570,6 @@ class HTMLTextField extends HTMLFormField { $attribs ); } - } class HTMLFloatField extends HTMLTextField { diff --git a/includes/Preferences.php b/includes/Preferences.php index 19e1c80670..308a9c2eaf 100644 --- a/includes/Preferences.php +++ b/includes/Preferences.php @@ -334,7 +334,7 @@ class Preferences { $defaultPreferences['emailaddress'] = array( - 'type' => $wgAuth->allowPropChange( 'emailaddress' ) ? 'text' : 'info', + 'type' => $wgAuth->allowPropChange( 'emailaddress' ) ? 'email' : 'info', 'default' => $user->getEmail(), 'section' => 'personal/email', 'label-message' => 'youremail', diff --git a/includes/specials/SpecialResetpass.php b/includes/specials/SpecialResetpass.php index dd8b9dd023..67e68b3ec4 100644 --- a/includes/specials/SpecialResetpass.php +++ b/includes/specials/SpecialResetpass.php @@ -128,14 +128,24 @@ class SpecialResetpass extends SpecialPage { } function pretty( $fields ) { + global $wgHtml5; $out = ''; foreach( $fields as $list ) { list( $name, $label, $type, $value ) = $list; if( $type == 'text' ) { $field = htmlspecialchars( $value ); } else { + $attribs = array( 'id' => $name, 'type' => $type ); + if ( $wgHtml5 ) { + # All three fields are required, and we should focus the + # first (wpPassword) + $attribs['required'] = ''; + if ( $name == 'wpPassword' ) { + $attribs['autofocus'] = ''; + } + } $field = Xml::input( $name, 20, $value, - array( 'id' => $name, 'type' => $type ) ); + $attribs ); } $out .= ''; $out .= ""; diff --git a/includes/templates/Userlogin.php b/includes/templates/Userlogin.php index 1caa7ea210..b853c8ab49 100644 --- a/includes/templates/Userlogin.php +++ b/includes/templates/Userlogin.php @@ -12,6 +12,8 @@ if( !defined( 'MEDIAWIKI' ) ) die( -1 ); */ class UserloginTemplate extends QuickTemplate { function execute() { + global $wgHtml5; + if( $this->data['message'] ) { ?>
@@ -37,7 +39,11 @@ class UserloginTemplate extends QuickTemplate { + value="text('name'); ?>" size='20'" /> @@ -109,6 +115,8 @@ class UsercreateTemplate extends QuickTemplate { } function execute() { + global $wgHtml5, $wgMinimalPasswordLength; + if( $this->data['message'] ) { ?>
@@ -132,7 +140,11 @@ class UsercreateTemplate extends QuickTemplate { + value="text('name') ?>" size='20' /> @@ -140,7 +152,11 @@ class UsercreateTemplate extends QuickTemplate { + value="" size='20' 0 ) { + echo ' required=""'; +} +?> /> data['usedomain'] ) { @@ -165,14 +181,18 @@ class UsercreateTemplate extends QuickTemplate { + size='20' 0 ) { + echo ' required=""'; +} +?> /> data['useemail'] ) { ?> - ' class='loginText' name="wpEmail" id="wpEmail" tabindex="5" value="text('email') ?>" size='20' />
-- 2.20.1