获取精确的浏览器呈现文本(RTL和LTR方向混合)

时间:2017-06-22 09:21:22

标签: javascript html right-to-left bidi

有没有办法通过浏览器检索实际呈现的文本(在从右到左文本方向的上下文中)?

<html dir="rtl">
<body>
  <p id='ko'>Hello (world)</p>
  <p id='ok'>Hello <bdo dir='ltr'>(world)</bdo></p>
</body>
</html>

将呈现:

  • in chrome

enter image description here

  • in firefox

enter image description here

但两者都有 document.getElementById('ok').textContent === document.getElementById('ko').textContentdocument.getElementById('ok').innerText === document.getElementById('ko').innerTexttrue(适用于两种浏览器)。

有没有办法获取网页中显示的实际文字?

https://jsfiddle.net/019kvo56/1/

1 个答案:

答案 0 :(得分:1)

您可以从direction获取getComputedStyle(elem) CSS属性,但这只是在元素级别,因此您无法确切知道浏览器如何呈现textNodes

所以你需要做的是:

  • 首先从容器中获取所有textNodes(最好使用TreeWalker)。
  • 使用Range object
  • 选择每个字符
  • 凭借Range getBoundingClientRect()方法获取每个角色的当前位置。
  • 对它们进行排序
  • 取回他们的文字值

这是一个现场演示:

&#13;
&#13;
function getDisplayedText(container) {

  var r = document.createRange(); // to get our nodes positions

  var nodes = []; // first grab all the nodes
  var treeWalker = document.createTreeWalker(container, NodeFilter.SHOW_TEXT, null, false);
  while (treeWalker.nextNode()) nodes.push(treeWalker.currentNode);

  var chars = []; // then get all its contained characters
  nodes.forEach(n => {
    n.data.split('').forEach((c, i) => {
      r.setStart(n, i); // move the range to this character
      r.setEnd(n, i+1);
      chars.push({
        text: c,
        rect: r.getBoundingClientRect() // save our range's DOMRect
      })
    })
  });

  return chars.filter(c => c.rect.height) // keep only the displayed ones (i.e no script textContent)
    .sort((a, b) => { // sort ttb ltr
      if (a.rect.top === b.rect.top) {
        return a.rect.left - b.rect.left;
      }
      return a.rect.top - b.rect.top;
    })
    .map(n => n.text)
    .join('');
}

console.log('ko : ', getDisplayedText(ko));
console.log('ok : ', getDisplayedText(ok));
&#13;
<div dir="rtl">
  <p id='ko'>Hello (world)</p>
  <p id='ok'>Hello <bdo dir='ltr'>(world)</bdo></p>
</div>
&#13;
&#13;
&#13;

现在,至于为什么webkit确实渲染了最后一个)翻转并且首先...我不知道他们是否正确或不这样做...