Insertar html cuando el cursor estaba en un contenido editable

Quiero insertar algunos html en un div satisfactorio.

Al editar el contenido, el usuario hace clic en un ícono, aparece un cuadro de diálogo e ingresa el texto url & anchor en el cuadro de diálogo. Esto hace que el div editable pierda su foco y el enlace se inserta al principio del div, no cuando el cursor estaba. Intenté muchas cosas, pero estoy atascado.

Identificación “rte” de mi div editable de contenido

id de “link_add” del cuadro de diálogo

$('#link_add').click(function (e) { $('#rte').focus(); document.execCommand('insertHTML', false, 'html content test'); close_modal (); e.preventDefault(); }); 

También probé la solución de set execcommand solo para un div , usando:

 function execCommandOnElement(el, commandName, value) 

Pero esto vacía el div y simplemente pega el nuevo contenido.

Considero que se trata de un diálogo “en línea” (muy parecido al diálogo de enlace de StackOverflow, por ejemplo), que mueve el foco y, por lo tanto, la selección. La solución parece ser guardar y restaurar la selección. Llame a getSelection () para obtener una referencia a la selección y guarde las anchorNode , anchorOffset , focusNode y focusOffset y luego use collapse(anchorNode, anchorOffset) y extend(focusNode, focusOffset) para restaurar la selección una vez que haya enfocado el contenteditable div. (Si no está interesado en ambos nodos, puede collapse(focusNode, focusOffset) .

Debe guardar y restaurar la selección. Por ejemplo, IE lo pierde si la selección se contrae (es decir, solo un símbolo de intercalación) cuando el elemento editable pierde el foco. Tenga en cuenta que IE <9 tiene objetos de selección y rango completamente diferentes de otros navegadores. Aquí hay un código para hacer esto que funcionará en todos los navegadores principales, incluido IE más antiguo. Sin embargo, tenga en cuenta que no restaurará la dirección original de la selección. Si necesita hacer eso, la solución se vuelve más complicada y no se puede hacer en IE.

 var saveSelection, restreSelection; if (window.getSelection) { // IE 9 and non-IE saveSelection = function() { var sel = window.getSelection(), ranges = []; if (sel.rangeCount) { for (var i = 0, len = sel.rangeCount; i < len; ++i) { ranges.push(sel.getRangeAt(i)); } } return ranges; }; restoreSelection = function(savedSelection) { var sel = window.getSelection(); sel.removeAllRanges(); for (var i = 0, len = savedSelection.length; i < len; ++i) { sel.addRange(savedSelection[i]); } }; } else if (document.selection && document.selection.createRange) { // IE <= 8 saveSelection = function() { var sel = document.selection; return (sel.type != "None") ? sel.createRange() : null; }; restoreSelection = function(savedSelection) { if (savedSelection) { savedSelection.select(); } }; } 

Antes de abrir su diálogo:

 var savedSel = saveSelection(); 

Después de cerrar el diálogo:

 restreSelection(savedSel); 

Alternativamente, si estuvieras haciendo una gran cantidad de manipulación de selección / rango, podrías usar el módulo de guardar / restaurar de selección de mi biblioteca Rangy , pero sería excesivo solo para este uso.

Probablemente la sugerencia anterior no funcionaría correctamente, debido a dos razones: primero, necesita usar window.getSelection (). GetRangeAt (i) .cloneRange (), y hay segundo, – la selección y el rango son datos reales y se actualizan automáticamente con el usuario relacionado acciones, como nuevas selecciones y enfoques.