Insert given string in a "contenteditable" div at cursor position
New here? Learn about Bountify and follow @bountify to get notified of new bounties! x

I am looking for a solution to be able to insert a given text (emoji in the example) at the caret position.

The solution I have right now always inserts at the end, obviously.
I have tried different SO solutions but none worked in more browsers (looking for maximum support on desktop and mobile). Also tried (the deprecated) execCommand.

Maybe I'm missing something.

https://codepen.io/cx19/pen/abBjmNb

(Willing to tip extra for a fairly good answer.)

Hello sir, I am not getting what exactly you need? I understand caret position but can you please explain with example to get better idea?
pym26 1 month ago
awarded to aragornagh

Crowdsource coding tasks.

3 Solutions

Winning solution
Tipped

Or something like this:

Sounds great! I'm not able to test on more devices right now, but I'm not seeing any problems with it. Thanks!
cx19 1 month ago

I got one solution here. Please update it according to your requirement. Thanks.

var caretPos = 0;

function addEmoji(event) {
  this.insertIntoFormula(`<span>${event.target.innerHTML}</span>&nbsp;`, caretPos);
 }
function insertIntoFormula(specialChar, pos) {
     const textarea = document.getElementById('field-content');
      let value = textarea.innerHTML;
      let beforeText = value.slice(0, pos);
   let afterText = value.slice(pos);

 value = beforeText + specialChar + afterText;
  textarea.innerHTML = value;
}

function getCaretCharacterOffsetWithin(event) {
  let element = event.target;
  let caretOffset = 0;
let doc = element.ownerDocument || element.document;
let win = doc.defaultView || doc.parentWindow;
let sel;
if (typeof win.getSelection != "undefined") {
sel = win.getSelection();
if (sel.rangeCount > 0) {
  let range = win.getSelection().getRangeAt(0);
  let preCaretRange = range.cloneRange();
  preCaretRange.selectNodeContents(element);
     console.log('Range: ' + preCaretRange);
  preCaretRange.setEnd(range.endContainer, range.endOffset);
  caretOffset = preCaretRange.toString().length;
}
 } else if ( (sel = doc.selection) && sel.type != "Control") {
let textRange = sel.createRange();
let preCaretTextRange = doc.body.createTextRange();
preCaretTextRange.moveToElementText(element);
preCaretTextRange.setEndPoint("EndToEnd", textRange);
caretOffset = preCaretTextRange.text.length;
}
console.log('Caret: ' + caretOffset);
caretPos = caretOffset;
 } 
View Timeline