Jek Jek - 3 years ago 129
CSS Question

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.

Answer Source

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>

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download