Inserte html en el cursor en un div contento
Tengo un div con un conjunto contenteditable y estoy capturando la pulsación de teclas usando jquery para llamar a preventDefault() cuando se presiona la tecla Intro. De manera similar a esta pregunta que inserta texto en el cursor, me gustaría insertar html directamente; para abreviar, diremos que es una etiqueta br. Usar la respuesta a la pregunta anterior realmente funciona en IE, ya que utiliza el método range.pasteHTML, pero en otros navegadores la etiqueta br aparecería como texto sin formato y no como html. ¿Cómo podría modificar la respuesta para insertar html y no texto?
En la mayoría de los navegadores, puede utilizar el insertNode()
método del Rango que obtiene de la selección. En IE <9 puedes usar pasteHTML()
, como mencionaste. A continuación se muestra una función para hacer esto en los principales navegadores. Si el contenido ya está seleccionado, se reemplaza, por lo que en realidad se trata de una operación de pegado. Además, agregué código para colocar el cursor después del final del contenido insertado.
jsFiddle: http://jsfiddle.net/jwvha/1/
Código:
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);
}
}
ACTUALIZACIÓN 21 DE AGOSTO DE 2013
Como se solicitó en los comentarios, aquí hay un ejemplo actualizado con un parámetro adicional que especifica si se selecciona o no el contenido insertado.
Demostración: http://jsfiddle.net/timdown/jwvha/527/
Código:
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 <= 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";
};