7

Sto facendo uso di un div contentedit in combinazione con la libreria Javascript rangy per inserire HTML nella posizione del cursore.div contenteditable: IE8 non felice con la rimozione backspace dell'elemento HTML

Fine della giornata il contenuto del div appare comunemente come:

<div contenteditable="true"> 
    "Hello " 
    <button contenteditable="false" data-id="147">@John Smith</button> 
    " " 
</div> 

utenti vengono proposti alla pressione '@' e ottenere in seguito inserito come un pulsante quando selezionato (ala Google Plus). Inserisco anche un &nbsp; dopo questo pulsante.

Il pulsante viene rimosso in Chrome/Safari/Firefox quando si preme backspace (dopo aver rimosso prima il &nbsp;), ma non in IE8. In IE8 il cursore salta semplicemente sopra il pulsante senza rimuoverlo. Ciò che è ancora più bizzarro in IE8 è se lasci lo &nbsp; vicino al pulsante - e posiziona il cursore proprio accanto al pulsante - rimuove il pulsante sul backspace. Quindi è felice quando c'è un &nbsp; alla destra del cursore.

Qualcuno sa di cosa ho bisogno per far funzionare IE8 i.t.o. rimuovendo il pulsante su backspace senza la necessità di un &nbsp; alla destra del cursore? (alcune informazioni su questo strano comportamento potrebbero anche aiutare)

P.S. Non ho ancora testato le altre versioni di IE

+0

Perché avete la contenteditable = false sul pulsante? – MorganTiley

+1

In modo che lo cancelli dal DOM (in un colpo solo) quando si preme backspace o quando si preme delete (questo attualmente funziona in Chrome/Safari/Firefox). Se contenteditable = true, il testo del pulsante diventa modificabile, il che non è il mio caso d'uso. –

+0

fico, non lo sapevo. (Non ho lavorato con gli input in contEd prima). Che dire della gestione del keydown backspace e del controllo del parallelismo del primo nodo nell'intervallo di selezione? – MorganTiley

risposta

6

Il mio suggerimento sarebbe quello di verificare prima che il punto di inserimento sia posizionato dopo il nodo non modificabile e, in tal caso, creare un intervallo che inizi immediatamente dopo l'elemento non modificabile e termini nella posizione di inserimento. Controlla se il testo in questo intervallo è vuoto. Se lo è, ciò significa che il punto di inserimento viene posizionato direttamente dopo l'elemento non modificabile, quindi in tal caso rimuovere l'elemento. Infine, posiziona il cursore in corrispondenza del quale non è stato modificato.

demo dal vivo: http://jsfiddle.net/timdown/vu3ub/

Codice:

document.onkeypress = function(e) { 
    e = e || window.event; 
    var keyCode = e.which || e.keyCode; 
    if (keyCode !== 8) { 
     return; 
    } 

    var sel = rangy.getSelection(); 
    if (sel.rangeCount === 0) { 
     return; 
    } 

    var selRange = sel.getRangeAt(0); 
    if (!selRange.collapsed) { 
     return; 
    } 

    var nonEditable = document.getElementById("nonEditable"); 
    if (!nonEditable) { 
     return; 
    } 

    // Check the caret is located after the non-editable element 
    var range = rangy.createRange(); 
    range.collapseAfter(nonEditable); 

    if (selRange.compareBoundaryPoints(range.START_TO_END, range) == -1) { 
     return; 
    } 

    // Check whether there is any text between the caret and the 
    // non-editable element. If not, delete the element and move 
    // the caret to where it had been 
    range.setEnd(selRange.startContainer, selRange.startOffset); 
    if (range.toString() === "") { 
     selRange.collapseBefore(nonEditable); 
     nonEditable.parentNode.removeChild(nonEditable); 
     sel.setSingleRange(selRange); 

     // Prevent the default browser behaviour 
     return false; 
    } 
}; 
+0

Brillante! Enorme ringraziamento per una risposta così completa. L'ho ottimizzato leggermente - invece di usare document.getElementById ("non Editabile") ho fatto uso di selRange.startContainer.previousSibling (dato che non so quale nodo devo rimuovere su backspace). –

+0

Grazie mille per l'ottima risposta, Tim. Questo è stato estremamente utile per me oggi. –

1

ho fatto un jsfiddle con un rapido esempio di come a guardare il campo della selezione e utilizzare la proprietà previousSibling del startContainer per trovare il pulsante: jsfiddle

Metti il ​​cursore in aaa e mostrerà che il pulsante è precedente. mettilo in ccc e mostrerà bbb.

Quindi con questo è possibile gestire l'evento keydown del div, controllare se la chiave è backspace + previousSibling è il pulsante e rimuoverlo con jQuery.

previousSibling è null se è un textnode, solo FYI.

+0

Very cool.Penso di poter usare il fratello precedente in combinazione con l'offset della gamma come soluzione. Riferirò su come va. –