Cara mendeteksi konten kotak teks telah berubah

417

Saya ingin mendeteksi kapan konten kotak teks telah berubah. Saya dapat menggunakan metode keyup, tetapi itu juga akan mendeteksi penekanan tombol yang tidak menghasilkan huruf, seperti tombol panah. Saya memikirkan dua metode untuk melakukan ini menggunakan peristiwa keyup:

  1. Periksa dengan jelas apakah kode ascii dari tombol yang ditekan adalah huruf \ backspace \ delete
  2. Gunakan closure untuk mengingat teks apa yang ada di kotak teks sebelum tombol stroke dan periksa apakah ini sudah berubah.

Keduanya terlihat agak rumit.

olamundo
sumber
7
Yap, menangkap keyup untuk ini buruk. Anda dapat menempelkan barang tanpa menekan tombol sama sekali.
pemboros
2
ada kemungkinan Anda dapat memposting solusi akhir Anda? Saya perlu mengatasi masalah ini juga :)
Matt Dotson
1
atau .keyup()acara ... info lebih lanjut di sini: stackoverflow.com/questions/3003879/…
Victor S
1
Lihat $ ("# beberapa input"). ChangePolling () ; untuk pembungkus yang memeriksa nilai saat ini dan memicu .change()jika telah berubah.
Joel Purra
Anda perlu memeriksa ini juga stackoverflow.com/a/23266812/3160597
azerafati

Jawaban:

714

Mulai amati acara 'masukan' alih-alih 'ubah'.

jQuery('#some_text_box').on('input', function() {
    // do your stuff
});

... yang bagus dan bersih, tetapi dapat diperpanjang ke:

jQuery('#some_text_box').on('input propertychange paste', function() {
    // do your stuff
});
Atul Vani
sumber
12
'hidup' sudah usang. jadi manfaatkan 'on' stackoverflow.com/a/15111970/1724777
NavaRajan
21
Satu-satunya kejatuhan 'input' adalah tidak kompatibel dengan IE <9.
Catfish
5
input adalah acara html5 yang tidak didukung di semua browser. developer.mozilla.org/en-US/docs/Web/API/window.oninput
commonpike
18
Anda juga dapat membahas lebih banyak pangkalan dengan menggunakan: .on ('input properti
ubah
23
Satu-satunya kejatuhan IE <9 adalah tidak ada yang menggunakannya!
sohaiby
67

Gunakan acara pertukaran dalam HTML / JavaScript standar.

Di jQuery itu adalah perubahan () acara. Sebagai contoh:

$('element').change(function() { // do something } );

EDIT

Setelah membaca beberapa komentar, bagaimana dengan:

$(function() {
    var content = $('#myContent').val();

    $('#myContent').keyup(function() { 
        if ($('#myContent').val() != content) {
            content = $('#myContent').val();
            alert('Content has been changed');
        }
    });
});
Waleed Amjad
sumber
3
Ya, ini mirip dengan apa yang saya sarankan di opsi # 2 dalam pertanyaan saya. Saya lebih suka penutupan karena menggunakan global akan membuat fungsi ini hanya berfungsi untuk satu kotak teks. Bagaimanapun, sepertinya jquery aneh tidak memiliki cara yang lebih sederhana untuk melakukan ini.
olamundo
1
Memang aneh, tapi saya ragu ada cara yang lebih baik untuk melakukannya. Anda dapat menggunakan setInterval dan kemudian memeriksa apakah konten telah diubah setiap 0,1 detik dan kemudian melakukan sesuatu. Ini juga akan termasuk pasta mouse dan sebagainya. Tapi itu tidak terdengar terlalu elegan.
Waleed Amjad
4
Masih mungkin bahwa konten dapat diubah tanpa keystroke, misalnya dengan menempelkannya dengan mouse. Jika Anda peduli tentang ini, Anda secara teoritis dapat menangkap acara mouse juga, tetapi pengaturan itu bahkan lebih buruk. Di sisi lain, jika Anda bersedia mengabaikan perubahan yang digerakkan oleh mouse, ini akan dilakukan.
Adam Bellaire
45

Acara 'perubahan' tidak berfungsi dengan benar, tetapi 'input' sempurna.

$('#your_textbox').bind('input', function() {
    /* This will be fired every time, when textbox's value changes. */
} );
schwarzkopfb
sumber
7
Ini berfungsi dengan baik untuk situasi saya, meskipun penggunaan .ondirekomendasikan dari 1,7 dan seterusnya (daripada .bind).
Nick
8
OP tidak menentukan kebutuhan untuk kompatibilitas lintas browser. @schwarzkopfb memberikan solusi. Tidak ada alasan untuk memilih karena Anda memiliki perwakilan untuk melakukannya.
David East
3
@ David dia juga tidak menentukan browser mana
ozz
9
@ jmo21 Saya pikir kita bisa berasumsi untuk pengembangan web ketika browser tidak spesifik solusinya harus lintas fungsional. Norma ini mendukung semua browser.
Chris
3
@ Chris "Norma ini mendukung semua browser" - hanya jika Anda sadis. Tidak ada alasan bagus untuk menghindari kebaikan HTML5 untuk 2% pengguna global di IE 8/9. caniuse.com/#feat=input-event
Yarin
39

Bagaimana dengan ini:

<jQuery 1.7

$("#input").bind("propertychange change keyup paste input", function(){
    // do stuff;
});

> jQuery 1.7

$("#input").on("propertychange change keyup paste input", function(){
    // do stuff;
});

Ini berfungsi di IE8 / IE9, FF, Chrome

Ikan lele
sumber
1
Masalah yang saya miliki dengan jawaban ini adalah ia akan menyala setelah Anda mengaburkan kotak teks, bahkan jika nilainya tidak berubah. Pelakunya adalah "perubahan".
Justin
Apakah Anda menggunakan Chrome? Tampaknya ini adalah bug dengan chrome dan bukan perubahan acara jQuery bugs.jquery.com/ticket/9335
Catfish
berfungsi tetapi memiliki bug kecil jika Anda melakukan console.lognilai dari bidang itu log dua kali setiap kali Anda memasukkan karakter.
Samuel M.
21

Gunakan closure untuk mengingat teks apa yang ada di kotak centang sebelum tombol stroke dan periksa apakah ini sudah berubah.

Ya. Anda tidak harus menggunakan penutupan, tetapi Anda harus mengingat nilai lama dan membandingkannya dengan yang baru.

Namun! Ini masih tidak akan menangkap setiap perubahan, karena ada cara mengedit konten kotak teks yang tidak melibatkan penekanan tombol apa pun. Misalnya memilih rentang teks kemudian klik kanan-potong. Atau menyeretnya. Atau menjatuhkan teks dari aplikasi lain ke dalam kotak teks. Atau mengubah kata melalui periksa ejaan browser. Atau...

Jadi, jika Anda harus mendeteksi setiap perubahan, Anda harus memilihnya. Anda bisa window.setIntervalmemeriksa bidang terhadap nilai sebelumnya setiap (katakanlah) detik. Anda juga bisa kawat onkeyupuntuk fungsi yang sama sehingga perubahan yang berada disebabkan oleh penekanan tombol tercermin lebih cepat.

Rumit? Iya. Tapi begitulah atau lakukan saja cara pertukaran HTML biasa dan jangan mencoba untuk memperbarui secara instan.

bobince
sumber
1
Saat ini inputacara HTML5 layak dan bekerja di versi terbaru dari semua browser utama.
Tim Down
13
$(document).on('input','#mytxtBox',function () { 
 console.log($('#mytxtBox').val());
});

Anda dapat menggunakan acara 'input' untuk mendeteksi perubahan konten di kotak teks. Jangan gunakan 'live' untuk mengikat acara karena sudah usang di Jquery-1.7, Jadi manfaatkan 'on'.

NavaRajan
sumber
@NavaRajan Baru mengujinya lagi di IE9. benar-benar tidak bekerja di backspace.
Flores
Saya ingin TIDAK menggunakan .Live, tapi masalah yang saya alami adalah saya entah bagaimana sudah "kembali ke masa depan" dan pada proyek mvc3 di mana pemimpin tim ingin tetap dengan "out of the box" jadi tidak hanya EF 4.0, tetapi jquery 1.5.1 sedang digunakan THUS .on () tidak ada di 1.5.1, seperti yang ditambahkan dalam jquery versi 1.7 api.jquery.com/on
Tom Stickel
5

Saya berasumsi bahwa Anda mencari untuk melakukan sesuatu yang interaktif ketika kotak teks berubah (yaitu mengambil beberapa data melalui ajax). Saya mencari fungsi yang sama ini. Saya tahu menggunakan global bukan solusi yang paling kuat atau elegan, tapi itulah yang saya lakukan. Berikut ini sebuah contoh:

var searchValue = $('#Search').val();
$(function () {
    setTimeout(checkSearchChanged, 0.1);
});

function checkSearchChanged() {
    var currentValue = $('#Search').val();
    if ((currentValue) && currentValue != searchValue && currentValue != '') {
        searchValue = $('#Search').val();
        $('#submit').click();
    }
    else {
        setTimeout(checkSearchChanged, 0.1);
    }
}

Satu hal penting yang perlu diperhatikan di sini adalah bahwa saya menggunakan setTimeout dan tidak mengaturInterval karena saya tidak ingin mengirim beberapa permintaan sekaligus. Ini memastikan bahwa penghitung waktu "berhenti" ketika formulir dikirimkan dan "dimulai" saat permintaan selesai. Saya melakukan ini dengan memanggil checkSearchChanged ketika panggilan ajax saya selesai. Jelas Anda dapat memperluas ini untuk memeriksa panjang minimum, dll.

Dalam kasus saya, saya menggunakan ASP.Net MVC sehingga Anda dapat melihat cara mengikat ini dengan MVC Ajax juga di posting berikut:

http://geekswithblogs.net/DougLampe/archive/2010/12/21/simple-interactive-search-with-jquery-and-asp.net-mvc.aspx

Doug Lampe
sumber
4

Saya akan merekomendasikan untuk melihat widget autocomplete jQuery UI. Mereka menangani sebagian besar kasus di sana karena basis kode mereka lebih matang daripada kebanyakan di luar sana.

Di bawah ini adalah tautan ke halaman demo sehingga Anda dapat memverifikasinya berfungsi. http://jqueryui.com/demos/autocomplete/#default

Anda akan mendapatkan manfaat paling banyak dari membaca sumber dan melihat bagaimana mereka menyelesaikannya. Anda dapat menemukannya di sini: https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.autocomplete.js .

Pada dasarnya mereka melakukan semuanya, mereka mengikat input, keydown, keyup, keypress, focus and blur. Kemudian mereka memiliki penanganan khusus untuk semua jenis kunci seperti page up, page down, up arrow key and down arrow key. Penghitung waktu digunakan sebelum mendapatkan isi dari kotak teks. Ketika pengguna mengetik kunci yang tidak sesuai dengan perintah (tombol atas, tombol bawah dan sebagainya) ada timer yang mengeksplorasi konten setelah sekitar 300 milidetik. Sepertinya ini dalam kode:

// switch statement in the 
switch( event.keyCode ) {
            //...
            case keyCode.ENTER:
            case keyCode.NUMPAD_ENTER:
                // when menu is open and has focus
                if ( this.menu.active ) {
                    // #6055 - Opera still allows the keypress to occur
                    // which causes forms to submit
                    suppressKeyPress = true;
                    event.preventDefault();
                    this.menu.select( event );
                }
                break;
            default:
                suppressKeyPressRepeat = true;
                // search timeout should be triggered before the input value is changed
                this._searchTimeout( event );
                break;
            }
// ...
// ...
_searchTimeout: function( event ) {
    clearTimeout( this.searching );
    this.searching = this._delay(function() { // * essentially a warpper for a setTimeout call *
        // only search if the value has changed
        if ( this.term !== this._value() ) { // * _value is a wrapper to get the value *
            this.selectedItem = null;
            this.search( null, event );
        }
    }, this.options.delay );
},

Alasan untuk menggunakan timer adalah agar UI mendapat kesempatan untuk diperbarui. Ketika Javascript sedang berjalan, UI tidak dapat diperbarui, oleh karena itu panggilan ke fungsi penundaan. Ini berfungsi dengan baik untuk situasi lain seperti menjaga fokus pada kotak teks (digunakan oleh kode itu).

Jadi Anda bisa menggunakan widget atau menyalin kode ke widget Anda sendiri jika Anda tidak menggunakan jQuery UI (atau dalam kasus saya mengembangkan widget khusus).

Michael Yagudaev
sumber
2

Saya ingin bertanya mengapa Anda mencoba mendeteksi ketika konten kotak teks berubah secara real time ?

Alternatifnya adalah dengan mengatur timer (via setIntval?) Dan membandingkan nilai yang terakhir disimpan dengan yang sekarang dan kemudian reset timer. Ini akan menjamin menangkap perubahan APAPUN, baik yang disebabkan oleh tombol, mouse, beberapa perangkat input lain yang tidak Anda pertimbangkan, atau bahkan JavaScript yang mengubah nilainya (kemungkinan lain yang tidak disebutkan) dari bagian aplikasi yang berbeda.

DVK
sumber
situasi saya (yang mengarahkan saya ke pertanyaan ini) adalah saya harus menunjukkan tombol 'Perbarui Keranjang' ketika jumlah dalam kotak teks diubah. pengguna tidak tahu mereka perlu kehilangan fokus dan mungkin tidak melihat tombolnya.
Simon_Weaver
Maaf, saya tidak yakin ini menjawab pertanyaan "mengapa tidak memeriksa perbedaan pada jadwal". Cukup periksa sesering mungkin (setiap 1/4 detik) dan pengguna tidak akan tahu bedanya.
DVK
1

apakah Anda mempertimbangkan untuk menggunakan acara perubahan ?

$("#myTextBox").change(function() { alert("content changed"); });
Canavar
sumber
5
AFAIK, itu dipicu hanya ketika fokus elemen hilang. Seseorang yang akrab dengan penutupan mungkin tahu tentang ini. :)
simon
ya, ini tidak akan berhasil - acara perubahan dipanggil hanya ketika kotak teks kehilangan fokus. Saya ingin menangani perubahan tepat setelah tombol ditekan.
olamundo
1

Gunakan textchangeacara tersebut melalui jQuery shim yang disesuaikan untuk inputkompatibilitas lintas-browser . http://benalpert.com/2013/06/18/a-near-perfect-oninput-shim-for-ie-8-and-9.html (paling baru bercabang github: https://github.com/pandell /jquery-splendid-textchange/blob/master/jquery.splendid.textchange.js )

Ini menangani semua tag input termasuk <textarea>content</textarea>, yang tidak selalu berfungsi dengan baik change keyupdll. (!) Hanya jQuery yang on("input propertychange")menangani <textarea>tag secara konsisten, dan di atas adalah shim untuk semua browser yang tidak mengerti inputacara.

<!DOCTYPE html>
<html>
<head>
<script class="jsbin" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="https://raw.githubusercontent.com/pandell/jquery-splendid-textchange/master/jquery.splendid.textchange.js"></script>
<meta charset=utf-8 />
<title>splendid textchange test</title>

<script> // this is all you have to do. using splendid.textchange.js

$('textarea').on("textchange",function(){ 
  yourFunctionHere($(this).val());    });  

</script>
</head>
<body>
  <textarea style="height:3em;width:90%"></textarea>
</body>
</html>

Tes JS Bin

Ini juga menangani tempel, hapus, dan tidak menduplikasi upaya pada keyup.

Jika tidak menggunakan shim, gunakan on("input propertychange")acara jQuery .

// works with most recent browsers (use this if not using src="...splendid.textchange.js")

$('textarea').on("input propertychange",function(){ 
  yourFunctionHere($(this).val());    
});  
Ber
sumber
0

Ada contoh kerja yang lengkap di sini .

<html>
<title>jQuery Summing</title>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"> </script>
$(document).ready(function() {
$('.calc').on('input', function() {
var t1 = document.getElementById('txt1');
var t2 = document.getElementById('txt2');
var tot=0;
if (parseInt(t1.value))
tot += parseInt(t1.value);
if (parseInt(t2.value))
tot += parseInt(t2.value);
document.getElementById('txt3').value = tot;
});
});
</script>
</head>
<body>
<input type='text' class='calc' id='txt1'>
<input type='text' class='calc' id='txt2'>
<input type='text' id='txt3' readonly>
</body>
</html>
worldofjr
sumber
0

Sesuatu seperti ini seharusnya bekerja, terutama karena focusdan focusoutakan berakhir dengan dua nilai yang terpisah. Saya menggunakan di datasini karena menyimpan nilai dalam elemen tetapi tidak menyentuh DOM. Ini juga merupakan cara mudah untuk menyimpan nilai yang terhubung ke elemennya. Anda bisa dengan mudah menggunakan variabel dengan cakupan yang lebih tinggi.

var changed = false;

$('textbox').on('focus', function(e) {
    $(this).data('current-val', $(this).text();
});

$('textbox').on('focusout', function(e) {
    if ($(this).data('current-val') != $(this).text())
        changed = true;
    }
    console.log('Changed Result', changed);
}
smcjones
sumber
0

Kode ini mendeteksi setiap kali konten kotak teks telah diubah oleh pengguna dan dimodifikasi oleh kode Javascript.

var $myText = jQuery("#textbox");

$myText.data("value", $myText.val());

setInterval(function() {
    var data = $myText.data("value"),
    val = $myText.val();

    if (data !== val) {
        console.log("changed");
        $myText.data("value", val);
    }
}, 100);
Sandeep Yadav
sumber