浏览器选择复制知多少

发布 : 2019-04-26 分类 : 前端,每天学一点 浏览 :

1. 简单的练手需求

现在有一个div元素,点击复制按钮后我希望复制div元素里的内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div id="target">我想被复制</div>
<button onclick="copy()">复制div里的内容</button>
<script>
var copyText = '';
window.addEventListener('copy', function (e) {
e.preventDefault();
e.clipboardData.setData('text/plain', copyText);
});

function copy() {
copyText = document.querySelector('#target').innerHTML;
document.execCommand('copy')
}
</script>

对于inputtextarea这类本身就可编辑的元素而言,直接取元素的value值即可。

2. 进阶需求

现在我们希望使用JavaScript复制指定区域的内容,并且保留浏览器渲染引擎渲染的样式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<div id="target">
<div>title is here</div>
<ul>
<li>aaa</li>
<li>bbb</li>
<li>ccc</li>
</ul>
</div>
<div>
<p>我不想被选中</p>
</div>
<div>
<button onclick="copy()" id="copy">复制</button>
</div>
<script>
var copyText = '';
window.addEventListener('copy', function (e) {
e.preventDefault();
e.clipboardData.setData('text/plain', copyText);
});

function copy() {
copyText = document.querySelector('#target').innerHTML;
document.execCommand('copy')
}
</script>

在这样的情况,我们粘贴出来的就是html文本,如果使用innerText,那么复制出来的就是纯文本,会丢失ul的样式。

我们希望看到的效果:

3. createRange

这种情况下,我们就必须老老实实得进行复制的流程,首先选中需要复制的内容,然后进行复制操作,将选中的内容放到剪贴板上。选中文本的过程就必须使用createRange方法了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<div id="target" contenteditable>
<div>title is here</div>
<ul>
<li>aaa</li>
<li>bbb</li>
<li>ccc</li>
</ul>
</div>
<div>
<p>我不想被选中</p>
</div>
<div>
<button onclick="func1()" id="choose">选择</button>
<button onclick="func2()" id="copy">复制</button>
</div>
</body>
<script>
function func1() {
selectText('target')
}

function func2() {
document.execCommand('copy')
}

function selectText(containerid) {
var range;
if (document.selection) {
range = document.body.createTextRange();
range.moveToElementText(document.getElementById(containerid));
range.select();
} else if (window.getSelection) {
range = document.createRange();
range.selectNodeContents(document.getElementById(containerid));
window.getSelection().removeAllRanges();
window.getSelection().addRange(range);
}
}
</script>

contenteditable属性可以使得div元素处于可编辑状态,这种情况下,在#target元素中使用ctrl+A时也不会选中页面中的其它内容,同样也适合那些复制之前需要编辑更改的内容。

IE9以下支持:document.selection

IE9、Firefox、Safari、Chrome和Opera支持:window.getSelection()

4. 选择指定长度的文本内容

在上面的范例里,我们使用了selectNodeContents()的方法,让我们可以选取整个指定的DOM

除了全选,我们也可以使用setStart()以及setEnd()的方法,指定要选取的文字,不过因为这两个方法是针对「节点node」的操作,所以放在里面的,就是我们要选择节点,以及从这个节点起算的第几个字元。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<div id="target" contenteditable>
<div id="start">title is here</div>
<ul>
<li>aaa</li>
<li id="end">bbb</li>
<li>ccc</li>
</ul>
</div>
<div>
<p>我不想被选中</p>
</div>
<div>
<button onclick="func1()" id="choose">选择</button>
<button onclick="func2()" id="copy">复制</button>
</div>
</body>
<script>
function func1() {
selectText()
}

function func2() {
document.execCommand('copy')
}

function selectText() {
var range;
if (window.getSelection) {
range = document.createRange();
// 注意setStart和setEnd的参数
range.setStart(document.querySelector('#start').firstChild, 0);
range.setEnd(document.querySelector('#end').firstChild, 3);
window.getSelection().removeAllRanges();
window.getSelection().addRange(range);
}
}
</script>

除了纯粹的选取之外,我们也可以使用cloneContents()方法来同时复制并贴上,使用deleteContents()来删除,使用extractContents()同时剪下并贴上。

5. 更多

本文源码地址:>>>点我进入

有contenteditable属性的容器,单击后选中全部文本:>>>点我进入

教你如何选中元素内的所有文本内容:>>>点我进入

selectNode和selectNodeContents的区别:>>>点我进入

自動選取某個區域的文字:>>>点我进入

MDN参考文档 - Range:>>>点我进入

本文作者 : 冰比冰水冰
原文链接 : http://iceiceice.top/2019/04/26/copy/
版权声明 : 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!
留下足迹