Fraser Xu Thoughts on life and code.

使用HTML5建立无与伦比的表单

写在前面:一直没有好好研究过HTML的表单元素,偶然在html5rocks发现了这篇好文章,应用HTML5来建立表单元素,虽然说目前浏览器兼容性不是很好,但很多地方还是具有很高的实用价值的,于是就随便翻译了一下,“信,达,雅”没有一项达标,主要供本人学习使用,本着开源精神分享给大家,勿拍砖,欢迎转载(注明出处)。

博客这里显示demo效果不是很好,请移步至jsfiddle 获得实时效果。

简介

过去,不管是开发者还是用户都不太喜欢网页表单元素,原因在于建立表单的过程和所带来的用户体验都不能使两者满意。但是HTML5带来了新的转机。一些新的表单元素,属性,输入框类型,基于浏览器的表单验证,CSS3样式技术和表单数据对象等都使得创建表单更加容易,当然也更加充满乐趣。

浏览器支持

笔者写这篇文章的时候,各种浏览器对于所有的新表单元素,输入框元素和属性等的支持都存在很大区别。即使对于某些被浏览器所支持的特性,不同浏览器却呈现出不同的行为。浏览器对于HTML5表单的支持也正在快速的变化当中。在编写这边文章的同时,你可以查看这个表格来查看浏览器对于表单的最新支持情况。

新特性概览

新元素

HTML5对于输入框和表单引入的新元素

元素 用途 注释
progress Represents completion of a task.显示任务进度 The progress element could represent the progress of a file being uploaded.
meter Represents a scalar measurement within a known range.显示可控范围 The meter element could be used to represent something like a temperature or weight measurement.
datalist Represents a set of option elements that can be used in combination with the new list attribute for input to make dropdown menus.下拉列表显示 When the input with the associated datalist gets focus, a dropdown menu appears and contains the values from the datalist.
keygen A control for key-pair generation. When the form is submitted, the private key gets stored in the local keystore, and the public key is sent to the server.
output Displays the results of a calculation.显示计算结果 An example use of the output element could be to display the sum of the values of two input elements.

新输入框类型

HTML5引入了13种新的输入框类型。对于浏览器不支持的类型,自动显示为普通的文本输入框。

输入类型 用途 注释
tel For entering a telephone number.用于输入电话号码 tel does not enforce a particular syntax, so if you want to ensure a particular format, you can use pattern or setCustomValidity() to do additional validation.
search To prompt users to enter text that they want to search for.供用户输入搜索文字 The difference between search and text is primarily stylistic. Using an input type of search might result in the input field being styled in a way that is consistent with that platform's search fields.
url For entering a single URL.用于输入单一URL地址 url is intended for entering a single, absolute URL, which represents a pretty wide range of values.
email For entering either a single email address or a list of email addresses.单一或多个email邮箱地址 If the multiple attribute is specified, then multiple email addresses can be entered, separated by commas.
datetime For entering a date and time with the time zone set to UTC.用于输入日期时间
date For entering a date with no time zone.日期
month For entering a date with a year and a month, but no time zone.月份
week For entering a date that consists of a week-year number and a week number, but no time zone.星期 An example of this format is 2011-W05 for the fifth week of 2011.
time For entering a time value with hour, minute, seconds, and fractional seconds, but no time zone.时间
datetime-local For entering a date and time with no time zone.本地化时间
number For numerical input.数字 Valid values are floating point numbers.
range For numerical input, but unlike number, the actual is not important.范围 The implementation of the range control is a slider in most browsers that support it.
color For choosing color through a color well control.颜色 The value must be a valid lowercase simple color such as #ffffff.

新的输入框属性

HTML5同时针对输入框和表单元素引入了一些新的属性

Attribute Purpose Notes
autofocus Focuses the input on the element when the page is loaded.页面加载完毕后自动锁定至输入框 autofocus can be applied to input, select, textarea, and button.
placeholder Gives the user a hint about what sort of data they should enter.占位符 The placeholder value is displayed in light text until the element gets focus and the user enters some data. It can be specified on input and textarea.
form Specifies one or more forms to which the input element belongs.定义输入框元素 By using the form attribute, the input elements can be placed anywhere on the page, not just within the form element. Also, a single input element can be associated with more than one form.
required A boolean attribute that means the element is required.必填项 The required attribute is helpful for doing browser-based validation without using custom JavaScript.
autocomplete For specifying that a field should not autocomplete or be pre-filled by the browser based on a user's past entries.自动补全 The autocomplete attribute for fields like a credit card number or one-time password, which you don't want autocomplete. By default, autocomplete is in the on state, so if you want to disable it, set it to off.
pattern For validating an element's value against a regular expression.正则 When using a pattern, you should also specify a title value to give the user a description of the pattern that's expected.
dirname For submitting the directionality of the control with the form.文字方向 For example, if the user entered text data with right-to-left directionality and the input element contained the dirname attribute, then an indication of the right-to-left directionality would be submitted along with the input value.
novalidate For disabling form submission validation when specified on a form element.禁用验证
formaction For overriding the action attribute on the form element.覆盖表单元素的动作属性 This attribute is supported on input and button elements.
formenctype For overriding the enctype attribute on the form element.覆盖表单元素编码属性 This attribute is supported on input and button elements.
formmethod For overriding the method attribute on the form element.覆盖表单元素方法属性 This attribute is supported on input and button elements.
formnovalidate For overriding the novalidate attribute on the form element.覆盖禁用验证属性 This attribute is supported on input and button elements.
formtarget For overriding the target attribute on the form element.覆盖目标属性 This attribute is supported on input and button elements.

表单数据对象

XMLHttpRequest一项新的提升就是对FormData(表单数据)的支持。有了FormData对象,你可以使用XMLHttpRequest技术建立并发送数据,当然还有文件。在使用这项技术时,数据传输的格式和之前通过表单的submit()方法提交的格式一样。

FormData允许通过使用JavaScript来建立HTML表单,然后使用XMLHttpRequest.send()方法来提交。范例如下:

var formData = new FormData();
formData.append("part_num", "123ABC"); 
formData.append("part_price", 7.95);
formData.append("part_image", somefile)

var xhr = new XMLHttpRequest();
xhr.open("POST", "http://some.url/");  
xhr.send(formData);

你同样也可使用FormData在提交数据之前在已存在的表单里添加数据。

var formElement = document.getElementById("someFormElement");
var formData = new FormData(formElement);
formData.append("part_description", "The best part ever!");

var xhr = new XMLHttpRequest();
xhr.open("POST", "http://some.url/");
xhr.send(formData);

基于浏览器的表单验证

坦白说,表单验证令人蛋疼,但是却又不得不做。对于现在的基于客户端的表单验证,大多数人都会编写自定义的JavaScript或者使用JS库去实现表单验证,从而确定用户在提交数据之前已经在必填项填入相应数据。

新的输入框属性,例如required和pattern结合了CSS伪类选择器来简化验证和显示过程。同时也有一些高级的验证技术允许你自定义验证过程。

REQUIRED属性

如果required属性存在,在表单提交之前输入框一定要包含数据。下面就是一个使用email类型来确保用户在提交数据之前已经输入了合法的邮箱地址的例子:

<input type="email" id="email_addr" name="email_addr" required />

PATTERN属性

patterns使用了正则表达式来验证输入框区域。下面这个例子演示了在必填项输入框输入零件编号。我们要求下面输入的零件编号包含3个大写英文字母以及4个数字。required和pattern的使用确保了用户在提交数据之前已经根据要求输入了对应的数据类型。在用户鼠标悬浮在区域上时,title属性的内容将会被显示。

<input type="text" id="part" name="part" required pattern="[A-Z]{3}[0-9]{4}"
       title="Part numbers consist of 3 uppercase letters followed by 4 digits."/>

上面的例子中,我们还可以通过使用CSS来高亮显示不合法的数据类型。代码如下

:invalid {
  border: 2px solid #ff0000;
}

FORMNOVALIDATE属性

formnovalidate属性可以应用在输入框或者按钮上。如果代码中包含了该属性,用户提交验证将会被禁用。下面这个例子演示了如何实现在点击submit按钮时验证,而在点击save按钮时不进行验证。

<input type="text" id="part" name="part" required pattern="[A-Z]{3}[0-9]{4}"
       title="Part numbers consist of 3 uppercase letters followed by 4 digits."/>
<input type="submit" formnovalidate value="Save">
<input type="submit" value="Submit">

Constraint Validation API(限制验证)

Constraint Validation API提供了强大自定义表单验证方法。该API可以允许设定自定义错误,检查元素是否合法,判断元素不合法等。下面这个例子演示判断用户两次输入邮箱地址相同。

<label>Email:</label>
<input type="email" id="email_addr" name="email_addr">

<label>Repeat Email Address:</label>
<input type="email" id="email_addr_repeat" name="email_addr_repeat" oninput="check(this)">

<script>
function check(input) {
  if (input.value != document.getElementById('email_addr').value) {
    input.setCustomValidity('The two email addresses must match.');
  } else {
    // input is valid -- reset the error message
    input.setCustomValidity('');
  }
}
</script>

完整范例演示

下面这段代码演示了使用以上的技术来实现一个预定请求的表单。

$99.00

HTML和JavaScript代码如下

<form oninput="total.value = (nights.valueAsNumber * 99) + 
 ((guests.valueAsNumber - 1) * 10)">

  <label>Full name:</label>
  <input type="text" id="full_name" name="full_name" placeholder="Jane Doe" required>

  <label>Email address:</label>
  <input type="email" id="email_addr" name="email_addr" required>

  <label>Repeat email address:</label>
  <input type="email" id="email_addr_repeat" name="email_addr_repeat" required 
   oninput="check(this)">

  <label>Arrival date:</label>
  <input type="date" id="arrival_dt" name="arrival_dt" required>

  <label>Number of nights (rooms are $99.00 per night):</label>
  <input type="number" id="nights" name="nights" value="1" min="1" max="30" required>

  <label>Number of guests (each additional guest adds $10.00 per night):</label>
  <input type="number" id="guests" name="guests" value="1" min="1" max="4" required>

  <label>Estimated total:</label>
  $<output id="total" name="total">99</output>.00
  <br><br>

  <label>Promo code:</label>
  <input type="text" id="promo" name="promo" pattern="[A-Za-z0-9]{6}" 
   title="Promo codes consist of 6 alphanumeric characters.">

  <input type="submit" value="Request Reservation" /> 
</form>

<script>
function check(input) {
  if (input.value != document.getElementById('email_addr').value) {
    input.setCustomValidity('The two email addresses must match.');
  } else {
    // input is valid -- reset the error message
    input.setCustomValidity('');
  }
}
</script>

CSS代码如下:

:invalid { 
  border-color: #e88;
  -webkit-box-shadow: 0 0 5px rgba(255, 0, 0, .8);
  -moz-box-shadow: 0 0 5px rbba(255, 0, 0, .8);
  -o-box-shadow: 0 0 5px rbba(255, 0, 0, .8);
  -ms-box-shadow: 0 0 5px rbba(255, 0, 0, .8);
  box-shadow:0 0 5px rgba(255, 0, 0, .8);
}

:required {
  border-color: #88a;
  -webkit-box-shadow: 0 0 5px rgba(0, 0, 255, .5);
  -moz-box-shadow: 0 0 5px rgba(0, 0, 255, .5);
  -o-box-shadow: 0 0 5px rgba(0, 0, 255, .5);
  -ms-box-shadow: 0 0 5px rgba(0, 0, 255, .5);
  box-shadow: 0 0 5px rgba(0, 0, 255, .5);
}

form {
  width:300px;
  margin: 20px auto;
}

input {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  border:1px solid #ccc;
  font-size:20px;
  width:300px;
  min-height:30px;
  display:block;
  margin-bottom:15px;
  margin-top:5px;
  outline: none;

  -webkit-border-radius:5px;
  -moz-border-radius:5px;
  -o-border-radius:5px;
  -ms-border-radius:5px;
  border-radius:5px;
}

input[type=submit] {
  background:none;
  padding:10px;
}

原文链接:http://www.html5rocks.com/en/tutorials/forms/html5forms/

原创翻译,转载请注明出处:Coursegarden