I have a div with contenteditable set and I am capturing keypress using jquery to call preventDefault() when the enter key is pressed. Similar to this question which inserts text at the cursor, I would like to directly insert html, for brevity we'll say its a br tag. Using the answer to the question above actually works in IE as it uses the range.pasteHTML method, but in other browsers the br tag would appear as plain text and not html. How could I modify the answer to insert html and not text ?
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();
}
}
}
isOrContains
function) –
Friedafriedberg pasteHtmlAtCaret ()
function in an onload
handler where nothing else can see it. See jsfiddle.net/jwvha/211 for the fix. –
Assignment document.execCommand()
usually works with the browser's undo stack, so you may be able to use document.execCommand("InsertHTML", false, "<b>Some bold text</b>")
. However, I haven't tested that undo will still work with that, and IE does not support that command. Finally, there is an UndoManager spec in the works that will be the solution for this in the long term and is starting to get implemented in browsers: dvcs.w3.org/hg/undomanager/raw-file/tip/undomanager.html –
Assignment insertHTML
:-) only pesky IE won't get the native undo/redo :-/ –
Bosom <iframe>
. My version is here –
Beckford document.execCommand("InsertHTML")
for browsers other than IE? (It better for undo/redo functions) –
Corporal document.execCommand('insertHtml')
AND putting the cursor after the inserted HTML? when i'm inserting an html element which is contenteditable="false"
the cursor gets "swallowed" and I can't even move it. The problem with document.execCommand is, that you don't get a reference to the newly inserted element. –
Porkpie click
(usually wysiwyg-editor's toolbar buttons are outside the editing area) –
Perfumery mousedown
event instead and prevent the default click action of the button; 2) make the toolbar button unselectable, or 3) save the selection before clicking the toolbar button (maybe via the mousedown
event) and restore it afterwards (but before doing the insertion) –
Assignment var doc = document.getElementById("your_iframe").contentWindow.document;
// IE <= 10
if (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";
var r = getSelection().getRangeAt(0);
r.insertNode(r.createContextualFragment('<b>Hello</b>'));
//select this range
getSelection().removeAllRanges();
getSelection().addRange(r);
//collapse to end/start
getSelection().collapseToEnd()
© 2022 - 2024 — McMap. All rights reserved.