用ZeroClipboard实现跨浏览器点击复制访问功能
在访问一些国外网站的时候,我们通常会遇到一些需要复制某段文字的网站,然后只需轻轻点击一下按钮,就可以实现“点击 复制 访问”的三部一按。英文是这样的“click to copy visit and paste”或者是“click to copy and open site”。有时候,我们当然也想实现这样的功能啦,可以所以就得动手折腾一下了。
之前何苦呢在“10个优秀Google Code代码项目”一文中题有提到过ZeroClipboard这个项目。下面,何苦呢继续发挥转载的天赋,为大家献上这篇用ZeroClipboard实现跨浏览器点击复制访问功能的技术文章。
编者按:在我们做WEB开发的过程当中,对跨浏览器页面内容的拷贝粘贴也许是一个很小的需求,但也可能是一个很锦上添花的需求。由于浏览器市场的混乱,各种浏览器对于一些细节的处理也各不相同,这使得前端程序员不得不通过取巧的方式来解决跨浏览器的问题。那么,ZeroClipboard就是为这样一使命而来,它通过结合Flash的一些特性,来实现跨浏览器剪切、粘贴内容的需求。
本文译作者:杨松、冯冀川,二人皆为搜狐新媒体中心的高级工程师。其中杨松同学精通C、Python、PHP等语言,对于前端也有所涉猎。冯冀川同学则是资深的前端开发工程师,精通JavaScript,同时也对服务器端开发深有研究。
总览:
ZeroClipboard类库通过使用一个看不到的flash,提供了一种将文本拷贝进入系统剪贴板的简便方法。名字中的Zero意味着这个类库是看不到的,从而完全的不影响你对用户界面的掌控。
这个类库完全兼容Flash Player 10,在Flash Player 10中使用复制操作的时候,需要用户的点击事件作为flash场景的初始化,而类库则是动态的在你要执行复制操作的DOM元素层之上,创建一个包含了复制 操作的透明flash,这样,在你要操作的DOM元素上的标准鼠标事件就可以被flash利用了,而且,类库还为你提供了监听鼠标滑过和鼠标按下的事件的 方法。
这个类库还支持Flash Player 9,但是需要注意的是,如果你使用了“富HTML”的特性,你网页的受众就得有Flash Player 10,类库并没有提供自动的兼容Flash Player 9的flash.
使用方法:
接下来我们展示下怎么使用这个粘贴板类库。
安装
在你的页面中,简单的包含这么一段javascript脚本,就可以使用这个类库啦。
- <script type="text/javascript" src="ZeroClipboard.js"></script>
当然,还需要保证“ZeroClipBoard.swf”这个文件能被浏览器加载到,当这个文件和页面在同一个文件夹的时候,就可以被自动的加载到了,当然,如果这个文件被放在别的地方,你就得用下面的代码来指明这个文件的URL了。
- ZeroClipboard.setMoviePath("http://YOURSERVER/path/ZeroClipboard.swf");
如果想使用类库1.0.7中“富HTML”特性,就必须设置使用在1.0.7版压缩包中新加入的”ZeroClipboard10.swf”文件。例如:
- ZeroClipboard.setMoviePath("ZeroClipboard10.swf");
或者自定义一个不在当前文件夹的位置:
- ZeroClipboard.setMoviePath("http://YOURSERVER/path/ZeroClipboard10.swf");
客户端:
好了,现在我们可以创建一个或者多个客户端。这里的客户端是页面上剪贴板类库的一个实例,它关联着一个按钮或者别的DOM元素。大部分情况下,一个实例就可 以搞定问题了,但是如果你的页面上有多个“复制到剪贴板”的按钮,你就可以为每个按钮创建一个实例。下面是创建一个客户端实例的代码:
- var clip = new ZeroClipboard.Client();
接下来,你可以设置一些选项。
设置选项
当创建了客户端实例之后,你可是设置一些选项,这些选项包括设置要拷贝的文字或者其他的一些内容,接下来的章节将描述所有可以设置的选项。
要拷贝的文字
当用户点了flash元素后,这个方法允许你向粘贴板中拷贝设置你要拷贝的文本。你可以在任意你希望的时间调用这个方法:页面第一次加载的时候,或者在onMouseOver或onMouseDown事件之后,比如:
- clip.setText("Copy me!");
手型光标
这个选项控制着当用户的鼠标移动到flash上之后,到底是显示“手型”还是“箭头型”光标,这里是用例:
- clip.setHandCursor(true);
参数值只接受true(显示手型光标)或者false(显示箭头光标),默认是ture,你可以随时设置这个选项。
胶接
胶接是一种类似于“连接”页面中flash和DOM元素的处理过程,类库会自动的创建一个和DOM元素一样大小的flash,并且让他悬浮在DOM元素之上,由于这个flash完全是透明的,因此,用户感觉不到任何异常。
Flash 会接受点击事件并且拷贝刚才你用setText()设置的那个文本到系统剪贴板(flash player10 限制只能是用户的点击事件才能激活和系统剪贴板的交互进程),同时还可以监听类似于鼠标悬停或者数遍按下的这种事件(详见下面的事件句柄)还可以向你的 DOM元素设置CSS样式(详见下面的CSS特效)哦。下面的例子展示了如何将类库实例黏贴到DOM元素上:
- clip.glue("d_clip_button");
你可以通过DOM元素的id(如上所示)或者直接就用DOM元素自己的引用,剩下的事情—创建flash,设置你的选项,将flash浮动在DOM元素上,静候用户的点击都有类库自己完成了。
胶接系统是一个可选的实现,如果你更倾向于自己处理flash的这些实现,请看下边的自定义实现章节。
实现的建议
在实践的时候,非常建议在要绑定的按钮外层创建一个“容器”层,并且将css属性中的position设置为relative,然后给glue()传递两个 参数,一个是按钮DOM元素或者按钮的ID,另外一个就是容器元素或者容器元素的ID。这样类库就可以将flash创建在容器元素内(而不是body元素内),从更加精确的定位,例如:
- <div id="d_clip_container" style="position:relative">
- <div id="d_clip_button">Copy to Clipboard</div>
- </div>
代码:
- clip.glue( ‘d_clip_button‘, ‘d_clip_container‘ );
需要注意的是,如果胶接在一个容器元素的话,reposition方法(见下节)就不在生效了。
定义页面大小
如果由于页面变动或者其它一些导致你的DOM元素有所变动的话,你就需要重新定义一下flash的位置。这个可以一个叫做repostion的方法来实现,例如:
- clip.reposition();
一个典型的做法是将它放置在window.onresize处理函数中。
如果由于一些原因导致你的DOM元素被破坏或者创新创造了,你可以将新的id或者dom元素的引用传递给reposition,但是需要住注意的是,新元素必须和之前的元素拥有一样的大小,类库不支持(最少现在不支持)元素修改大小。
注意:reposition仅仅支持胶接单个元素,如果你还胶接了一个父级元素,于就不能再次调用reposition()
隐藏和展示
如果你有一个ajax的web应用程序可以动态的改变内容,你也可以在flash动画被点播的时候显示和隐藏他们,可能是一个无关紧要的剪贴板按钮,例如:
- clip.hide();
- clip.show();
show()函数在执行的时候也可以调用reposition()函数。
CSS效果
既然flash动画浮动在你DOM元素的最顶端,它将会在浏览器捕获这些鼠标事件之前接收它们(是否可以理解 为事件的捕获与冒泡行为)。无论如何,为了方便起见这些事件通过你的剪贴板时你可以捕获他们(看下面的事件句柄介绍)。但是除此之外,这个flash动画 也能够在你的DOM元素上触发起一个可以模拟‘:hover’和‘:active’的CSS伪类。
如果这个功能可用,鼠标滑过并且点击flash动画的时候同样可以将css的hover和active类从你的DOM元素上添加或者删除掉。它从本质上允许 你的button行为正常,即使这个浮动的flash正在接收所有的鼠标事件。请注意事实上CSS的伪类’:hover’和’:active’并不会被当 做可编程的程序在当前的浏览器上激活(说白了,就他妈的不能执行就完了,应该是这意思吧)。与之替代的,子类名称为’hover’和’active’的能 够被正常使用。例如:
- #d_clip_button {
- width:150px;
- text-align:center;
- border:1px solid black;
- background-color:#ccc;
- margin:10px; padding:10px;
- }
- #d_clip_button.hover { background-color:#eee; }
- #d_clip_button.active { background-color:#aaa; }
和这些类相关的DOM元素ID为:’d_clip_button’。在用户依次滑过并且点下flash动画期间,’hover’和’active’子类将会自动的被激活。它们的行为准确的说就像是CSS的’hover’和’active’伪类一样。
这个CSS效果默认是开启的。如果要关闭它,可以通过设置setCSSEffects()函数的参数为false来完成。例如:
- clip.setCSSEffects(false);
你可以在任何的时候做这个操作。
自定义的实现
如果你希望有自己的flash影片实例,并且完全摒弃整合和CSS系统,你可以简单的调用getHTML()方法,它将为flash影片返回一个OBJECT/EMBED标签。例如:
- var html = clip.getHTML(150, 20);
这个方法需要你传递影片的宽度与高度。返回的HTML片段能够被插入到DOM元素中,或者你也可以选择用document.write()方法写入到页面。
注意:微软的IE看上去有一个bug,flash的对外接口(主要指javascript和flash之间的通信)不能够被正确的激活,除非你将 object标签插入到元素中的时候,这个元素已经被添加到DOM中了(应该可以这样理解,这个元素已经显示在DOM文档中了,而不是只创建在内存 中,IE貌似是有这样的bug)。因此请确保在你用innerHTML属性向元素中插入HTML片段的时候先调用appendChild()方法。
- // 举个例子
- // other browser
- var div = document.createElement("div");
- div.innerHTML = "……some html";
- document.body.appendChild(div);
- // Microsoft Internet Explorer
- var div = document.createElement("div");
- document.body.appendChild(div);
- div.innerHTML = "……some html";
- // 相对于代码的表现力,其他的语言显得都很浮云。
事件处理:
这个剪贴板类库允许你设置一些不同的事件处理程序。它们所有都可以通过调用addEventListener()方法,例如:
- clip.addEventListener("onLoad", my_load_handler);
第一个参数是事件的名称,第二个参数是一个函数的引用,这个函数也可以通过一个名称传入(字符串格式),实际上引用的是这个函数对象,或者一个PHP风格的对象、方法数组:
- clip.addEventListener("onMouseDown", [myObject, "myMethod"] );
这样你就象上面PHP代码那样,可以通过在指定的对象上调用指定的方法来召回之前对象的上下文,但我还是假定你可能恰好使用了javascript的bind()方法达到了同样的效果。
这个事件的名称对大小写不敏感,并且前缀’on’也是可选的。例如这个参数的值为’onLoad’, ‘onload’或者’load’它们表达的意思是一样的。
你自定义的函数将至少有一个参数可以传递 —— 一个引用剪切板的对象。然而,毫无疑问的事件会传入额外的参数,这些将在下面的每一个章节中描述。下列的子章节描述所有和你相关的可用事件。
onLoad
onLoad事件将在flash影片完全载入并且准备就绪的时候被触发。请注意,你不需要为这个监听事件设置选项——如果你在载入之前调用它,它将自动的传入到影片中。例如:
- clip.addEventListener("onLoad", my_load_handler );
- function my_load_handler( client ) {
- alert( "movie has loaded" );
- }
这个句柄会得到一个剪贴板对象作为参数。
onMouseOver
当用户的鼠标指针进入到flash影片时,onMouseOver事件被触发,你可以用它来在你的DOM元素上模拟一个翻转的效果,不过CSS Effects用一种非常简单的方式可以实现。例如:
- clip.addEventListener("onMouseOver", my_mouse_over_handler );
- function my_mouse_over_handler( client ) {
- alert( "mouse is over movie" );
- }
这个句柄会得到一个剪贴板对象作为参数。
onMouseOut
当用户的鼠标指针离开进入到flash影片时,onMouseOut事件被触发,你可以用它来在你的DOM元素上模拟一个翻转的效果,不过CSS Effects用一种非常简单的方式可以实现。例如:
- clip.addEventListener( ‘onMouseOut‘, my_mouse_out_handler );
- function my_mouse_out_handler(client) {
- alert("mouse has left movie");
- }
onMouseDown
当用户点击flash的时候,就触发了onMouseDown事件,请注意,这个事件并不保证当用户还在flash上时放开了鼠标按钮,你可以使用这个事件在你DOM元素上模拟一下点击效果,用来验证CSS效果比较简单,例如使用:
- clip.addEventListener( ‘onMouseDown‘, my_mouse_down_handler );
- function my_mouse_down_handler(client) {
- alert("mouse button is down");
- }
这个句柄会得到一个剪贴板对象作为参数。
onMouseUp
当用户释放了鼠标按钮(当鼠标在flash上悬停的时候点下鼠标)的时候会触发onMouseUp事件,请注意,这个事件并不能保证鼠标光标还在flash上,你可以使用这个事件在你DOM元素上模拟一下点击效果,用来验证CSS效果比较简单,例如使用:
- clip.addEventListener("onMouseUp", my_mouse_up_handler);
- function my_mouse_up_handler(client) {
- alert("mouse button is up");
- }
这个句柄会得到一个剪贴板对象作为参数。
onComplete
当文本被成功的拷贝到剪贴板时会触发onComplete事件,例如:
- clip.addEventListener("onComplete", my_complete);
- function my_complete( client, text ) {
- alert("Copied text to clipboard: " + text );
- }
这个句柄会得到两个参数,一个参数是剪贴板客户端对象的引用,一个是被拷贝的文本。
destroy
或许,你还希望能彻底的移除剪贴板对象的flash,例如当成功的拷贝文本到剪贴板之后。这意为着用户就不能在通过点击来拷贝多余的文本了,简单的调用destroy()方法就能达成这个目的,例如:
- clip.destroy();
这样就从DOM中移除了flash,而且重置了剪贴板对象。如果你想将这个对象和别的容器链接走一起来完成复制人物的话,可以通过再次调用glue()方法或者getHTML方法来完成.
注意:由于一些安全因素,你或许不能在onComplete的句柄函数中直接调用这个方法,原因是调用了destory方法的javascript线程可能 会和flash产生冲突,这可能会导致浏览器崩溃(比如说IE),最好通过使用setTimeout方法将调用destroy的线程放置在一个计时器中, 用于保证安全。
使用心得:
在现实的使用中,这个clipboard类库面临的最大问题有两个
1. 用户的browser不支持flash,那这就彻底的没办法了
2. 页面中元素的z-index远远大于swf的z-index.swf的默认z-index是99,因此,很容易被它要悬浮的元素给遮盖住。
以上“用ZeroClipboard实现跨浏览器点击复制访问功能”转载自
http://www.showmuch.com/article/article_45.html
原文题目"跨浏览器的通用粘贴板类库:ZeroClipboard"
能不能插件化?