Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Browser/Selection & Range #8

Open
canvascat opened this issue Jan 8, 2021 · 0 comments
Open

Browser/Selection & Range #8

canvascat opened this issue Jan 8, 2021 · 0 comments

Comments

@canvascat
Copy link
Owner

下面是一段复制 html 到剪切板的代码:

function copyHTMLElementToClipboard(targetNode: Node) {
  const selection = window.getSelection()
  selection.removeAllRanges()
  const range = new Range()
  range.selectNode(targetNode)
  selection.addRange(range)
  document.execCommand('copy')
  selection.removeAllRanges()
}

Range 本质上是一对“边界点”:范围起点和范围终点。range 对象具有以下属性:

image

  • startContainerstartOffset —— 起始节点和偏移量,
    • 在上例中:分别是 <p> 中的第一个文本节点和 2
  • endContainerendOffset —— 结束节点和偏移量,
    • 在上例中:分别是 <b> 中的第一个文本节点和 3
  • collapsed —— 布尔值,如果范围在同一点上开始和结束(所以范围内没有内容)则为 true
    • 在上例中:false
  • commonAncestorContainer —— 在范围内的所有节点中最近的共同祖先节点,
    • 在上例中:<p>

最开始的例子中用到了 Range.selectNode(targetNode) 方法,它将 Range 设置为包含整个 targetNode 及其内容。Range 的起始和结束节点的父节点与 targetNode 的父节点相同。

另外两个方法更能精确设置范围:

  • range.setStart(startNode, startOffset):startNode 用于设定起始位置,startOffset 表示从 startNode 的开始位置算起的偏移量。
  • range.setEnd(endNode, endOffset): endNode 用于设定结束位置,endOffset 表示从 endNode 的结束位置算起的偏移量。

其中 offset 偏移是以节点为单位:

<p id="p">Example: <i>italic</i> and <b>bold</b></p>
<script>
  const range = new Range();
  range.setStart(p, 1);
  range.setEnd(p, 3);
</script>

得到的范围为 <i>italic</i> and ,如果要精确到文字,则 Node 需要精确到文字节点:

range.setStart(p.firstChild, 2);
range.setEnd(p.firstChild.nextSibling.nextSibling, 2);

得到范围 ample: <i>italic</i> an

在创建了选择范围后需要将选择范围附加到网页中,文档选择则由 Selection 对象表示的,可通过 window.getSelection()document.getSelection() 来获取。

回到第一个例子,使用 selection.removeAllRanges() selection 对象中移除所有的 range,然后创建新的 range,使用 selection.addRange 添加,最后使用 document.execCommand('copy') 执行复制。

提到 execCommand,在MDN文档中可以发现 Obsolete 标注,替代方案有 Clipboard,不过操作起来比较繁琐,还需要向用户申请权限(也许安全问题就是 execCommand Obsolete 的原因吧)。

参考:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant