使用Vanilla JS实现一键完成范围选择和复制的功能
你好。
我是Mandai,负责Wild 开发团队。
ZeroClipboard实现了通过按下按钮将预定字符串复制到剪贴板的功能
Zero Clipboard 是一个库,允许您仅通过安装和加载 JavaScript 和 SWF 文件来创建复制按钮,我记得它非常容易安装。
不过,最近我感觉事情不太顺利,所以我想了想,意识到了一些事情。
Google Chrome 默认禁用 Flash!
并不是说不能玩Flash。
谷歌浏览器默认禁用 Flash 并不意味着它完全忽略它。
如果您进行适当的设置,它应该可以工作。
为了给您快速解释,请从 URL 字段右侧的三个垂直点中选择“设置”,然后从左上角的汉堡包中转到“高级设置”→“隐私和安全”。
Flash操作设置隐藏在“内容设置”类别中,因此请酌情更改。
把它放在这样的地方可能看起来像是一个恶意举动,但如果你问谷歌,它会合理地认为存在太多安全漏洞。
虽然是这样支持的,但是我不认为它以后会流行起来,所以我想尽快摆脱Flash。
JavaScript 最近已经标准化,其 API 也得到了改进。
也许是由于最近 JavaScript 的流行,JavaScript 在浏览器端的实现正在以极快的速度进展。
最近,jQuery 经常被视为坏人,因为它会导致网站渲染速度变慢,但实际上,在很多情况下您可以对此采取一些措施。
我想有很多情况你别无选择,只能引入它,因为CSS框架已经采用了它。
将字符串复制到剪贴板的过程(即本文的主题)是一个典型的示例,该过程曾经无法单独使用 JavaScript 完成,但现在可以完成!
这就是“Vanilla JS”发挥作用的地方。
所以,介绍变得很长,但从现在开始我想尝试使用纯 Vanilla JS 复制到剪贴板。
处理顺序是
- 选择要复制的字符串
- 复制
就这样。
选择要复制的字符串
选择字符串比复制需要更多步骤,因此一旦理解了这部分,就可以在这里完成。
有两个与字符串选择相关的对象:Range 对象和 Selection 对象。
Range 对象是一个保存指示选择页面范围的信息的对象。
另外,Selection 对象是管理 Range 对象的站立对象,并且具有一个或多个 Range 对象。
由于是 Range 对象选择字符串,因此您可以通过从 Selection 对象中提取 Range 对象或创建一个新的 Range 对象来获取 Range 对象。
// 创建一个新的 Range 对象 var range = document.createRange(); // 从 Selection 对象获取 Range 对象 var Selection = window.getSelection(); var range = Selection.getRangeAt(0);
无论您使用哪种方法获取它,变量 range 的内容都是相同的 Range 对象,因此您可以以任何您喜欢的方式准备 Range 对象。
这次,我将尝试使用从 Selection 对象中提取的 Range 对象来实现它。
假设包含要复制的字符串的标签如下所示:
<div id="hoge">你想要复制的字符串</div>
使用 getElementById() 方法获取 DOM。
var hoge = document.getElementById('hoge');
接下来,指定选择范围。
有两种方法可以指定: 如果要复制 DOM 元素的所有内容,请使用 Range 对象的 selectNodeContents() 方法。
range.selectNodeContents(hoge);
另外,如果您只想复制 DOM 元素的一部分,请使用 Range 对象的 setStart() 方法指定起点,并使用 setEnd() 方法指定终点。
这里需要注意的是,如果使用 getElementById() 方法只获取到 DOM 的一部分,如果将其原样传递给 setStart() 和 setEnd() 方法,通常会出现错误,因此只需提取列的节点并传递它。
range.setStart(hoge, 7); range.setEnd(hoge, 15); // 发生错误 // 未捕获 IndexSizeError: 无法在 'Range' 上执行 'setStart': 偏移量 7 处没有子项。
这个错误中的IndexSize意味着通过查看hoge对象中DOM数组的索引,没有第七个Node。我们以为我们会传递一个字符串并使用第七个字符作为起点,但是识别似乎存在差异。
因此,需要将hoge对象中包含的文本节点传递给setStart()和setEnd()方法的第一个参数。检索文本节点的最佳方法似乎是从firstChild 属性。
var hoge = document.getElementById('hoge'); var hogeTextNode = hoge.firstChild; range.setStart(hogeTextNode, 7); range.setEnd(hogeTextNode, 15);
一旦指定了选择范围,您所要做的就是将其选中,但这里也存在陷阱。
要进行选择,只需使用 addRange() 方法将具有指定选择范围的 Range 对象添加到 Selection 对象即可。
Selection.addRange(range); // 发生错误 // 不支持不连续选择。
意思是不支持不连续(non-contigious)Selection,但是不连续是什么意思呢?
在此示例中,Range 对象是从 Selection 对象中提取的,这就是上述错误的含义。
Selection 对象已经有一个 Range 对象,因此如果使用 addRange() 方法添加它,它将有两个 Range 对象,这就是错误指示的不连续 Selection 状态。
你要指定为选择范围的是后面添加的Range对象,所以最快的方法就是把Selection对象一开始就有的Range对象删除,添加一个Range对象,这是一种创建状态的方法你只有一个的地方。
Selection.removeAllRanges(); // 顾名思义,删除所有 Range 对象 Selection.addRange(range);
现在您可以选择它。
综上所述,要在屏幕上选择一个字符串,代码如下。
// 从 Selection 对象获取 Range 对象 var Selection = window.getSelection(); var range = Selection.getRangeAt(0); var textNode = document.getElementById('hoge').firstChild; // DOM 中的字符串.selectNodeContents(textNode); // 使用 selectNodeContents() 方法,无需提取文本节点 // 仅选择 DOM 的一部分 range.setStart(textNode, 7); // 通过Selection对象设置selection.removeAllRanges(); Selection.addRange(range);
将字符串复制到剪贴板
要对所选字符串执行“Ctrl + C”,请使用下面的 execCommand() 方法。
document.execCommand('复制');
现在您已将选定的字符串复制到剪贴板,您所要做的就是在任意位置按“Ctrl + V”。
概括
选择字符串花了相当多的空间,但你觉得呢?
它在 Stack Overflow 等上到处发布,但我不知道为什么会发生错误,因为没有总结理解它所需的信息,而且我觉得我不擅长在 JavaScript 中使用剪贴板。做到了,所以如果你能理解错误背后的逻辑,那就不再可怕了。
就是这样。