Insert html at caret in a contenteditable div
In most browsers, you can use the insertNode()
method of the Range you obtain from the selection. In IE < 9 you can use pasteHTML()
, as you mentioned. Below is a function to do this in all major browsers. If content is already selected, it is replaced, so this is effectively a paste operation. Also, I added code to place the caret after the end of the inserted content.
jsFiddle: http://jsfiddle.net/jwvha/1/
Code:
function pasteHtmlAtCaret(html) { var sel, range; if (window.getSelection) { // IE9 and non-IE sel = window.getSelection(); if (sel.getRangeAt && sel.rangeCount) { range = sel.getRangeAt(0); range.deleteContents(); // Range.createContextualFragment() would be useful here but is // only relatively recently standardized and is not supported in // some browsers (IE9, for one) var el = document.createElement("div"); el.innerHTML = html; var frag = document.createDocumentFragment(), node, lastNode; while ( (node = el.firstChild) ) { lastNode = frag.appendChild(node); } range.insertNode(frag); // Preserve the selection if (lastNode) { range = range.cloneRange(); range.setStartAfter(lastNode); range.collapse(true); sel.removeAllRanges(); sel.addRange(range); } } } else if (document.selection && document.selection.type != "Control") { // IE < 9 document.selection.createRange().pasteHTML(html); }}
UPDATE 21 AUGUST 2013
As requested in the comments, here is an updated example with an extra parameter that specifies whether or not to select the inserted content.
Demo: http://jsfiddle.net/timdown/jwvha/527/
Code:
function pasteHtmlAtCaret(html, selectPastedContent) { var sel, range; if (window.getSelection) { // IE9 and non-IE sel = window.getSelection(); if (sel.getRangeAt && sel.rangeCount) { range = sel.getRangeAt(0); range.deleteContents(); // Range.createContextualFragment() would be useful here but is // only relatively recently standardized and is not supported in // some browsers (IE9, for one) var el = document.createElement("div"); el.innerHTML = html; var frag = document.createDocumentFragment(), node, lastNode; while ( (node = el.firstChild) ) { lastNode = frag.appendChild(node); } var firstNode = frag.firstChild; range.insertNode(frag); // Preserve the selection if (lastNode) { range = range.cloneRange(); range.setStartAfter(lastNode); if (selectPastedContent) { range.setStartBefore(firstNode); } else { range.collapse(true); } sel.removeAllRanges(); sel.addRange(range); } } } else if ( (sel = document.selection) && sel.type != "Control") { // IE < 9 var originalRange = sel.createRange(); originalRange.collapse(true); sel.createRange().pasteHTML(html); if (selectPastedContent) { range = sel.createRange(); range.setEndPoint("StartToStart", originalRange); range.select(); } }}
var doc = document.getElementById("your_iframe").contentWindow.document;// IE <= 10if (document.selection){ var range = doc.selection.createRange(); range.pasteHTML("<b>Some bold text</b>");// IE 11 && Firefox, Opera .....}else if(document.getSelection){ var range = doc.getSelection().getRangeAt(0); var nnode = doc.createElement("b"); range.surroundContents(nnode); nnode.innerHTML = "Some bold text";};
by reading quickly and hoping not to be off topic, here is a track for those who, like me, need to insert code at the cursor level of a div:
document.getElementById('editeur').contentWindow.document.execCommand('insertHTML', false, '<br />');
'editeur' is iframe :
<iframe id="editeur" src="contenu_editeur_wysiwyg.php"></iframe>
contenu_editeur_wysiwyg.php :
<html><head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></head><body><div></div></body></html>
don't forget :
document.getElementById('editeur').contentDocument.designMode = "on";