ZeroClipboard2跨瀏覽器複製貼上
摘要:我們平時常用到的複製貼上功能,在瀏覽器端,要想使用一個按鈕來實現,使用原生js程式碼來實現,是困難的,幸好ZeroClipboard的出現,解決了這一尷尬的問題。
ZeroClipboard2簡介
在前端頁面設計時,按鈕常常伴隨著資料的提交或重置出現。然而某一次,需求是點選按鈕,將後臺展示在頁面的特定內容複製到剪下板,這樣使用者就省去了選中文字並按Crtl+C的操作。這使我有機會接觸並使用到了一款好的工具:ZeroClipboard2。
ZeroClipboard2實現原理很簡單:利用透明的 flash 覆蓋在複製按鈕上,點選 flash,將複製內容傳入到 flash 中,再通過 flash 把傳入的內容寫到剪貼簿上。
ZeroClipboard2使用方法也簡單粗暴:把 flash 和 js 放到同一路徑下,然後引用 js 即可。
ZeroClipboard2簡單應用
先看一個例子,瞭解一下最簡單的ZeroClipboard2使用:
可能用到的工具
- ZeroClipboard2.2.0
- Eclipse 4.5
- Tomcat 7
- JQuery 1.7.2
- ExtJs
如下 clip.html
<!DOCTYPE HTML>
<html >
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<title>ZeroClipboard 測試</title >
</head>
<body>
文字:
<input type="text" name="txt" id="content" value="要複製的內容" />
<button id="copy" data-clipboard-target="content">copy</button>
<br /><br />
貼上:
<input type="text">
</body>
</html>
<script type="text/javascript" src="js/ZeroClipboard.js"></script>
<script type="text/javascript" >
window.onload = function(){
var clip = new ZeroClipboard(document.getElementById("copy"));
};
</script>
專案的骨架:
使用時需要引入ZeroClipboard2所需要的檔案ZeroClipboard.js和ZeroClipboard.swf檔案,建議將其放入一個目錄下。
程式碼中用到的data-clipboard-target
屬性是為了指定要複製內容的id,ZeroClipboard 將依次嘗試通過該元素的value、textContent、innerText屬性來獲取文字資料,將content的資料繫結到id為copy的button上。
由於 Flash 本地沙箱的安全限制,以上程式碼如果是在本地HTML檔案中被瀏覽器直接開啟,將無法正常工作。我是用Tomcat執行的,而且如果是Eclipse預設方式開啟的頁面,也是不能工作的,需要在本地瀏覽器中開啟。
在chrom中開啟:
點選copy,在貼上欄中Ctrl+v,即可看到效果:
ZeroClipboard2與JQuery :
實際使用時,我們很少將js程式碼與html程式碼放在一起,而是引入js檔案,可能還會用到JQuery。
改進 clip.html
<!DOCTYPE HTML>
<html >
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<title>ZeroClipboard 測試</title>
</head>
<body>
文字:
<input type="text" name="txt" id="content" value="要複製的內容" />
<button id="copy" data-clipboard-target="content">copy</button>
<br /><br />
貼上:
<input type="text">
</body>
</html>
<script type="text/javascript" src="js/ZeroClipboard.js"></script>
<script type="text/javascript" src="js/jquery-1.7.2.js"></script>
<script type="text/javascript" src="js/demo.js"></script>
引入的demo.js
$(document).ready(function(){
var clip = new ZeroClipboard($("#copy"));
});
專案的骨架:
ZeroClipboard2與ExtJs:
在生產環境中,我們使用的是ExtJs。在這個過程中,最難控制的就是何時初始化ZeroClipboard,因為ExtJs的按鈕是在後期生成的,我不能很容易的新增諸如data-clipboard-target
屬性的方法告訴ZeroClipboard去複製什麼內容,也沒有一個很清楚的位置去寫new ZeroClipboard()
這樣的邏輯,那麼該如何處理呢?
- ExtJs 應該在適當的位置初始化ZeroClipboard
在使用ExtJS建立button時,常常使用如下方法:
Ext.onReady(function(){
var buttonName = new Ext.Button({
id:"buttonName",
renderTo:Ext.getBody(),
minWidth:100,
handler:function(){
Ext.MessageBox.show({
title: '提示' ,
msg: '你點選了我!' ,
buttons: Ext.MessageBox.OK ,
fn: function(){}
});
}
});
});
那麼在初始化button時,就應該考慮初始化ZeroClipboard。你可以在瀏覽器的console中檢視初始化是否完成。
- 在頁面載入完成以後,在瀏覽器中應該存在ZeroClipboard物件。
- 使用自帶方法檢視:ZeroClipboard.state()
- 如果一切順利,可以看到ZeroClipboard.state().flash.ready的值為true.
- 使用ZeroClipboard自帶的複製方法
有時候,我們無法給button設定data-clipboard-target
屬性,可以使用ZeroClipboard自帶的複製方法繫結資料。
其中setText()
是最簡單且常用的方法
var clip = new ZeroClipboard($("#copy"));
clip.setText($("#content").val());
//可以設定3中格式,帶有格式的內容貼上到不同的程式,顯示對應的效果
clip.setText("複製的內容");
clip.setHtml("<p>複製的內容</p>");
clip.setRichText("{\\rtf1\n{\\b 複製的內容}}");
還有一種通用的設定方法setData()
clip.setData("text/plain", "複製的內容");
clip.seData("text/html", "<p>複製的內容</p>");
clip.setData("application/rtf", "{\\rtf1\n{\\b 複製的內容}}");
ZeroClipboard2第一次複製不生效:
在ZeroClipboard2與ExtJs結合使用時,我發現,每次複製的第一次不生效,需要點選第二下複製按鈕,才能實現複製效果。在琢磨之後發現,我在繫結資料的時候使用的是setText()
方法,而該方法設定的資料是一次性的,使用該方法設定複製資料後,只在下一次複製操作時生效。之後即使你點選複製按鈕也不再執行復制,除非你再次呼叫setText()
方法。
解決這個問題,我們在button的回撥函式中使用了的事件copy
,改用setData()
方法:
clip.on("copy", function(e){
e.clipboardData.setData("text/plain", "複製的文字")
});