2009-10-25 7 views
30

Mam obszar tekstowy, w którym ludzie wprowadzają jakiś tekst (naturalnie), i chcę, aby było tak, aby żądanie AJAX było co jakiś czas zgłaszane, aby uzyskać pewne sugestie dotyczące tego, co jest tekstem (np. Podobne pytania dotyczące przepełnienia stosu, ale dla textarea, a nie wprowadzania tekstu). Problem polega na tym, że nie mogę wykonać żądania AJAX przy każdym naciśnięciu klawisza (byłoby to bezużyteczne i wymagałoby dużego nakładu zasobów) i nie jestem pewien, jaki byłby najbardziej efektywny sposób (co X słów? Co X sekund). ? albo coś innego?).Jak wywołać zdarzenie onkeyup, które jest opóźnione, dopóki użytkownik nie wstrzyma pisania?

Jaki byłby najlepszy sposób robienia tego?

Z góry dziękuję.

+1

możliwym duplikatu [jQuery .keyup () opóźnienie] (http: // stackoverflow.com/questions/1909441/jquery-keyup-delay) – kenorb

+0

@kenorb to pytanie było pierwsze, a wspomniane referencje zostały uznane za duplikat tych pytań, ale administratorzy nie chcieli zamknąć pytania, ponieważ tytuł był lepszy i ma około 132931 widoków, co jest dość niezwykłe. – Adam

+0

Nie ma znaczenia, że ​​jest starszy, a drugi ma więcej głosów i wyświetleń, patrz: [Czy powinienem zgłosić pytanie jako duplikat, jeśli otrzymał lepsze odpowiedzi?] (Http://meta.stackoverflow.com/q/ 251938/55075). Tytuł można zawsze zmienić na lepszy. Mogą być zawsze [połączone] (http://meta.stackexchange.com/a/147651/191655). – kenorb

Odpowiedz

60

Można połączyć obsługę zdarzeń keypress z setTimeout, aby wysłać żądanie Ajax przez określony czas po naciśnięciu klawisza, anulowanie i ponowne uruchomienie zegara, jeśli inne naciśnięcie nastąpi przed upływem czasu. Zakładając, że masz z textarea id „myTextArea” i funkcji Ajax zwrotnej zwanej 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

Jest to ogólnie przyjęty "właściwy" sposób na zrobienie tego. Dobrze powiedziane. –

+0

Dzięki Tim, genialne rozwiązanie: D –

+3

użyj onkeykey, jeśli chcesz mieć możliwość przechwytywania kluczowych zdarzeń Backspace. – barkmadley

0

Jeśli interesują Cię rozwiązania jQuery, dobrym pomysłem jest jQuery Suggest.

Bezsensowne wymyślanie koła za każdym razem.

+0

To nie działa dla mnie, ponieważ nie chcę aktualizować textarea ani niczego z sugerowanymi sugestiami. Po prostu chcę utworzyć żądanie AJAX, aby uzyskać zawartość innego elementu na stronie, każde X naciśnięć klawiszy lub co X sekund, które wpisuje użytkownik, lub coś podobnego. Zastanawiam się, jaka byłaby najbardziej wydajna opcja. –

1

Osobiście użyłbym setInterval, który monitorowałby obszar tekstowy dla zmian i wykonałby tylko wywołania zwrotne AJAX po wykryciu zmiany. każda sekunda powinna być szybka i wystarczająco powolna.

+0

Wymaga to setInterval do uruchomienia na zawsze. Rozwiązanie Tima jest znacznie bardziej eleganckie, działa tylko wtedy, gdy ktoś faktycznie wchodzi w interakcję z polem tekstowym. –

+0

działaj na zawsze, aż strona zostanie rozładowana. Również jeśli chcesz przekazać informację zwrotną, gdy użytkownik pisze, moje rozwiązanie jest lepsze, ponieważ ma możliwość wysłania żądania, jeśli użytkownik pisze szybciej niż jeden klucz na sekundę. Nie twierdzę, że rozwiązanie Tima nie jest eleganckie, ale w niektórych przypadkach nie jest to rozwiązanie zależne od aplikacji. – barkmadley

9

Inną alternatywą jest użycie niewielkiej jQuery plugin o nazwie bindWithDelay. Używa tej samej techniki setTimeout, co akceptowana odpowiedź, ale obsługuje limity czasowe w sposób przezroczysty, więc twój kod jest trochę łatwiejszy do odczytania. source code można zobaczyć na github.

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

Jeśli używasz tej funkcji dużo wokół miejsca i nie chcesz, aby śledzić wszystkie odn setTimeout itp Potem pakowanych to aż do wtyczki dostępnej here.

Wtyczka dodaje kilka opcji do zwykłej metody $ .ajax do buforowania i anulowania poprzednich wywołań ajaxowych.

2

Jeśli używasz pliku underscore.js, możesz użyć debounce function.

Przykład (jQuery wykorzystywane do keyup):

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

Co szukasz nazywa debouncing. Oto ogólny algorytm w rodzimej JavaScript:

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

A oto przykład jak używać go z onkeyup imprezy:

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" />

Powiązane problemy