skip to Main Content

I am working on my javascript to check the cursor position in the contenteditable to see if the cursor is on the last line then return the boolean as true, otherwise false.

When I try this:

function checkLine() {

  var myElement = document.getElementById('editor');
   var startPosition = myElement.selectionStart;
   var endPosition = myElement.selectionEnd;
   var endofLine = false;

 if(startPosition == endPosition){
    endofLine = true;
 }
  return endofLine;
}

It is always return as true when I selected the cursor on the first line, second, third and forth lines in the contenteditable without the last line, it should have return as false when the cursor is not on the last line.

What I am trying to achieve is when I select on the first, second, third and forth lines in the contenteditable, I want the boolean to return as false and when I select the cursor on the last line, I want the boolean to return as true.

Can you please show me an example how I can check the cursor in the contenteditable that if they are on the end line then return the boolean as true otherwise false?

EDIT: Could you please clear up the code a bit and use something like this?

function checkLine() {
  // get last div
  const last = $('#editor').querySelector(":last-of-type");
  var endofLine = false;

  // if there is no div, that means there's only one line
  if (!last) {
     return true;
  }

  const sel = window.getSelection();
  let parent = sel.getRangeAt(0).commonAncestorContainer;
  if (parent.nodeType !== 1) {
      parent = parent.parentNode;
  }
  return parent === last
}

3

Answers


  1. Sorry for the delay, I edited my code to be working with contenteditable Div:

    $(document).ready(function () {
        $("#submit").on('click', function(){
           checkLine();
        });
        
        function checkLine() {
        var myElement = document.getElementById('editor');
         var startPosition = getCaretPosition();
         var endPosition = myElement.innerText.split("n").length;
         var endofLine = 'false';
         if(startPosition == endPosition){
            endofLine = 'true';
         }
        $('#post_text').html(endofLine);
      }
      
      function getCaretPosition() {
      var sel = document.getSelection();
        sel.modify("extend", "backward", "paragraphboundary");
        if(sel.anchorNode != undefined) sel.collapseToEnd();
        
        var pos = Array.prototype.indexOf.call(sel.baseNode.parentNode.parentNode.childNodes, sel.baseNode.parentNode);
        //if(sel.anchorNode != undefined) sel.collapseToEnd();
        
        return pos + 1;
    }
    });
    <div class="button">
        <div id="editor" contenteditable="true" style="border-width: 2px;border-style: outset;border-color: buttonborder;"></div>
        <button id="submit">Submit</button>
      </div>
    <p id="post_text"></p>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    Login or Signup to reply.
  2. We can take advantage of the fact that with contenteditable divs, when a user enters a new line, a new div is automatically created for that line. This way, we can query the last div of the contenteditable and see if the cursor is in it.

    const editor = document.getElementById("editor")
    editor.addEventListener("keyup", () => console.log(checkLine()))
    
    function checkLine() {
      // get last div
      const last = editor.querySelector("div:last-of-type")
      
      // if there is no div, that means there's only one line
      if(!last) return true
      
      const sel = window.getSelection()
      let parent = sel.getRangeAt(0).commonAncestorContainer
      if(parent.nodeType !== 1) parent = parent.parentNode
      return parent === last
    }
    /* css just for the demo */
    #editor { outline: none; }
    #editor:empty::before {
      content: "Start typing...";
      pointer-events: none;
      color: #bbbbbb;
    }
    <div id="editor" contenteditable></div>
    Login or Signup to reply.
  3. When the user makes a line break in a contenteditable tag that string is wrapped in a <div>. In the example below when triggered by a "click" or "keydown" event on the <fieldset contenteditable> it will:

    1. gather all <div> into an Array
    2. find the specific <div> the user clicked on or typing into
    3. display the line number
    4. and display a message if it’s the last line
    // Reference <form>
    const main = document.forms.main;
    /**
     * Reference all form controls in <form>
     * In this instance it's all <fieldset> and <output>
     */
    const fc = main.elements;
    // An array of multiple events
    const events = ["click", "keydown"];
    // Register fieldset#editor to the "click" and "keydown" nevents
    events.forEach(e => fc.editor.addEventListener(e, lineBreak));
    
    // Event handler passes Event Object by default
    function lineBreak(e) {
      /**
       * Collect all direct descendant tags of #editor
       * and convert it into an Array. (all <div>)
       */
      const lines = Array.from(this.children);
      /**
       * Get the tag in which the cursor is in (the <div> 
       * clicked or typed into).
       */
      const L = window.getSelection().anchorNode.parentNode;
      // Find it's index and 1 to it
      let lineNo = lines.indexOf(L) + 1;
      // Set the value of output#line to that of lineNo OR 1
      fc.line.value = lineNo || 1;
      // If lineNo is equal to the total number of <div>s...
      if (lineNo === lines.length) {
        // ...add "last" class to output#line...
        fc.line.classList.add("last");
        // ...otherwise...
      } else {
        // ...remove "last" class to output#line
        fc.line.classList.remove("last");
      }
    }
    .last {
      color: red;
    }
    
    .last::after {
      content: " is the last line";
    }
    <form id="main">
      <fieldset id="ui">
        <legend>Line: <output id="line"></output></legend>
        <fieldset id="editor" contenteditable></fieldset>
      </fieldset>
    </form>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search