返回 登录
32

我与<input>不得不说的事儿

阅读28007

有人擅长木匠活,有人擅长织毛衣。有人习惯避开90年代留下的HTML规则,可偏偏我就不是这种人。本文就来讲一个我和input之间的故事:<input>是如何变成了一个混蛋的,以及它必死的原因。

早年历史

1995年是值得大书特书的一年。《老友记》,《急诊室的故事》,《希娜》火了起来。TLC凭借一首《Waterfalls》跃居榜首。浏览器是好的,因为HTML很好。那时候有Mosaic,网景(Netscape),和IE1,HTML2规范正在标准化。1995年也正是input标签诞生的一年,现在它已经这么老了!都可以为它的年龄干一杯了,现在的确值得来好好谈一谈。

input诞生时有八种类型:text, password, checkbox, radio, image, hidden, submit 和 reset,随后的一个RFC添加了file类型。

等等,你说……image?好吧,我们来谈谈这个。

<input type="image" src="cat.png">看起来像一个图片,但是实际上是一个图片按钮,点击时会提交(x,y)坐标,表示你点击的图片的位置。如果不指定src,按钮会显示“Submit”。如果使用的是火狐,会显示”Submit Query”,如果使用IE,什么都不会显示。

另外,type=input在默认情况下只是一个空文本框,在Chrome,Safari和火狐浏览器中的指示信息分别是”No file chosen”、 “no file selected”和”No file selected”。

黑马<textarea>

我一直认为,input和textarea是不同时期的产物,这样可以解释他们为何如此大相径庭。这种说法从某种意义上也讲得通,input是从1993年在Mosaic上开始出现的,是INSIDE改进的版本。他们都是HTML2的产物。HTML2标准规定,input是一个自关闭的标签,拥有一个value属性,而textarea则需要关闭,有自己的内容数据。他们的作用都是呈现可供编辑的文本框:

<input value="batman">
<textarea rows="1">batman</textarea>

update:有网友指出,<textarea>支持多行,但是换行符不能在value属性中表示,所以它就采用了需要关闭的标签,中间包裹内容数据的方式。这就说的通了。

1995-2011,缓慢发展的几年

1999年,HTML4只添加了type="button".我最喜欢的特性是,在没有自定义style的时候,将 <input type="button"><input type="button" value="Submit">写在同一行,在Chrome/Safari/Edge浏览器中看起来不是垂直排列的:

然后一切都开始变糟了……

后来,2011年HTML5的input添加了大量的类型。但是现在已经2015年了,大部分都还没实现。这份“太长不看”的特性列表简单来说,有下面几点:type=color只适用于Firefox/Chrome,date/time的input只能在Chrome/Edge/iOS上正常工作,还有,所有Chrome支持的特性Opera都支持。这里有一个所有input的demo

下面我们来说点有意思的。

<input type="search">对于padding,border还有20世纪那该死的圆边风格的边框有些随意,在各个浏览器中的显示效果完全是不可控制的

如果你幸运地使用了一个支持type="date"的浏览器,不用担心输入日期的样式——::webkit预设了八种选择器,但是只可以用于input输入框的样式,而不能用于下拉菜单。毕竟,CSS对你的身体不好。

当你觉得不能更糟的时候,JavaScript来了

我了解所有CSS的古怪地方。我用Chrome工作了两年,现在就靠着Blink团队旁工作,我知道我们所写的各种渲染器都存在着各种各样的bug。然而,<input>的API并不古怪——它只是一罐子蜘蛛,当你打开罐子的那一瞬间,一切都太迟了。你被蜘蛛淹没了,就连你的猫都成了蜘蛛。最好放把火吧。

从1995年开始,input的radio类型和checkbox类型有了额外的属性checked,来判定是否选择的状态。这也意味着,所有别的input类型也有了这种属性,HTMLInputElement可以包含HTMLInputElement,然后这一个里面又可以包含HTMLInputElement。所以下面这段代码可以工作,即使毫无意义。

var textInput = document.querySelector('input[type="text"]');
console.log(textInput.checked);  // prints false.
textInput.checked = true;
console.log(textInput.checked);  // prints true.
// 没有打开潘多拉.

酷。

input里也有文本,文本可以被选择。所以HTMLInputElement原型可以定义两种属性selectionStartselectionEnd,定义选择区域:

document.querySelector(‘input’).selectionStart += 2;

这段代码会事先在文本区域选择两个字符。但是只对text,urlpassword有用,对于别的类型,会抛出一个异常:

Uncaught DOMException: Failed to read the 'selectionStart'
property from 'HTMLInputElement': The input element's type ('number')
does not support selection.

即使文本可以被选择:

所以这些无关紧要的特性在某些情况下能正常工作,有时候就不能。很好地破坏了API的一致性。

事情还要复杂的多。重点是,都过去21年了,浏览器在input上都没有统一,在“如何表示用户没有选择文件”上都没有达成共识。

现在来想象一下,将来所有的Web组件都提供了原生支持,出现了一种新的标准<better-input>,真正包含DOM元素,而不再是div的大锅粥。想象一下<better-input>在所有浏览器的样式都统一,在任何地方看起来都一样。好好做个美梦吧~ ✨


原文链接:<input> I ♡ you, but you’re bringing me down
编译:赖信涛,关注Python,喜欢编程和电子游戏。个人博客:http://www.kawabangga.com/

评论