Cursorposition (in Zeichen) innerhalb eines Texteingabefelds abrufen

211

Wie kann ich die Caret-Position aus einem Eingabefeld heraus ermitteln?

Ich habe über Google ein paar Kleinigkeiten gefunden, aber nichts kugelsicheres.

Grundsätzlich wäre so etwas wie ein jQuery-Plugin ideal, also könnte ich es einfach tun

$("#myinput").caretPosition()
MarkB29
quelle
2
Versuchen Sie, nach 'Cursorposition' zu suchen, die Ihnen viel mehr Treffer sowie einige Themen dazu auf SO liefert.
Alec
2
@CMS Das Finden der Position in a <input>ist viel einfacher als in a <textarea>.
Andrew Mao
1
@ AndrewMao: und viel schwieriger, wenn der Text gescrollt wird und das Caret hinter sizeZeichen steht.
Dan Dascalescu
@alec: Ich bin damit einverstanden, dass die Suche nach Cursor anstelle von Caret zu mehr Ergebnissen führen kann. Wie bereits an anderer Stelle erwähnt, habe ich gelernt, dass Caret der passendere Begriff ist. Ein Cursor repräsentiert einen Ort in irgendetwas, während ein Caret einen Ort speziell im Text darstellt.
Suncat2000

Antworten:

247

Einfacheres Update:

Verwenden Sie ein field.selectionStart Beispiel in dieser Antwort .

Vielen Dank an @commonSenseCode für diesen Hinweis.


Alte Antwort:

Diese Lösung gefunden. Nicht jquery-basiert, aber es gibt kein Problem, es in jquery zu integrieren:

/*
** Returns the caret (cursor) position of the specified text field (oField).
** Return value range is 0-oField.value.length.
*/
function doGetCaretPosition (oField) {

  // Initialize
  var iCaretPos = 0;

  // IE Support
  if (document.selection) {

    // Set focus on the element
    oField.focus();

    // To get cursor position, get empty selection range
    var oSel = document.selection.createRange();

    // Move selection start to 0 position
    oSel.moveStart('character', -oField.value.length);

    // The caret position is selection length
    iCaretPos = oSel.text.length;
  }

  // Firefox support
  else if (oField.selectionStart || oField.selectionStart == '0')
    iCaretPos = oField.selectionDirection=='backward' ? oField.selectionStart : oField.selectionEnd;

  // Return results
  return iCaretPos;
}
bezmax
quelle
9
else if (oField.selectionStart || oField.selectionStart == '0')könnte seinelse if (typeof oField.selectionStart==='number')
user2428118
Was ist die Idee von "oField.focus ()"? Es funktioniert für mich ohne diese Linie. Seien Sie vorsichtig, wenn Sie ein Unschärfeereignis für Ihre Eingabe verwenden und diese Funktion innerhalb eines Rückrufs ausführen.
Kirill Reznikov
Testen Sie das im IE? Dieser ganze if-Abschnitt wird nur im IE ausgeführt. Im IE gibt es nur eine globale Auswahl, deshalb document.selectionnicht field.selectionoder so. Außerdem war es in IE 7 möglich (ich weiß nicht, ob es in 8+ noch möglich ist), etwas auszuwählen und dann TAB aus dem Feld zu entfernen, ohne die Auswahl zu verlieren. Auf diese Weise wird bei Auswahl des Texts, aber nicht fokussiertem Feld die document.selectionNullauswahl zurückgegeben. Um dieses Problem zu umgehen, müssen Sie sich daher auf das Element konzentrieren, bevor Sie das lesen document.selection.
Bezmax
Immer 0 für Chrom und Firefox
Kaushik Thanki
117

Schön, vielen Dank an Max.

Ich habe die Funktionalität in seiner Antwort in jQuery verpackt, wenn jemand sie verwenden möchte.

(function($) {
    $.fn.getCursorPosition = function() {
        var input = this.get(0);
        if (!input) return; // No (input) element found
        if ('selectionStart' in input) {
            // Standard-compliant browsers
            return input.selectionStart;
        } else if (document.selection) {
            // IE
            input.focus();
            var sel = document.selection.createRange();
            var selLen = document.selection.createRange().text.length;
            sel.moveStart('character', -input.value.length);
            return sel.text.length - selLen;
        }
    }
})(jQuery);
MarkB29
quelle
3
Ist das nicht input = $(this).get(0)dasselbe wie input = this?
Mic
4
@Mic nein, nicht in einem jQuery-Plugin. In einem Plugin thisbezieht sich auf ein vollständig verpacktes Set. Sein Code ist immer noch falsch, es sollte einfach so sein this.get(0). Sein Code funktionierte wahrscheinlich immer noch, weil das erneute Umwickeln eines verpackten Sets nichts bewirkt.
Chev
1
Dies gibt mir falsche Informationen. Ich habe mir die Cursorpositionen angesehen, als ich Text eingefügt habe. Meine Geige, die dies demonstriert, ist: jsfiddle.net/fallenreaper/TSwyk
Fallenreaper
1
Firefox generiert bei input.selectionStart eine NS_ERROR_FAILURE. Wenn die Eingabe vom Typ Zahl ist, verpacken Sie sie in einen Versuch {} catch {}?
Niall.Campbell
wäre schön für die neuen Bienen, wenn Sie die Verwendung für die Funktion hinzufügen
Muhammad Omer Aslam
98

SEHR LEICHT

Antwort aktualisiert

Verwenden Sie es selectionStart, es ist kompatibel mit allen gängigen Browsern .

document.getElementById('foobar').addEventListener('keyup', e => {
  console.log('Caret at: ', e.target.selectionStart)
})
<input id="foobar" />

Update: Dies funktioniert nur, wenn kein Typ definiert ist oder type="text"für die Eingabe.

CommonSenseCode
quelle
2
Wenn ich die Position mit der Maus ändere, wird sie nicht in der Konsole gedruckt. Gibt es eine Möglichkeit, das Problem zu beheben?
Eugene Barsky
3
@EugeneBarsky Fügen Sie einfach einen neuen Ereignis-Listener für das Klick-Ereignis hinzu. Sie können die .selectionStartEigenschaft jederzeit überprüfen ( document.getElementById('foobar').selectionStart), sie muss sich nicht in einem Ereignis-Listener befinden.
JJJ
3
Super, funktioniert aber nicht in Firefox oder Chrome, wenn der Eingabetyp Nummer ist.
Adam R. Gray
26

Habe eine sehr einfache Lösung . Versuchen Sie den folgenden Code mit verifiziertem Ergebnis -

<html>
<head>
<script>
    function f1(el) {
    var val = el.value;
    alert(val.slice(0, el.selectionStart).length);
}
</script>
</head>
<body>
<input type=text id=t1 value=abcd>
    <button onclick="f1(document.getElementById('t1'))">check position</button>
</body>
</html>

Ich gebe dir das fiddle_demo

Rajesh Paul
quelle
13
sliceist eine relativ teure Operation und fügt dieser "Lösung" nichts hinzu - el.selectionStartentspricht der Länge Ihres Slice; gib das einfach zurück. Darüber hinaus sind die anderen Lösungen komplizierter, weil sie sich mit anderen Browsern befassen, die dies nicht unterstützen selectionStart.
Mpen
Ich habe Jobs beendet, bei denen ich mit Code mit solchen Variablennamen arbeiten musste.
Michael Scheper
@ Michael Scheper - Du meinst 'el' für Element und 'val' für Wert? Das sind ziemlich häufig ...
user2782001
6
@ user2782001: Ich habe falsch geschrieben - mein Hauptanliegen war der Funktionsname. f1ist ungefähr so ​​aussagekräftig wie 'user2782001'. 😉
Michael Scheper
16

Dafür gibt es jetzt ein schönes Plugin: Das Caret Plugin

Dann können Sie die Position mit abrufen $("#myTextBox").caret()oder über einstellen$("#myTextBox").caret(position)

Jens Mikkelsen
quelle
1
das caret plugin scheint für textarea elemente keine
eingaben
4
Nun, ich habe es für <input type = "text" id = "myTextBox" /> zum Laufen gebracht und verwende den obigen Code.
Jens Mikkelsen
14
   (function($) {
    $.fn.getCursorPosition = function() {
        var input = this.get(0);
        if (!input) return; // No (input) element found
        if (document.selection) {
            // IE
           input.focus();
        }
        return 'selectionStart' in input ? input.selectionStart:'' || Math.abs(document.selection.createRange().moveStart('character', -input.value.length));
     }
   })(jQuery);
George
quelle
10

Hier gibt es einige gute Antworten, aber ich denke, Sie können Ihren Code vereinfachen und die Überprüfung auf inputElement.selectionStartUnterstützung überspringen : Er wird nicht nur in IE8 und früheren Versionen (siehe Dokumentation ) unterstützt, was weniger als 1% der aktuellen Browsernutzung entspricht .

var input = document.getElementById('myinput'); // or $('#myinput')[0]
var caretPos = input.selectionStart;

// and if you want to know if there is a selection or not inside your input:

if (input.selectionStart != input.selectionEnd)
{
    var selectionValue =
    input.value.substring(input.selectionStart, input.selectionEnd);
}
pmrotule
quelle
2

Möglicherweise benötigen Sie zusätzlich zur Cursorposition einen ausgewählten Bereich. Hier ist eine einfache Funktion, Sie brauchen nicht einmal jQuery:

function caretPosition(input) {
    var start = input[0].selectionStart,
        end = input[0].selectionEnd,
        diff = end - start;

    if (start >= 0 && start == end) {
        // do cursor position actions, example:
        console.log('Cursor Position: ' + start);
    } else if (start >= 0) {
        // do ranged select actions, example:
        console.log('Cursor Position: ' + start + ' to ' + end + ' (' + diff + ' selected chars)');
    }
}

Angenommen, Sie möchten es bei einer Eingabe aufrufen, wenn sich die Cursorposition ändert oder die Maus bewegt (in diesem Fall verwenden wir jQuery .on()). Aus Leistungsgründen kann es eine gute Idee sein, setTimeout()Unterstriche hinzuzufügen oder etwas Ähnliches, _debounce()wenn Ereignisse eintreten:

$('input[type="text"]').on('keyup mouseup mouseleave', function() {
    caretPosition($(this));
});

Hier ist eine Geige, wenn Sie sie ausprobieren möchten: https://jsfiddle.net/Dhaupin/91189tq7/

Dhaupin
quelle
0

const inpT = document.getElementById("text-box");
const inpC = document.getElementById("text-box-content");
// swch gets  inputs .
var swch;
// swch  if corsur is active in inputs defaulte is false .
var isSelect = false;

var crnselect;
// on focus
function setSwitch(e) {
  swch = e;
  isSelect = true;
  console.log("set Switch: " + isSelect);
}
// on click ev
function setEmoji() {
  if (isSelect) {
    console.log("emoji added :)");
    swch.value += ":)";
    swch.setSelectionRange(2,2 );
    isSelect = true;
  }

}
// on not selected on input . 
function onout() {
  // الافنت  اون كي اب 
  crnselect = inpC.selectionStart;
  
  // return input select not active after 200 ms .
  var len = swch.value.length;
  setTimeout(() => {
   (len == swch.value.length)? isSelect = false:isSelect = true;
  }, 200);
}
<h1> Try it !</h1>
    
		<input type="text" onfocus = "setSwitch(this)" onfocusout = "onout()" id="text-box" size="20" value="title">
		<input type="text" onfocus = "setSwitch(this)"  onfocusout = "onout()"  id="text-box-content" size="20" value="content">
<button onclick="setEmoji()">emogi :) </button>

Omar bakhsh
quelle