2010-10-31 16 views
16

Il mio compito è quello di impostare un cursore di testo da visualizzare all'interno di un nodo di span vuoto all'interno di un div contentEditable.Impostazione della posizione del cursore su un nodo vuoto all'interno di un elemento ContentEditable

Quanto segue non mi dà problemi su Firefox 3.6:

<!DOCTYPE html> 
<html> 
    <head> 
     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
     <script type="text/javascript" src="js/jquery-1.4.3.min.js"> 
     </script> 
     <style> 
      #multiple { 
       border: 1px solid #ccc; 
       width: 800px; 
       min-height: 20px; 
       padding: 5px; 
       outline: none; 
      } 
     </style> 
     <script> 
      $(document).ready(function(){ 

    var contentEditable = document.getElementById('multiple'); 
    var lastItem = contentEditable.getElementsByTagName('span').item(2); 

       var selectElementText = function(el, win){ 
        win = win || window; 
        var doc = win.document, sel, range; 
        if (win.getSelection && doc.createRange) {      
         range = doc.createRange(); 
         range.selectNodeContents(el); 
         range.collapse(false); 
         sel = win.getSelection(); 
         sel.removeAllRanges(); 
         sel.addRange(range); 
        } 
        else 
         if (doc.body.createTextRange) { 
          range = doc.body.createTextRange(); 
          range.moveToElementText(el); 
          range.select(); 
         } 
       } 

       contentEditable.focus(); 
       selectElementText(lastItem); 
      }); 
     </script> 
     <title>Range Selection Tasks (Make Me Want to Cry)</title> 
    </head> 
    <body> 
     <div id="multiple" contentEditable="true"> 
      <span style="color:red">First</span><span style="color:green">Second</span><span style="color:blue"></span> 
     </div> 
    </body> 
</html> 

... ma su Webkit e IE, la messa a fuoco è impostato al penultima arco. Non ho idea del perché. Funziona se inserisco uno spazio all'interno dell'ultimo intervallo, ma poi ottengo una selezione dell'intervallo di un carattere.

Detto questo, è accettabile avere spazi bianchi nell'ultimo nodo se il cursore è all'inizio.

Qualsiasi aiuto con questo sarebbe molto apprezzato. Grazie in anticipo.

risposta

4

Il modello di selezione/intervallo di IE è basato su indici nel contenuto del testo, ignorando i limiti degli elementi. Credo che sia impossibile impostare il focus di input all'interno di un elemento inline senza testo. Sicuramente con il tuo esempio non posso mettere a fuoco l'interno dell'ultimo elemento cliccando o con i tasti freccia.

Funziona quasi se si imposta ogni span su display: block, sebbene ci sia ancora un comportamento molto strano, dipendente dall'esistenza di spazi bianchi nel genitore. Hacking del display per apparire in linea con trucchi come float, inline-block e posizione assoluta rendono IE che tratta ogni elemento come una casella di modifica separata. Gli elementi di blocco posizionati in modo relativo l'uno accanto all'altro funzionano, ma probabilmente non è pratico.

Se ti fa sentire meglio, IE9 risolve definitivamente questa spiacevolezza e adotta il modello di gamma standard. (Urrà!)

è accettabile avere spazi bianchi nell'ultimo nodo se il punto di inserimento è all'inizio.

Probabilmente lo farei, quindi, a meno che un esperto di selezione IE possa pensare a qualcosa di meglio. (Chiamando Tim Down!)

+0

Grazie per la risposta rapida e ponderata. Non crederai a quanti diversi hack e soluzioni alternative ho tentato mentre cercavo di farlo funzionare. In realtà, se hai esperienza di IE, probabilmente hai una buona idea. Buono a sapersi che IE9 finalmente adotta il modello standard. Con un po 'di fortuna dovrei far migrare tutti i miei utenti entro il 2019 ... – Mike

+5

Ciao! Sono abbastanza certo che è impossibile posizionare il punto di inserimento all'interno di un elemento inline vuoto in IE. Più in generale, in IE è impossibile posizionare il punto di inserimento all'inizio del primo nodo di testo all'interno di un elemento. Questo vale anche per WebKit: https://bugs.webkit.org/show_bug.cgi?id=15256#c4. L'aggiunta di spazi bianchi è buona come sembra, penso. Ho fatto ricorso all'inserimento di un carattere BOM Unicode ('U + FEFF', rendering come larghezza zero in tutti i principali browser) all'inizio di un nodo di testo, che funziona ma ti lascia l'incubo logistico di rimuovere le BOM quando il cursore si sposta altrove . –

+0

Ugh! Quanto spiacevole! Grazie. – bobince

1

Ho trovato una soluzione alternativa per Webkit, non so se qualcuno lo ha trovato prima ma invece di aggiungere a livello di codice uno spazio a larghezza zero, puoi fare la stessa cosa con la proprietà del contenuto css3 nel dopo psuedo-selector degli elementi in cui vuoi inserire il cursore. Questo ha il vantaggio che i caratteri extra non vengono visualizzati nel DOM e l'utente non può navigare tra il cursore. Quindi in pratica non ha bisogno di ripulire.

Per farlo funzionare per qualsiasi elemento figlio del contenuto di elementi modificabili sarebbe qualcosa di simile:

#mycontenteditableelement *:after { 
    content: '\200B'; 
} 

non ho controllato tutto, ma ho il sospetto questo è una soluzione completa.

+1

Utilizzare a proprio rischio: qualcuno da webkit raccomanda di non usare questa tecnica perché l'uso di psuedo-selector è mal supportato in aree contenteditable e può causare il crash del webkit o il raggiungimento di uno stato incoerente. Di nuovo, vedi webkit bugzilla: bugs.webkit.org/show_bug.cgi?id=15256 – bwindels

0

L'applicazione di un altezza minima e la larghezza minima per elementi all'interno contenteditable con inline-block può fare alcuni buoni, effetti collaterali anche se l'impatto è impreviste:

#multiple * { 
    min-height: 1em; 
} 
span, b, strong, i, em, a, etc { 
    display: inline-block; 
    min-width: 1em; 
    background-color: hsla(0, 50%, 50%, .5); /* this is only a visual aid; discard @ will */ 
    vertical-align: middle; /* so elements w/ inline-block align w/ text correctly */ 
} 

Troverete ci sono ancora problemi, ma se sei disposto a sacrificare alcuni problemi per un insieme più piccolo di altri, questo può essere un vantaggio.

11

Set dell'elemento innerHTML ad un carattere zero-width:

('element').innerHTML = '&#200B'; 

Ora il carret può andare lì.

+2

Questo ha funzionato alla grande; Ho usato '​' nel mio markup ('ÈB;' non è stato reso correttamente). – duma

+4

Questa risposta combina l'identificatore html e unicode. Utilizzare "​" o "\ u200B" per fare riferimento a uno spazio non-rottura di lunghezza zero. – daw

0

Per me impostare il contenuto di contenteditable div su <br> funziona. Ho provato a impostarlo su nbsp; ma questo crea uno spazio extra per i caratteri nel div prima di iniziare a modificare.

Spero che questo aiuti.

Problemi correlati