Metin alanı değişim tespiti


132

Javascript kullanarak metin alanında değişiklik olayını nasıl tespit ederim?
Yazarken kaç karakter kaldığını tespit etmeye çalışıyorum.

Onchange olayını kullanmayı denedim, ancak bu yalnızca odak olmadığında devreye giriyor gibi görünüyor.

Yanıtlar:


97

Sen kullanıma gerekecek onkeyup ve onchange bunun için. Onchange, bağlam menüsünün yapıştırılmasını önleyecek ve onkeyup her tuş vuruşu için çalışacaktır.

Benim cevap bakınız textArea üzerinde MAXLENGTH empoze etmek nasıl bir kod örneği için.


3
Sadece Josh'un söylediği şeyi vurgulamak istedim, bunun için keyup'ı değil, keyup kullanmanız gerektiğini vurgulamak istedim: keydown çağrısı metin alanında değişiklik yapılmadan önce çağrılıyor gibi görünüyor, bu yüzden yanlış uzunluğu kullanıyor olacaksınız (ve Ne kadar durumda olduğunuzu gerçekten bilin: yazıyor veya siliyor olabilir ve metin seçilebilir, yani +/- 1'den daha fazlası olabilir).
brianmearns

65
Burada -1 veriyorum, üzgünüm! onkeyupgiriş tespiti için korkunç bir olaydır. oninputVe onpropertychange(IE desteği için) kullanın .
Andy E

6
"Sadece" sorun olduğunu onchangeedilir DEĞİL bir bağlam menüsü kes / yapıştır oluştuğunda ateş etti.
Tom

4
Onkeydown ve bir setTimeout kullanmak çok daha duyarlıdır, böylece anahtarın serbest bırakılmasını beklemek yerine anında değişiklik algılaması elde edersiniz. Ayrıca kesip yapıştırmanız gerekiyorsa, kes ve yapıştır olaylarını kullanın.
Kevin B

1
Uyarı: onkeyup size sorun çıkarabilir. Örnek: Diyelim ki sadece giriş içeriği değiştiğinde bir şeyler yapmalısınız. Bir keyup'ın girişi değiştireceğini varsayarsanız, bu doğru değildir. Girişe odaklanın. Bir sonraki alana geçmek için "sekme" yi kullanın. Şimdi girişe geri dönmek için "shift + tab" kullanın. keyup tetiklenir, ancak girdi gerçekte kullanıcı tarafından değiştirilmedi.
Zig Mandel

117

Yıl 2012, PC sonrası dönem burada ve hala bu kadar basit bir şeyle mücadele etmemiz gerekiyor. Bu çok basit olmalı .

Bu rüya gerçekleşene kadar, işte bunu yapmanın en iyi yolu, çapraz tarayıcı: ve olaylarının bir kombinasyonunu kullanıninputonpropertychange , örneğin:

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

inputOlay ilgilenir IE9 +, FF, Chrome, Opera ve Safari ve onpropertychangeilgilenir IE8 (o da IE6 ve 7 ile çalışır, ancak bazı hatalar vardır).

Kullanmanın avantajı inputve onpropertychangeonlar (basıldığında gibi gereksiz yere ateş kalmamasıdır Ctrlveya Shiftanahtarları); bu nedenle , metin alanı içeriği değiştiğinde nispeten pahalı bir işlem yürütmek istiyorsanız, gitmenin yolu budur .

Şimdi, IE, her zaman olduğu gibi, bunu desteklemek için yarım yamalak bir iş yapıyor: IE'de karakterler metin alanından silindiğindeinput ne onpropertychangetetikleniyor ne de ateşleniyor. Dolayısıyla, IE'de karakterlerin silinmesini halletmeniz gerekiyorsa, kullanın ( / kullanmak yerine , çünkü kullanıcı bir tuşa basıp basılı tutsa bile yalnızca bir kez ateşlenir).keypresskeyupkeydown

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

DÜZENLEME: Hatta yukarıdaki çözüm mükemmel, hem haklı Açıklamalarda belirttiği edilmez görünüyor: varlığı addEventListenertextarea üzerinde mülkiyet yok değil sen aklı başında bir tarayıcı ile çalışıyoruz ima; Benzer varlığı attachEventözelliği yok değil IE ima. Kodunuzun gerçekten hava geçirmez olmasını istiyorsanız, bunu değiştirmeyi düşünmelisiniz. İşaretçiler için Tim Down'ın yorumuna bakın .


1
Bu en iyi yaklaşımdır. Buradaki çıkarımlardan hoşlanmıyorum (için tarayıcı desteği olay addEventListeneriçin destek anlamına gelmez inputveya tam tersi); özellik tespiti daha iyi olurdu. Bununla ilgili bir tartışma için bu blog gönderisine bakın .
Tim Down

Bu konuda Tim ile tamamen aynı fikirdeyim. oninputbunu nasıl yapmamız gerektiğidir, ancak muhtemelen addEventListenertarayıcı desteği için testiniz olarak kullanmamalısınız . Her durumda +1.
Ben D

1
Katılmıyorum, giriş IE9 ile ilgilenmez. Bağlam menüsü aracılığıyla Kes / Yapıştır maalesef aynı zamanda giriştir ve geri al. Test etme zahmetine girmedim, ancak IE10 + 'nın bu sorunu çözdüğü bahse hiç para yatırmam.
Stefan Steiger

1
@StefanSteiger, bu yüzden cevabım keypressolayı IE9'da (ve muhtemelen sonraki sürümlerde de) bu durumu ele almak için kullanmayı öneriyor .
Vicky Chijwani

inputolay işleyicisi, .oninputobject özelliği uygulanarak da tanımlanabilir .
idare edin

20
  • Google-Chrome için bir giriş yeterli olacaktır (Windows 7'de Sürüm 22.0.1229.94 m ile test edilmiştir).
  • IE 9 için, oninput, bağlam menüsü ve geri tuşu aracılığıyla kesme dışında her şeyi yakalayacaktır.
  • IE 8 için, bir girişe ek olarak yapıştırmayı yakalamak için onpropertychange gereklidir.
  • IE 9 + 8 için, backspace'i yakalamak için onkeyup gerekir.
  • IE 9 + 8 için, onmousemove içerik menüsü aracılığıyla kesmeyi yakalamak için bulduğum tek yol

Firefox'ta test edilmedi.

    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>

1
Müthiş işlev adları :)
Jonas Gröger

8

Bunun tam olarak senin sorunun olmadığını biliyorum ama bunun yararlı olabileceğini düşündüm. Belirli uygulamalar için, bir tuşa her basıldığında değişiklik işlevinin etkinleşmesi güzeldir. Bu, aşağıdaki gibi bir şeyle başarılabilir:

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

Bu, belirli bir gecikme süresi içinde daha yeni bir olayın tetiklenip tetiklenmediğini test ederek çalışır. İyi şanslar!


1
Gecikmiş eylemi 'kısma' için +1! Uygulamamda benzer bir şey kullanıyorum.
psulek

7

Bu sorunun JavaScript'e özgü olduğunu biliyorum, ancak mevcut tüm tarayıcılarda bir metin alanı değiştiğinde HER ZAMAN bunu algılamanın iyi ve temiz bir yolu yok gibi görünüyor. JQuery'nin bizim için hallettiğini öğrendim. Metin alanlarındaki bağlamsal menü değişikliklerini bile yönetir. Giriş türünden bağımsız olarak aynı sözdizimi kullanılır.

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

veya

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

4
Değişim olayının jQuery ile düz JS'den daha tutarlı olmadığını buldum. JQuery kullandım bind("input cut paste"...ve bir cazibe gibi çalışıyor - klavye veya bağlam menüsünü kullanarak yazmak, kesmek ve yapıştırmak; hatta metin sürükle / bırak.
Lawrence Dol

2
Maalesef, FF changeiçin olayı tetiklemiyor textarea.
dma_k

4

Textarea değişikliğinde olayı dinleyebilir ve istediğiniz değişiklikleri yapabilirsiniz. İşte bir örnek.

(() => {
	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>


1

HTML5 giriş doğrulama / kalıp özniteliği ile eşleştirilmişse anahtarlama yeterli olmalıdır. Bu nedenle, girişi doğrulamak ve .checkValidity () durumuna göre hareket etmek için bir kalıp (regex) oluşturun. Aşağıdaki gibi bir şey işe yarayabilir. Sizin durumunuzda, bir normal ifadenin uzunluğa uymasını istersiniz. Çözümüm burada çevrimiçi olarak kullanımda / demo yapılabilir .

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

0

IE 11 için jquery olmadan ve yalnızca tek bir metin alanı için kullandım kod:

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

ve html:

<TEXTAREA onpropertychange='limit_char(5)' ...

-1

Bunu dene. Çok basit ve 2016 olduğu için çoğu tarayıcıda çalışacağından eminim.

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

Yani url'yi kimliğe göre alıyorsunuz, ancak kodunuzda gösterilmiyor.
AbsoluteƵERØ

-8

Yapabileceğiniz en iyi şey, belirli bir süre için çağrılacak bir işlev ayarlamak ve bu işlevi metin alanınızın içeriğini kontrol etmektir.

self.setInterval('checkTextAreaValue()', 50);

7
yoklama çok kötü bir fikir. Sadece performansı yok edecek. Ayrıca, yayınlanan diğerleri gibi, bazı çözümler de var
Pier-Olivier Thibault

2
Bu 21. yüzyıl. Hiçbir tarayıcı, her 50 ms'de bir dizi karşılaştırması yaparken sorun yaşamamalıdır. Seçicilerinizi önbelleğe alın ve bu tamamen kabul edilebilir bir çözümdür.
nullability
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.