Dive Into HTML5:表单

我们都知道网页上的表单。用一个<form>标签,加上几个<input type="text">元素,可能也会有一个<input type="password">等等,最后则是一个<input type="submit">按钮。好了,这就是一个表单。

不过,你还不知道表单的另一半。HTML5 定义了一些可以用在表单中的新的输入类型。这里的“使用”,意思是你现在就可以使用它们——不需要任何技巧性代码。但是,现在也不要高兴太早,因为这些激动人心的新特性并不是每个浏览器都支持的。不过,令人欣慰的是,在现代浏览器中,你的代码可以正常工作,在早期浏览器中,你的代码还是能正常工作的,只不过不能按照新特性去显示。这意味着,这种新特性可以用于每一个浏览器,甚至 IE6(只不过有些浏览器不能正确显示罢了。所谓“不能显示”,是说不能显示出新特性,只能按照一般表单显示,并不是显示异常)。

占位文本

IE Firefox Safari Chrome Opera iPhone Android
3.7+ 4.0+ 4.0+ 11.0+ 4.0+

HTML5带来的第一个改进是输入框的占位符。只要输入框中没有文字,并且没有焦点,就可以显示占位文本。如果你点击(或者用 tab 键)输入框,占位文本就会消失。

你之前应该见过这种占位文本。例如,早期版本的 Mozilla Firefox 会在地址栏显示“Search Bookmarks and History”:

当你点击(或者使用 tab 键)到地址栏上,占位文本就会消失:

下面是我们使用占位文本的代码:

<form>
    <input name="q" placeholder="Search Bookmarks and History">
    <input type="submit" value="Search">
</form>

不支持占位文本的浏览器就会忽略这个属性。这并没有什么关系,不是吗?看看你的浏览器支不支持占位文本吧!

FAQ

Q: 我能在placeholder属性中使用 HTML 标记吗?例如,我想插入一张图片,或者改变颜色?

A:placeholder属性只能接受文本,不能是 HTML 标记。但是,有一些 CSS 扩展则允许修改某些浏览器的占位文本的样式。

自动焦点

IE Firefox Safari Chrome Opera iPhone Android
4.0+ 4.0+ 3.0+ 10.0+

我们可以使用 JavaScript 让表单的第一个输入框自动获得焦点。例如当你打开 Google.com 的主页时,搜索输入框就会自动获得焦点。这种特性对于大多数人都很方便,但是可能惹恼另外一些人。他们可能会有特殊需求。如果你希望按下空格键向下滚动页面,但是当焦点在输入框时,就无法达到这一目的。(此时只会在输入框输入空格,而不是滚动页面。)当你在页面仍然在加载的时候,将焦点放在另一个输入框上时,网站的自动焦点脚本就会画蛇添足地将焦点移回到最初的输入框。这无疑会打断你的流程,让你在错误的地方输入文字。

由于这种自动焦点是有 JavaScript 实现的,有时就会有一些边界问题。另外还有一些人根本不希望你的页面“绑架”了焦点。

为解决这个问题,HTML5 为所有表单控件引入了autofocus属性。autofocus属性同我们说起的这个功能很类似:当页面加载完毕时,它将输入焦点移动到一个指定的输入框。但是,因为这是一个标记的属性,而不是脚本,因此其行为对所有 web 站点都是一致的。并且,浏览器扩展开发人员也可以提供一种禁止这种 autofocus 行为的插件。

下面是如何使用 autofocus 的一个例子:

<form>
    <input name="q" autofocus>
    <input type="submit" value="Search">
</form>

对于不支持autofocus属性的浏览器则会忽略这个属性。下面来看看你的浏览器是不是支持 autofocus 吧!

什么?你想让 autofocus 域能够在所有浏览器都正常运行,不仅仅是支持 HTML5 的浏览器?那么,你仍然可以使用 autofocus 脚本,但是需要做两个小的改动:

  1. 为 HTML 标签添加autofocus属性;
  2. 检测浏览器是否支持autofocus属性,仅当浏览器不支持aotufocus属性时才运行你自己编写的脚本。

来看一个简单的例子:

<form name="f">
    <input id="q" autofocus>
    <script>
        if (!("autofocus" in document.createElement("input"))) {
            document.getElementById("q").focus();
        }
    </script>
    <input type="submit" value="Go">
</form>
...

尽早设置焦点

很多 web 页面等到window.onload发出之后才去设置焦点。但是,window.onload事件只有当所有图像都加载完毕之后才会发出。如果你的页面有大量图像,那么,这么一段脚本(也就是通过监听window.onload事件设置焦点)可能会在用户已经开始与页面交互之后又重新设置了焦点。这就是为什么高级用户痛恨这种 autofocus 脚本。

而我们前面给出的例子则是将 autofocus 脚本放到了表单域之后。这是一个完美的解决方案,但是它要求你必须将 JavaScript 脚本放置在页面中间。(有些后端系统甚至不允许你这么做。)如果你不能在页面中间插入脚本,你应该使用诸如 jQuery 的$(document).ready()这样的事件,来替代window.onload

<head>
    <script src=jquery.min.js></script>
    <script>
        $(document).ready(function() {
            if (!("autofocus" in document.createElement("input"))) {
                $("#q").focus();
            }
        });
    </script>
</head>
<body>
    <form name="f">
    <input id="q" autofocus>
    <input type="submit" value="Go">
</form>

jQuery 在页面 DOM 可用时就会发出自定义的 ready 事件。所谓“DOM 可用”,也就是页面的文本加载完毕,但是图像并不一定加载完毕。这不是一个很好的实现——如果页面异常得大,或者是网络连接异常得慢,用户可能在你的脚本执行之前就与页面交互了。但是,这也比等待window.onload事件发出要好得多。

如果你愿意,并且能够将一段独立的脚本插入到页面标记之中,那么还有一种折中的解决方案。你可以使用 jQuery 的自定义事件来创建一个自己的事件,比如说 autofocus_ready。然后在 autofocus 表单域可用的时候手动发出这个事件。感谢 E. M. Sternberg 告诉我这种技术。

<head>
    <script src=jquery.min.js></script>
    <script>
        $(document).bind('autofocus_ready', function() {
            if (!("autofocus" in document.createElement("input"))) {
                $("#q").focus();
            }
        });
    </script>
</head>
<body>
    <form name="f">
    <input id="q" autofocus>
    <script>$(document).trigger('autofocus_ready');</script>
    <input type="submit" value="Go">
</form>

这种实现几乎和第一种一样好。它在表单域可用时设置其焦点,而此时,页面文本依然在加载过程中。但是这种实现将你的应用程序逻辑(也就是设置表单域的焦点)从 body 移到 head 中。这个例子使用的是 jQuery,但是自定义事件的概念并不是 jQuery 所特有的。其他 JavaScript 库,例如 YUI 和 Dojo 也提供了类似的功能。

总结一下:

  • 恰当地设置焦点很重要;
  • 如果可能,就要让浏览器去设置焦点,使用的是表单域的autofocus属性;
  • 如果你希望兼容老版本的浏览器,首先检测它是不是支持autofocus属性,确保仅在不支持autofocus属性的浏览器上才运行这段脚本;
  • 尽早设置焦点。在表单域标记后插入脚本。如果你不喜欢这么做,那就使用一个支持自定义事件的 JavaScript 库,在表单域标记后立刻发出一个自定义事件。如果还不行,使用类似 jQuery 的$(document).ready()这样的事件;
  • 下下策是在window.onload事件发出之后设置焦点。

One Response

  1. 林宜萍 2016年12月8日

Leave a Reply