Insert text at cursor in a content editable div
JavascriptContenteditableJavascript Problem Overview
I have a contenteditable div where I need to insert text at the caret position,
This can be easily done in IE by document.selection.createRange().text = "banana"
Is there a similar way of implementing this in Firefox/Chrome?
(I know a solution exists here , but it can't be used in contenteditable div, and looks clumsy)
Thank you!
Javascript Solutions
Solution 1 - Javascript
The following function will insert text at the caret position and delete the existing selection. It works in all the mainstream desktop browsers:
function insertTextAtCaret(text) {
var sel, range;
if (window.getSelection) {
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0);
range.deleteContents();
range.insertNode( document.createTextNode(text) );
}
} else if (document.selection && document.selection.createRange) {
document.selection.createRange().text = text;
}
}
UPDATE
Based on comment, here's some code for saving and restoring the selection. Before displaying your context menu, you should store the return value of saveSelection
in a variable and then pass that variable into restoreSelection
to restore the selection after hiding the context menu and before inserting text.
function saveSelection() {
if (window.getSelection) {
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
return sel.getRangeAt(0);
}
} else if (document.selection && document.selection.createRange) {
return document.selection.createRange();
}
return null;
}
function restoreSelection(range) {
if (range) {
if (window.getSelection) {
sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
} else if (document.selection && range.select) {
range.select();
}
}
}
Solution 2 - Javascript
-
Get a Selection Object with
window.getSelection()
. -
Use
Selection.getRangeAt(0).insertNode()
to add a textnode. -
If necessary, move the cursor position behind the added text with
Selection.modify()
. (Not standardized, but this feature is supported in Firefox, Chrome and Safari)function insertTextAtCursor(text) { let selection = window.getSelection(); let range = selection.getRangeAt(0); range.deleteContents(); let node = document.createTextNode(text); range.insertNode(node); for(let position = 0; position != text.length; position++) { selection.modify("move", "right", "character"); }; }
Solution 3 - Javascript
UPD: since ~2020 solution is obsoleted (despite it can work yet)
// <div contenteditable id="myeditable">
// const editable = document.getElementById('myeditable')
// editable.focus()
// document.execCommand('insertHTML', false, '<b>B</b>anana')
document.execCommand('insertText', false, 'banana')
Solution 4 - Javascript
I have used next code to insert icons in chat msg
<div class="chat-msg-text" id="chat_message_text" contenteditable="true"></div>
<script>
var lastCaretPos = 0;
var parentNode;
var range;
var selection;
$(function(){
$('#chat_message_text').focus();
$('#chat_message_text').on('keyup mouseup',function (e){
selection = window.getSelection();
range = selection.getRangeAt(0);
parentNode = range.commonAncestorContainer.parentNode;
});
})
function insertTextAtCursor(text) {
if($(parentNode).parents().is('#chat_message_text') || $(parentNode).is('#chat_message_text') )
{
var span = document.createElement('span');
span.innerHTML=text;
range.deleteContents();
range.insertNode(span);
//cursor at the last with this
range.collapse(false);
selection.removeAllRanges();
selection.addRange(range);
}
else
{
msg_text = $("#chat_message_text").html()
$("#chat_message_text").html(text+msg_text).focus()
}
}
</script>
Solution 5 - Javascript
Pasting plain text can be handled with the following code.
const editorEle = document.getElementById('editor');
// Handle the `paste` event
editorEle.addEventListener('paste', function (e) {
// Prevent the default action
e.preventDefault();
// Get the copied text from the clipboard
const text = e.clipboardData
? (e.originalEvent || e).clipboardData.getData('text/plain')
: // For IE
window.clipboardData
? window.clipboardData.getData('Text')
: '';
if (document.queryCommandSupported('insertText')) {
document.execCommand('insertText', false, text);
} else {
// Insert text at the current position of caret
const range = document.getSelection().getRangeAt(0);
range.deleteContents();
const textNode = document.createTextNode(text);
range.insertNode(textNode);
range.selectNodeContents(textNode);
range.collapse(false);
const selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
}
});
Solution 6 - Javascript
just an easier method with jquery:
copy the entire content of the div
var oldhtml=$('#elementID').html();
var tobejoined='<span>hii</span>';
//element with new html would be
$('#elementID').html(oldhtml+tobejoined);
simple!