Metin Giriş alanında imleç konumunu (karakter olarak) alma


211

Bir giriş alanından düzeltme konumunu nasıl alabilirim?

Google üzerinden birkaç parça ve parça buldum, ancak hiçbir kurşun geçirmez değil.

Temelde bir jQuery eklentisi gibi bir şey ideal olurdu, bu yüzden basitçe yapabilirim

$("#myinput").caretPosition()

2
Size çok daha fazla isabet sağlayacak 'imleç konumu' aramasını ve SO ile ilgili bazı konuları aramayı deneyin.
Alec

1
olası yinelenen textarea imleç konumunu elde etme? . Ayrıca bakınız: FieldSelection eklentisi
CMS

2
@CMS Bir konumunda konum bulmak, bir konumunda <input>yapmaktan çok daha basittir <textarea>.
Andrew Mao

1
@AndrewMao: ve metin kaydırılırsa ve düzeltme işareti geçmiş sizekarakterler ise daha da zorlaşır .
Dan Dascalescu

@alec: Düzeltme işareti yerine imleç aramanın daha fazla sonuç verebileceğini kabul ediyorum. Başka bir yerde belirtildiği gibi, caretin daha uygun bir terim olduğunu öğrendim . Bir imleç herhangi bir şeydeki bir konumu temsil ederken, bir caret özellikle metindeki bir konumu temsil eder.
Suncat2000

Yanıtlar:


247

Daha kolay güncelleme:

field.selectionStart Bu cevapta örnek kullanın .

Bunu belirttiği için @commonSenseCode'a teşekkürler.


Eski cevap:

Bu çözümü buldum. Jquery tabanlı değil ancak jquery'ye entegre etmekte sorun yok:

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

9
else if (oField.selectionStart || oField.selectionStart == '0')olabilirelse if (typeof oField.selectionStart==='number')
user2428118

"OField.focus ()" fikri nedir? Bu çizgi olmadan benim için çalışıyor. Girişinizde bulanıklık olayı kullanırsanız ve bu işlevi geri arama içinde yürütürseniz dikkatli olun.
Kirill Reznikov

Bunu IE'de test ediyor musunuz? Tüm bölüm sadece IE üzerinde yürütülürse. IE'de sadece küresel bir seçim var, bu yüzden öyle ya da öyle document.selectiondeğil field.selection. Ayrıca, IE 7'de (8+'de hala mümkün olup olmadığını bilmiyorum) bir şey seçmek ve ardından seçimi kaybetmeden alandan SEKMEK mümkün oldu. Bu şekilde, metin seçildiğinde ancak alan odaklanmadığında, document.selectionsıfır seçimi döndürür. Bu nedenle, bu hata için bir geçici çözüm olarak, okumadan önce öğeye odaklanmanız gerekir document.selection.
bezmax

her zaman krom ve firefox için 0 alıyorum
Kaushik Thanki

117

Güzel, Max'e teşekkürler.

Kimse kullanmak istiyorsa işlevselliği onun cevabını jQuery içine tamamladım.

(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);

3
İle input = $(this).get(0)aynı değil input = thismi?
Mic

4
@Mic no, bir jQuery eklentisinde değil. Bir eklentide thistam sarılmış bir seti ifade eder. Kodu hala yanlış, sadece olmalı this.get(0). Kodu muhtemelen hala işe yaradı çünkü sarılmış bir seti yeniden sarmak hiçbir şey yapmıyor.
Chev

1
Bu bana yanlış bilgi veriyor. Metin girerken imleç konumlarına bakıyordum. Bunu gösteren benim keman: jsfiddle.net/fallenreaper/TSwyk
Fallenreaper

1
Firefox input.selectionStart girişinde bir NS_ERROR_FAILURE oluşturur. Giriş sayı tipindeyken başlat {} catch {}?
niall.campbell

işlev için kullanım eklerseniz yeni arılar için iyi olurdu
Muhammed Ömer Aslam

99

ÇOK KOLAY

Güncel cevap

Kullanım selectionStart, tüm büyük tarayıcılarla uyumludur .

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

Güncelleme: Bu yalnızca tip tanımlanmadığında veya type="text"girişte çalışır.


2
Fareyi kullanarak konumu değiştirirsem, konsolda yazdırılmaz. Bunu düzeltmenin bir yolu var mı?
Eugene Barsky

3
@EugeneBarsky Tıklama etkinliği için yeni bir etkinlik dinleyicisi ekleyin. .selectionStartÖzelliği istediğiniz zaman kontrol edebilirsiniz ( document.getElementById('foobar').selectionStart), bir olay dinleyicisinin içinde olması gerekmez.
JJJ

3
harika, ancak giriş türü sayı olduğunda Firefox veya Chrome'da çalışmaz.
Adam

26

Çok basit bir çözüm buldum . Doğrulanmış sonuçla aşağıdaki kodu deneyin-

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

Sana fiddle_demo veriyorum


13
slicenispeten pahalı bir işlemdir ve bu 'çözüme' hiçbir şey katmaz - el.selectionStartdilimin uzunluğuna eşdeğerdir; Sadece geri ver. Dahası, diğer çözümlerin daha karmaşık olmasının nedeni, desteklemeyen diğer tarayıcılarla uğraşmalarıdır selectionStart.
mpen

Ben böyle değişken isimleri ile kod ile çalışmak zorunda işten çıktım.
Michael Scheper

@Michael Scheper - Öğe için 'el', değer için 'val' mu demek istediniz? Bunlar oldukça yaygın ...
user2782001

6
@ user2782001: Yanlış yazıyorum — asıl endişem işlev adıydı. f1'kullanıcı2782001' kadar anlamlı. 😉
Michael Scheper


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

10

Burada yayınlanan birkaç iyi yanıt var, ancak kodunuzu basitleştirip inputElement.selectionStartdestek kontrolünü atlayabileceğinizi düşünüyorum : sadece geçerli tarayıcı kullanımının % 1'inden daha azını temsil eden IE8 ve önceki sürümlerde ( belgelere bakın ) desteklenmiyor .

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

2

Belki de imleç konumuna ek olarak seçilen bir aralığa ihtiyacınız vardır. İşte basit bir işlev, jQuery'ye bile ihtiyacınız yok:

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

Diyelim ki bir girdi üzerinde değiştiğinde veya fare imleç konumunu hareket ettirdiğinde (bu örnekte jQuery kullanıyoruz .on()) bir giriş çağırmak istiyorsunuz . Performansla ilgili nedenlerden dolayı, etkinlikler setTimeout()içeri giriyorsa Alt Çizgi eklemek veya iyi bir fikir olabilir _debounce():

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

İşte denemek istiyorsanız bir keman: https://jsfiddle.net/Dhaupin/91189tq7/


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>

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.