Atur posisi caret keyboard di kotak teks html

173

Adakah yang tahu cara memindahkan papan ketik di kotak teks ke posisi tertentu?

Misalnya, jika kotak teks (mis. Elemen input, bukan area teks) memiliki 50 karakter di dalamnya dan saya ingin memposisikan tanda sisipan sebelum karakter 20, bagaimana saya melakukannya?

Ini berbeda dari pertanyaan ini: jQuery Mengatur Posisi Kursor di Area Teks , yang membutuhkan jQuery.

Jonhobbs
sumber

Jawaban:

205

Dikutip dari Josh Stodola's Setting Posisi caret keyboard di Textbox atau TextArea dengan Javascript

Fungsi generik yang akan memungkinkan Anda untuk memasukkan tanda sisipan di setiap posisi kotak teks atau teks yang Anda inginkan:

function setCaretPosition(elemId, caretPos) {
    var elem = document.getElementById(elemId);

    if(elem != null) {
        if(elem.createTextRange) {
            var range = elem.createTextRange();
            range.move('character', caretPos);
            range.select();
        }
        else {
            if(elem.selectionStart) {
                elem.focus();
                elem.setSelectionRange(caretPos, caretPos);
            }
            else
                elem.focus();
        }
    }
}

Parameter yang diharapkan pertama adalah ID dari elemen yang ingin Anda sisipkan papan ketik keyboard. Jika elemen tidak dapat ditemukan, tidak ada yang akan terjadi (jelas). Parameter kedua adalah indeks posisi caret. Nol akan meletakkan papan ketik keyboard di awal. Jika Anda melewatkan angka yang lebih besar dari jumlah karakter dalam nilai elemen, itu akan menempatkan tanda sisipan keyboard di akhir.

Diuji pada IE6 dan lebih tinggi, Firefox 2, Opera 8, Netscape 9, SeaMonkey, dan Safari. Sayangnya di Safari tidak berfungsi dalam kombinasi dengan acara onfocus).

Contoh menggunakan fungsi di atas untuk memaksa papan ketik keyboard melompat ke akhir semua textareas pada halaman ketika mereka menerima fokus:

function addLoadEvent(func) {
    if(typeof window.onload != 'function') {
        window.onload = func;
    }
    else {
        if(func) {
            var oldLoad = window.onload;

            window.onload = function() {
                if(oldLoad)
                        oldLoad();

                func();
            }
        }
    }
}

// The setCaretPosition function belongs right here!

function setTextAreasOnFocus() {
/***
 * This function will force the keyboard caret to be positioned
 * at the end of all textareas when they receive focus.
 */
    var textAreas = document.getElementsByTagName('textarea');

    for(var i = 0; i < textAreas.length; i++) {
        textAreas[i].onfocus = function() {
            setCaretPosition(this.id, this.value.length);
        }
    }

    textAreas = null;
}

addLoadEvent(setTextAreasOnFocus);
Ta01
sumber
4
if(elem.selectionStart)rusak ketika selectionStart adalah 0 seperti juga ditunjukkan oleh jawaban jhnns.
mpartel
1
Ini tidak berhasil untuk saya. Ketika saya mengklik kotak teks yang sebenarnya saya miliki saya berharap posisi tanda sisipan berada di awal. Lihat jsfiddle.net/khx2w
elad.chen
Fungsi setCaretPosition berfungsi dengan baik. Namun, fungsi addActionHandler Anda tidak. Tetapi bahkan tanpa itu, saya tidak bisa mendapatkan kursor untuk fokus. Kemungkinan besar, itu karena browser menetapkan posisi kursor itu sendiri berdasarkan pada posisi klik. Sepertinya tidak ada jalan keluar dari apa yang bisa saya katakan, tapi saya bisa saja salah total.
GJK
Bekerja di IE9, FF25, tetapi bukan Chrome 30. Lebih baik daripada tidak sama sekali!
Umber Ferrule
saya sudah elem.value = elem.value.replace(/^9/g,'+79') dalam kode. Pada kursor OperaMINI setelah +. fungsi ini tidak membantu
eri
52

Tautan dalam jawabannya rusak, yang ini harusnya berfungsi (semua kredit masuk ke blog.vishalon.net ):

http://snipplr.com/view/5144/getset-cursor-in-html-textarea/

Jika kode hilang lagi, berikut adalah dua fungsi utama:

function doGetCaretPosition(ctrl)
{
 var CaretPos = 0;

 if (ctrl.selectionStart || ctrl.selectionStart == 0)
 {// Standard.
  CaretPos = ctrl.selectionStart;
 }
 else if (document.selection)
 {// Legacy IE
  ctrl.focus ();
  var Sel = document.selection.createRange ();
  Sel.moveStart ('character', -ctrl.value.length);
  CaretPos = Sel.text.length;
 }

 return (CaretPos);
}


function setCaretPosition(ctrl,pos)
{
 if (ctrl.setSelectionRange)
 {
  ctrl.focus();
  ctrl.setSelectionRange(pos,pos);
 }
 else if (ctrl.createTextRange)
 {
  var range = ctrl.createTextRange();
  range.collapse(true);
  range.moveEnd('character', pos);
  range.moveStart('character', pos);
  range.select();
 }
}
kekal
sumber
1
+1 untuk fungsi-fungsi dasar, meskipun beberapa penyesuaian harus dilakukan . Jumlah garis harus dikurangi dari "pos", saat menggunakan metode rentang.
Rob W
36

Karena saya benar-benar benar-benar membutuhkan solusi ini, dan solusi dasar yang umum ( fokuskan input - kemudian atur nilainya sama dengan dirinya sendiri ) tidak berfungsi lintas-browser , saya meluangkan waktu untuk mengubah dan mengedit semuanya agar berfungsi. Membangun berdasarkan kode @ kd7 inilah yang saya buat.

Nikmati! Bekerja di IE6 +, Firefox, Chrome, Safari, Opera

Teknik penentuan posisi tanda kurung antar browser (contoh: memindahkan kursor ke AKHIR)

// ** USEAGE ** (returns a boolean true/false if it worked or not)
// Parameters ( Id_of_element, caretPosition_you_want)

setCaretPosition('IDHERE', 10); // example

Daging dan kentang pada dasarnya adalah setCaretPosition @ kd7 , dengan tweak terbesar adalah if (el.selectionStart || el.selectionStart === 0), di firefox selectionStart mulai dari 0 , yang dalam boolean tentu saja beralih ke False, jadi itu melanggar di sana.

Dalam chrome masalah terbesar adalah bahwa hanya memberikan itu .focus()tidak cukup (terus memilih SEMUA teks!) Oleh karena itu, kami menetapkan nilai itu sendiri, untuk dirinya sendiri el.value = el.value;sebelum memanggil fungsi kami, dan sekarang ia memiliki pemahaman & posisi dengan masukan untuk menggunakan selectionStart .

function setCaretPosition(elemId, caretPos) {
    var el = document.getElementById(elemId);

    el.value = el.value;
    // ^ this is used to not only get "focus", but
    // to make sure we don't have it everything -selected-
    // (it causes an issue in chrome, and having it doesn't hurt any other browser)

    if (el !== null) {

        if (el.createTextRange) {
            var range = el.createTextRange();
            range.move('character', caretPos);
            range.select();
            return true;
        }

        else {
            // (el.selectionStart === 0 added for Firefox bug)
            if (el.selectionStart || el.selectionStart === 0) {
                el.focus();
                el.setSelectionRange(caretPos, caretPos);
                return true;
            }

            else  { // fail city, fortunately this never happens (as far as I've tested) :)
                el.focus();
                return false;
            }
        }
    }
}
Mark Pieszak - Trilon.io
sumber
@ mcpDESIGNS Saya mencoba menggunakan fungsi ini ketika fokus dibuat pada input teks, tapi saya tidak ke mana-mana, Bisakah Anda membantu menerapkan fungsi ini menggunakan javascript murni?
elad.chen
@ elad.chen Apakah Anda mencoba memposisikan mereka di ujung kotak teks segera setelah mereka fokus pada itu?
Mark Pieszak - Trilon.io
@ mcpDESIGNS Saya ingin menempatkan kursor di awal bidang segera setelah elemen sedang difokuskan. Lihat biola: jsfiddle.net/KuLTU/3
elad.chen
@ elad.chen Maaf atas keterlambatan tanggapan gila! Ubah saja kejadian itu .onclickalih-alih .onfocusdalam fungsi search_field_focus Anda
Mark Pieszak - Trilon.io
2
el.value = el.value; [...] if(el !== null)- Saya akan menukar dua baris ini. Jika elnull, el.value = el.valueakan gagal, sehingga baris itu harus di dalam if.
BackSlash
21

Saya telah menyesuaikan jawaban kd7 sedikit karena elem.selectionStart akan bernilai false ketika selectionStart kebetulan 0.

function setCaretPosition(elem, caretPos) {
    var range;

    if (elem.createTextRange) {
        range = elem.createTextRange();
        range.move('character', caretPos);
        range.select();
    } else {
        elem.focus();
        if (elem.selectionStart !== undefined) {
            elem.setSelectionRange(caretPos, caretPos);
        }
    }
}
Johannes Ewald
sumber
5

Saya menemukan cara mudah untuk memperbaiki masalah ini, diuji di IE dan Chrome:

function setCaret(elemId, caret)
 {
   var elem = document.getElementById(elemId);
   elem.setSelectionRange(caret, caret);
 }

Berikan id kotak teks dan posisi tanda sisipan ke fungsi ini.

Iam_NSA
sumber
3

Jika Anda perlu memfokuskan beberapa kotak teks dan satu-satunya masalah Anda adalah bahwa seluruh teks akan disorot sedangkan Anda ingin tanda sisipan berada di akhir, maka dalam kasus tertentu, Anda dapat menggunakan trik ini untuk menetapkan nilai kotak teks untuk dirinya sendiri setelah fokus:

$("#myinputfield").focus().val($("#myinputfield").val());
manish_s
sumber
2
<!DOCTYPE html>
<html>
<head>
<title>set caret position</title>
<script type="application/javascript">
//<![CDATA[
window.onload = function ()
{
 setCaret(document.getElementById('input1'), 13, 13)
}

function setCaret(el, st, end)
{
 if (el.setSelectionRange)
 {
  el.focus();
  el.setSelectionRange(st, end);
 }
 else
 {
  if (el.createTextRange)
  {
   range = el.createTextRange();
   range.collapse(true);
   range.moveEnd('character', end);
   range.moveStart('character', st);
   range.select();
  }
 }
}
//]]>
</script>
</head>
<body>

<textarea id="input1" name="input1" rows="10" cols="30">Happy kittens dancing</textarea>

<p>&nbsp;</p>

</body>
</html>
Dirp
sumber
2
function SetCaretEnd(tID) {
    tID += "";
    if (!tID.startsWith("#")) { tID = "#" + tID; }
    $(tID).focus();
    var t = $(tID).val();
    if (t.length == 0) { return; }
    $(tID).val("");
    $(tID).val(t);
    $(tID).scrollTop($(tID)[0].scrollHeight); }
Keith Cromm
sumber
Uncaught TypeError: Object [object HTMLInputElement] tidak memiliki metode 'beginWith'
bobpaul
1
@ bobpaul: tIDharus id elemen, bukan objek elemen itu sendiri. Jika Anda melewatkan objek elemen, Anda bisa menghapus 2 baris pertama dalam metode ini, dan itu akan berhasil.
awe
2

Saya akan memperbaiki kondisi seperti di bawah ini:

function setCaretPosition(elemId, caretPos)
{
 var elem = document.getElementById(elemId);
 if (elem)
 {
  if (typeof elem.createTextRange != 'undefined')
  {
   var range = elem.createTextRange();
   range.move('character', caretPos);
   range.select();
  }
  else
  {
   if (typeof elem.selectionStart != 'undefined')
    elem.selectionStart = caretPos;
   elem.focus();
  }
 }
}
Alexander Gavriliuk
sumber