18

I've been searching a lot but i could't find a way to get (X,Y) coordinates for the caret on a content editable div,there's a lot of content on the web about this,but the problem none of the pages i found get the coordinates according to the top of the div,so my question in a simpler way is:

How can i get the (X,Y) coordinates of the caret on a contenteditable div,but the Y coordinate must be calculated according to the top of the div and not from the top of the visible part of the page?

Note 1: I need specially the Y coordinate.

Note 2: I can only use pure javascript,no JQUERY.

My way:

I haven't found a direct way to do this,so as a workaround i thought on getting the Y coordinate according to the visible part of the page and the hidden part of the Div and sum the results(I'm currently working on this but i getting no luck!).

Mateus
  • 2,640
  • 5
  • 44
  • 62

4 Answers4

11

try this:

var selection = window.getSelection(),
    range = selection.getRangeAt(0),
    rect = range.getClientRects()[0];

in the rect var you should find the position:

rect.left -> for the x coordinate rect.top -> for the y coordinate

there is also rect.width and rect.height. In case the user has some text selected rect.width will be >0.

Oliver Wolf
  • 249
  • 4
  • 8
  • my client rects have a length of 0 – Vasily Hall May 13 '20 at 18:52
  • Slightly weirdly, rect.width can be > 0 if the caret is at the end of a line too. The selection seems to contain the "virtual" newline added by wrapping the text. So a better way of checking if there's text selected is to see if the start and end containers and offsets are both equal. Not massively relevant, but curious! – Peter Bagnall Jul 30 '20 at 08:53
9
  1. get selection and range

     var sel = window.getSelection();
     var range = sel.getRangeAt(0);
    
  2. insert collapsed div

     var div = document.createElement(...)
     range.insertNode(div)
    
  3. get div coordinates

  4. remove the div
Edgar Abgaryan
  • 113
  • 1
  • 7
0

to find on (X,Y) coordinate and using pure javascript, this function I found may do the trick: in this Source you will find all explanation about their process (the code below is taken from the same source):

function getPosition(el) {
  var xPos = 0;
  var yPos = 0;

  while (el) {
    if (el.tagName == "BODY") {
      // deal with browser quirks with body/window/document and page scroll
      var xScroll = el.scrollLeft || document.documentElement.scrollLeft;
      var yScroll = el.scrollTop || document.documentElement.scrollTop;

      xPos += (el.offsetLeft - xScroll + el.clientLeft);
      yPos += (el.offsetTop - yScroll + el.clientTop);
    } else {
      // for all other non-BODY elements
      xPos += (el.offsetLeft - el.scrollLeft + el.clientLeft);
      yPos += (el.offsetTop - el.scrollTop + el.clientTop);
    }

    el = el.offsetParent;
  }
  return {
    x: xPos,
    y: yPos
  };
}
Simo
  • 431
  • 1
  • 7
  • 20
-1

try this http://plnkr.co/edit/T2S7sKByTIesEVC6R8jQ?p=preview

document.addEventListener("DOMContentLoaded", function(event) { 
  var pointer = document.querySelector('#marker')
  function checkCaret() {
    if(document.getSelection()) {
      if(document.getSelection().baseNode) {
        var position = document.getSelection().baseNode.parentNode.getBoundingClientRect()
        pointer.style.top = position.top + 'px'
      }
    }
  }
  setInterval(checkCaret, 500)
});
Marcus
  • 341
  • 1
  • 8