Deteksi pertukaran teksareare

132

Bagaimana cara mendeteksi perubahan acara pada textarea menggunakan javascript?
Saya mencoba mendeteksi jumlah karakter yang tersisa saat Anda mengetik.

Saya mencoba menggunakan acara onchange, tetapi itu tampaknya hanya masuk ketika fokus keluar.

teepusink
sumber

Jawaban:

97

Anda harus menggunakan onkeyup dan onchange untuk ini. Perubahan akan mencegah penyisipan menu konteks, dan onkeyup akan diaktifkan untuk setiap penekanan tombol.

Lihat jawaban saya di Cara memaksakan maxlength pada textArea untuk contoh kode.

Josh Stodola
sumber
3
Hanya ingin menekankan apa yang sudah dikatakan Josh, bahwa Anda harus menggunakan keyup, bukan keydown untuk ini: keydown tampaknya dipanggil sebelum perubahan sebenarnya dibuat ke textarea, jadi Anda akan menggunakan panjang yang salah (dan Anda tidak perlu t benar-benar tahu bagaimana Anda: bisa mengetik atau menghapus, dan bisa saja teks yang dipilih berarti lebih dari +/- 1).
brianmearns
65
Saya memberi -1 di sini, maaf! onkeyupadalah peristiwa yang mengerikan untuk deteksi input. Gunakan oninputdan onpropertychange(untuk dukungan IE).
Andy E
6
"Hanya" masalah adalah onchangeadalah TIDAK dipecat ketika konteks-menu cut / paste terjadi.
Tom
4
Jauh lebih responsif untuk menggunakan onkeydown dan setTimeout sehingga Anda mendapatkan deteksi perubahan instan daripada menunggu kunci dirilis. Jika Anda juga perlu menangkap cut and paste, gunakan acara cut and paste.
Kevin B
1
Peringatan: onkeyup dapat memberi Anda masalah. Contoh: katakanlah Anda hanya boleh melakukan sesuatu jika konten input berubah. Jika Anda menganggap keyup akan mengubah input, itu tidak benar. Letakkan fokus pada input. Gunakan "tab" untuk pindah ke bidang berikutnya. Sekarang gunakan "shift + tab" untuk kembali ke input. keyup menyala namun input sebenarnya tidak diubah oleh pengguna.
Zig Mandel
117

Ini tahun 2012, era pasca-PC ada di sini, dan kita masih harus berjuang dengan sesuatu yang mendasar seperti ini. Ini seharusnya sangat sederhana .

Sampai saat impian itu terpenuhi, inilah cara terbaik untuk melakukan ini, lintas-browser: gunakan kombinasi dari inputdan onpropertychangeacara , seperti:

var area = container.querySelector('textarea');
if (area.addEventListener) {
  area.addEventListener('input', function() {
    // event handling code for sane browsers
  }, false);
} else if (area.attachEvent) {
  area.attachEvent('onpropertychange', function() {
    // IE-specific event handling code
  });
}

The inputevent mengurus IE9 +, FF, Chrome, Opera dan Safari , dan onpropertychangemengurus IE8 (juga bekerja dengan IE6 dan 7, tetapi ada beberapa bug).

Keuntungan menggunakan inputdan onpropertychangeadalah mereka tidak memecat secara tidak perlu (seperti ketika menekan tombol Ctrlatau Shift); jadi jika Anda ingin menjalankan operasi yang relatif mahal ketika konten textarea berubah, ini adalah cara untuk pergi .

Sekarang IE, seperti biasa, melakukan pekerjaan setengah-setengah untuk mendukung ini: tidak ada input atauonpropertychange di IE ketika karakter dihapus dari textarea. Jadi, jika Anda perlu menangani penghapusan karakter di IE, gunakankeypress (sebagai lawan dari menggunakan keyup/ keydown, karena mereka hanya sekali saja memecat meskipun pengguna menekan dan menahan tombol ke bawah).

Sumber: http://www.alistapart.com/articles/expanding-text-areas-made-elegant/

EDIT: Tampaknya bahkan solusi di atas tidak sempurna, seperti yang ditunjukkan dengan benar di komentar: keberadaan addEventListenerproperti di textarea tidak menyiratkan Anda bekerja dengan browser yang waras; demikian pula keberadaan attachEventproperti tidak menyiratkan IE. Jika Anda ingin kode Anda benar-benar kedap udara, Anda harus mempertimbangkan untuk mengubahnya. Lihat komentar Tim Down untuk petunjuk.

Vicky Chijwani
sumber
1
Ini adalah pendekatan terbaik. Saya tidak suka kesimpulan di sini (dukungan browser untuk addEventListenertidak menyiratkan dukungan untuk inputacara tersebut, atau sebaliknya); deteksi fitur akan lebih baik. Lihat posting blog ini untuk diskusi tentang ini.
Tim Down
Sepenuhnya setuju dengan Tim yang satu ini. oninputadalah bagaimana kita harus melakukan ini, tetapi Anda mungkin tidak boleh menggunakan addEventListenersebagai tes Anda untuk dukungan browser. +1 dalam hal apa pun.
Ben D
1
Tidak setuju, input tidak akan menangani IE9. Memotong / menempel melalui contextmenu sayangnya juga input, dan begitu juga backspace. Saya tidak repot-repot menguji, tapi saya tidak akan menempatkan uang pada taruhan bahwa IE10 + memperbaiki masalah itu.
Stefan Steiger
1
@StefanSteiger itulah sebabnya jawaban saya menyarankan juga menggunakan keypressacara tersebut untuk menangani kasus itu di IE9 (dan mungkin versi yang lebih baru juga).
Vicky Chijwani
inputevent handler juga dapat didefinisikan dengan mengimplementasikan .oninputproperti objek.
Pegangan
20
  • Untuk Google-Chrome, oninput akan cukup (Diuji pada Windows 7 dengan Versi 22.0.1229.94 m).
  • Untuk IE 9, oninput akan menangkap semuanya kecuali dipotong melalui contextmenu dan backspace.
  • Untuk IE 8, pertukaran properti diperlukan untuk mendapatkan tempel di samping oninput.
  • Untuk IE 9 + 8, onkeyup diperlukan untuk menangkap backspace.
  • Untuk IE 9 + 8, onmousemove adalah satu-satunya cara yang saya temukan untuk menangkap pemotongan melalui contextmenu

Tidak diuji pada Firefox.

    var isIE = /*@cc_on!@*/false; // Note: This line breaks closure compiler...

    function SuperDuperFunction() {
        // DoSomething
    }


    function SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally() {
        if(isIE) // For Chrome, oninput works as expected
            SuperDuperFunction();
    }

<textarea id="taSource"
          class="taSplitted"
          rows="4"
          cols="50"
          oninput="SuperDuperFunction();"
          onpropertychange="SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally();"
          onmousemove="SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally();"
          onkeyup="SuperDuperFunctionBecauseMicrosoftMakesIEsuckIntentionally();">
Test
</textarea>
Stefan Steiger
sumber
1
Nama-nama fungsi luar biasa :)
Jonas Gröger
8

Saya tahu ini bukan pertanyaan Anda, tetapi saya pikir ini mungkin berguna. Untuk aplikasi tertentu, menyenangkan untuk memiliki fungsi perubahan, tidak setiap kali tombol ditekan. Ini dapat dicapai dengan sesuatu seperti ini:

var text = document.createElement('textarea');
text.rows = 10;
text.cols = 40;
document.body.appendChild(text);

text.onkeyup = function(){
var callcount = 0;
    var action = function(){
        alert('changed');
    }
    var delayAction = function(action, time){
        var expectcallcount = callcount;
        var delay = function(){
            if(callcount == expectcallcount){
                action();
            }
        }
        setTimeout(delay, time);
    }
    return function(eventtrigger){
        ++callcount;
        delayAction(action, 1200);
    }
}();

Ini bekerja dengan menguji apakah peristiwa yang lebih baru telah dipecat dalam periode penundaan tertentu. Semoga berhasil!

pengguna45743
sumber
1
+1 untuk tindakan tertunda 'pelambatan'! Saya menggunakan sesuatu yang serupa di aplikasi saya.
psulek
7

Saya tahu pertanyaan ini khusus untuk JavaScript, namun, sepertinya tidak ada cara yang baik dan bersih untuk SELALU mendeteksi ketika sebuah teks berubah di semua browser saat ini. Saya telah belajar jquery telah merawatnya untuk kita. Bahkan menangani perubahan menu kontekstual ke area teks. Sintaks yang sama digunakan terlepas dari jenis input.

    $('div.lawyerList').on('change','textarea',function(){
      // Change occurred so count chars...
    });

atau

    $('textarea').on('change',function(){
      // Change occurred so count chars...
    });
Tim Duncklee
sumber
4
Saya menemukan bahwa acara perubahan tidak lebih konsisten dengan jQuery daripada dengan JS biasa. Saya menggunakan jQuery's bind("input cut paste"...dan berfungsi seperti pesona - mengetik, memotong & menempel menggunakan keyboard atau menu konteks; bahkan drag / drop teks.
Lawrence Dol
2
Sayangnya, FF tidak memecat changeacara untuk textarea.
dma_k
4

Anda dapat mendengarkan acara tentang perubahan textarea dan melakukan perubahan seperti yang Anda inginkan. Ini salah satu contohnya.

(() => {
	const textArea = document.getElementById('my_text_area');
  textArea.addEventListener('input', () => {
    let textLn =  textArea.value.length;
    if(textLn >= 100) {
      textArea.style.fontSize = '10pt';
    }

  })
})()
<html>
<textarea id='my_text_area' rows="4" cols="50" style="font-size:40pt">
This text will change font after 100.
</textarea>
</html>

Pankaj Manali
sumber
1

Keyup harus memadai jika dipasangkan dengan atribut validasi / pola input HTML5. Jadi, buat pola (regex) untuk memvalidasi input dan bertindak berdasarkan status .checkValidity (). Sesuatu seperti di bawah ini bisa berfungsi. Dalam kasus Anda, Anda ingin regex mencocokkan panjang. Solusi saya sedang digunakan / demo-online di sini .

<input type="text" pattern="[a-zA-Z]+" id="my-input">

var myInput = document.getElementById = "my-input";

myInput.addEventListener("keyup", function(){
  if(!this.checkValidity() || !this.value){
    submitButton.disabled = true;
  } else {
    submitButton.disabled = false;
  }
});
Ronnie Royston
sumber
0

Kode yang saya gunakan untuk IE 11 tanpa jquery dan hanya untuk satu textarea:

Javascript:

// Impede que o comentário tenha mais de num_max caracteres
var internalChange= 0; // important, prevent reenter
function limit_char(max)
{ 
    if (internalChange == 1)
    {
        internalChange= 0;
        return;
    }
    internalChange= 1;
    // <form> and <textarea> are the ID's of your form and textarea objects
    <form>.<textarea>.value= <form>.<textarea>.value.substring(0,max);
}

dan html:

<TEXTAREA onpropertychange='limit_char(5)' ...
Rogério Silva
sumber
-1

Coba yang ini. Ini sederhana, dan karena ini 2016 saya yakin itu akan berfungsi pada sebagian besar browser.

<textarea id="text" cols="50" rows="5" onkeyup="check()" maxlength="15"></textarea> 
<div><span id="spn"></span> characters left</div>

function check(){
    var string = document.getElementById("url").value
    var left = 15 - string.length;
    document.getElementById("spn").innerHTML = left;
}
standar
sumber
Jadi Anda mendapatkan url dengan id, tetapi tidak ditampilkan dalam kode Anda.
AbsoluteƵERØ
-8

Hal terbaik yang dapat Anda lakukan adalah mengatur fungsi yang akan dipanggil pada jumlah waktu tertentu dan fungsi ini untuk memeriksa konten textarea Anda.

self.setInterval('checkTextAreaValue()', 50);
Ico
sumber
7
pemungutan suara adalah ide yang sangat buruk. Itu hanya akan menghancurkan kinerja. Juga, seperti diposting lainnya, ada beberapa solusi
Pier-Olivier Thibault
2
Ini adalah abad ke-21. Seharusnya tidak ada peramban yang kesulitan menangani perbandingan string setiap 50 ms. Cache pemilih Anda dan ini adalah solusi yang bisa diterima.
nullability