Try   HackMD

之前興起實作了版權訊息的顯示時,有發現有些網站除了顯示版權訊息外,還會在複製網頁內容時,自動加上版權聲明、作者與網址等資訊。當時我覺得頗有趣,決定要來研究看看如何實作。

老樣子我把採坑的過程都寫了下來,如果只想知道最後的結果就直接拉到底吧。

剪貼簿 DOM 事件

既然行為牽扯到複製與貼上,我第一個反應就是翻翻跟剪貼簿相關的 DOM 事件類型,果然找到一些可以用事件分別是:copypaste。想了下我的應用情境,我應該是要在它複製時,加上版權訊息,畢竟執行貼上時應該已經離開這個網站了,不會再次觸發 DOM 事件。

這簡單用 EventListenter 就好:

document.addEventListener('copy', function (evt) { // ToDo: append source hyperlink });

另外, 這樣寫法也行:

document.body.oncopy = function () { setTimeout( function () { // ToDo: append source hyperlink }, 100) }

取得複製並修改文字

取得文字

根據找到的資料,剪貼簿的資料儲存在 clipboardData 物件中,可以藉由 getData() 方法並傳入指定資料格式以取得數據:

document.addEventListener('copy', function (evt) { let text = clipboardData.getData("text/plain"); console.log(text); });

不過,這樣直接硬幹似乎有點問題,我遲遲沒看到應該出現的 log,反而出現 Error:

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

細看了下介紹,原來是瀏覽器的問題。文件中有提到,clipboardData 這個物件,在 IE 中是屬於 window 物件的屬性;但對於其他瀏覽器來說,此物件是屬於 event 的屬性。所以我嘗試改寫了剛剛程式,多了個判斷式:

document.addEventListener('copy', function (evt) { let clipdata = evt.clipboardData || window.clipboardData; let text = clipdata.getData("text/plain"); console.log(text); });

不過,這樣出來的值卻是 null 的,或許跟瀏覽器的版本有關?所以我又翻了些資料發現相關的寫法五花八門,有諸如:event.originalEvent.clipboardData.getData('text');window.event.clipboardData.getData('text');等寫法,不過這些寫法不是 Error 就是 null(沮喪 😔)。


最後終於找到一個可用的寫法:

document.addEventListener('copy', function (evt) { let text = navigator.clipboard.readText(); console.log(text); });

但這個只能在 Chrome 上運作,而且即便在 Chrome 上也必須先得到使用者允許授權才能讀取:

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →


所以我換了個想法,改用了 document.getSelection。不同於前面的實作方法,是從剪貼簿中取值,在進行複製前有一個必備的前行動作–反白,這個方法就是將反白的文字取出。

document.addEventListener('copy', function (evt) { let text = document.getSelection().toString(); console.log(text); });

修改文字

搞定文字取出後,下一步就是對文字動手腳後回填。這部分就真的得仰賴剪貼簿 clipboardData 了,還好這個時候它沒有跟我鬧脾氣,順利回填了:

document.addEventListener('copy', function (evt) { let text = document.getSelection().toString(); if (text) { text = text + "\n\n" + "=========================================\n" + "{網站資訊}" } let clipdata = evt.clipboardData || window.clipboardData; clipdata.setData("text",text); evt.preventDefault(); });

就此,功能終於搞定了!(灑花)

參考資料

  1. 小火柴的蓝色理想 (2016-09-18)。深入理解DOM事件类型系列第四篇——剪贴板事件。檢自 博客园 (2021-11-23)。
  2. JS教程 (2018-10-07)。複製網頁內容,貼上之後自動加上網址的實現方法(指令碼之家特別整理)Script。檢自 IT閱讀 (2021-11-23)。
  3. (2018-06-28)。js 剪下板應用clipboardData詳細解析。檢自 程式前沿 (2021-11-23)。
  4. GiorgosK (2018-04-14)。window.clipboardData.getData("Text") doesnt work in chrome。檢自 Stack Overflow (2021-11-23)。
  5. Element: copy event。檢自 Web APIs|MDN (2021-11-23)。
  6. pj2452 (2015-01-02)。javascript - "Unable to get property 'getData' of undefined or null reference" in IE but not Chrome。檢自 Stack Overflow (2021-12-02)。
  7. MGA (2017-01-16)。javascript - Uncaught TypeError: Cannot read property 'getData' of undefined。檢自 Stack Overflow (2021-12-02)。
  8. MaxLeeBK (2021-09-25)。那些被忽略但很好用的 Web API / Clipboard。檢自 iT 邦幫忙 (2021-12-02)。

更新紀錄

最後更新日期:2022-04-29 23:44
  • 2022-04-29 發布
  • 2021-12-02 完稿
  • 2021-11-23 起稿



本文作者: 辛西亞.Cynthia
本文連結辛西亞的技能樹 / hackmd 版本
版權聲明: 部落格中所有文章,均採用 姓名標示-非商業性-相同方式分享 4.0 國際 (CC BY-NC-SA 4.0) 許可協議。轉載請標明作者、連結與出處!