【问题标题】:Find the relative position-in-DOM of two elements anywhere within an HTML document查找 HTML 文档中任意位置的两个元素在 DOM 中的相对位置
【发布时间】:2021-11-20 20:42:43
【问题描述】:

我有一些 HTML 可以包含带有特定类的<span>s(我们称之为marker)。这些 span 可以位于文档中特定 <div> 下的任何位置 - 作为直接子节点,或任意深度嵌套在其他节点中。

然后我有一段由用户选择的特定文本(所以我可以使用window.getSelection() 调用从Selection.anchorNode 中找到锚节点)。我想根据需要使用 Javascript 和 jQuery 找出 last marker <span> 在选择之前出现在文档中。例如:

<div class="container">
  <div>
    <div>
      <span>Some text<span class="marker">Marker 1</span></span>
    </div>
    <div>
       <div>
          <span>Foo</span>
          <span>THIS IS THE SELECTION ANCHOR NODE</span>
       </div>
       <span class="marker">Marker 2</span>
  </div>
</div><!-- end of container -->

会找到Marker 1,即使他们是“表亲”。

是否有一种“标准”方法来确定一个元素在 DOM 中的相对“线性”位置,以便我可以确定一个元素是否在另一个元素“之前”?

我不关心页面上的位置 (x, y),所以 CSS order 之类的东西无关紧要。


我曾想过,但似乎并不理想:

  • 使用[closest()][2] 遍历每个.marker 的父级(和选择范围)并构造某种节点的字典顺序,这似乎很昂贵且容易出错
  • 遍历.markers 的父级并存储在其中找到的跨度列表

对于听起来好像 DOM 已经知道的东西(因为文档有其特定的顺序),它们似乎都需要大量的簿记和手动 DOM 遍历。

【问题讨论】:

  • 我投票结束这个问题,因为表明缺乏研究。
  • 你用什么代码来获取你的 div。这也与这个问题有关。
  • 这能得到你想要的吗? jsfiddle.net/p4bf6ceg
  • @HanletEscaño 没有从 Selection 对象引用锚节点,所以它根本不依赖于选择?该节点是来自selection.anchorNode 的直接HTML 元素,但可以使用$( anchor_node ) 轻松进行jQuery 处理。

标签: javascript html jquery dom


【解决方案1】:

如果我对您的理解正确,这应该可以帮助您:

let xpath = '(//span[@class="marker"][not(.//preceding::*[contains(.,"SELECTION ANCHOR")])])[last()]',
result = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
console.log(result.textContent);    

【讨论】:

  • 如果用户选择了在文档中多次出现的文本,这将不起作用。
【解决方案2】:

您可以使用Node.prototype.compareDocumentPosition 方法来确定一个元素是否在另一个元素之前:

const anchor = document.getElementById("anchor");
const markers = document.querySelectorAll(".marker"); // get all the markers in DOM order
const previous = [...markers].filter( // get only the markers before
  (elem) => anchor.compareDocumentPosition(elem) === Node.DOCUMENT_POSITION_PRECEDING
).pop(); // get the last one
console.log( previous );
<div class="container">
  <div>
    <div>
      <span>Some text<span class="marker">Marker 0</span></span>
      <span>Some text<span class="marker">Marker 1</span></span>
    </div>
    <div>
       <div>
          <span>Foo</span>
          <span id="anchor">THIS IS THE SELECTION ANCHOR NODE</span>
       </div>
       <span class="marker">Marker 2</span>
  </div>
</div><!-- end of container -->

【讨论】:

  • 确认!它有一个功能!谢谢!还有一种很好的方法来找出正确的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-22
  • 2011-11-22
  • 2022-07-30
  • 1970-01-01
  • 2012-01-05
相关资源
最近更新 更多