最近接到的需求類似「點擊按鈕後自動複製折價券代碼」這樣的功能,因此研究了一下如何實現前端利用 Javascript 複製文字。
多年前曾在「如何用語法保護網頁文章著作權」多篇系列文寫相關功能,但這些年網頁技術進展很快,HTML5 新的 api 讓複製文字變得相當簡單。
過去網頁前端的大魔王是 IE,為了 IE 的相容性得傷透腦筋,然而隨著 IE 的式微,取而代之的是另一個大魔王 iOS,蘋果裝置的諸多限制讓 JS 複製文字異常難解,因此本篇詳細研究該如何跨瀏覽器、跨平台相容 JS 複製文字的問題。
以前網頁用 JS 複製文字很困難,必須用 Flash 繞過瀏覽器的限制,可參考這篇「點選自動複製 ( ZeroClipboard )」,缺點是瀏覽器的 Flash 功能被關閉就無效。
後來 HTML 5 新增了「Clipboard API」,可直接存取剪貼簿的資料,真的方便許多,但缺點是蘋果 iOS 裝置不支援。
所以這件事要做到跨裝置、瀏覽器支援,一方面可使用 Clipboard API,一方面需要單獨對 iOS 裝置進行處理。
這個討論串「Copy to clipboard using Javascript in iOS」對 iOS 的狀況說明的很詳細,摘錄重點如下:
另外 iOS 裝置用 JS 執行複製文字時,上還有些不太好的效果,例如:
有國外高手寫了「clipboard.js」解決複製文字的問題,也能相容 iOS 裝置。這篇「實現前端點擊按鈕自動複製剪貼板功能」取用了 clipboard.js 的程式碼進行調整。
那麼開頭提到的「點擊按鈕後自動複製折價券代碼」這個功能,根據以上相關資訊進行修改後,提供範例程式碼如下:
範例程式碼的效果,如同下面這個按鈕,複製後會自動複製數字123456 ,可自行測試:
若在 iOS 進行複製,會發現如前所述,螢幕自動捲到下方,因為這個用來暫時存放複製文字的 textarea 元素,預設放在 body 的最後面,當 iOS 進行選取的動作時,游標就會自動移動到頁尾。
要解決這個問題,需要在觸發 click 的程式碼最後面,例如在 window.Clipboard.copy(value); 的下一行,加入以下程式碼,計算按鈕元素的座標,強制螢幕捲回按鈕的位置:
多年前曾在「如何用語法保護網頁文章著作權」多篇系列文寫相關功能,但這些年網頁技術進展很快,HTML5 新的 api 讓複製文字變得相當簡單。
過去網頁前端的大魔王是 IE,為了 IE 的相容性得傷透腦筋,然而隨著 IE 的式微,取而代之的是另一個大魔王 iOS,蘋果裝置的諸多限制讓 JS 複製文字異常難解,因此本篇詳細研究該如何跨瀏覽器、跨平台相容 JS 複製文字的問題。
一、Javascript 複製文字的進程
以前網頁用 JS 複製文字很困難,必須用 Flash 繞過瀏覽器的限制,可參考這篇「點選自動複製 ( ZeroClipboard )」,缺點是瀏覽器的 Flash 功能被關閉就無效。
後來 HTML 5 新增了「Clipboard API」,可直接存取剪貼簿的資料,真的方便許多,但缺點是蘋果 iOS 裝置不支援。
所以這件事要做到跨裝置、瀏覽器支援,一方面可使用 Clipboard API,一方面需要單獨對 iOS 裝置進行處理。
二、iOS 的限制
這個討論串「Copy to clipboard using Javascript in iOS」對 iOS 的狀況說明的很詳細,摘錄重點如下:
- iOS 版本 > 10 的時候:
- 只有 input、textarea 這兩個元素的文字可以複製
- 這兩個元素的屬性必須是可以編輯(contenteditable)、不能是只讀狀態(readonly)
- 這兩個元素內的文字必須是選取狀態才能複製
- 符合以上條件後,即可使用 Clipboard API
- iOS 版本 < 10 的時候:
- Safari 有些限制,只能經由 "點擊"這個動作來觸發複製文字的程式碼
- 意思就是無法偷偷在背景自動執行程式來複製文字
另外 iOS 裝置用 JS 執行複製文字時,上還有些不太好的效果,例如:
- 可能會彈出鍵盤
- 螢幕會捲動到要複製文字的 input、textarea 位置
三、範例程式碼
有國外高手寫了「clipboard.js」解決複製文字的問題,也能相容 iOS 裝置。這篇「實現前端點擊按鈕自動複製剪貼板功能」取用了 clipboard.js 的程式碼進行調整。
那麼開頭提到的「點擊按鈕後自動複製折價券代碼」這個功能,根據以上相關資訊進行修改後,提供範例程式碼如下:
<input value="填入要複製的字串 例如 123456" style="display:none;"/><button class="copy_coupon">【123456】點擊複製數字</button>
<script src='//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js'></script>
<script>
window.Clipboard = (function(window, document, navigator) {
var textArea,
copy;
function isOS() {
return navigator.userAgent.match(/ipad|iphone/i);
}
function createTextArea(text) {
textArea = document.createElement('textArea');
textArea.value = text;
document.body.appendChild(textArea);
}
function selectText() {
var range,
selection;
if (isOS()) {
range = document.createRange();
range.selectNodeContents(textArea);
selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
textArea.setSelectionRange(0, 999999);
} else {
textArea.select();
}
}
function copyToClipboard() {
document.execCommand("Copy");
document.body.removeChild(textArea);
}
copy = function(text) {
createTextArea(text);
selectText();
copyToClipboard();
};
return {
copy: copy
};
})(window, document, navigator);
$(".copy_coupon").on("click", function() {
var $this = $(this),
value = $this.prev("input").val();
window.Clipboard.copy(value);
});
</script>
範例程式碼的效果,如同下面這個按鈕,複製後會自動複製數字
四、補充
若在 iOS 進行複製,會發現如前所述,螢幕自動捲到下方,因為這個用來暫時存放複製文字的 textarea 元素,預設放在 body 的最後面,當 iOS 進行選取的動作時,游標就會自動移動到頁尾。
要解決這個問題,需要在觸發 click 的程式碼最後面,例如在 window.Clipboard.copy(value); 的下一行,加入以下程式碼,計算按鈕元素的座標,強制螢幕捲回按鈕的位置:
$("html, body").scrollTop($this.offset().top)
更多 Javascript 相關技巧: