Come ottenere la posizione della colonna del cursore (non dei pixel) in un'area di testo, in caratteri, dall'inizio?


174

Come si ottiene la posizione del cursore in un <textarea>JavaScript utilizzando?

Per esempio: This is| a text

Questo dovrebbe tornare 7.

Come lo otterresti per restituire le stringhe che circondano il cursore / selezione?

Ad esempio: 'This is', '', ' a text'.

Se la parola "è" è evidenziata, allora ritornerebbe 'This ', 'is', ' a text'.


Vedi questa domanda: stackoverflow.com/questions/164147/… e se avrai newline, anche la nota qui: stackoverflow.com/questions/235411/…
bobince

1
Se stai usando jQuery puoi usare il plugin jquery caret $ ('textarea'). GetSelection (). Start plugins.jquery.com/plugin-tags/caret @ ++
redochka

Ho trovato una buona soluzione su blog.vishalon.net/index.php/… L' ho testato su Firefox e Chrome, e ha funzionato in entrambi. Lo scrittore afferma che funziona anche con IE + Opera.
pycoder112358,

Uso semplice textarea.selectionStart, textarea. selectionEnd, textarea.setSelectionRange developer.mozilla.org/en-US/docs/Web/API/HTMLTextAreaElement
EAndreyF

Risposte:


173

Con Firefox, Safari (e altri browser basati su Gecko) puoi facilmente usare textarea.selectionStart, ma per IE che non funziona, quindi dovrai fare qualcosa del genere:

function getCaret(node) {
  if (node.selectionStart) {
    return node.selectionStart;
  } else if (!document.selection) {
    return 0;
  }

  var c = "\001",
      sel = document.selection.createRange(),
      dul = sel.duplicate(),
      len = 0;

  dul.moveToElementText(node);
  sel.text = c;
  len = dul.text.indexOf(c);
  sel.moveStart('character',-1);
  sel.text = "";
  return len;
}

( codice completo qui )

Ti consiglio anche di controllare il plugin jQuery FieldSelection , che ti consente di farlo e molto altro ...

Modifica: ho effettivamente implementato nuovamente il codice sopra:

function getCaret(el) { 
  if (el.selectionStart) { 
    return el.selectionStart; 
  } else if (document.selection) { 
    el.focus(); 

    var r = document.selection.createRange(); 
    if (r == null) { 
      return 0; 
    } 

    var re = el.createTextRange(), 
        rc = re.duplicate(); 
    re.moveToBookmark(r.getBookmark()); 
    rc.setEndPoint('EndToStart', re); 

    return rc.text.length; 
  }  
  return 0; 
}

Guarda un esempio qui .


1
Ciò non distingue tra le posizioni del cursore quando il cursore è posizionato su una linea vuota. Vedi stackoverflow.com/questions/3053542/…
Tim Down

4
Questa risposta non affronta il problema delle righe vuote.
Tim Down,

6
Come posso usare questo per div CONTENTEDITABLE?
Muhammet Göktürk Ayan

1
Potresti voler riformulare un po 'questa risposta, Safari (and other Gecko based browsers)sembra implicare che Safari usi Gecko. Gecko è il motore di Mozilla; Safari utilizza WebKit.
Codice inutile

1
il cursore alla posizione 0 fallirebbe il test if (el.selectionStart) { return el.selectionStart; }...
okm

57

Aggiornato il 5 settembre 2010

Visto che tutti sembrano essere diretti qui per questo problema, sto aggiungendo la mia risposta a una domanda simile, che contiene lo stesso codice di questa risposta ma con uno sfondo completo per coloro che sono interessati:

Document.selection.createRange di IE non include righe vuote iniziali o finali

Prendere in considerazione le interruzioni di riga finali è complicato in IE e non ho visto alcuna soluzione che lo faccia correttamente, comprese altre risposte a questa domanda. È possibile, tuttavia, utilizzare la seguente funzione, che ti restituirà l'inizio e la fine della selezione (che sono gli stessi nel caso di un cursore) all'interno di un <textarea>testo o <input>.

Si noti che l'area di testo deve essere attiva affinché questa funzione funzioni correttamente in IE. In caso di dubbi, chiama focus()prima il metodo textarea .

function getInputSelection(el) {
    var start = 0, end = 0, normalizedValue, range,
        textInputRange, len, endRange;

    if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") {
        start = el.selectionStart;
        end = el.selectionEnd;
    } else {
        range = document.selection.createRange();

        if (range && range.parentElement() == el) {
            len = el.value.length;
            normalizedValue = el.value.replace(/\r\n/g, "\n");

            // Create a working TextRange that lives only in the input
            textInputRange = el.createTextRange();
            textInputRange.moveToBookmark(range.getBookmark());

            // Check if the start and end of the selection are at the very end
            // of the input, since moveStart/moveEnd doesn't return what we want
            // in those cases
            endRange = el.createTextRange();
            endRange.collapse(false);

            if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
                start = end = len;
            } else {
                start = -textInputRange.moveStart("character", -len);
                start += normalizedValue.slice(0, start).split("\n").length - 1;

                if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) {
                    end = len;
                } else {
                    end = -textInputRange.moveEnd("character", -len);
                    end += normalizedValue.slice(0, end).split("\n").length - 1;
                }
            }
        }
    }

    return {
        start: start,
        end: end
    };
}

Mi scusi, ma cosa significa " range && range.parentElement () "?
sergzach,

C'è un problema se vogliamo ottenere la posizione del cursore in IE (se la selezione è vuota). In questo caso restituisce 0 come inizio e lunghezza stringa come fine (se utilizziamo true anziché range && range.parentElement () == el ).
sergzach,

@sergzach: range && range.parentElement() == elè lì per verificare se la selezione è all'interno dell'area di testo ed è necessaria. Non vi è alcun problema con la funzione di ottenere la posizione del cursore fino a quando l'area di testo ha lo stato attivo . Se non sei sicuro, chiama il focus()metodo textarea prima di chiamare getInputSelection(). Aggiungerò una nota alla risposta.
Tim Down,

1
@Tim: quando si fa clic su un elemento div per rivelare la selezione, "inizio" e "fine" sono sempre gli stessi.
Misha Moroshko,

3
@Misha: non è colpa della funzione: questo è ciò che è effettivamente selezionato al momento dell'esecuzione della funzione. Puoi vederlo visivamente dopo aver chiuso la finestra di avviso. Come ho detto nella mia risposta alla tua recente interrogazione, due possibili soluzioni utilizzano la mousedownmanifestazione o l'aggiunta unselectable="on"al <div>elemento.
Tim Down,

3

Ho modificato la funzione sopra per tenere conto dei resi di trasporto in IE. Non è stato testato ma ho fatto qualcosa di simile nel mio codice, quindi dovrebbe essere praticabile.

function getCaret(el) {
  if (el.selectionStart) { 
    return el.selectionStart; 
  } else if (document.selection) { 
    el.focus(); 

    var r = document.selection.createRange(); 
    if (r == null) { 
      return 0; 
    } 

    var re = el.createTextRange(), 
    rc = re.duplicate(); 
    re.moveToBookmark(r.getBookmark()); 
    rc.setEndPoint('EndToStart', re); 

    var add_newlines = 0;
    for (var i=0; i<rc.text.length; i++) {
      if (rc.text.substr(i, 2) == '\r\n') {
        add_newlines += 2;
        i++;
      }
    }

    //return rc.text.length + add_newlines;

    //We need to substract the no. of lines
    return rc.text.length - add_newlines; 
  }  
  return 0; 
}

2

Se non è necessario supportare IE, è possibile utilizzare selectionStarte gli selectionEndattributi di textarea.

Per ottenere la posizione del cursore basta usare selectionStart:

function getCaretPosition(textarea) {
  return textarea.selectionStart
}

Per ottenere le stringhe che circondano la selezione, utilizzare il seguente codice:

function getSurroundingSelection(textarea) {
  return [textarea.value.substring(0, textarea.selectionStart)
         ,textarea.value.substring(textarea.selectionStart, textarea.selectionEnd)
         ,textarea.value.substring(textarea.selectionEnd, textarea.value.length)]
}

Demo su JSFiddle .

Vedi anche i documenti HTMLTextAreaElement .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.