Reputation: 15715
Just like I can get an element from a point with document.elementFromPoint
or document.getElementFromPoint
, is it possible to somehow get a text node if the point is at a text node? I guess if at least I could get the text node's position and size I could then figure out which of them contains the point. But then DOM nodes don't have position properties. Is it possible to do this at all?
Upvotes: 15
Views: 3433
Reputation: 1692
You can use document.caretPositionFromPoint(x, y)
for this but note that you'll need to fall back to document.caretRangeFromPoint(x, y)
if document.caretPositionFromPoint
is not available (e.g. in Safari as of writing, and Chrome/Edge versions before v128).
caretRangeFromPoint
is non-standard, and deprecated, but it won't be removed at this point since many sites rely on it. So between those two, you have full browser support.
If you're dealing with a huge number of nodes, this should be much more performant than iterating through all text nodes, creating ranges, and checking the bounds of those ranges.
Upvotes: 4
Reputation: 196
Here is an implementation that works in all current browsers: https://github.com/nuxodin/q1/blob/master/q1.dom.js
document.betaNodeFromPoint = function(x, y){
var el = document.elementFromPoint(x, y);
var nodes = el.childNodes;
for ( var i = 0, n; n = nodes[i++];) {
if (n.nodeType === 3) {
var r = document.createRange();
r.selectNode(n);
var rects = r.getClientRects();
for ( var j = 0, rect; rect = rects[j++];) {
if (x > rect.left && x < rect.right && y > rect.top && y < rect.bottom) {
return n;
}
}
}
}
return el;
};
Upvotes: 18
Reputation: 173532
Considering this document (fiddle):
<html>
<body>
some text here
<p id="para1">lalala</p>
bla bla
</body>
</html>
And this code:
$(document).on('click', function(evt) {
var elem = document.elementFromPoint(evt.clientX, evt.clientY);
console.log(elem);
});
When you click anywhere inside the <p>
tag, the tag element itself is logged. However, when the surrounding text is clicked, the <body>
is returned because text fragments are not considered elements.
Conclusion
It's not possible to accomplish what you want with elementFromPoint()
and because text fragments don't receive click events, I don't think it's possible at all.
Upvotes: 0
Reputation: 57209
You can use element.nodeName
to see if it's a text node, and then element.nodeValue
for its value.
Upvotes: 0