document.caretPositionFromPoint抓得太高了

时间:2014-06-23 07:34:18

标签: javascript firefox firefox-addon firefox-addon-sdk

我正在处理my "jump-to-anchor" add-on的更新,这是一个Firefox附加组件,可让您右键单击文档中的某个位置(希望)获得最接近点击点的锚点。

在提交附加组件后,我意识到我可以通过查找单击的实际文本节点来改进算法,并从那里查找(而不是当前单击元素的第一个子节点)。但是,在我的测试中(针对我刚刚阅读的页面http://tools.ietf.org/html/rfc5323#section-2.3.2),通过document.caretPositionFromPoint抓取的文本节点高于预期。

var x = 0, y = 0;
window.addEventListener('click', function (e) {
    if (e.button === 2) { // Avoid grabbing for the actual selection // Doesn't seem to execute on the final context menu click anyways
        x = e.pageX;
        y = e.pageY;
    }
});
self.on('click', function () { // , data
    // I added the next two lines just in case the user clicked off screen
    x = x > window.mozInnerScreenX ? window.mozInnerScreenX : (x < 0 ? 0 : x);
    y = y > window.mozInnerScreenY ? window.mozInnerScreenY : (y < 0 ? 0 : y);
    var caretPosition = document.caretPositionFromPoint(x, y);
    var node = caretPosition.offsetNode;

    // Doesn't grab the right node.nodeValue here always--seems to grab too high up

    // (Then search the node for an anchor, or recursively check the deepest child of the previous element sibling on up and keep looking for previous element siblings.)
});

听起来像个臭虫?

更新

重现的步骤:

  1. https://github.com/brettz9/jump-to-anchor/tree/document.caretPositionFromPoint安装XPI(或使用带有SDK的cfx xpi从源代码安装)
  2. 转到http://tools.ietf.org/html/rfc5323#section-2.3.2
  3. 尝试在第2.3.3节(注释:2.3.3)中右键单击并查看它经常一直到#34;#page-10&#34;锚而不是&#34;#section-2.3.3&#34;锚
  4. (在Github的当前代码中,我已将e.button === 2检查注释掉,但结果是相同的。)

1 个答案:

答案 0 :(得分:2)

事实证明,MDN上的文档是完全错误的。 .caretPositionFromPoint期望you pass coordinates relative to the current viewport

因此,您必须使用e.clientX / e.clientY

此外,.mozInnerScreenX / Y并没有做您预期的事情。如果要检查window.innerWidth.innerHeight是视口中的有效坐标,请使用x / y

所以这就是我尝试过的以及似乎有用的内容(摘录):

var x = 0, y = 0;
window.addEventListener('click', function (e) {
        x = e.clientX;
        y = e.clientY;
});
self.on('click', function () { // , data
    x = Math.max(0, Math.min(innerWidth, x));
    y = Math.max(0, Math.min(innerHeight, y));
    var caretPosition = document.caretPositionFromPoint(x, y);
    var node = caretPosition.offsetNode;
    // ...
});