获取所选文本的所有 DOM 块元素

发布于 2024-10-03 23:28:26 字数 373 浏览 3 评论 0原文

在 HTML 文档中选择文本时,可以从一个 DOM 元素开始到另一个元素,途中可能会跳过多个其他元素。使用 DOM API,可以获得选择范围、所选文本,甚至所有所选 DOM 元素的父元素(根据所使用的浏览器使用 commonAncestorContainer 或parentElement())。但是,据我所知,除了获取包含所有元素的单个父元素之外,无法列出所有包含所选文本元素的元素。使用父节点并遍历子节点是行不通的,因为在该父节点中可能还有其他未选择的同级节点。

那么,有没有一种方法可以获取包含所选文本的所有这些元素。我主要对获取块元素(p,h1,h2,h3,...等)感兴趣,但我相信如果有一种方法可以获取所有元素,那么我可以遍历它们并过滤它们以获得我想要的想。我欢迎任何想法和建议。

谢谢。

When selecting texts in HTML documents, one can start from within one DOM element to another element, possibly passing over several other elements on the way. Using DOM API, it is possible to get the range of the selection, the selected texts, and even the parent element of all those selected DOM elements (using commonAncestorContainer or parentElement() based on the used browser). However, there is no way I am aware of that can list all those containing elements of the selected texts other than getting the single parent element that contains them all. Using the parent and traversing the children nodes won't do it, as there might be other siblings which are not selected inside this parent.

So, is there is a way that I can get all these elements that contains the selected texts. I am mainly interested in getting the block elements (p, h1, h2, h3, ...etc) but I believe if there is a way to get all the elements, then I can go through them and filter them to get what I want. I welcome any ideas and suggestions.

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

江南烟雨〆相思醉 2024-10-10 23:28:26

关键是 window.getSelection().getRangeAt(0) https:// developer.mozilla.org/en/DOM/range

这里有一些示例代码,您可以使用它们来完成您想要的操作。提及您真正想要的目的将有助于人们提供更好的答案。

var selection = window.getSelection();
var range = selection.getRangeAt(0);
var allWithinRangeParent = range.commonAncestorContainer.getElementsByTagName("*");

var allSelected = [];
for (var i=0, el; el = allWithinRangeParent[i]; i++) {
  // The second parameter says to include the element 
  // even if it's not fully selected
  if (selection.containsNode(el, true) ) {
    allSelected.push(el);
  }
}


console.log('All selected =', allSelected);

这不是最有效的方法,您可以使用 Range 的 startContainer/endContainer 以及 nextSibling/previousSibling 和 childNode 自己遍历 DOM。

Key is window.getSelection().getRangeAt(0) https://developer.mozilla.org/en/DOM/range

Here's some sample code that you can play with to do what you want. Mentioning what you really want this for in question will help people provide better answers.

var selection = window.getSelection();
var range = selection.getRangeAt(0);
var allWithinRangeParent = range.commonAncestorContainer.getElementsByTagName("*");

var allSelected = [];
for (var i=0, el; el = allWithinRangeParent[i]; i++) {
  // The second parameter says to include the element 
  // even if it's not fully selected
  if (selection.containsNode(el, true) ) {
    allSelected.push(el);
  }
}


console.log('All selected =', allSelected);

This is not the most efficient way, you could traverse the DOM yourself using the Range's startContainer/endContainer, along with nextSibling/previousSibling and childNodes.

浪推晚风 2024-10-10 23:28:26

您可以使用我的 Rangy 库 来执行此操作。它为所有浏览器(包括 IE)提供了 DOM Range 和 Selection 对象的实现,并具有额外的 Range 方法。其中之一是 getNodes()

function isBlockElement(el) {
    // You may want to add a more complete list of block level element
    // names on the next line
    return /h[1-6]|div|p/i.test(el.tagName);
}

var sel = rangy.getSelection();
if (sel.rangeCount) {
    var range = sel.getRangeAt(0);
    var blockElements = range.getNodes([1], isBlockElement);
    console.log(blockElements);
}

You can use my Rangy library to do this. It provides an implementation of DOM Range and Selection objects for all browsers, including IE, and has extra Range methods. One of these is getNodes():

function isBlockElement(el) {
    // You may want to add a more complete list of block level element
    // names on the next line
    return /h[1-6]|div|p/i.test(el.tagName);
}

var sel = rangy.getSelection();
if (sel.rangeCount) {
    var range = sel.getRangeAt(0);
    var blockElements = range.getNodes([1], isBlockElement);
    console.log(blockElements);
}
撑一把青伞 2024-10-10 23:28:26

听起来您可以使用从 jQuery API 遍历

可能是 .contents()

希望有帮助!

It sounds like you could use Traversing from the jQuery API.

Possibly .contents()

Hope that helps!

梦醒灬来后我 2024-10-10 23:28:26

这是基于 @Juan Mendes 回复的 es6 方法:

const selection = window.getSelection();
const range = selection.getRangeAt(0);
const elementsFromAncestorSelections = range.commonAncestorContainer.getElementsByTagName("*");

const allSelectedElements = Array.from(elementsFromAncestorSelections).reduce(
  (elements, element) =>
    selection.containsNode(element, true)
      ? [...elements, element]
      : elements,
  [],
);

Here is a es6 approach based on @Juan Mendes response:

const selection = window.getSelection();
const range = selection.getRangeAt(0);
const elementsFromAncestorSelections = range.commonAncestorContainer.getElementsByTagName("*");

const allSelectedElements = Array.from(elementsFromAncestorSelections).reduce(
  (elements, element) =>
    selection.containsNode(element, true)
      ? [...elements, element]
      : elements,
  [],
);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文