使用JS實現(xiàn)自定義復制的功能

本文介紹了JS與剪貼板相關的底層功能模暗。

1. 背景

事情的起因是這樣的沟绪,在從簡書上面找了個別人的文章復制了一些內(nèi)容氧吐,當復制的內(nèi)容超過了一定字數(shù)的時候博个,就發(fā)現(xiàn)粘貼出來的東西多了一些內(nèi)容怀樟,如下圖所示。

1.png

由于最近剛好在研究JS的復制剪切盆佣,于是對這個功能進行深入研究往堡。

2. document.execCommand

之前使用了一個插件Clipboard.js實現(xiàn)了JS的復制功能,研究之后發(fā)現(xiàn)是調(diào)用HTML5的document.execCommand共耍,才能實現(xiàn)瀏覽器端的復制功能虑灰。

語法

bool = document.execCommand(aCommandName, aShowDefaultUI, aValueArgument)
返回值

一個 Boolean,如果是 false則表示操作不被支持或未被啟用痹兜。

參數(shù)

我們這里只需要用到一些簡單的功能穆咐,因此只使用第一個參數(shù)aCommandName就可以了。
一個 DOMString字旭,命令的名稱对湃。可用命令列表請參閱文檔遗淳。

命令

這里簡單介紹一些用到的命令拍柒。

copy

拷貝當前選中內(nèi)容到剪貼板。啟用這個功能的條件因瀏覽器不同而不同洲脂,而且不同時期斤儿,其啟用條件也不盡相同。使用之前請檢查瀏覽器兼容表恐锦,以確定是否可用。

cut

剪貼當前選中的文字并復制到剪貼板疆液。啟用這個功能的條件因瀏覽器不同而不同一铅,而且不同時期,其啟用條件也不盡相同堕油。使用之前請檢查瀏覽器兼容表潘飘,以確定是否可用肮之。

paste

在光標位置粘貼剪貼板的內(nèi)容,如果有被選中的內(nèi)容卜录,會被替換戈擒。剪貼板功能必須在 user.js 配置文件中啟用。


從上面的介紹可以看出艰毒,復制功能都是對當前選中內(nèi)容進行的相關操作筐高,這都需要能獲取到當前選中的對象,因此找到了一個新的API丑瞧。

3. Window.getSelection

這個方法是對用戶選擇的文本范圍進行的一些操作柑土。

概述

返回一個 Selection對象,表示用戶選擇的文本范圍或光標的當前位置绊汹。

語法

const selection = window.getSelection() ;
  • selection
    是一個Selection對象稽屏。 如果想要將selection轉(zhuǎn)換為字符串,可使用 String.toString()方法西乖。

示例

function foo() {
    let selObj = window.getSelection(); 
    console.log(selObj);
    let selectedText = selObj.toString();
    let selRange = selObj.getRangeAt(0);
    // 其他代碼
}
  • selObj 是一個Selection 對象狐榔。
  • selectedText 是一個字符串(被選中的文本)。

4. 實現(xiàn)思路

  1. 首先要響應瀏覽器的copy事件获雕,使用e.preventDefault() 阻止默認的復制事件薄腻。
  2. 在響應瀏覽器的copy事件時,通過Window.getSelection()獲取到當前選中內(nèi)容典鸡。然后使用document.createRange()保存下此時用戶選中區(qū)的狀態(tài)被廓,以供后面使用。
  3. 創(chuàng)建一個<textarea>標簽萝玷,將他移到屏幕外邊嫁乘,將上一步中的內(nèi)容,放到文本框內(nèi)球碉。并以字符串的形式添加上額外的內(nèi)容蜓斧。(注:為了能在添加的內(nèi)容達到換行的效果,需要使用<textarea>標簽而不是<input>睁冬,需要換行處添加'\n'字符串)
  4. 使用文本框的setSelectionRange()將文本框的內(nèi)容選中挎春,使用document.execCommand將此選中的內(nèi)容進行復制。
  5. 最后豆拨,使用selectionObject.addRange(range)將此前選中的選區(qū)進行選中直奋。(注:此處詳見參考資料3)

5. 實現(xiàn)代碼

此代碼在新版的chorme和firefox均可生效。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>addCopy</title>
    <style>
        #test {
            border: 1px solid #000;
        }
    </style>
</head>

<body>

    <dl id="test">
        <dt>
            <code>copy</code>
        </dt>
        <dd>拷貝當前選中內(nèi)容到剪貼板施禾。啟用這個功能的條件因瀏覽器不同而不同脚线,而且不同時期,其啟用條件也不盡相同弥搞。使用之前請檢查瀏覽器兼容表邮绿,以確定是否可用渠旁。</dd>
        <dt>
            <code>cut</code>
        </dt>
        <dd>&nbsp;剪貼當前選中的文字并復制到剪貼板。啟用這個功能的條件因瀏覽器不同而不同船逮,而且不同時期顾腊,其啟用條件也不盡相同。使用之前請檢查瀏覽器兼容表挖胃,以確定是否可用杂靶。</dd>
        <dt>
            <code>paste</code>
        </dt>
        <dd>在光標位置粘貼剪貼板的內(nèi)容,如果有被選中的內(nèi)容冠骄,會被替換伪煤。剪貼板功能必須在 user.js 配置文件中啟用。</dd>
    </dl>

    <p>復制以上黑框內(nèi)的內(nèi)容后在下面textarea粘貼看一下</p>
    <textarea rows="4"></textarea>

    <script type="text/javascript">
        function makeAdditionMessage(targetDom, additionMsg) {
            var body = document.getElementsByTagName('body')[0];
            //使用textarea可以在添加內(nèi)容的時候產(chǎn)生換行的效果
            var hideTextarea = document.createElement('textarea');
            body.appendChild(hideTextarea);
            hideTextarea.style.position = 'absolute';
            hideTextarea.style.left = '-9999px';
            hideTextarea.style.top = '-9999px';

            targetDom.addEventListener('copy', function (e) {
                // 禁止默認的copy事件
                e.preventDefault();
                var selectionObject = window.getSelection();
                var selectString = selectionObject.toString();

                // 注意凛辣,這里制作的range光標選中框需要放在 生成新選區(qū)之前進行制作
                var range = document.createRange();
                range.setStart(selectionObject.anchorNode, selectionObject.anchorOffset);
                range.setEnd(selectionObject.focusNode, selectionObject.focusOffset);

                // 添加新增的內(nèi)容抱既,并將它們放入剪切板
                hideTextarea.value = selectString;
                hideTextarea.value += additionMsg;
                hideTextarea.focus();
                hideTextarea.setSelectionRange(0, hideTextarea.value.length);
                var copy = document.execCommand('copy');

                // 將此前選中的文本再進行選中
                selectionObject.removeAllRanges();
                selectionObject.addRange(range);
            })
        }

        var test = document.getElementById('test');
        var msg = '\n\n這是額外的第一行內(nèi)容\n這是第二行';
        makeAdditionMessage(test, msg);
    </script>

</body>

</html>

6. 實現(xiàn)效果

  1. 選中某些文本進行復制
3.png
  1. 粘貼出來的示意圖
4.png

7. 參考資料

  1. https://developer.mozilla.org/zh-CN/docs/Web/API/Document/execCommand
  2. https://developer.mozilla.org/zh-CN/docs/Web/API/Window/getSelection
  3. http://www.zhangxinxu.com/wordpress/?p=1591
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市扁誓,隨后出現(xiàn)的幾起案子防泵,更是在濱河造成了極大的恐慌,老刑警劉巖蝗敢,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捷泞,死亡現(xiàn)場離奇詭異,居然都是意外死亡寿谴,警方通過查閱死者的電腦和手機锁右,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來讶泰,“玉大人咏瑟,你說我怎么就攤上這事』臼穑” “怎么了码泞?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長狼犯。 經(jīng)常有香客問我余寥,道長,這世上最難降的妖魔是什么悯森? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任宋舷,我火速辦了婚禮,結(jié)果婚禮上瓢姻,老公的妹妹穿的比我還像新娘肥缔。我一直安慰自己,他們只是感情好汹来,可當我...
    茶點故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布续膳。 她就那樣靜靜地躺著,像睡著了一般收班。 火紅的嫁衣襯著肌膚如雪坟岔。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天摔桦,我揣著相機與錄音社付,去河邊找鬼。 笑死邻耕,一個胖子當著我的面吹牛鸥咖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播兄世,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼啼辣,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了御滩?” 一聲冷哼從身側(cè)響起鸥拧,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎削解,沒想到半個月后富弦,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡氛驮,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年腕柜,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片矫废。...
    茶點故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡盏缤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出磷脯,到底是詐尸還是另有隱情蛾找,我是刑警寧澤,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布赵誓,位于F島的核電站打毛,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏俩功。R本人自食惡果不足惜幻枉,卻給世界環(huán)境...
    茶點故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望诡蜓。 院中可真熱鬧熬甫,春花似錦、人聲如沸蔓罚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至郑象,卻和暖如春贡这,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背厂榛。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工盖矫, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人击奶。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓辈双,卻偏偏與公主長得像,于是被迫代替她去往敵國和親柜砾。 傳聞我的和親對象是個殘疾皇子湃望,可洞房花燭夜當晚...
    茶點故事閱讀 44,601評論 2 353

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn)局义,斷路器喜爷,智...
    卡卡羅2017閱讀 134,651評論 18 139
  • 內(nèi)容來自于 iOS文檔中 About Text Handling in iOS 部分 ios平臺提供了顯示及編輯文...
    縱橫而樂閱讀 6,765評論 2 21
  • 之前是在一些類似于www.bootcss.com類似的網(wǎng)站見到過復制按鈕,點擊之后一整行文字都可以復制萄唇,然后到指定...
    李博洋li閱讀 23,691評論 4 9
  • 事件源對象 event.srcElement.tagName event.srcElement.type 捕獲釋放...
    孤魂草閱讀 888評論 0 0
  • Objective 你對今天學的記得什么檩帐? 1.尊重就像空氣。它存在的時候另萤,你感覺不到它湃密;但一旦它不存在了,你就立...
    太后只說話不發(fā)威閱讀 203評論 0 0