问题
I'm working on an update to my "jump-to-anchor" add-on which is a Firefox add-on to let you right-click somewhere in a doc to (hopefully) get the closest anchor above the click point.
After submitting the add-on, I realized I could improve the algorithm by finding the actual text node where clicked, and look up from there (instead of the first children of the current clicked element). However, in my tests (against a page I happened to be reading, http://tools.ietf.org/html/rfc5323#section-2.3.2 ), the text node grabbed via document.caretPositionFromPoint is higher than expected.
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.)
});
Sound like a bug?
UPDATE:
Steps to reproduce:
- Install the XPI from https://github.com/brettz9/jump-to-anchor/tree/document.caretPositionFromPoint (or use
cfx xpi
with SDK to install from source) - Go to http://tools.ietf.org/html/rfc5323#section-2.3.2
- Try right-clicking within section 2.3.3 (note: 2.3.3) and see it often go all the way up to the "#page-10" anchor instead of the "#section-2.3.3" anchor.
(In the current code at Github, I have the e.button === 2
check commented out, but the result is the same.)
回答1:
Turns out that the documentation on MDN is outright wrong. .caretPositionFromPoint
expects that you pass coordinates relative to the current viewport.
So you'll have to use e.clientX
/e.clientY
!
Also, .mozInnerScreenX
/Y
doesn't do what you might expect it to do. Use window.innerWidth
/.innerHeight
if you want to check that x
and y
are valid coordinates within the viewport.
So here is what I tried and what seems to have worked (excerpt):
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;
// ...
});
来源:https://stackoverflow.com/questions/24360624/document-caretpositionfrompoint-grabbing-too-high