更多字段类型与客户端数据验证

本文介绍多行文本(textarea)、列表(select)和按钮(button)元素,以及如何在客户端对表单数据进行基本的验证工作,并可以通过样式突出显示错误的数据。

多行文本

表单中,多行文本使用textarea元素实现,其中,<textarea>标记常用的属性包括:

  • id和name,指定元素的ID和名称。
  • cols,指定元素的宽度,单位为字符数量。
  • rows,指定元素的高度,单位为行。
  • maxlength,指定最多允许的字符数,此属性在HTML5标准中添加到textarea元素中,在早期HTML表单中,需要配合JavaScript代码控制字符数量。

下面的代码演示了textarea元素的应用。

HTML
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <style>
        .button1 {
            border: 1px solid #f5f5f5;
            border-radius: 1em;
            background-image: linear-gradient(#fafafa,orange);
            font-size: 0.9em;
            padding: 0.5em 1.5em;
            color: #333;
        }
        textarea {
            vertical-align:top;
        }
    </style>
</head>
<body>
<form action="test.aspx">
<p>
    <label for="comment">说明</label>
    <textarea id="comment" name="comment" cols="40" rows="5" maxlength="100">
</textarea>
</p>
<p>
    <input type="submit" value="提交表单" class="button1" />
</p>
</form>
</body>
</html>

由于textarea元素默认会与label底部(bottom)对齐,所以在style元素中添加了textarea元素的垂直对齐为顶部对齐。Chrome浏览器中的显示效果如下图所示。

textarea

列表

使用select和option元素可以创建下拉列表和普通列表,其中,<select>标记中的常用属性包括:

  • id和name,指定元素的ID和名称。
  • size,指定列表显示的高度尺寸,单位为行,如果设置1则显示为下拉列表,大于1时显示为普通列表。

option元素定义在select元素中,用于创建列表项。下面代码演示了下拉列表的应用。

HTML
<form action="test.aspx">
    <p>
        <label for="sex">请选择性别</label>
        <select id="sex" name="sex" size="1">
            <option value="0">保密</option>
            <option value="1">男</option>
            <option value="2">女</option>
        </select>
    </p>
    <p>
        <input type="submit" value="提交表单" class="button1" />
    </p>
</form>

下图显示了点击向下箭头显示列表后的效果。

下拉列表

点击“提交表单”按钮后,列表元素会向服务器提交选中列表项中value属性的值,本例中,“保密”为0,男为1,女为2。此外,如果指定默认选中的项目,可以在<option>标记中添加selected属性。

当size属性设置大于1时,会显示为普通列表,如下面的代码。

HTML
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <style>
        .button1 {
            border: 1px solid #f5f5f5;
            border-radius: 1em;
            background-image: linear-gradient(#fafafa,orange);
            font-size: 0.9em;
            padding: 0.5em 1.5em;
            color: #333;
        }
        select {
            vertical-align:top;
        }
    </style>
</head>
<body>
<form action="test.aspx">
    <p>
        <label for="merchandise">请选择商品</label>
        <select id="merchandise" name="merchandise" size="6">
            <option value="101">大米</option>
            <option value="102">小米</option>
            <option value="103">面粉</option>
            <option value="201">上海青</option>
            <option value="202">大白菜</option>
            <option value="203">白萝卜</option>
        </select>
    </p>
    <p>
        <input type="submit" value="提交表单" class="button1" />
    </p>
</form>
</body>
</html>

本例,同样将select元素的垂直对齐设置为顶部对齐,页面显示效果如下图所示。

列表

如果允许多选,可以在<select>标记中添加multiple属性,选中多个列表项时,提交的数据为逗号分隔的列表项(option)的value属性值,操作效果如下图所示。

列表多选

上例中的商品分为两类,此时,还可以使用optgroup元素将列表项分组,如下面的代码。

HTML
<form action="test.aspx">
    <p>
        <label for="merchandise">请选择商品</label>
        <select id="merchandise" name="merchandise" size="6" multiple>
            <optgroup label="主食">
                <option value="101">大米</option>
                <option value="102">小米</option>
                <option value="103">面粉</option>
            </optgroup>
            <optgroup label="蔬菜">
                <option value="201">上海青</option>
                <option value="202">大白菜</option>
                <option value="203">白萝卜</option>
            </optgroup>
        </select>
    </p>
    <p>
        <input type="submit" value="提交表单" class="button1" />
    </p>
</form>

代码中,optgroup元素可以包含一组option元素定义的列表项,<optgroup>标记中使用label属性指定分组名称,显示效果如下图所示。

列表项分组

按钮元素

button元素可以创建包含图标和文本的按钮,使得按钮样式更加多样化。与input元素创建的按钮相似,button元素同样可以使用type属性设置按钮的类型,包括:

  • submit,创建提交表单数据的按钮。
  • button,普通按钮,需要通过onclick等事件和JavaScript创建操作代码。
  • reset,创建重置表单的按钮,即字段都恢复到初始状态。

下面的代码创建了一个图片和文本的提交按钮。

HTML
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <style>
        .button2 {
            border: 1px solid #f5f5f5;
            border-radius: 0.5em;
            background-image: linear-gradient(#fafafa,orange);
            padding: 0.5em 1.5em;
            color: #333;
        }
        .button2 img {
            display: inline-block;
            height: 1em;
            vertical-align: middle;
            margin-right:2px;
        }
    </style>
</head>
<body>
<form action="test.aspx">
    <p>
        <label for="user">用户</label>
        <input id="user" name="user" maxlength="30" size="30" />
    </p>
    <p>
        <button type="submit" class="button2">
            <img alt="save" src="/img/save16.png" />提交表单
        </button>
    </p>
</form>
</body>
</html>

本例需要准备/img/save16.png图片文件,页面显示效果如下图所示。

带图标的按钮

客户端数据验证

从网页采集数据时,可以在客户端和服务器端分别进行数据验证工作。在客户端可以对数据是否为空、基本格式和规则等进行验证,而服务器端会做最终的验证,以保证存入数据库的数据真实、有效、安全。

数据字段默认值是可选(optional)的,如果字段数据不允许为空,即字段是必填项时,可以在元素中添加required属性。在CSS样式中,可以使用optional和required属性的同名伪类设置相应的样式。

对于数值类的字段,则可以通过in-range和out-of-range伪类设置数据在范围内和不在范围内的样式。

判断字段中的数据是否通过验证,可以通过valid和invalid伪类设置样式。

下面的代码会创建一个表单和一些数据字段,并进行一些验证相关的设置。

HTML
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <style>
        .button1 {
            border: 1px solid #f5f5f5;
            border-radius: 1em;
            background-image: linear-gradient(#fafafa,orange);
            font-size: 0.9em;
            padding: 0.5em 1.5em;
            color: #333;
        }
        input:required {
            background-color:lightyellow;
        }
        input:invalid{
            background-color:lightpink;
        }
    </style>
</head>
<body>
    <form action="test.aspx">
        <p>
            <label for="fullname">姓名</label>
            <input id="fullname" name="fullname" maxlength="30" required />
        </p>
        <p>
            <label for="email">电子邮箱</label>
            <input id="email" name="email" type="email" maxlength="50" size="50" required />
        </p>
        <p>
            <label for="age">年龄</label>
            <input id="age" name="age" type="number" min="16" max="100" required />
        </p>
        <p>
            <label>性别</label>
            <input id="sex_0" name="sex" type="radio" value="0" checked />
            <label for="sex_0">保密</label>
            <input id="sex_1" name="sex" type="radio" value="1" />
            <label for="sex_1">男</label>
            <input id="sex_2" name="sex" type="radio" value="2" />
            <label for="sex_2">女</label>
        </p>
        <p>
            <label for="nickname">昵称</label>
            <input id="nickname" name="nickname" maxlength="30" />
        </p>
        <p>
            <label for="mphone">手机号码</label>
            <input id="mphone" name="mphone" maxlength="11" />
        </p>
        <p>
            <input type="submit" value="提交表单" class="button1" />
        </p>
    </form>
</body>
</html>

下图显示了表单的默认状态。

表单默认状态

本例,姓名、电子邮箱、年龄为必填项,在input元素中使用了required属性,其默认背景色为浅黄色(lightyellow),但在没有通过验证时显示为浅粉色(lightpink)。此外,年龄设置了取值范围为16到100,如果数据不在范围内,同样会显示为浅粉色(lightpink)。

请注意,性别定义为单选组,在“保密”项中使用了checked属性,表示此项已选中;在单选组中设置一个默认值可以保证总是有一个可用的有效数据。

昵称和手机号码定义为可选数据项,这里显示为默认样式。

字段元素中,还可以使用正则表达式模式验证数据格式。正则表达式的模式通过元素(如input和textarea)的pattern属性定义。如下面的代码,在手机号码元素添加pattern属性,并指定手机号码的验证模式。

HTML
<p>
    <label for="mphone">手机号码</label>
    <input id="mphone" name="mphone" maxlength="11"
           pattern="^1\d{10}$"/>
</p>

代码中设置的模式为"^1\d{10}$",表示以数字1开始,以10个数字结束,这也是常见的11位手机号码格式。设置验证模式后,如果手机号码不为空也不是以1开始的11位手机号则会显示为浅粉色(lightpink),即验证不通过。

正则表达式的模式定义,可以参考如下两篇文章:

  • http://caohuayu.com/article/Article.aspx?id=a251032
  • http://caohuayu.com/article/Article.aspx?id=a261011

此外,在表单中默认启动验证,如果需要暂时取消数据验证,可以在<form>标记中添加novalidate属性。另一种跳过表单数据验证的方法是在提交按钮(type属性值等于submit的input或button元素)中添加formnovalidate属性,点击此按钮表单数据会直接提交。

自定义验证

客户端如果需要更复杂的验证算法,可以通过元素的oninput事件执行自定义验证函数,这里需要JavaScript编码。下面的代码给出一个简单的示例。

HTML
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <style>
        .button1 {
            border: 1px solid #f5f5f5;
            border-radius: 1em;
            background-image: linear-gradient(#fafafa,orange);
            font-size: 0.9em;
            padding: 0.5em 1.5em;
            color: #333;
        }
        input:required {
            background-color:lightyellow;
        }
        input:invalid {
            background-color: lightpink;
        }
    </style>
</head>
<body>
    <form action="test.aspx">
        <p>
            <label for="txt1">自定义文本验证</label>
            <input id="txt1" name="txt1" maxlength="30" required 
                   oninput="checkData(this)" />
        </p>
        <p>
            <input type="submit" value="提交表单" class="button1" />
        </p>
    </form>
</body>
</html>
<script>
    function checkData(e) {
        if (e.value.length < 3) {
            e.setCustomValidity("最少需要3个字符");
        } else {
            e.setCustomValidity("");
        }
    }
</script>

本例,在input元素中使用oninput属性设置输入时的事件响应代码,这里使用自定义的JavaScript函数checkData(),参数this表示向函数传递当前元素对象。checkData()函数中,使用元素对象的setCustomValidity()方法设置错误提示信息,为空字符串时表示没有错误。这里,使用e.value.length属性获取input元素输入的字符数,如果少于3个则验证不通过。下图显示了不输入内容和输入少于3个字符时的提示信息。

自定义验证

请注意,验证数据正确性时,需要保密的算法不应放在客户端,而是应该在服务器端进行检查和验证,因为在客户端是可以查看网页源代码的。