Search code examples
javascriptjqueryhtmlcsscontenteditable

Get ID of selected contenteditable element's child where cursor caret is located


I'm currently trying to make an editor using contenteditable divs, but I'm having an issue where clicking backspace in say child-2 at the start will result in merging child-1 and child-2 together, which defeats its own purpose.

I'm finding the current caret position using the function:

caret: function() {
    if (window.getSelection) {
        sel = window.getSelection();
        if (sel.getRangeAt) return sel.getRangeAt(0).startOffset;
    }
    return null;
}

Which has been working perfectly, but to fix the merging issue I need to find out which element is currently selected and use that data with the caret location to use event.preventDefault() and stop a potential merge.

This is frame that I'm using and talking about:

<div id="parent" contenteditable="true">
  <div id="child-1">
    One
  </div>
  <div id="child-2">
    Two
  </div>
  <div id="child-3">
    Three
  </div>
</div>

To find the selected element I've tried this:

console.log(document.activeElement);

To see if this prints out the ID of the child selected, though this outputs the entire parent element into the console instead of just the ID.


Solution

  • Use Event Delegation to easily find the clicked node. Other events such as key and mouse can be added as well.

    Details are commented in demo

    Demo

    // Refernce the parent of all of the target nodes
    var parent = document.getElementById('parent');
    // Register the click event to #parent
    parent.addEventListener('click', idNode);
    
    // This is the callback that is invoked on each click
    function idNode(e) {
      /* If the node clicked (e.target) is not the 
      || the registered event listener 
      || (e.currentTarget = #parent)
      */
      if (e.target !== e.currentTarget) {
        // Get the #id of clicked node
        var ID = e.target.id;
        // Reference e.target by its #id
        var child = document.getElementById(ID);
    
      }
      // Log the #id of each e.target at every click
      console.log('The caret is located at ' + ID);
      
      // Return the e.target as a DOM node when needed
      return child;
    
    }
    <div id="parent" contenteditable="true">
      <div id="child-1">
        One
      </div>
      <div id="child-2">
        Two
      </div>
      <div id="child-3">
        Three
      </div>
    </div>