剪貼板複製粘貼操做彙總

剪貼板

在前端平常開發中,對剪貼板相關的操做相對較少。但針對某些特定的應用場景,又是必不可少會用到的。好比:富文本編輯器開發、ctrl + v 上傳圖片、支付寶紅包口令自動複製(典型被玩壞兒了的用途)javascript

剪貼板操做途徑

剪貼板事件

操做剪貼板,最基礎的方式爲監聽剪貼板事件。出於兼容性考慮,通常都只在剪貼板事件處理函數中訪問 clipboardData ,非 IE 瀏覽器讀數據只能在 onpaste 事件時可用。要使用剪貼板事件讀寫數據,就必須得用戶主動使用快捷鍵或者右鍵菜單。因此監聽板事件的主要應用場景是用戶觸發後對數據進行攔截處理。html

document.execCommand

document.execCommand() 方法用於操縱可編輯區域的內容,例如最經常使用的 'copy' 命令可將選擇區域的內容複製到剪貼板中,配合 window.getSelection() 方法就能夠實現自動選擇內容區域並寫入內容到剪貼板。clipboard.js 庫及紅包口令自動複製主要就經過此方法實現的。前端

此方法也有一些問題:java

  • Chrome \ Safari 不支持 'paste' 命令
  • Chrome 不能直接在後臺調用 'copy' 命令,需用戶點擊觸發
  • IE 可直接在後臺調用和點擊觸發 'copy' 命令,但會出現權限提示

Asynchronous Clipboard API

看過上面的介紹,你會發現,操做剪貼板到處受限,並且迂迴曲折,更困難的是有些功能是沒法實現的。但不能否認,形成這一困惑很大一部分緣由是安全考慮。node

試想一下,當你瀏覽網頁,點了下頁面或者按鈕,就複製了支付寶紅包口令,會怎樣?呃,還能接受?那麼 'rm -rf /' 呢?(我用 Windows,我怕啥ios

而作爲 Clipboard API 新增內容的 Asynchronous Clipboard API 及 Clipboard Permissions API 就是爲了解決上述問題而來的,專治各類迂迴曲折及安全風險。截至目前(2018.03),Chrome 66 實現了部分功能,預測將來會有變化,本文不作詳細介紹。暫概括特色以下:git

  • HTTPS 下才能調用
  • 頁面處於活動選項卡才能調用
  • 基於 Promise,便於異步操做和錯誤處理
  • 實現了編程方式的粘貼(讀)和複製(寫)
  • 粘貼(讀)和複製(寫)權限已添加到 Permissions API 中 ,操做須要用戶受權
  • Clipboard Permissions API 目前僅適用於 Asynchronous Clipboard API。根據規範,將來會添加到全部 Clipboard API 中

處理粘貼 ( paste )

對於粘貼,目前普遍支持的僅有快捷鍵及右鍵菜單觸發,而 IE 支持的編程方式使用場景很少,這裏不作介紹。github

純文本或帶格式文本

對純文本的攔截編程

El.addEventListener('paste', event => {
    event.preventDefault();
    let clipboardData = event.clipboardData || window.clipboardData, // IE 兼容
        plainText = clipboardData.getData('text');  // 無格式文本
    
    // ... 對 plainText 進行一系列處理操做
    
    document.execCommand('insertText', false, plainText);  // 插入無格式文本
    document.execCommand('paste', false, plainText);  // IE 兼容
})
複製代碼

如需對有格式文本進一步處理,可用如下方法轉換爲 DOM 結構,再進行操做。(IE 瀏覽器沒法得到 'text/html' 因此沒法實現下面的功能)api

/* 仍在上述事件處理函數中,下面均省略 */
    let plainHTML = clipboardData.getData('text/html'),   // 有格式文本
        domContainer = document.createElement('div');
    domContainer.innerHTML = plainHTML;
    
    // ... 對 domContainer 進行一系列處理操做
    
    El.innerHTML = domContainer.innerHTML; // 使用 innerHTML 方式總體插入
    El.appendChild(nodeOfDomContainer); // 只插入其中某個節點
複製代碼

圖片

如 DOM 結構中含有圖片標籤,可考慮上傳圖片至服務器中,而後將其 src 替換爲服務器返回的地址。

如複製的是單個圖片(例如 word 中複製過來的),可使用下述方法獲得圖片的 DataURL,再上傳。(IE 瀏覽器粘貼圖片會自動生成帶 DataURL 的圖片標籤,因此不須要下述方法)

let items = clipboardData.items;
    for (let i = 0; i < items.length; i++) {
        let item = items[i];
        if (/image/.test(item.type)) {
            let file = item.getAsFile(), // 獲得文件對象
                reader = new FileReader();
            reader.onload = function() {
                upload(reader.result) // 上傳圖片,僞代碼
            }
            reader.readAsDataURL(file); // 讀取爲 DataURL / Base64
        }
    }
複製代碼

處理複製 ( copy )

快捷鍵及右鍵菜單觸發

常見應用場景是攔截複製操做,對複製內容加工後再寫入剪貼板,例如在知乎複製大段文本後加入版權信息。

El.addEventListener('copy', event => {
    event.preventDefault();
    let clipboardData = event.clipboardData || window.clipboardData,
        text = window.getSelection().toString();
    
    // ... 對 text 進行一系列處理操做
    
    clipboardData.setData('text/plain', text); // 將處理好的 text 寫入剪貼板
    clipboardData.setData('text', text); // IE 兼容
})
複製代碼

編程式複製

雖是編程式複製,但沒法作到徹底自動複製,須要用戶先觸發 點擊 事件。clipboard.js 庫及紅包口令自動複製(在 document 上監聽 click 事件)主要就經過此方法實現的。

固定內容

Button.addEventListener('click', event => {
    let sometext = '紅包碼 xxxxxx',
        hiddenInput = document.createElement('input');
    hiddenInput.value = sometext;
    hiddenInput.setAttribute('readonly', '');
    hiddenInput.style.position = 'absolute';
    hiddenInput.style.left = '-9999px';
    document.body.appendChild(hiddenInput);
    hiddenInput.select();
    hiddenInput.setSelectionRange(0, hiddenInput.value.length); // ios
    document.execCommand('copy');
    document.body.removeChild(hiddenInput);
})
複製代碼

複製某個元素內的文本

Button.addEventListener('click', event => {
    let someElement = document.getElementById('someelement'),
        selection = window.getSelection(),
        range = document.createRange();
    range.selectNodeContents(element);
    selection.removeAllRanges();
    selection.addRange(range);
    document.execCommand('copy');
})
複製代碼

能夠發現,目前對剪貼板的操做真是千奇百怪,但願新的 API 快快成爲現實吧(作夢)!

參考

[1] Clipboard API and events | w3c

[2] clipboard.js | Github

[3] 利用 javascript 實現富文本編輯器 | 掘金

[4] 富文本編輯器初探 | 掘金

[5] JavaScript複製內容到剪貼板 | 掘金

相關文章
相關標籤/搜索