<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>岁月如歌 &#187; google</title>
	<atom:link href="http://lifesinger.org/blog/tag/google/feed/" rel="self" type="application/rss+xml" />
	<link>http://lifesinger.org/blog</link>
	<description>关注用户体验、前端开发，记录生活点滴、岁月足迹。</description>
	<lastBuildDate>Wed, 28 Jul 2010 00:40:47 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Google Docs Ctrl + C 技术浅析</title>
		<link>http://lifesinger.org/blog/2010/07/goog-docs-copy-tech/</link>
		<comments>http://lifesinger.org/blog/2010/07/goog-docs-copy-tech/#comments</comments>
		<pubDate>Tue, 27 Jul 2010 07:42:10 +0000</pubDate>
		<dc:creator>lifesinger</dc:creator>
				<category><![CDATA[开发]]></category>
		<category><![CDATA[clipboard]]></category>
		<category><![CDATA[google]]></category>

		<guid isPermaLink="false">http://lifesinger.org/blog/?p=2657</guid>
		<description><![CDATA[用 google docs 打开 pdf 文件，选中文本： 表面上没有任何有趣的地方。但仔细一看，会发现选区的颜色是浅蓝色，而不是默认蓝。第一直觉是是有什么特殊的 CSS 属性，立马 firebug: 不看不知道，一看真蹊跷。selection-highlight 是选区，选区下面是一张图片 page-image! 于是立刻发现一个非常牛逼的特性：Ctrl + C 可以复制图片中的文字！ google 太强悍了，好在前端代码都是开源的，下面简单分析下。 首先数据在哪呢，这个比较容易找到，在 firebug 里有一个请求返回的数据如下： &#60;?xml version="1.0" encoding="UTF-8"?&#62; &#60;pdf2xml&#62; &#60;meta name="Creator" content="Adobe Acrobat 8.1 Combine Files"/&#62; &#60;meta name="Producer" content="Adobe Acrobat 8.1"/&#62; &#60;meta name="CreationDate" content="20100316080708-04'00'"/&#62; &#60;page t="0" l="0" w="612" h="773"&#62; &#60;text l="188" t="754" w="237" h="11" p="188,24,214,15,232,37,271, 7,280,39,322,7,330,11,344,24,370,23,395,20,418,7"&#62; Please post [...]]]></description>
			<content:encoded><![CDATA[<p>用 google docs 打开 pdf 文件，选中文本：<br />
<img src="http://lifesinger.org/blog/wp-content/uploads/2010/07/goog-docs-tech-01.png" width="429" height="171" /></p>
<p>表面上没有任何有趣的地方。但仔细一看，会发现选区的颜色是浅蓝色，而不是默认蓝。第一直觉是是有什么特殊的 CSS 属性，立马 firebug:<br />
<img src="http://lifesinger.org/blog/wp-content/uploads/2010/07/goog-docs-tech-02.png" width="526" height="324" /></p>
<p>不看不知道，一看真蹊跷。<code>selection-highlight</code> 是选区，选区下面是一张图片 <code>page-image</code>!<br />
于是立刻发现一个非常牛逼的特性：<strong><code>Ctrl + C</code> 可以复制图片中的文字！</strong></p>
<p>google 太强悍了，好在前端代码都是开源的，下面简单分析下。<span id="more-2657"></span></p>
<p>首先数据在哪呢，这个比较容易找到，在 firebug 里有一个请求返回的数据如下：</p>
<pre>
&lt;?xml version="1.0" encoding="UTF-8"?&gt;

&lt;pdf2xml&gt;
&lt;meta name="Creator" content="Adobe Acrobat 8.1 Combine Files"/&gt;
&lt;meta name="Producer" content="Adobe Acrobat 8.1"/&gt;
&lt;meta name="CreationDate" content="20100316080708-04'00'"/&gt;
&lt;page t="0" l="0" w="612" h="773"&gt;
 &lt;text l="188" t="754" w="237" h="11" p="188,24,214,15,232,37,271,
7,280,39,322,7,330,11,344,24,370,23,395,20,418,7"&gt;
Please post comments or corrections to the Author Online forum at&lt;/text&gt;
...
</pre>
<p>有了这份数据，就可以根据选区得到对应的文本。</p>
<p>接下来的问题是，如何将文本放到剪贴板里？第一反应是用 flash 实现，但感觉 google 不会这么做。禁用掉 flash 插件后，功能正常，这说明是用 js 实现的。</p>
<p>通过 Profile 工具 + Fiddler + 肉眼识别 + 运气，终于定位到了关键代码：</p>
<pre>
n.am = function(a) {
    if (! (!this.k.Ca &#038;&#038; Mr(this, a))) {
        ac &#038;&#038; this.lf.focus();
        this.lf.select();
        Nr(this, a)
    }
};
</pre>
<p>只要注释掉上面的代码，<code>Ctrl + C</code> 复制功能就无效。<code>focus</code> 和 <code>select</code> 为我们提供了进一步线索，在 HTML 里，发现了秘密：<br />
<img src="http://lifesinger.org/blog/wp-content/uploads/2010/07/goog-docs-tech-03.png" width="514" height="50" /></p>
<p>到此真相大白：当用户按下 <code>Ctrl + C</code> 时，js 会注入事件，首先根据坐标从数据里取出对应文本，然后将文本赋值给 textarea, 并将其激活和选中。这样，就和用户选中 textarea 的内容，再按下 <code>Ctrl + C</code> 的效果是一样了。</p>
<p>强悍的 google, 技术创新无处不在！</p>
<p>注意：利用 textarea 只能复制纯文本，如果想复制富文本，可以借鉴 google docs 编辑 Word 文档时的处理方式：采用 iframe 充当临时容器，有兴趣的可以进一步研究。</p>
<p>简单演示：<a href="http://lifesinger.github.com/lab/2010/goog-docs-copy-demo.html">goog-docs-copy-demo.html</a></p>
<p>发现这个秘密后，最近在疯狂搞编辑器的牛人<a href="http://yiminghe.javaeye.com/">承玉</a>（欢迎搞编辑器的其他牛人加盟）立刻想到了各大站长们非常喜爱的功能：<a href="http://yiminghe.javaeye.com/blog/722264">附带警告信息的禁止copy</a>. 据说，能成功复制的，都不是“人”。</p>
<p>我的尝试是：点击按钮，复制指定文本到 Clipboard 里。应用场景是点击按钮复制证件号码等。尝试代码大家可以看上面 demo 页面源码中的注释。事件可以正常模拟并分发出去，但复制操作惨兮兮地失败了。感觉原因在于浏览器安全限制，对于触发的异步 <code>Ctrl + C</code>, 浏览器会限制其功能。 </p>
<p>Google 的产品里有很多秘密，真诱人，创意无限！</p>
]]></content:encoded>
			<wfw:commentRss>http://lifesinger.org/blog/2010/07/goog-docs-copy-tech/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Closure Compiler vs. YUICompressor</title>
		<link>http://lifesinger.org/blog/2009/11/closure-compiler-vs-yuicompressor/</link>
		<comments>http://lifesinger.org/blog/2009/11/closure-compiler-vs-yuicompressor/#comments</comments>
		<pubDate>Tue, 10 Nov 2009 03:41:03 +0000</pubDate>
		<dc:creator>lifesinger</dc:creator>
				<category><![CDATA[开发]]></category>
		<category><![CDATA[closure]]></category>
		<category><![CDATA[compress]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[YUI]]></category>

		<guid isPermaLink="false">http://lifesinger.org/blog/?p=2273</guid>
		<description><![CDATA[Google Closure Compiler 挺让人心动。昨晚试用了一把，与 YUICompressor 的对比如下： 下载 DOS 脚本包：downloads list]]></description>
			<content:encoded><![CDATA[<p>Google Closure Compiler 挺让人心动。昨晚试用了一把，与 YUICompressor 的对比如下：</p>
<div style="width:510px;text-align:left" id="__ss_2462617"><object style="margin:0px" width="510" height="415"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=closure-compiler-vs-yui-compressor-091109210742-phpapp02&#038;stripped_title=closure-compiler-vs-yuicompressor" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=closure-compiler-vs-yui-compressor-091109210742-phpapp02&#038;stripped_title=closure-compiler-vs-yuicompressor" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="505" height="415"></embed></object></div>
<p>下载 DOS 脚本包：<a href="http://code.google.com/p/ourtools/downloads/list">downloads list</a></p>
]]></content:encoded>
			<wfw:commentRss>http://lifesinger.org/blog/2009/11/closure-compiler-vs-yuicompressor/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>google.com 首页代码分析</title>
		<link>http://lifesinger.org/blog/2009/06/google-com-src-study/</link>
		<comments>http://lifesinger.org/blog/2009/06/google-com-src-study/#comments</comments>
		<pubDate>Wed, 10 Jun 2009 14:44:26 +0000</pubDate>
		<dc:creator>lifesinger</dc:creator>
				<category><![CDATA[开发]]></category>
		<category><![CDATA[google]]></category>

		<guid isPermaLink="false">http://lifesinger.org/blog/?p=1834</guid>
		<description><![CDATA[机缘巧合，对 google.com 的首页代码产生了浓厚兴趣。一点“分析”，杂记如下： 不同浏览器推送不同代码 上图是在不同浏览器下，保存的 google 首页代码。 注意：文件大小是经过 IntelliJ IDEA 格式化处理后的大小。 其中 Chrome 和 Safari 的代码是一样的，Opera 仅仅一个 js 函数的写法与 Chrome 不同。差异最大的是 Firefox 和 IE。 我的想法：大部分应用场景下，针对不同浏览器实现不同版本，会增加开发和维护成本。google 首页采取这种差异化方案，很可能是考虑到要最大限度降低网页流量。毕竟对于日访问量上千万的网站来说，减少一个字符都能节约可观的流量。精简节约，在 google 首页上体现得淋漓尽致，下面会继续提及。 doctype 的写法 只有 Firefox 用了&#60;!doctype html&#62;来激活标准模式。其它浏览器下，都是简单粗暴的 Quirks 模式。 我的想法：Firefox 下也可以直接用 Quirks 模式，视觉差异上极小。不清楚 google 为何仅针对 Firefox 开启了标准模式。 值得注意的是，在 google 搜索结果页，所有浏览器下都使用了&#60;!doctype html&#62;. 毕竟结果页复杂些，依旧用 Quirks 模式的话，会增加开发成本。首页因为简单，Quirks 和 Standards 相比，没什么显著差别，因此能省就省。 关于 [...]]]></description>
			<content:encoded><![CDATA[<p>机缘巧合，对 google.com 的首页代码产生了浓厚兴趣。一点“分析”，杂记如下：</p>
<h4>不同浏览器推送不同代码</h4>
<p><img src="http://lifesinger.org/blog/wp-content/uploads/2009/06/google_src_diff.png" alt="google_src_diff.png" width="273" height="166" /></p>
<p>上图是在不同浏览器下，保存的 google 首页代码。<br />
注意：文件大小是经过 IntelliJ IDEA 格式化处理后的大小。</p>
<p>其中 Chrome 和 Safari 的代码是一样的，Opera 仅仅一个 js 函数的写法与 Chrome 不同<span id="more-1834"></span>。差异最大的是 Firefox 和 IE。</p>
<p>我的想法：大部分应用场景下，针对不同浏览器实现不同版本，会增加开发和维护成本。google 首页采取这种差异化方案，很可能是考虑到要最大限度降低网页流量。毕竟对于日访问量上千万的网站来说，减少一个字符都能节约可观的流量。精简节约，在 google 首页上体现得淋漓尽致，下面会继续提及。</p>
<h4>doctype 的写法</h4>
<p>只有 Firefox 用了<code>&lt;!doctype html&gt;</code>来激活标准模式。其它浏览器下，都是简单粗暴的 Quirks 模式。</p>
<p>我的想法：Firefox 下也可以直接用 Quirks 模式，视觉差异上极小。不清楚 google 为何仅针对 Firefox 开启了标准模式。</p>
<p>值得注意的是，在 google 搜索结果页，所有浏览器下都使用了<code>&lt;!doctype html&gt;</code>. 毕竟结果页复杂些，依旧用 Quirks 模式的话，会增加开发成本。首页因为简单，Quirks 和 Standards 相比，没什么显著差别，因此能省就省。</p>
<p>关于 doctype, 强烈推荐阅读：<a href="http://hsivonen.iki.fi/doctype/">Activating Browser Modes with Doctype</a></p>
<p>对浏览器来说，doctype 实际上仅影响浏览模式，因此能从简就从简。W3C 校验，我觉得没必要，很少关注。</p>
<h4>精简，还是精简</h4>
<p>以 Firefox 下 google 首页的源码为例：</p>
<ol>
<li>html, body 缺胳膊少腿</li>
<li>html 元素的很多属性没有用双引号括起来</li>
<li>class, id 等命名很短</li>
<li>script 和 style 元素没 type 等属性</li>
<li>没有 keywords 和 description 等 meta 值，我是搜索老大，哈哈</li>
<li>balabala 等等</li>
</ol>
<p>想起一句话：遵守规范的一个重要标准，就是知道何时打破它，并大胆地打破。从这层意义上讲，google 首页是非常遵守规范的。</p>
<h4>没有完美</h4>
<p>细心点，还可以发现：</p>
<ol>
<li>引号去得不彻底，比如<code>&lt;img alt="Google" ...</code></li>
<li>还有<code>padding-left: 0px</code>, px 可以去掉</li>
</ol>
<p>js 上，也有进一步精简的余地。比如下面两行完全一样的代码，很囧：</p>
<pre>
if(google.y) google.y.first = [];
if(google.y) google.y.first = [];
</pre>
<p>还有一段代码，div 提前到 script 前面能省去判断：</p>
<pre>
&lt;script&gt;
function wgjp() {
    var xjs = document.createElement('script');
    xjs.src = '/extern_chrome/1mZ_-PL2Zjc.js';
    (document.getElementById('xjsd') || document.body).appendChild(xjs)
};
&lt;/script&gt;
&lt;div id=xjsd&gt;&lt;/div&gt;
</pre>
<p>也许吹毛求疵了，笑过。</p>
<h4>预加载</h4>
<p>看代码：</p>
<pre>
&lt;body onload="sf();if(document.images){new Image().src='/images/nav_logo4.png'}" ...
</pre>
<p>这就是 YSlow 34条性能法则中的 <a href="http://developer.yahoo.com/performance/rules.html#preload">Preload Components</a>. google 首页提前加载了搜索结果页的 css  sprite. 另外赞一下这个 sprite 图的组织，很 cute.</p>
<h4>延迟加载</h4>
<p>看代码：</p>
<pre>
window.setTimeout(function() {
            var a = document.createElement("script");
            a.src = "/extern_js/f/.../XRt_2Y4Z5sM.js";
            (document.getElementById("xjsd") || document.body).appendChild(a)
        }, 0);
</pre>
<p>上面这个 js 挺大的，包含了 google 的 js 库和输入框的提示补全组件。这个 setTimeout 起到了将下载进程延迟到 window.onload 后。很小的代码调整，却提升了不少用户体验，实在划算。</p>
<p>另提一下，这个 js 在不同浏览器下也有不同版本，大小差异比较明显。为了尽可能减少流量，google 还真费心。</p>
<h4>奇淫技巧</h4>
<p>代码虽少，淫荡之处却摇曳生姿：</p>
<p>1. 遍历数组</p>
<pre>
for (var i = 0,c; c = ["ad","p","pa","zd","ac","pc","pah","ph","zc"][i++];) {
    // doing something, such as console.log(c)
}
</pre>
<p>2. 短路语句</p>
<pre>
function _gjp() {
    !(window._gjwl.hash &#038;&#038; window._gjuc()) &#038;&#038; setTimeout(_gjp, 500)
}
</pre>
<p>短路表达式很常用，但用短路单独做语句，还真精简。</p>
<h4>语义化</h4>
<p>从语义上讲，google 的 html 代码是比较糟糕的。但考虑到各种浏览终端，或许 google 目前的写法非常优化。没有接触过跨n &gt; 20的浏览器开发经验，对此不多说。</p>
<h4>小结</h4>
<p>从首页代码中，能看出 google 推崇的是：简单 + 实用 + 性能。我越来越认同这种观点。</p>
]]></content:encoded>
			<wfw:commentRss>http://lifesinger.org/blog/2009/06/google-com-src-study/feed/</wfw:commentRss>
		<slash:comments>40</slash:comments>
		</item>
		<item>
		<title>从谷歌的一个Bug说起，谈谈键盘事件的兼容性</title>
		<link>http://lifesinger.org/blog/2008/08/keyboard-event-compatibility/</link>
		<comments>http://lifesinger.org/blog/2008/08/keyboard-event-compatibility/#comments</comments>
		<pubDate>Tue, 26 Aug 2008 09:55:32 +0000</pubDate>
		<dc:creator>lifesinger</dc:creator>
				<category><![CDATA[思考]]></category>
		<category><![CDATA[DOM]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://lifesinger.org/blog/?p=77</guid>
		<description><![CDATA[右图是谷歌首页，当输入某个词时，会弹出自动补全提示。功能并不复杂，但到要兼容各个浏览器，谷歌为此可能花费了不少功夫。然而完美实在是很难得，仔细测试可以发现一个处理得不妥的Bug： 除了Ctrl+X/C/V，Ctrl+Z/Y也是经常使用的快捷键。在Firefox/Safari/Opera中访问谷歌，一切都很正常。但当我们打开IE浏览谷歌时，Ctrl+Z/Y不起作用了。在当今特别是中国，IE是份量最重的浏览器，谷歌首页有此问题，完全可以归为一个Bug. 这个Bug究竟是怎么引起的呢？为了进一步讨论，我们先来看看各个浏览器下，当输入法开启和未开启时，对键盘等事件的响应情况。 猛击查看 JavaScript键盘事件测试小结 通过上面这篇测试小结，我们可以看出，要实现谷歌的自动补全功能并不是一件很简单的事。目前可以找到的解决方案有： 方案一：通过监听keydown, keypress, keyup事件来实现。这是大部分JavaScript教科书里的做法，对于拉丁语系国家，是没有问题的。但输入法一开启后，一切就都不美妙了： 无论有没有输入法，通过鼠标右键粘贴复制时，key事件都触发不了，真糟糕。 输入法开启时，各个浏览器表现不同。不同输入法之间还有差异，太让人沮丧了。 输入法开启时，Opera压根不触发键盘事件。亲爱的Opera，叫我怎么爱上你？ 考虑到中文用户，特别是第一条（不少中文用户习惯使用右键菜单来粘贴复制），第一个方案基本可以枪毙掉。 方案二：不考虑这些烦人的键盘事件，直接采用定时器来实现。在输入框获取焦点时，触发定时器，失去焦点时，关闭定时器。定时器每隔200ms检查输入框的值，根据值的变化来进行下一步响应。这个trick很简单，基本上能解决大部分问题（谷歌的自动完成就是这么做的^o^）。但有以下不妥： 性能问题。（因为仅在获取焦点时触发定时器，性能问题倒是可以不考虑的） ie下，此方法会导致Ctrl+Z/Y快捷键失效。 firefox下，用定时器实现表单输入时的即时校验，当输入法开启时，如果校验函数在输入未完成时改变输入框的值，会导致输入框的值变成空。（这个属于不可忽视的Bug，很恼人） 方案二自动解决了右键菜单粘贴的问题，对于自动补全功能来说，一般应用场景下也足够用，但对谷歌来说，感觉有此Bug是不妥的。如果用方案二来实现表单输入时的即时校验，上面的第3点会导致firefox的中文用户很不爽。 苦思冥想许久，在键盘事件中折腾来折腾去，感觉怎么做都无法同时解决上面的所有不妥。昨天静下心来对所有A级浏览器的键盘事件在输入法开启和未开启时做了个仔细的测试后，下面这个方案就很清晰的浮了出来： 方案三：在上面的浏览器事件测试中，有一个很让人高兴的发现：所有浏览器中，都会触发input(ie下可以用propertychange)事件。而且input事件仅在输入框的值有变化时才会触发。在输入法开启时，input也能正常触发（虽然会触发一些冗余的input，但比起定时器来好很多）。在右键菜单粘贴等操作时，也能正确触发input. 采用input/propertychange, 几近完美。但需要注意以下几点： ie下，如果监听的事件函数中，有页面输出操作，如YAHOO.log(&#8230;), 会导致Ctrl+Z/Y失效。（深层次原因还需仔细探索，感觉页面输出操作只是表象） 对于表单输入时的即时校验来说，比如只能输入数字的输入框，当输入字母时，监听input事件的实现会在字母显示出来后，立刻又删除掉（和keyup的实现效果一样），没有监听keypress的效果好（不会先显示出来）。因此对于即时校验来说，可以结合input和keypress，在输入法未开启时，给用户更友好的体验。 最后，看一个根据方案三来实现的简单例子：表单输入时的即时校验 2008-08-28补充： oninput事件：a). 当脚本中改变value时，不会触发；b). 从浏览器的自动下拉提示中选取时，不会触发。 onpropertychange事件：当input设置为disable=true后，onpropertychange不会触发。 参考资料 很让人敬佩的鼠标事件总结：JavaScript Madness: Keyboard Events Realazy的探索：输入法下keyup失效的解决方案]]></description>
			<content:encoded><![CDATA[<p><a href="http://lifesinger.org/blog/wp-content/uploads/2008/08/google_bug.png"><img src="http://lifesinger.org/blog/wp-content/uploads/2008/08/google_bug-150x150.png" alt="点击小图看大图" title="google_bug" width="150" height="150" class="alignright size-small wp-image-83 " /></a></p>
<p>右图是谷歌首页，当输入某个词时，会弹出自动补全提示。功能并不复杂，但到要兼容各个浏览器，谷歌为此可能花费了不少功夫。然而完美实在是很难得，仔细测试可以发现一个处理得不妥的Bug：</p>
<p class="blockstrong">除了Ctrl+X/C/V，Ctrl+Z/Y也是经常使用的快捷键。在Firefox/Safari/Opera中访问谷歌，一切都很正常。但当我们<strong>打开IE浏览谷歌时，Ctrl+Z/Y不起作用了</strong>。在当今特别是中国，IE是份量最重的浏览器，谷歌首页有此问题，完全可以归为一个Bug.</p>
<p>这个Bug究竟是怎么引起的呢？为了进一步讨论，我们先来看看各个浏览器下，当输入法开启和未开启时，对键盘等事件的响应情况。</p>
<p class="blockstrong">猛击查看<a href="http://lifesinger.org/blog/wp-content/uploads/2008/08/keyboard_events.html"> JavaScript键盘事件测试小结</a></p>
<p>通过上面这篇测试小结，我们可以看出，要实现谷歌的自动补全功能并不是<span id="more-77"></span>一件很简单的事。目前可以找到的解决方案有：</p>
<p><em>方案一：通过监听keydown, keypress, keyup事件来实现。</em>这是大部分JavaScript教科书里的做法，对于拉丁语系国家，是没有问题的。但输入法一开启后，一切就都不美妙了：</p>
<ol>
<li>无论有没有输入法，通过鼠标右键粘贴复制时，key事件都触发不了，真糟糕。</li>
<li>输入法开启时，各个浏览器表现不同。不同输入法之间还有差异，太让人沮丧了。</li>
<li>输入法开启时，Opera压根不触发键盘事件。亲爱的Opera，叫我怎么爱上你？</li>
</ol>
<p>考虑到中文用户，特别是第一条（不少中文用户习惯使用右键菜单来粘贴复制），第一个方案基本可以枪毙掉。</p>
<p><em>方案二：不考虑这些烦人的键盘事件，直接采用定时器来实现。</em>在输入框获取焦点时，触发定时器，失去焦点时，关闭定时器。定时器每隔200ms检查输入框的值，根据值的变化来进行下一步响应。这个trick很简单，基本上能解决大部分问题（谷歌的自动完成就是这么做的^o^）。但有以下不妥：</p>
<ol>
<li>性能问题。（因为仅在获取焦点时触发定时器，性能问题倒是可以不考虑的）</li>
<li>ie下，此方法会导致Ctrl+Z/Y快捷键失效。</li>
<li>firefox下，用定时器实现表单输入时的即时校验，当输入法开启时，如果校验函数在输入未完成时改变输入框的值，会导致输入框的值变成空。（这个属于不可忽视的Bug，很恼人）</li>
</ol>
<p>方案二自动解决了右键菜单粘贴的问题，对于自动补全功能来说，一般应用场景下也足够用，但对谷歌来说，感觉有此Bug是不妥的。如果用方案二来实现表单输入时的即时校验，上面的第3点会导致firefox的中文用户很不爽。</p>
<p>苦思冥想许久，在键盘事件中折腾来折腾去，感觉怎么做都无法同时解决上面的所有不妥。昨天静下心来对所有A级浏览器的键盘事件在输入法开启和未开启时做了个仔细的测试后，下面这个方案就很清晰的浮了出来：</p>
<p><em>方案三：在上面的浏览器事件测试中，有一个很让人高兴的发现：所有浏览器中，都会触发input(ie下可以用propertychange)事件。</em>而且input事件仅在输入框的值有变化时才会触发。在输入法开启时，input也能正常触发（虽然会触发一些冗余的input，但比起定时器来好很多）。在右键菜单粘贴等操作时，也能正确触发input. 采用input/propertychange, 几近完美。但需要注意以下几点：</p>
<ol>
<li>ie下，如果监听的事件函数中，有页面输出操作，如YAHOO.log(&#8230;), 会导致Ctrl+Z/Y失效。（深层次原因还需仔细探索，感觉页面输出操作只是表象）</li>
<li>对于表单输入时的即时校验来说，比如只能输入数字的输入框，当输入字母时，监听input事件的实现会在字母显示出来后，立刻又删除掉（和keyup的实现效果一样），没有监听keypress的效果好（不会先显示出来）。因此对于即时校验来说，可以结合input和keypress，在输入法未开启时，给用户更友好的体验。</li>
</ol>
<p>最后，看一个根据方案三来实现的简单例子：<a href="http://lifesinger.org/blog/wp-content/uploads/2008/08/test_input.html">表单输入时的即时校验</a></p>
<h4>2008-08-28补充：</h4>
<ol>
<li>oninput事件：a). 当脚本中改变value时，不会触发；b). 从浏览器的自动下拉提示中选取时，不会触发。</li>
<li>onpropertychange事件：当input设置为disable=true后，onpropertychange不会触发。</li>
</ol>
<h4>参考资料</h4>
<ul>
<li>很让人敬佩的鼠标事件总结：<a href="http://unixpapa.com/js/key.html">JavaScript Madness: Keyboard Events</a></li>
<li>Realazy的探索：<a href="http://realazy.org/blog/2007/10/31/solution-of-keyup-failing-when-ime-is-on/">输入法下keyup失效的解决方案</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://lifesinger.org/blog/2008/08/keyboard-event-compatibility/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
	</channel>
</rss>
