2009-10-25 13 views
30

Tôi có một vùng văn bản nơi mọi người nhập một số văn bản (tự nhiên), và tôi muốn làm cho nó để một yêu cầu AJAX được thực hiện mỗi bây giờ và sau đó để có được một số gợi ý về những gì textarea là về (như stack tràn câu hỏi liên quan, nhưng cho một vùng văn bản, không phải là kiểu nhập văn bản). Vấn đề là tôi không thể thực hiện một yêu cầu AJAX ở mỗi lần nhấn phím (nó sẽ vô dụng và tốn rất nhiều tài nguyên), và tôi không chắc đó là cách hiệu quả nhất để làm điều đó (mỗi từ X? Mỗi X giây) hay cái gì khác?).Làm cách nào để kích hoạt sự kiện onkeyup bị trì hoãn cho đến khi người dùng tạm dừng việc nhập của họ?

Cách tốt nhất để thực hiện việc này là gì?

Cảm ơn bạn trước.

+1

thể trùng lặp của [jQuery .keyup () delay] (http: // stackoverflow.com/questions/1909441/jquery-keyup-delay) – kenorb

+0

@kenorb câu hỏi này là thực tế đầu tiên, và bạn tham chiếu được coi là một bản sao của câu hỏi này, nhưng quản trị viên không muốn đóng câu hỏi vì tiêu đề tốt hơn và nó có khoảng 132931 lượt xem khá đáng chú ý. – Adam

+0

Nó không quan trọng này là cũ hơn, người kia có nhiều phiếu bầu và lượt xem hơn, hãy xem: [Tôi có nên gắn cờ một câu hỏi là trùng lặp nếu nó đã nhận được câu trả lời tốt hơn không?] (Http://meta.stackoverflow.com/q/ 251938/55075). Tiêu đề có thể luôn được chỉnh sửa thành tiêu đề tốt hơn. Chúng có thể luôn luôn [sáp nhập] (http://meta.stackexchange.com/a/147651/191655). – kenorb

Trả lời

60

Bạn có thể kết hợp bộ xử lý sự kiện keypress với setTimeout để bạn gửi yêu cầu Ajax một khoảng thời gian sau khi nhấn phím, hủy và khởi động lại bộ hẹn giờ nếu một lần nhấn khác xảy ra trước khi bộ hẹn giờ kết thúc. Giả sử bạn có một textarea với id 'myTextArea' và một chức năng Ajax callback được gọi là doAjaxStuff:

function addTextAreaCallback(textArea, callback, delay) { 
    var timer = null; 
    textArea.onkeypress = function() { 
     if (timer) { 
      window.clearTimeout(timer); 
     } 
     timer = window.setTimeout(function() { 
      timer = null; 
      callback(); 
     }, delay); 
    }; 
    textArea = null; 
} 

addTextAreaCallback(document.getElementById("myTextArea"), doAjaxStuff, 1000); 
+2

Đây là cách "đúng" được chấp nhận chung để thực hiện việc này. Nói hay lắm. –

+0

Cảm ơn Tim, giải pháp tuyệt vời: D –

+3

sử dụng onkeyup nếu bạn muốn có thể nắm bắt các sự kiện phím backspace. – barkmadley

0

Nếu bạn quan tâm đến các giải pháp jQuery, jQuery Suggest là cách triển khai tốt.

Không có ý nghĩa sáng tạo lại bánh xe mỗi lần.

+0

Điều này không hiệu quả đối với tôi, vì tôi không muốn cập nhật văn bản hoặc bất kỳ điều gì với các đề xuất được đưa ra. Tôi chỉ muốn thực hiện một yêu cầu AJAX để lấy nội dung của một phần tử khác trong trang, mỗi lần nhấn phím X, hoặc mỗi X giây người dùng đang gõ, hoặc một cái gì đó. Chỉ cần tự hỏi những gì sẽ là lựa chọn hiệu quả nhất. –

1

Cá nhân tôi sẽ sử dụng setInterval để theo dõi văn bản thay đổi và chỉ thực hiện các cuộc gọi lại AJAX khi phát hiện thay đổi được thực hiện. mỗi giây sẽ nhanh và đủ chậm.

+0

Điều này yêu cầu setInterval chạy mãi mãi. Giải pháp của Tim thanh lịch hơn nhiều, chỉ chạy khi ai đó thực sự tương tác với hộp văn bản. –

+0

chạy vĩnh viễn cho đến khi trang được tải xuống. Ngoài ra, nếu bạn muốn cung cấp một số phản hồi khi người dùng nhập giải pháp của tôi tốt hơn vì nó có cơ hội gửi yêu cầu nếu người dùng nhập nhanh hơn một khóa mỗi giây. Tôi không nói rằng giải pháp của Tim không phải là thanh lịch, nhưng trong một số trường hợp nó không phải là giải pháp tùy thuộc vào ứng dụng. – barkmadley

9

Một lựa chọn khác là sử dụng một plugin jQuery nhỏ gọi là bindWithDelay. Nó sử dụng cùng một kỹ thuật setTimeout mà câu trả lời được chấp nhận có, nhưng xử lý hết thời gian chờ để mã của bạn dễ đọc hơn một chút. Các source code có thể được nhìn thấy trên github.

$("#myTextArea").bindWithDelay("keypress", doAjaxStuff, 1000) 
0

Nếu bạn đang sử dụng rất nhiều tính năng này trên các trang web và không muốn để theo dõi tất cả các refs setTimeout vv sau đó tôi đóng gói này thành một plugin có sẵn here.

Plugin thêm một vài tùy chọn vào phương thức $ .ajax bình thường để đệm và hủy cuộc gọi ajax trước đó.

2

Nếu bạn đang sử dụng underscore.js, bạn có thể sử dụng debounce function.

Ví dụ (jQuery sử dụng cho KeyUp):

$('#myTextArea').keyup(_.debounce(function(){ 
    alert('hello'); 
}, 500)); 
4

bạn đang tìm kiếm gì được gọi là debouncing. Đây là một thuật toán chung trong JavaScript mẹ đẻ:

function debounce(fn, duration) { 
    var timer; 
    return function() { 
    clearTimeout(timer); 
    timer = setTimeout(fn, duration) 
    } 
} 

và đây là một ví dụ về cách sử dụng nó với một sự kiện onkeyup:

function debounce(fn, duration) { 
 
    var timer; 
 
    return function(){ 
 
    clearTimeout(timer); 
 
    timer = setTimeout(fn, duration); 
 
    } 
 
} 
 

 
$(function(){ 
 
    
 
    $('#txtSearch').on('keyup', debounce(function(){ 
 
    
 
    alert('You paused your typing!'); 
 
    
 
    }, 500)); 
 
    
 
});
input{ 
 
    padding:.5em; 
 
    font-size:16px; 
 
    width:20em; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<input id="txtSearch" placeholder="Type here" />

Các vấn đề liên quan