Wie erhalte ich von Anfang an die Position der Caret-Spalte (nicht der Pixel) in einem Textbereich in Zeichen?

174

Wie erhält man die Caret-Position in einem <textarea>mit JavaScript?

Beispielsweise: This is| a text

Dies sollte zurückkehren 7.

Wie würden Sie es bekommen, die Zeichenfolgen zurückzugeben, die den Cursor / die Auswahl umgeben?

ZB : 'This is', '', ' a text'.

Wenn das Wort "ist" hervorgehoben ist, würde es zurückkehren 'This ', 'is', ' a text'.

Unruhiger Wanderer
quelle
Siehe diese Frage: stackoverflow.com/questions/164147/… und wenn Sie Zeilenumbrüche haben, auch den Hinweis dazu hier: stackoverflow.com/questions/235411/…
bobince
1
Wenn Sie jQuery verwenden, können Sie das jquery caret plugin $ ('textarea'). GetSelection () verwenden. Starten Sie plugins.jquery.com/plugin-tags/caret @ ++
redochka
Unter blog.vishalon.net/index.php/… habe ich eine gute Lösung gefunden. Ich habe sie in Firefox und Chrome getestet und sie hat in beiden funktioniert. Der Autor sagt, dass es auch in IE + Opera funktioniert.
Pycoder112358
Einfache Verwendung textarea.selectionStart, textarea. selectionEnd, textarea.setSelectionRange developer.mozilla.org/en-US/docs/Web/API/HTMLTextAreaElement
EAndreyF

Antworten:

173

Mit Firefox, Safari (und anderen Gecko-basierten Browsern) können Sie textarea.selectionStart problemlos verwenden, aber für IE funktioniert das nicht, sodass Sie Folgendes tun müssen:

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;
}

( vollständiger Code hier )

Ich empfehle Ihnen auch, das jQuery FieldSelection Plugin zu überprüfen. Es ermöglicht Ihnen dies und vieles mehr ...

Bearbeiten: Ich habe den obigen Code tatsächlich neu implementiert:

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; 
}

Hier finden Sie ein Beispiel hier .

CMS
quelle
1
Dies unterscheidet nicht zwischen Caret-Positionen, wenn das Caret auf einer leeren Linie steht. Siehe stackoverflow.com/questions/3053542/…
Tim Down
4
Diese Antwort befasst sich nicht mit dem Problem der Leerzeilen.
Tim Down
6
Wie kann ich dies für CONTENTEDITABLE div verwenden?
Muhammet Göktürk Ayan
1
Vielleicht möchten Sie diese Antwort ein wenig umformulieren. Safari (and other Gecko based browsers)Scheint zu implizieren, dass Safari Gecko verwendet. Gecko ist Mozillas Motor; Safari verwendet WebKit.
Nutzloser Code
1
Caret auf Position 0 würde den Test nicht bestehen if (el.selectionStart) { return el.selectionStart; }...
okm
57

Aktualisiert am 5. September 2010

Da hier anscheinend alle für dieses Problem verwiesen werden, füge ich meine Antwort einer ähnlichen Frage hinzu, die denselben Code wie diese Antwort enthält, jedoch den vollständigen Hintergrund für diejenigen bietet, die interessiert sind:

Die document.selection.createRange des IE enthält keine führenden oder nachfolgenden Leerzeilen

Das Berücksichtigen von Zeilenumbrüchen ist im IE schwierig, und ich habe keine Lösung gefunden, die dies korrekt ausführt, einschließlich anderer Antworten auf diese Frage. Es ist jedoch möglich, die folgende Funktion zu verwenden, die Ihnen den Anfang und das Ende der Auswahl (die im Fall eines Carets gleich sind) innerhalb eines <textarea>oder eines Textes zurückgibt <input>.

Beachten Sie, dass der Textbereich den Fokus haben muss, damit diese Funktion im IE ordnungsgemäß funktioniert. Rufen Sie im Zweifelsfall focus()zuerst die Methode des Textbereichs auf .

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
    };
}
Tim Down
quelle
Entschuldigung, aber was bedeutet " range && range.parentElement () "?
Sergzach
Es gibt ein Problem, wenn wir die Position von Caret im IE erhalten möchten (wenn die Auswahl leer ist). In diesem Fall wird 0 als Start und Zeichenfolgenlänge als Ende zurückgegeben (wenn true anstelle von range && range.parentElement () == el verwendet wird ).
Sergzach
@sergzach: Das range && range.parentElement() == elist da, um zu testen, ob die Auswahl innerhalb des Textbereichs liegt und notwendig ist. Es gibt kein Problem mit der Funktion, die Caret-Position zu erhalten , solange der Textbereich den Fokus hat . Wenn Sie sich nicht sicher sind, rufen Sie vor dem Aufruf die focus()Methode des Textbereichs auf getInputSelection(). Ich werde der Antwort eine Notiz hinzufügen.
Tim Down
1
@Tim: Wenn Sie auf ein div-Element klicken, um die Auswahl anzuzeigen, sind "Start" und "Ende" immer gleich.
Mischa Moroshko
3
@ Mischa: Das ist nicht die Schuld der Funktion: Das ist es, was tatsächlich zum Zeitpunkt der Ausführung der Funktion ausgewählt wird. Sie können es visuell sehen, nachdem Sie das Warnfeld geschlossen haben. Wie ich in meiner Antwort auf Ihre letzte Frage erwähnt habe, verwenden zwei mögliche Problemumgehungen das mousedownEreignis oder das Hinzufügen unselectable="on"zum <div>Element.
Tim Down
3

Ich habe die obige Funktion geändert, um Wagenrückläufe im IE zu berücksichtigen. Es ist ungetestet, aber ich habe etwas Ähnliches in meinem Code gemacht, damit es funktioniert.

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; 
}
Kennzeichen
quelle
2

Wenn Sie IE nicht unterstützen müssen, können Sie selectionStartund selectionEndAttribute von verwenden textarea.

Um die Caret-Position zu erhalten, verwenden Sie einfach selectionStart:

function getCaretPosition(textarea) {
  return textarea.selectionStart
}

Verwenden Sie den folgenden Code, um die Zeichenfolgen zu erhalten, die die Auswahl umgeben:

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 auf JSFiddle .

Siehe auch HTMLTextAreaElement-Dokumente .

Michał Perłakowski
quelle