4

I need to get the line number with the cursor in it or better the offset of the cursor in a contenteditable body element.

How can i achieve this?

Thariama
  • 50,002
  • 13
  • 138
  • 166
  • Please add an example HTML ` – powtac Feb 21 '12 at 17:57
  • 2
    possible duplicate of [How to get cursor position in textarea?](http://stackoverflow.com/questions/263743/how-to-get-cursor-position-in-textarea) – FishBasketGordo Feb 21 '12 at 17:57
  • 2
    Please ask a new question instead of changing the context heavily. – Bergi Feb 21 '12 at 18:03
  • @Thariama Did you end up finding a solution for this? – Sherwin Yu Dec 18 '13 at 05:55
  • @SherwinYu: Yes, but it will only work if the line-height of all lines is the same. The idea is to insert a dummy element at the caret posititon calculate the position relative to the body start and then divide this value with the line height. this gives you the line numbers – Thariama Dec 18 '13 at 13:38
  • @Thariama Wow that is quite involved (and a very cool hack). Thanks. Did you happen to find a code sample of this? – Sherwin Yu Dec 18 '13 at 14:03
  • @SherwinYu: i added an answer with code to get you started – Thariama Dec 18 '13 at 15:35

2 Answers2

2

I found a solution to my problem, but it will only work if the line-height of all lines are the same. The idea is to insert a dummy element at the caret posititon, calculate the position relative to the body start and then divide this value by the line-height. The result is the number of line the caret is in.

Here some code to get started with:

        // get lineheight, eighter line-height or min-height
        var $elem = $(ed.getBody().firstElementChild);
        var lineHeight = parseInt($elem.css('line-height'), 10) || parseInt($elem.css('min-height'), 10);

        var rng = ed.selection.getRng();
        rng.collapse(true);

        var bm = ed.selection.getBookmark();
        var $marker = $(ed.getBody()).find('#'+bm.id);
        var elem = ed.getDoc().getElementById(bm.id+'_start');
        try {
            box = elem.getBoundingClientRect();
        } 
        catch(e){}

        var doc = ed.getDoc(),
            docElem = doc.documentElement,
            body = ed.getBody(),
            win = ed.getWin(),
            clientTop  = docElem.clientTop  || body.clientTop  || 0,
            clientLeft = docElem.clientLeft || body.clientLeft || 0,
            scrollTop  = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop,
            scrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,
            top  = box.top  + scrollTop  - clientTop,
            left = box.left + scrollLeft - clientLeft;

        // set Bookmark
        ed.selection.moveToBookmark(bm);

        var caret_line = Math.floor( (top) / lineHeight ) + 1;
Thariama
  • 50,002
  • 13
  • 138
  • 166
0

Here is one of my older tools on the subject.

/**
 * @description This operation splits the content of a text area based on its cursor position
 *              and selection.
 * @param targetNode This argument expects the text node to be split.
 * @return This operation returns an object containing {first, middle, last}.
 */
var splitTextAreaBySelection = function(targetNode)
{
  var target = document.getElementById('Area_'+targetNode.uid);
  var response = {};

  // IE fails this DOM3 operation. Use IE proprietary code here to recover.
  // WARNING: This proprietary IE code has Win32 platform dependency!
  if (typeof(target.selectionStart) === "undefined")
  {
    var content = targetNode.content;
    // this captures the area selected text.
    var r = document.selection.createRange();
    if (r !== null) {
      // thankfully the middle is easy to get!
      response.middle = r.text;
      // now we must create a new text range and mess with it until the cursor             position can be discovered.
      var re = target.createTextRange();
      var rc = re.duplicate();
      re.moveToBookmark(r.getBookmark());
      rc.setEndPoint('EndToStart', re);          
      var cursorPos = rc.text.length;
      // now that we have the cursor position, we can abstract the first and last         strings from the content.
      response.first = content.substr(0,cursorPos);
      response.last = content.substr(cursorPos + response.middle.length);
    }
    else
    {
      response.first = content;
    }
  }
  else
  {
    response.first = target.value.substring(0,target.selectionStart);
    response.middle = arget.value.substring(target.selectionStart, target.selectionEnd);
    response.last = target.value.substring(target.selectionEnd, target.textLength);
  }
  return response;
};
C.S.
  • 422
  • 2
  • 9
  • well, my contenteditable element is the body of an iframe (rte). unfortunately this code does not word – Thariama Feb 22 '12 at 08:35