After searching for a way to get the text Y and X position in an element on-click, I came across this question How to get the position of text within an element?
aaron‘s answer was the closest i got to what i need.
I tried to change the script a bit but with partial success.
Here is my progress, i get this error { "message": "Uncaught IndexSizeError: Failed to execute 'setStart' on 'Range': There is no child at offset 512.", "filename": "https://stacksnippets.net/js", "lineno": 38, "colno": 15 }
when pressing on childNodes 3 and 5.
How do i go about getting childNodes 3 and 5 and etc. to give a response similar to “childNode 1” without wrapping the text with a span tag?
function findClickedWord(parentElt, x, y) {
/*if (parentElt.nodeName !== '#text') {
console.log('didn't click on text node');
return null;
}*/
var range = document.createRange();
//var words = parentElt.textContent;//.split(' ');
var sentences = [];
console.log('parentElt.childNodes.length ',parentElt.childNodes.length)
for (var i = 0; i < parentElt.childNodes.length; i++) {
sentences[i] = parentElt.childNodes[i].textContent
}
var start = 0;
var end = 0;
for (var i = 0; i < sentences.length; i++) {
var words = sentences[i];
end = start+words.length;
range.setStart(parentElt.childNodes[i], start);
range.setEnd(parentElt.childNodes[i], end);
var rects = range.getClientRects();
var clickedRect = isClickInRects(rects);
if (clickedRect) {
return [words, start, clickedRect];
}
start = end + 1;
}
function isClickInRects(rects) {
for (var i = 0; i < rects.length; ++i) {
var r = rects[i]
if (r.left<x && r.right>x && r.top<y && r.bottom>y) {
return r;
}
}
return false;
}
return null;
}
function onClick(e) {
var elt = document.getElementById('info');
var clicked = findClickedWord(e.target, e.clientX, e.clientY);
/*var clicked = [];
for (var i = 0; i < e.target.childNodes.length; i++) {
if(e.target.childNodes[i])
clicked = findClickedWord(e.target.childNodes[i], e.clientX, e.clientY);
}*/
elt.innerHTML = 'Nothing Clicked';
if (clicked) {
var myChildNode = clicked[0];
var start = clicked[1];
var r = clicked[2];
elt.innerHTML = 'Clicked: (top:'+r.top+', left:'+r.left+') context of:'+myChildNode+' at offset '+start;
}
}
document.addEventListener('click', onClick);
#info {
position: absolute;
bottom: 0;
background-color: cyan;
}
<div class="parent">
<div class="child"> (childNode 1) Bacon ipsum dolor amet meatball bresaola t-bone tri-tip brisket. Jowl pig picanha cupim landjaeger, frankfurter spare ribs chicken. Porchetta jowl pancetta drumstick shankle cow spare ribs jerky tail kevin biltong capicola brisket venison bresaola. Flank sirloin jowl andouille meatball venison salami ground round rump boudin turkey capicola t-bone. Sirloin filet mignon tenderloin beef, biltong doner bresaola brisket shoulder pork loin shankle turducken shank cow. Bacon ball tip sirloin ham. <div> (childNode 2) "this text is Ok if clicked"</div> (childNode 3) click on this text to see the error <a href='#'> (childNode 4) Link is Ok if clicked</a> (childNode 5) and click here two see anther error.
</div>
<div id="info">Click somewhere in the paragraph above</div>
</div>