Phát hiện trao đổi văn bản


132

Làm cách nào để phát hiện sự kiện thay đổi trên textarea bằng javascript?
Tôi đang cố gắng phát hiện có bao nhiêu ký tự còn lại khi bạn nhập.

Tôi đã thử sử dụng sự kiện onchange, nhưng dường như chỉ khởi động khi hết tiêu điểm.

Câu trả lời:


97

Bạn sẽ cần phải sử dụng onkeyup onchange cho việc này. Việc trao đổi sẽ ngăn việc dán menu ngữ cảnh và onkeyup sẽ kích hoạt cho mọi tổ hợp phím.

Xem câu trả lời của tôi về Cách áp đặt maxlength cho textArea cho một mẫu mã.


3
Chỉ muốn nhấn mạnh những gì Josh đã nói, rằng bạn nên sử dụng keyup, không phải keydown cho việc này: keydown dường như được gọi trước khi thay đổi thực sự được thực hiện cho textarea, vì vậy bạn sẽ sử dụng sai độ dài (và bạn không ' Tôi thực sự biết bạn tắt như thế nào: có thể gõ hoặc xóa và có thể có văn bản được chọn có nghĩa là nó không chỉ là +/- 1).
brianmearn

65
Tôi đang cho -1 ở đây, xin lỗi! onkeyuplà một sự kiện khủng khiếp để phát hiện đầu vào. Sử dụng oninputonpropertychange(để hỗ trợ IE).
Andy E

6
Vấn đề "duy nhất" onchangeKHÔNG được kích hoạt khi xảy ra cắt / dán menu ngữ cảnh.
Tom

4
Việc sử dụng onkeydown và setTimeout sẽ nhạy hơn nhiều để bạn có thể phát hiện thay đổi tức thì thay vì chờ khóa được phát hành. Nếu bạn cũng cần bắt cắt và dán, hãy sử dụng các sự kiện cắt và dán.
Kevin B

1
Cảnh báo: onkeyup có thể gây rắc rối cho bạn. Ví dụ: giả sử bạn chỉ nên làm gì đó nếu nội dung đầu vào thay đổi. Nếu bạn cho rằng một keyup sẽ thay đổi đầu vào, thì nó không đúng. Đặt trọng tâm vào đầu vào. Sử dụng "tab" để di chuyển đến trường tiếp theo. Bây giờ sử dụng "shift + tab" để quay lại đầu vào. keyup kích hoạt nhưng đầu vào không thực sự thay đổi bởi người dùng.
Zig Mandel

117

Đó là năm 2012, kỷ nguyên hậu PC đã ở đây và chúng ta vẫn phải vật lộn với những thứ cơ bản như thế này. Điều này nên rất đơn giản .

Cho đến khi ước mơ đó được thực hiện, đây là cách tốt nhất để thực hiện điều này, trình duyệt chéo: sử dụng kết hợp các sự kiện inputonpropertychange như vậy:

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

Sự inputkiện này quan tâm đến IE9 +, FF, Chrome, Opera và Safarionpropertychangechăm sóc IE8 (nó cũng hoạt động với IE6 và 7, nhưng có một số lỗi).

Ưu điểm của việc sử dụng inputonpropertychangelà chúng không bắn một cách không cần thiết (như khi nhấn Ctrlhoặc Shiftphím); Vì vậy, nếu bạn muốn chạy một hoạt động tương đối tốn kém khi nội dung textarea thay đổi, đây là cách để đi .

Bây giờ IE, như mọi khi, thực hiện một công việc nửa vời để hỗ trợ điều này: không phải inputcũng không onpropertychangekích hoạt trong IE khi các ký tự bị xóa khỏi vùng văn bản. Vì vậy, nếu bạn cần xử lý xóa các ký tự trong IE, hãy sử dụng keypress(trái ngược với việc sử dụng keyup/ keydown, vì chúng chỉ bắn một lần ngay cả khi người dùng nhấn và giữ phím).

Nguồn: http://www.alistapart.com/articles/Exanding-text-areas-ADE-elegant/

EDIT: Có vẻ như ngay cả những giải pháp trên là không hoàn hảo, như một cách đúng đắn chỉ ra trong các ý kiến: sự hiện diện của các addEventListenertài sản trên các vùng văn bản nào không bao hàm sự bạn đang làm việc với một trình duyệt lành mạnh; tương tự như sự hiện diện của attachEventtài sản không ngụ ý IE. Nếu bạn muốn mã của bạn thực sự kín, bạn nên xem xét thay đổi điều đó. Xem bình luận của Tim Down cho con trỏ.


1
Đây là cách tiếp cận tốt nhất. Tôi không thích các suy luận ở đây (hỗ trợ trình duyệt addEventListenerkhông ngụ ý hỗ trợ cho inputsự kiện hoặc ngược lại); phát hiện tính năng sẽ tốt hơn. Xem bài viết trên blog này để thảo luận về điều này.
Tim Down

Hoàn toàn đồng ý với Tim về điều này. oninputlà cách chúng tôi phải làm điều này, nhưng có lẽ bạn không nên sử dụng addEventListenerlàm thử nghiệm để hỗ trợ trình duyệt. +1 trong mọi trường hợp.
Bến D

1
Không đồng ý, đầu vào sẽ không quan tâm đến IE9. Cắt / Dán qua bối cảnh không may cũng là đầu vào, và backspace cũng vậy. Tôi không buồn kiểm tra, nhưng tôi sẽ không đặt bất kỳ khoản tiền nào vào cược mà IE10 + đã khắc phục vấn đề đó.
Stefan Steiger

1
@StefanSteiger đó là lý do tại sao câu trả lời của tôi cũng đề xuất sử dụng keypresssự kiện này để xử lý trường hợp đó trong IE9 (và có thể cả các phiên bản mới hơn).
Vicky Chijwani

inputxử lý sự kiện cũng có thể được xác định bằng cách thực hiện thuộc tính .oninputđối tượng.
xử lý

20
  • Đối với Google-Chrome, oninput sẽ là đủ (Đã thử nghiệm trên Windows 7 với Phiên bản 22.0.1229.94 m).
  • Đối với IE 9, oninput sẽ nắm bắt mọi thứ trừ việc cắt qua ngữ cảnh và backspace.
  • Đối với IE 8, onpropertychange được yêu cầu để bắt dán ngoài oninput.
  • Đối với IE 9 + 8, onkeyup là bắt buộc để bắt backspace.
  • Đối với IE 9 + 8, onmousemove là cách duy nhất tôi tìm thấy để cắt thông qua ngữ cảnh

Chưa được thử nghiệm trên 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>

1
Tên hàm tuyệt vời :)
Jonas Gröger 22/03/19

8

Tôi biết đây không chính xác là câu hỏi của bạn nhưng tôi nghĩ nó có thể hữu ích. Đối với một số ứng dụng, thật tuyệt khi có chức năng thay đổi kích hoạt không phải mỗi lần nhấn phím. Điều này có thể đạt được với một cái gì đó như thế này:

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

Điều này hoạt động bằng cách kiểm tra nếu một sự kiện gần đây đã xảy ra trong một khoảng thời gian trì hoãn nhất định. Chúc may mắn!


1
+1 cho hành động trì hoãn 'điều tiết'! Tôi sử dụng một cái gì đó tương tự trong ứng dụng của tôi.
psulek

7

Tôi biết câu hỏi này là dành riêng cho JavaScript, tuy nhiên, dường như không có cách nào hay, sạch để LUÔN phát hiện khi một văn bản thay đổi trong tất cả các trình duyệt hiện tại. Tôi đã học được jquery đã chăm sóc nó cho chúng tôi. Nó thậm chí còn xử lý các thay đổi menu theo ngữ cảnh cho các vùng văn bản. Cú pháp tương tự được sử dụng bất kể loại đầu vào.

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

hoặc là

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

4
Tôi thấy rằng sự kiện thay đổi không phù hợp với jQuery hơn là với JS đơn giản. Tôi đã sử dụng jQuery bind("input cut paste"...và nó hoạt động như một bùa mê - gõ, cắt và dán bằng bàn phím hoặc menu ngữ cảnh; thậm chí kéo / thả văn bản.
Lawrence Dol

2
Thật không may, FF không bắn changesự kiện cho textarea.
dma_k

4

Bạn có thể nghe sự kiện thay đổi textarea và thực hiện các thay đổi theo ý muốn. Đây là một ví dụ.

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

Keyup sẽ đủ nếu được ghép nối với thuộc tính mẫu / xác thực đầu vào HTML5. Vì vậy, hãy tạo một mẫu (regex) để xác thực đầu vào và hành động theo trạng thái .checkValids (). Một cái gì đó như dưới đây có thể làm việc. Trong trường hợp của bạn, bạn sẽ muốn một regex khớp với độ dài. Giải pháp của tôi là sử dụng / có thể demo trực tuyến tại đây .

<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

Mã tôi đã sử dụng cho IE 11 mà không cần jquery và chỉ cho một textarea duy nhất:

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

và html:

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

-1

Hãy thử cái này Thật đơn giản và kể từ năm 2016 tôi chắc chắn nó sẽ hoạt động trên hầu hết các trình duyệt.

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

Vì vậy, bạn đang nhận url theo id, nhưng nó không được hiển thị trong mã của bạn.
Tuyệt

-8

Điều tốt nhất mà bạn có thể làm là đặt một hàm được gọi trong một khoảng thời gian nhất định và hàm này để kiểm tra nội dung của vùng văn bản của bạn.

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

7
bỏ phiếu là một ý tưởng rất xấu. Nó sẽ chỉ phá hủy hiệu suất. Ngoài ra, giống như các bài đăng khác, một số giải pháp tồn tại
Cầu tàu-Olivier Thibault

2
Đây là thế kỷ 21. Không có trình duyệt nào gặp khó khăn khi xử lý so sánh chuỗi cứ sau 50 ms. Cache bộ chọn của bạn và đây là một giải pháp hoàn toàn chấp nhận được.
nullability
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.