JQuery kullanarak bir <input type = “text”> (hemen) değişikliğini hemen algıla


397

Bir <input type="text">kutunun değerinin değişmesi için birçok yol vardır , bunlar arasında:

  • basılmasını
  • kopyala yapıştır
  • JavaScript ile değiştirildi
  • tarayıcı veya araç çubuğu tarafından otomatik olarak tamamlandı

JavaScript işlevimin her an değiştiğinde (geçerli giriş değeriyle) çağrılmasını istiyorum. Ve sadece girişin odağını kaybettiği zaman değil, hemen çağrılmasını istiyorum.

Tüm tarayıcılarda (tercihen jQuery kullanarak) bunu yapmak için en temiz ve en sağlam yolu arıyorum.



Yanıtlar:


352

Bu jQuery kodu herhangi bir öğede anında değişiklik yapar ve tüm tarayıcılarda çalışmalıdır:

 $('.myElements').each(function() {
   var elem = $(this);

   // Save current value of element
   elem.data('oldVal', elem.val());

   // Look for changes in the value
   elem.bind("propertychange change click keyup input paste", function(event){
      // If value has changed...
      if (elem.data('oldVal') != elem.val()) {
       // Updated stored value
       elem.data('oldVal', elem.val());

       // Do action
       ....
     }
   });
 });

19
Herkesin referansı için, inputtüm modern tarayıcıları ( MDN referansı ) kapsaması gerektiğine inandığım HTML5 olayıdır . keyuphafif bir gecikmeyle gerisini yakalamalı ( inputtuşa basılırken tetiklenir). propertychangetescilli bir MS olayıdır ve pastegerçekten gerekli olup olmadığından emin değilim .
Jo Liss

71
Yanlış mıyım yoksa javascript ile metin değiştiğinde bu işe yaramazdocument.getElementById('txtInput').value = 'some text';
Mehmet Ataş

5
Mehmet, kod JS ile değiştirilen değerleri yakalamak anlamına gelmiyor.
phatmann

12
@ MehmetAtaş kısmen doğrudur. Referans inputolayı burada içerikleri JavaScript aracılığıyla değiştirilir zaman patlamaz belirtmektedir. Ancak, onpropertychangeolay yapar JS yoluyla modifikasyonu üzerine ateş (bkz burada ). Bu nedenle, içerikler IE'de JS aracılığıyla değiştirildiğinde bu kod çalışır, ancak diğer tarayıcılarda çalışmaz.
Vicky Chijwani

2
Propertychange, keyup vb. Olduğunda girişte özel bir olayı tetikleyebilir ve daha sonra herhangi bir yerde kullanabilirsiniz.
Ivan Ivković

122

JQuery için gerçek zamanlı fantezi bir çözüm> = 1.9

$("#input-id").on("change keyup paste", function(){
    dosomething();
})

"click" etkinliğini de tespit etmek istiyorsanız, sadece:

$("#input-id").on("change keyup paste click", function(){
    dosomething();
})

jQuery <= 1.4 kullanıyorsanız, liveyerine kullanın on.


3
Bunun bir dezavantajı var. Giriş alanından sekme tuşu ile ayrılırsanız - içerik düzenlenmemiş olsa bile keyup olayı atar.
Pawka

2
Datetimepicker öğesinin # input-id değerini ne zaman doldurduğunu nasıl tespit edebilirim? Olayların hiçbiri (değiştir, yapıştır) çalışmaz.
Pathros

Bu harika! 1.8.3 jquery ile denedim ve işe yarıyor. Hala ben bile 1.9.1 yükseltme bile bu yüzden değiştirmek zorunda bazı livequery () kodu var. Eski olduğunu biliyorum ama tüm web sitesi de öyle.
Asle

Bilginize: Klavye geçerli olmayan bir tarih seçmek için kullanılırsa bu olaylar boş bir değerle tetiklenir. yani. 30 Şub. Stackoverflow.com/questions/48564568/…
Olmstov

107

Maalesef bence setInterval ödülü kazandı:

<input type=text id=input_id />
<script>
setInterval(function() { ObserveInputValue($('#input_id').val()); }, 100);
</script>

En temiz çözüm, sadece 1 satır kod. Aynı zamanda en sağlam olanıdır, çünkü tüm farklı olaylar / yollar hakkında endişelenmenize gerek yoktur.input değer alabileceği .

'SetInterval' kullanmanın dezavantajları bu durumda geçerli görünmüyor:

  • 100 ms gecikme süresi? Birçok uygulama için 100ms yeterince hızlıdır.
  • Tarayıcıya yük eklendi mi? Genel olarak, sayfanıza çok sayıda ağır set eklenmesi aralıkları kötü. Ancak bu özel durumda, eklenen sayfa yükü algılanamaz.
  • Birçok girdiye göre ölçeklendirilmiyor mu? Çoğu sayfada, aynı setInterval'da koklayabileceğiniz birkaç girişten daha fazlası yoktur.

21
Nintendo 3DS tarayıcısını (Sürüm / 1.7552.EU) kullanırken, formdaki giriş alanındaki değişiklikleri algılamanın tek yolu bu gibi görünüyor.
Johan

4
Not: Aşırı yük hafifletilebilir. Giriş odaklanmaya başladığında setInterval'ı başlatırsanız ve giriş odaklanmayı kaybettiğinde clearInterval'ı başlatırsanız
Tebe

10
Neden sürekli çalışmasının bir nedeni olmayan sürekli çalışan bir 100ms aralık oluşturuyorsunuz? ETKİNLİK insanlar. Onları kullan.
Gavin

15
@Gavin, bu özel durumda JS olaylardan yoksun .. bize tanıyabilecek bir dizi olay bulun, kullanıcı girişleri, kullanıcı macunları, kullanıcı kesimleri, javascript eklemeleri, javascript kaldırma, formların otomatik tamamlanması, gizli formlar, görüntülenmeyen formlar.
Naramsim

2
@Gavin JS'de her giriş tetiklenen değiştirilmiş bir olay yok gibi görünüyor. (olay tetikleyici çözümlerinin hiçbirinin çalışmadığını görmek için bir document.getElementById (name) .value = Math.random ()) yapın.
Joeri

58

oninputEtkinliğe bağlanmak çoğu aklı başında tarayıcıda iyi çalışıyor gibi görünüyor. IE9 da destekliyor, ancak uygulama hatalı (karakterler silinirken olay tetiklenmiyor).

JQuery sürüm 1.7 + ile onyöntem böyle bir olay bağlamak için yararlıdır:

$(".inputElement").on("input", null, null, callbackFunction);

12
oninputinput[type=reset]Bu testte gördüğünüz gibi etkinlikle veya javascript düzenleme ile çalışmaz
Yukulélé

2
@ Yukulélé, En azından olası tüm kullanıcı eylemlerini tespit etmeye çalışmaktan daha kolay bir şekilde çalışabiliriz .
Pacerier

30

2017 yanıtı : input olayı IE8'den daha yeni bir şey için tam olarak bunu yapar.

$(el).on('input', callback)

6
Üzgünüm ama ... bu yukarıdaki HRJ'nin 2012 yanıtından nasıl farklı? Her neyse, inputetkinlik JS değişikliklerini algılayamıyor.
David

16

Maalesef, ölçütlerinize uyan bir etkinlik veya etkinlik kümesi yok. Tuşa basma ve kopyalama / yapıştırma işlemlerinin her ikisi de keyupetkinlikle yapılabilir. JS'deki değişiklikler daha zordur. Metin kutusunu ayarlayan kod üzerinde kontrolünüz varsa, en iyi seçeneğiniz, işlevi doğrudan çağırmak veya metin kutusundaki bir kullanıcı etkinliğini tetiklemek için değiştirmektir:

// Compare the textbox's current and last value.  Report a change to the console.
function watchTextbox() {
  var txtInput = $('#txtInput');
  var lastValue = txtInput.data('lastValue');
  var currentValue = txtInput.val();
  if (lastValue != currentValue) {
    console.log('Value changed from ' + lastValue + ' to ' + currentValue);
    txtInput.data('lastValue', currentValue);
  }
}

// Record the initial value of the textbox.
$('#txtInput').data('lastValue', $('#txtInput').val());

// Bind to the keypress and user-defined set event.
$('#txtInput').bind('keypress set', null, watchTextbox);

// Example of JS code triggering the user event
$('#btnSetText').click(function (ev) {
  $('#txtInput').val('abc def').trigger('set');
});

Bu kod üzerinde kontrolünüz yoksa setInterval(), metin kutusunu değişiklikler için 'izlemek' için kullanabilirsiniz :

// Check the textbox every 100 milliseconds.  This seems to be pretty responsive.
setInterval(watchTextbox, 100);

Bu tür bir aktif izleme, 'anında' güncellemeleri yakalamaz, ancak algılanabilir bir gecikme olmayacak kadar hızlı görünüyor. DrLouie'nin yorumlarda belirttiği gibi, çok sayıda girişi izlemeniz gerekiyorsa bu çözüm muhtemelen iyi ölçeklenmez. Daha setInterval()fazla veya daha az sıklıkta kontrol etmek için 2. parametreyi her zaman için ayarlayabilirsiniz .


FYI aslında tarayıcılar arasında değişen derecelerde OP kriterlerine uyacak şekilde birleştirilebilecek bir dizi olay var (ilk soru yorumundaki bağlantılara bakın). Bu cevap, söz konusu olayların hiçbirini kullanmaz ve ironik bir şekilde, muhtemelen tüm tarayıcılarda, hafif bir gecikmeyle de olsa çalışır;)
Crescent Fresh

OP, metin kutusundaki değişiklikleri JavaScript aracılığıyla yakalamak istiyor (örn myTextBox.value = 'foo';. Bu durumu ele alan JavaScript etkinliği yok
Annabelle

1
Birinin sekmeleri saklayacak 50 alanı varsa ne olur?
DoctorLouie

1
Evet, benim durumumda sadece 1 alanım var, ancak bunun birkaç alan için neden iyi çalışmadığını anlamıyorum. Muhtemelen tüm girişleri kontrol eden 1 setTimeout'a sahip olmak en verimli yöntem olacaktır.
Dustin Boswell

1
@Douglas: Hiçbir JavaScript olayı bu durumla başa çıkmıyor - Düzeltme: IE ile başa çıkabilir input.onpropertychangeve FF2 +, Opera 9.5, Safari 3 ve Chrome 1 ile başa çıkabilir input.__defineSetter__('value', ...)(DOM düğümlerinde işlevsel olmadığı belgelenmiş olmasına rağmen, doğrulayabilirim işe yarıyor). IE'nin uygulamasından tek sapma IE'nin işleyiciyi yalnızca programlı ayarda değil, aynı zamanda önemli olaylar sırasında da tetiklemesidir.
Crescent Fresh

6

Diğer cevaplardan herhangi birini beğenmediyseniz, biraz farklı bir çözüm:

var field_selectors = ["#a", "#b"];
setInterval(function() { 
  $.each(field_selectors, function() { 
    var input = $(this);
    var old = input.attr("data-old-value");
    var current = input.val();
    if (old !== current) { 
      if (typeof old != 'undefined') { 
        ... your code ...
      }
      input.attr("data-old-value", current);
    }   
  }   
}, 500);

Bağlam menüsü yapıştırmasını yakalamak için tıklama ve tuşlara güvenemeyeceğinizi düşünün.


Bu cevap benim için en iyisi oldu. $("input[id^=Units_]").each(function() {
Kullanana

4

Bu kodu bir yere ekleyin, bu işe yarayacaktır.

var originalVal = $.fn.val;
$.fn.val = function(){
    var result =originalVal.apply(this,arguments);
    if(arguments.length>0)
        $(this).change(); // OR with custom event $(this).trigger('value-changed');
    return result;
};

Bu çözümün val () 'da jQuery'de change () tetiklenmediği bulundu


3

Bir örnek oluşturdum. Senin için çalışsın.

var typingTimer;
var doneTypingInterval = 10;
var finaldoneTypingInterval = 500;

var oldData = $("p.content").html();
$('#tyingBox').keydown(function () {
    clearTimeout(typingTimer);
    if ($('#tyingBox').val) {
        typingTimer = setTimeout(function () {
            $("p.content").html('Typing...');
        }, doneTypingInterval);
    }
});

$('#tyingBox').keyup(function () {
    clearTimeout(typingTimer);
    typingTimer = setTimeout(function () {
        $("p.content").html(oldData);
    }, finaldoneTypingInterval);
});


<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>


<textarea id="tyingBox" tabindex="1" placeholder="Enter Message"></textarea>
<p class="content">Text will be replace here and after Stop typing it will get back</p>

http://jsfiddle.net/utbh575s/


3

Aslında javaScript değişikliklerini tespit etmek için döngüler kurmamız gerekmiyor. Tespit etmek istediğimiz öğeye zaten birçok olay dinleyicisi kurduk. sadece zararlı olmayan herhangi bir olayı tetiklemek işi yapar.

$("input[name='test-element']").on("propertychange change click keyup input paste blur", function(){
console.log("yeh thats worked!");
});

$("input[name='test-element']").val("test").trigger("blur");

ve ofc bu yalnızca projenizdeki javascript değişiklikleri üzerinde tam kontrole sahipseniz kullanılabilir.


2

En iyi yol, kendiniz listelediğiniz bu üç üssü kapsamaktır. Basit: onblur,: onkeyup, vb. İstediğiniz şey için çalışmaz, bu yüzden onları birleştirin.

KeyUp ilk ikisini kapsamalıdır ve Javascript giriş kutusunu değiştiriyorsa, iyi umarım kendi javascriptinizdir, bu yüzden sadece değiştiren işlevde bir geri arama ekleyin.


1
Basit çözüm için +1, ancak OP metin kutusunda kod yapmada değişiklik yapmak istemez / istemez.
Annabelle

Olası tüm olayları numaralandırmak benim için sağlam görünmüyor. Kullanıcı silme işlemini basılı tutarsa ​​keyup çalışır mı (yani bir tekrar tuşu)? Otomatik tamamlama (veya değerleri otomatik dolduran araç çubukları) ne olacak? Yoksa tuşa basma özel giriş kaynakları var mı? Özleyeceğiniz gibi bir şey olacağından endişe ediyorum.
Dustin Boswell

1

İşte bir otomatik tamamlama varyasyonu uygulamak için kullandığım bir çalışma örneği bir jqueryui seçici (liste) doldurur, ancak tam olarak bir açılır menü yapan jqueryui otomatik tamamlama gibi işlev istemiyorum.

$("#tagFilter").on("change keyup paste", function() {
     var filterText = $("#tagFilter").val();
    $("#tags").empty();
    $.getJSON("http://localhost/cgi-bin/tags.php?term=" + filterText,
        function(data) {
            var i;
            for (i = 0; i < data.length; i++) {
                var tag = data[i].value;
                $("#tags").append("<li class=\"tag\">" + tag + "</li>");
            }
        }); 
});

1

JQUERY YOK! (Zaten bu günlerde modası geçmiş)

Düzenleme: HTML olaylarını kaldırdım. HTML olaylarını KULLANMAYIN ... bunun yerine Javascript Olay Dinleyicilerini kullanın.

document.querySelector("#testInput").addEventListener("input", test);

function test(e) {
 var a = document.getElementById('output');
 var b = /^[ -~]+$/;
 if (e.target.value == '' || b.test(e.target.value)) {
  a.innerText = "Text is Ascii?.. Yes";
 } else if (!b.test(e.target.value)) {
  a.innerText = "Text is Ascii?.. No";
 }
}
Try pressing Alt+NumPad2+NumPad3 in the input, it will instantly detect a change, whether you Paste, Type, or any other means, rather than waiting for you to unselect the textbox for changes to detect.

<input id="testInput">
<br>
<a id="output">Text is Ascii?.. Yes</a>


0

<span contenteditable="true" spellcheck="false">Elemanı yerine kullanamaz <input type="text">mısın?

<span>( contenteditable="true" spellcheck="false"öznitelik olarak) <input>esas olarak aşağıdakilere göre ayrılır:

  • Bir tarz gibi değil <input>.
  • Bir valueözelliği yoktur, ancak metin innerTextiç bedeninin bir parçası olarak işlenir ve bir parçası haline gelir.
  • <input>Özelliği ayarlamanıza rağmen çok satırlıdır multiline="true".

Görünümü gerçekleştirmek için elbette CSS'de stil yazabilir, oysa değeri innerText bir olay için alabileceğiniz yazabilirsiniz:

İşte bir keman .

Ne yazık ki aslında IE ve Edge'de çalışmayan, bulamadığım bir şey var.


Bu yöntemi kullanma konusunda erişilebilirlik endişeleri olduğunu düşünüyorum.
Daniel Tonon

0

Bu soru 10 yıl önce gönderilmiş olmasına rağmen, hala bazı iyileştirmelere ihtiyaç duyduğuna inanıyorum. İşte benim çözümüm.

$(document).on('propertychange change click keyup input paste', 'selector', function (e) {
    // Do something here
});

Bu çözümle ilgili tek sorun, değer gibi javascript'ten değişirse tetiklemeyecektir $('selector').val('some value'). Javascript'ten değeri değiştirdiğinizde seçicinize herhangi bir olayı tetikleyebilirsiniz.

$(selector).val('some value');
// fire event
$(selector).trigger('change');

-2

bu örneği görebilir ve ilginizi çeken etkinliklerin hangileri olduğunu seçebilirsiniz:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script> 
<title>evetns</title>
</head>
<body>
<form>
    <input class="controlevents" id="i1" type="text" /><br />
    <input class="controlevents" id="i2" type="text" /><br />
    <input class="controlevents" id="i3" type="text" /><br />
    <input class="controlevents" id="i4" type="text" /><br />
    <input class="controlevents" id="i5" type="text" /><br />
</form>
<div id="datatext"></div>
</body>
</html>
<script>
$(function(){

function testingevent(ev){
    if (ev.currentTarget.tagName=="INPUT")
        $("#datatext").append("<div>id : " + ev.currentTarget.id + ", tag: " + ev.currentTarget.tagName + ", type: "+ ev.type +"</div>");
}   

    var eventlist = ["resizeend","rowenter","dragleave","beforepaste","dragover","beforecopy","page","beforeactivate","beforeeditfocus","controlselect","blur",
                    "beforedeactivate","keydown","dragstart","scroll","propertychange","dragenter","rowsinserted","mouseup","contextmenu","beforeupdate",
                    "readystatechange","mouseenter","resize","copy","selectstart","move","dragend","rowexit","activate","focus","focusin","mouseover","cut",
                    "mousemove","focusout","filterchange","drop","blclick","rowsdelete","keypress","losecapture","deactivate","datasetchanged","dataavailable",
                    "afterupdate","mousewheel","keyup","movestart","mouseout","moveend","cellchange","layoutcomplete","help","errorupdate","mousedown","paste",
                    "mouseleave","click","drag","resizestart","datasetcomplete","beforecut","change","error","abort","load","select"];

    var inputs = $(".controlevents");

    $.each(eventlist, function(i, el){
        inputs.bind(el, testingevent);
    });

});
</script>

4
Sanırım bir etkinlik türünü unuttun :)
Dustin Boswell

-3

Burada partiye geç olabilir ama sadece jQuery sağladığı .change () olayı kullanamazsınız.

Böyle bir şey yapabilmelisin ...

$(#CONTROLID).change(function(){
    do your stuff here ...
});

Her zaman gibi bir kontrol listesine bağlayabilirsiniz ...

var flds = $("input, textarea", window.document);

flds.live('change keyup', function() {
    do your code here ...
});

Canlı bağlayıcı, sayfada şu anda ve gelecekte var olan tüm öğelerin ele alınmasını sağlar.


2
Değişiklik olayı yalnızca odak kaybolduktan sonra tetiklenir, bu nedenle kullanıcı kutuya yazarken, yalnızca bittikten ve başka bir şey yapmaya devam ettikten sonra tetiklenmez.
Eli Sand

2
Buradaki diğer birçok yanıt gibi, öğenin değeri Javascript'ten değiştirildiğinde bu çalışmaz. OP'nin istediği diğer değişiklik durumlarını özleyip özlemediğini bilmiyorum.
Mark Amery

-4

Bunu yapmanın en hızlı ve temiz yolu:

Jquery kullanıyorum ->

$('selector').on('change', function () {
    console.log(this.id+": "+ this.value);
});

Benim için gayet iyi çalışıyor.


7
Bu zaten önerildi. Kullanıcı metni yazdığında yalnızca basit durumları ele alır.
Christophe
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.