Google Docs Ctrl + C 技术浅析
用 google docs 打开 pdf 文件,选中文本:

表面上没有任何有趣的地方。但仔细一看,会发现选区的颜色是浅蓝色,而不是默认蓝。第一直觉是是有什么特殊的 CSS 属性,立马 firebug:

不看不知道,一看真蹊跷。selection-highlight 是选区,选区下面是一张图片 page-image!
于是立刻发现一个非常牛逼的特性:Ctrl + C 可以复制图片中的文字!
google 太强悍了,好在前端代码都是开源的,下面简单分析下。
首先数据在哪呢,这个比较容易找到,在 firebug 里有一个请求返回的数据如下:
<?xml version="1.0" encoding="UTF-8"?> <pdf2xml> <meta name="Creator" content="Adobe Acrobat 8.1 Combine Files"/> <meta name="Producer" content="Adobe Acrobat 8.1"/> <meta name="CreationDate" content="20100316080708-04'00'"/> <page t="0" l="0" w="612" h="773"> <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"> Please post comments or corrections to the Author Online forum at</text> ...
有了这份数据,就可以根据选区得到对应的文本。
接下来的问题是,如何将文本放到剪贴板里?第一反应是用 flash 实现,但感觉 google 不会这么做。禁用掉 flash 插件后,功能正常,这说明是用 js 实现的。
通过 Profile 工具 + Fiddler + 肉眼识别 + 运气,终于定位到了关键代码:
n.am = function(a) {
if (! (!this.k.Ca && Mr(this, a))) {
ac && this.lf.focus();
this.lf.select();
Nr(this, a)
}
};
只要注释掉上面的代码,Ctrl + C 复制功能就无效。focus 和 select 为我们提供了进一步线索,在 HTML 里,发现了秘密:

到此真相大白:当用户按下 Ctrl + C 时,js 会注入事件,首先根据坐标从数据里取出对应文本,然后将文本赋值给 textarea, 并将其激活和选中。这样,就和用户选中 textarea 的内容,再按下 Ctrl + C 的效果是一样了。
强悍的 google, 技术创新无处不在!
注意:利用 textarea 只能复制纯文本,如果想复制富文本,可以借鉴 google docs 编辑 Word 文档时的处理方式:采用 iframe 充当临时容器,有兴趣的可以进一步研究。
发现这个秘密后,最近在疯狂搞编辑器的牛人承玉(欢迎搞编辑器的其他牛人加盟)立刻想到了各大站长们非常喜爱的功能:附带警告信息的禁止copy. 据说,能成功复制的,都不是“人”。
我的尝试是:点击按钮,复制指定文本到 Clipboard 里。应用场景是点击按钮复制证件号码等。尝试代码大家可以看上面 demo 页面源码中的注释。事件可以正常模拟并分发出去,但复制操作惨兮兮地失败了。感觉原因在于浏览器安全限制,对于触发的异步 Ctrl + C, 浏览器会限制其功能。
Google 的产品里有很多秘密,真诱人,创意无限!

July 27th, 2010 on 16:48
其实google一些细节确实三很诱人,但细节需要细心的体验和发现
July 27th, 2010 on 17:04
这个禁止 copy 的办法……我选中以后,无意中发现在浏览器的 “编辑” 菜单下面竟然有一个叫 “复制” 的菜单项,然后我就点了一下,然后,然后就没有然后了 ^_^
July 27th, 2010 on 17:06
je 需要注册才能回复,那么只好贴这儿了,相信你们一定能找到对付这种办法的办法 :)
July 27th, 2010 on 17:53
非常好,之前一直在纠结,只能用flash实现
转到我blog收藏了
July 27th, 2010 on 17:53
禁止copy 那个,因为我的Firefox 装了 Vimperator 插件,选中文字之后按下 “shift + y” 完全没有障碍,哈哈
July 27th, 2010 on 18:32
扣了一下代码,docs的实现果然牛逼
July 27th, 2010 on 18:50
恩,其实很多编辑器的过滤方式都是采用这个技巧来搞定的
July 27th, 2010 on 19:20
为啥我的firebug在选区后没看到请求数据的xml
刚出来的时候就分析过,但不知道他的数据放在哪儿,后来放弃了。
July 27th, 2010 on 19:29
有必要说下残酷的真相。。。Opera 10.5之前的版本复制没问题,因为不支持context menu,10.5之后也可以选择禁掉context menu。FX无需扩展也可禁掉context menu然后复制
July 27th, 2010 on 19:54
这种思路真够创新的。。
July 27th, 2010 on 21:56
顶吖,玉伯真的很有研究精神吖,我发现了半年都没明白怎么实现,已经被这个功能吓到了,结果昨天和玉伯提一下,当天夜里就搞出来了 …..
July 27th, 2010 on 23:08
哇~好玩意~打算折腾下搞到自己博客里~哇哈哈~
July 28th, 2010 on 9:16
2L啊…学习了.囧…
July 28th, 2010 on 9:31
创意啊
July 28th, 2010 on 9:48
还是有问题:选中/右键/复制,正常复制!
July 28th, 2010 on 17:37
这个复制方法,我在 CodeMirror 的代码里看到过,当时觉得奇怪为什么要这样做,看了这篇文章,似乎有些明白了。
July 30th, 2010 on 10:05
n.am = function(a) {
if (! (!this.k.Ca && Mr(this, a))) {
ac && this.lf.focus();
this.lf.select();
Nr(this, a)
}
};
说实话没看到这段代码,能解释下不?
August 1st, 2010 on 20:03
额,图片中文字都能复制么,真没有发现呢,厉害
August 2nd, 2010 on 12:28
我倒是觉得不要研究这种奇技淫巧吧,这样让互联网封闭的行为有够自私的。
August 3rd, 2010 on 8:57
为什么要异步的Ctrl+C呢?“选中”pdf文档上的“文本”时,就把内容寄存在textarea里并激活选中,Ctrl+C时什么都不用做,不可以吗?
August 10th, 2010 on 23:59
完整地看完了,不是很明白,有待进一步学习中。
August 12th, 2010 on 9:40
原來也有其它人在用, 我也是在一段長時間的摸索中, 把這技巧用上了.
不過現在弄到menu的command, 又卡住了. 因為以上是截取標準複制快捷鍵”Ctrl+C”,而用menu使出的指令確不能達到所要的功能.
August 14th, 2010 on 7:59
嗯,google喜欢创新,博主喜欢研究
August 16th, 2010 on 14:27
这就是谷歌的先进之处了。
leave a reply