Inserisci html quando il cursore si trovava in un div di modifica dei contenuti

Voglio inserire alcuni html in un div contenteditable.

Quando si modifica il contenuto, l’utente fa clic su un’icona, viene visualizzata una finestra di dialogo e inserisce il testo dell’URL e dell’ancora nella finestra di dialogo. Ciò causa che il div editabile perde il suo focus e il link è inserito all’inizio del div, non quando il cursore era. Ho provato molte cose ma sono bloccato.

“rte” id del mio contenuto modificabile div

ID “link_add” del pulsante nella finestra di dialogo

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

Ho anche provato la soluzione dal set di execcommand solo per un div , usando:

 function execCommandOnElement(el, commandName, value) 

Ma questo svuota il div e basta incollare il nuovo contenuto.

Immagino che questa sia una finestra di dialogo “in linea” (molto simile alla finestra di dialogo di collegamento di StackOverflow, ad esempio), che sposta lo stato attivo e quindi la selezione. La soluzione sembra essere quella di salvare e ripristinare la selezione. Chiama getSelection () per ottenere un riferimento alla selezione e salva le proprietà anchorNode , anchorOffset , focusNode e focusOffset e quindi usa collapse(anchorNode, anchorOffset) ed extend(focusNode, focusOffset) per ripristinare la selezione una volta focalizzato il div contenteditable. (Se non sei interessato a entrambi i nodes potresti semplicemente collapse(focusNode, focusOffset) .)

È necessario salvare e ripristinare la selezione. IE per uno lo perde se la selezione viene compressa (cioè solo un segno di omissione) quando l’elemento modificabile perde lo stato attivo. Nota che IE <9 ha oggetti di selezione e intervallo completamente diversi da altri browser. Ecco un codice per farlo funzionare in tutti i principali browser, incluso IE precedente. Si noti che non ripristinerà la direzione originale della selezione, tuttavia. Se è necessario, la soluzione diventa più complicata e non può essere eseguita in IE.

 var saveSelection, restoreSelection; 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(); } }; } 

Prima di aprire la finestra di dialogo:

 var savedSel = saveSelection(); 

Dopo aver chiuso la finestra di dialogo:

 restoreSelection(savedSel); 

In alternativa, se si stesse facendo un sacco di manipolazione di selezione / intervallo, si potrebbe usare il modulo di salvataggio / ripristino della selezione della mia libreria Rangy , ma sarebbe eccessivo per questo solo uso.

Probabilmente suggerito sopra non funzionerebbe correttamente, a causa di due ragioni: in primo luogo, è necessario utilizzare window.getSelection (). GetRangeAt (i) .cloneRange (), e c’è un secondo, – la selezione e l’intervallo sono dati viventi e si aggiorna automaticamente con l’utente correlato azioni, come nuove selezioni e focus.