Czy uruchomić funkcję javascript, gdy użytkownik zakończy pisanie zamiast na klawiaturze?


463

Chcę wyzwolić żądanie ajax, gdy użytkownik skończy pisać w polu tekstowym. Nie chcę, aby uruchamiała tę funkcję za każdym razem, gdy użytkownik wpisuje literę, ponieważ spowodowałoby to DUŻO żądań ajax, jednak nie chcę, aby musiała także naciskać przycisk Enter.

Czy istnieje sposób, dzięki któremu mogę wykryć, kiedy użytkownik skończył pisać, a następnie wykonać żądanie ajax?

Za pomocą jQuery tutaj! Dave


21
Myślę, że musisz zdefiniować dla nas „kończenie pisania”.
Surreal Dreams,

8
Podczas gdy odpowiedź @ Surreal Dreams spełnia większość twoich wymagań, jeśli użytkownik zacznie pisać ponownie PO upływie określonego czasu, wiele żądań zostanie wysłanych na serwer. Zobacz moją odpowiedź poniżej, która przechowuje każde żądanie XHR w zmiennej i anuluje je przed uruchomieniem nowego. Tak właśnie robi Google w wyszukiwaniu błyskawicznym .
Marko,


1
Co z rozmyciem? Wydaje mi się, że użytkownik definitywnie zakończył pisanie, gdy element wejściowy traci fokus.
Don P

3
Proste wyszukiwanie w Google mogłoby dać ci prostą odpowiedź: schier.co/blog/2014/12/08/…
Cannicide

Odpowiedzi:


687

Więc zgaduję, że zakończenie pisania oznacza, że ​​przestaniesz na chwilę, powiedzmy 5 sekund. Mając to na uwadze, zacznijmy odliczanie czasu, gdy użytkownik zwolni klawisz i wyczyść go, gdy go naciśnie. Zdecydowałem, że dane wejściowe to #myInput.

Dokonując kilku założeń ...

//setup before functions
var typingTimer;                //timer identifier
var doneTypingInterval = 5000;  //time in ms, 5 second for example
var $input = $('#myInput');

//on keyup, start the countdown
$input.on('keyup', function () {
  clearTimeout(typingTimer);
  typingTimer = setTimeout(doneTyping, doneTypingInterval);
});

//on keydown, clear the countdown 
$input.on('keydown', function () {
  clearTimeout(typingTimer);
});

//user is "finished typing," do something
function doneTyping () {
  //do something
}

4
Dzięki :) Zacząłem pisać komentarz do pytania i zdałem sobie sprawę, że mam dobry pomysł.
Surreal Dreams,

26
Ta odpowiedź nie działa poprawnie, zawsze będzie uruchamiana po 5 sekundach, chyba że użytkownik zacznie pisać bardzo wolno. Zobacz działające rozwiązanie poniżej.
będzie

3
Jeśli napotkasz tutaj kłopoty, ponieważ zegar uruchamia się natychmiast, spróbuj dodać cudzysłowy wokół wywołania funkcji: setTimeout ('functionToBeCalled', doneTypingInterval);
Largo,

3
Widzę kilka komentarzy, w których funkcja wywołania zwrotnego, doneTypingna przykład, działa natychmiast. Zwykle jest to wynikiem przypadkowego włączenia ()nazwy funkcji. Należy pamiętać, że powinien on czytać setTimeout(doneTyping,niesetTimeout(doneTyping(),
Anthony DiSanti

2
@Jessica do pracy z wklejaniem musisz dodać zdarzenie „wklej” w następujący sposób: on („wklejanie klucza”,
Sergey

397

Wybrana powyżej odpowiedź nie działa.

Ponieważ typingTimer jest czasami ustawiany wiele razy (naciśnięcie klawisza dwukrotnie przed uruchomieniem skrótu klawiaturowego dla szybkich maszyn do pisania itp.), To nie jest poprawnie usuwane.

Poniższe rozwiązanie rozwiązuje ten problem i wywołuje X sekund po zakończeniu zgodnie z żądaniem PO. Nie wymaga już także redundantnej funkcji keydown. Dodałem również zaznaczenie, aby wywołanie funkcji nie nastąpiło, jeśli dane wejściowe są puste.

//setup before functions
var typingTimer;                //timer identifier
var doneTypingInterval = 5000;  //time in ms (5 seconds)

//on keyup, start the countdown
$('#myInput').keyup(function(){
    clearTimeout(typingTimer);
    if ($('#myInput').val()) {
        typingTimer = setTimeout(doneTyping, doneTypingInterval);
    }
});

//user is "finished typing," do something
function doneTyping () {
    //do something
}

I ten sam kod w waniliowym rozwiązaniu JavaScript:

//setup before functions
let typingTimer;                //timer identifier
let doneTypingInterval = 5000;  //time in ms (5 seconds)
let myInput = document.getElementById('myInput');

//on keyup, start the countdown
myInput.addEventListener('keyup', () => {
    clearTimeout(typingTimer);
    if (myInput.value) {
        typingTimer = setTimeout(doneTyping, doneTypingInterval);
    }
});

//user is "finished typing," do something
function doneTyping () {
    //do something
}

To rozwiązanie korzysta z ES6, ale tutaj nie jest konieczne. Wystarczy wymienić letz vara funkcja strzałka z regularnym funkcji.


5
Przydatne może być nadal wywoływanie tej funkcji, nawet jeśli dane wejściowe są puste. Co zrobić, jeśli chcesz wyczyścić niektóre wyniki wyszukiwania (na przykład), gdy dane wejściowe są ponownie puste?
rvighne

7
Myślę, że powinniśmy również wziąć pod uwagę warunek, w którym użytkownik po prostu wkleja tekst w polu.
Vishal Nair

10
użyj, $('#myInput').on('input', function() {jeśli chcesz, aby działało to z kopiowaniem i wklejaniem. Nie widzę sensu sprawdzania, czy dane wejściowe są puste. Załóżmy, że chce usunąć to, co wpisał, nie uda się wywołać wywołania ajax.
billynoah

3
Dlaczego to if ($('#myInput').val)zamiast if ($('#myInput').val())? Powinna .valbyć funkcja?
wlnirvana

4
Dlaczego nie użyć $ (this) .val ()?
JoelFan

76

To tylko jedna linia z funkcją debounce underscore.js :

$('#my-input-box').keyup(_.debounce(doSomething , 500));

To w zasadzie mówi doSomething 500 milisekund po tym, jak przestanę pisać.

Aby uzyskać więcej informacji: http://underscorejs.org/#debounce


5
Wydaje się być dostępny również dla jQuery: code.google.com/p/jquery-debounce i github.com/diaspora/jquery-debounce
koppor

63
Dziwi mnie, jak ludzie reklamują „JEDNĄ LINIĘ KODU” jako niezwykle ważną. Świetny. JEDNA LINIA kodu, który wymaga załadowania pliku JS 1.1k. Nie głosuję za tym, ponieważ jest to rozwiązanie. Ale odważne jest to, że wiersz jest odważny, a także prowadzi do rozdętego kodu.
Wolfie,

1
@Wolfie, zgadzam się z tobą w sprawie rozdęcia kodu, ale Underscore i Lodash są dwiema najważniejszymi narzędziami zależnymi od NPM, więc może to być jedno-liniowe rozwiązanie dla wielu osób.
Paul

3
@Paul Zgadzam się, że jeśli ładujesz biblioteki do innych celów, dobrze jest używać wspólnego kodu. Ale załadowanie ponad K kodu dla potrzeb jednej linii nie jest wydajne. Zwłaszcza, że ​​platformy mobilne stają się coraz mniej nieograniczonymi danymi. Wiele stref euro płaci również za dane za pośrednictwem Internetu. Warto więc zwracać uwagę na wzdęcia, gdy jest to uzasadnione.
Wolfie

dlaczego dostałem:Uncaught ReferenceError: _ is not defined
Wilf

44

Tak, możesz ustawić limit czasu powiedzmy 2 sekundy dla każdego zdarzenia kluczowania, które uruchomi żądanie ajax. Możesz także zapisać metodę XHR i przerwać ją przy kolejnych naciśnięciach klawiszy, aby jeszcze bardziej zaoszczędzić pasmo. Oto coś, co napisałem dla mojego autouzupełniania.

var timer;
var x;

$(".some-input").keyup(function () {
    if (x) { x.abort() } // If there is an existing XHR, abort it.
    clearTimeout(timer); // Clear the timer so we don't end up with dupes.
    timer = setTimeout(function() { // assign timer a new timeout 
        x = $.getJSON(...); // run ajax request and store in x variable (so we can cancel)
    }, 2000); // 2000ms delay, tweak for faster/slower
});

Mam nadzieję że to pomoże,

Marko


Nie poleciłbym tego. Kod wyzwala żądanie API za każdym razem, gdy zostanie naciśnięty klawisz. Następnie anuluje żądanie, jeśli zostanie naciśnięty inny klawisz. Mimo że to rozwiązanie uniemożliwia wywołanie zwrotne AJAX podczas pisania przez użytkownika, nadal będzie hamowało serwer żądaniami.
lxg

Ixg, nie to nie będzie. Używana przez niego funkcja clearTimeout usuwa poprzednie zdarzenia Timeout, wywołując wywołanie API.
John Smith

@JohnSmith, nie zgadzam się, że prawdopodobnie lepiej najpierw wyczyścić stoper, a następnie sprawdzić, czy xhr jest pusty lub jakikolwiek stan może być, i na koniec uruchomić stoper z wywołaniem ajax
Fleuv

19
var timer;
var timeout = 1000;

$('#in').keyup(function(){
    clearTimeout(timer);
    if ($('#in').val) {
        timer = setTimeout(function(){
            //do stuff here e.g ajax call etc....
             var v = $("#in").val();
             $("#out").html(v);
        }, timeout);
    }
});

pełny przykład tutaj: http://jsfiddle.net/ZYXp4/8/


To działało dla mnie, ale pamiętaj, że kiedy użytkownik tabuluje się poza polem tekstowym, nie dostaniesz zdarzenia keyup, ponieważ do tego momentu stracił fokus. Zamiast tego ustawienie keydown wydaje się rozwiązać problem.
horatius83,

12

Obie 2 najlepsze odpowiedzi nie działają dla mnie. Oto moje rozwiązanie:

var timeout = null;

$('#myInput').keyup(function() {
    clearTimeout(timeout);

    timeout = setTimeout(function() {
        //do stuff here
    }, 500);
});

11

Podoba mi się odpowiedź Surreal Dream, ale stwierdziłem, że moja funkcja „doneTyping” uruchamiałaby się przy każdym naciśnięciu klawisza, tzn. Jeśli bardzo szybko wpiszesz „Hello”; zamiast strzelać tylko raz, gdy przestaniesz pisać, funkcja uruchomi się 5 razy.

Problem polegał na tym, że funkcja setTimeout w javascript nie wydaje się zastępować ani zabijać wcześniej ustawionych limitów czasu, ale jeśli zrobisz to sam, zadziała! Właśnie dodałem wywołanie clearTimeout tuż przed setTimeout, jeśli ustawiony jest typingTimer. Patrz poniżej:

//setup before functions
var typingTimer;                //timer identifier
var doneTypingInterval = 5000;  //time in ms, 5 second for example

//on keyup, start the countdown
$('#myInput').on("keyup", function(){
    if (typingTimer) clearTimeout(typingTimer);                 // Clear if already set     
    typingTimer = setTimeout(doneTyping, doneTypingInterval);
});

//on keydown, clear the countdown 
$('#myInput').on("keydown", function(){
    clearTimeout(typingTimer);
});

//user is "finished typing," do something
function doneTyping () {
    //do something
}

NB Chciałbym właśnie dodać to jako komentarz do odpowiedzi Surreal Dream, ale jestem nowym użytkownikiem i nie mam wystarczającej reputacji. Przepraszam!


10

Modyfikowanie zaakceptowanej odpowiedzi w celu obsługi dodatkowych przypadków, takich jak wklej:

//setup before functions
var typingTimer;                //timer identifier
var doneTypingInterval = 2000;  //time in ms, 2 second for example
var $input = $('#myInput');

// updated events 
$input.on('input propertychange paste', function () {
    clearTimeout(typingTimer);
    typingTimer = setTimeout(doneTyping, doneTypingInterval);      
});

//user is "finished typing," do something
function doneTyping () {
  //do something
}

6

Nie sądzę, aby w tym przypadku konieczne było zdarzenie keyDown (proszę powiedz mi, dlaczego się mylę). W moim skrypcie (innym niż jquery) podobne rozwiązanie wygląda tak:

var _timer, _timeOut = 2000; 



function _onKeyUp(e) {
    clearTimeout(_timer);
    if (e.keyCode == 13) {      // close on ENTER key
        _onCloseClick();
    } else {                    // send xhr requests
        _timer = window.setTimeout(function() {
            _onInputChange();
        }, _timeOut)
    }

}

To moja pierwsza odpowiedź na temat przepełnienia stosu, więc mam nadzieję, że kiedyś to komuś pomoże :)


6

Zadeklaruj następującą delayfunkcję:

var delay = (function () {
    var timer = 0;
    return function (callback, ms) {
        clearTimeout(timer);
        timer = setTimeout(callback, ms);
    };
})()

a następnie użyj go:

let $filter = $('#item-filter');
$filter.on('keydown', function () {
    delay(function () {            
        console.log('this will hit, once user has not typed for 1 second');            
    }, 1000);
});    

Twoje rozwiązanie jest fantastyczne, stary!
Deweloper

1
@Developer Bardzo dziękuję. Dodałem również inną odpowiedź, aby rozwiązać nieco bardziej złożony scenariusz (wiele kontroli na stronie).
Fabian Bigler,

dobre rozwiązanie. Korzystam z tego, ale zamiast keydown korzystam ze zdarzenia „input”
Budyn

Dzięki zdarzeniu keyup zadziałało to dla mnie świetnie. Dzięki.
Sinan Eldem

6

Późna odpowiedź, ale dodaję ją, ponieważ jest to rok 2019 i jest to całkowicie możliwe do osiągnięcia przy użyciu ładnego ES6, bez bibliotek stron trzecich, i uważam, że większość wysoko ocenianych odpowiedzi jest nieporęczna i obciążona zbyt dużą liczbą zmiennych.

Eleganckie rozwiązanie zaczerpnięte z tego doskonałego posta na blogu.

function debounce(callback, wait) {
  let timeout;
  return (...args) => {
      const context = this;
      clearTimeout(timeout);
      timeout = setTimeout(() => callback.apply(context, args), wait);
  };
}

window.addEventListener('keyup', debounce( () => {
    // code you would like to run 1000ms after the keyup event has stopped firing
    // further keyup events reset the timer, as expected
}, 1000))

1
To naprawdę powinna być najlepsza odpowiedź, biorąc pod uwagę rok
Dark Hippo

4

Cóż, ściśle mówiąc, nie, ponieważ komputer nie może odgadnąć, kiedy użytkownik skończył pisać. Możesz oczywiście odpalić licznik czasu na klucz i zresetować go przy każdym kolejnym kluczowaniu. Jeśli licznik czasu wygaśnie, użytkownik nie pisał przez czas licznika czasu - możesz nazwać to „zakończeniem pisania”.

Jeśli oczekujesz, że użytkownicy pauzują podczas pisania, nie ma sposobu, aby dowiedzieć się, kiedy są zrobione.

(O ile oczywiście nie można stwierdzić na podstawie danych, kiedy są gotowe)


3

Wydaje mi się, że rozwiązanie jest nieco prostsze w inputprzypadku tego wydarzenia:

var typingTimer;
var doneTypingInterval = 500;

$("#myInput").on("input", function () {
    window.clearTimeout(typingTimer);
    typingTimer = window.setTimeout(doneTyping, doneTypingInterval);
});

function doneTyping () {
    // code here
}

3

zgadzam się z odpowiedzią @going. Innym podobnym rozwiązaniem, które działało dla mnie, jest poniższe. Jedyną różnicą jest to, że używam .on („input” ...) zamiast keyup. To tylko przechwytuje zmiany na wejściu. inne klawisze, takie jak Ctrl, Shift itp. są ignorowane

var typingTimer;                //timer identifier
var doneTypingInterval = 5000;  //time in ms (5 seconds)

//on input change, start the countdown

$('#myInput').on("input", function() {    
    clearTimeout(typingTimer);
    typingTimer = setTimeout(function(){
        // doSomething...
    }, doneTypingInterval);
});

3

Właśnie wymyśliłem prosty kod, który czeka, aż użytkownik skończy pisać:

krok 1. ustaw limit czasu na zero, a następnie usuń bieżący limit czasu podczas pisania przez użytkownika.

krok 2. wyzeruj limit czasu przed zdefiniowaniem zmiennej przed wywołaniem zdarzenia kluczowania.

krok 3. zdefiniuj limit czasu dla zmiennej zadeklarowanej powyżej;

<input type="text" id="input" placeholder="please type" style="padding-left:20px;"/>
<div class="data"></div>

kod javascript

var textInput = document.getElementById('input');
var textdata = document.querySelector('.data');
// Init a timeout variable to be used below
var timefired = null;

// Listen for keystroke events
// Init a timeout variable to be used below
var timefired = null;// Listen for keystroke events
textInput.onkeyup = function (event) {
clearTimeout(timefired);
timefired = setTimeout(function () {
    textdata.innerHTML = 'Input Value:'+ textInput.value;
  }, 600);
};

1
pytanie jest już udzielone ... i jest bardzo podobne do tego
Mixone

3

Wdrożyłem wyszukiwanie w mojej aukcji i potrzebowałem, aby było ono oparte na ajax. Oznacza to, że przy każdej kluczowej zmianie wyszukiwane wyniki powinny być aktualizowane i wyświetlane. Powoduje to tak wiele wywołań ajax wysyłanych do serwera, co nie jest dobre.

Po pewnym czasie podszedłem do pingowania serwera, gdy użytkownik przestaje pisać.

To rozwiązanie działało dla mnie:

$(document).ready(function() {
    $('#yourtextfield').keyup(function() {
        s = $('#yourtextfield').val();
        setTimeout(function() { 
            if($('#yourtextfield').val() == s){ // Check the value searched is the latest one or not. This will help in making the ajax call work when client stops writing.
                $.ajax({
                    type: "POST",
                    url: "yoururl",
                    data: 'search=' + s,
                    cache: false,
                    beforeSend: function() {
                       // loading image
                    },
                    success: function(data) {
                        // Your response will come here
                    }
                })
            }
        }, 1000); // 1 sec delay to check.
    }); // End of  keyup function
}); // End of document.ready

Zauważysz, że podczas implementacji nie musisz używać żadnego timera.


2

Oto prosty kod JS, który napisałem:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="pt-br" lang="pt-br">
<head><title>Submit after typing finished</title>
<script language="javascript" type="text/javascript">
function DelayedSubmission() {
    var date = new Date();
    initial_time = date.getTime();
    if (typeof setInverval_Variable == 'undefined') {
            setInverval_Variable = setInterval(DelayedSubmission_Check, 50);
    } 
}
function DelayedSubmission_Check() {
    var date = new Date();
    check_time = date.getTime();
    var limit_ms=check_time-initial_time;
    if (limit_ms > 800) { //Change value in milliseconds
        alert("insert your function"); //Insert your function
        clearInterval(setInverval_Variable);
        delete setInverval_Variable;
    }
}

</script>
</head>
<body>

<input type="search" onkeyup="DelayedSubmission()" id="field_id" style="WIDTH: 100px; HEIGHT: 25px;" />

</body>
</html>

1

Za pomocą zdarzenia onblur można wykryć, kiedy pole tekstowe przestaje być aktywne: https://developer.mozilla.org/en/DOM/element.onblur

To nie to samo, co „przestaje pisać”, jeśli dbasz o przypadek, w którym użytkownik wpisuje kilka rzeczy, a następnie siedzi tam z zaznaczonym polem tekstowym.

W tym celu sugerowałbym powiązanie setTimeout ze zdarzeniem onclick i przyjęcie, że po x czasie bez naciśnięć klawiszy użytkownik przestał pisać.


1

Dlaczego nie skorzystać z onfocusout?

https://www.w3schools.com/jsreF/event_onfocusout.asp

Jeśli jest to formularz, zawsze pozostawiają fokus każdego pola wejściowego w celu kliknięcia przycisku przesyłania, abyś wiedział, że żadne dane wejściowe nie zostaną pominięte w wywołaniu modułu obsługi zdarzeń onfocusout.


1
Onfocusout miał słabe poparcie, kiedy zadano pytanie (teraz prawie 7 lat temu), a także efekt działania onfocusout byłby nieco inny. Będziesz musiał poczekać, aż użytkownik opuści fokus na elemencie, a dzięki rozwiązaniu timeout / debounce „odpala”, gdy tylko użytkownik przestanie pisać i użytkownik nie musi przełączać fokusa. Przykładem zastosowania może być jedna z tych formularzy rejestracyjnych, w których gdy użytkownik przestanie wprowadzać potencjalną nazwę użytkownika, po prawej stronie pola formularza pojawi się znacznik wyboru lub „X”, wskazujący, że nazwa jest dostępna.
David Zorychta

jeśli pasek wyszukiwania jest ostry, nikt nie musi wychodzić na zewnątrz, po pewnym czasie wynik zostanie wyświetlony bezpośrednio, ponieważ nie jest już pisane żadne otwarcie
P Satish Patro

1

Jeśli użytkownik musi odejść od pola, możemy użyć „onBlur” zamiast Onchange w JavaScript

  <TextField id="outlined-basic"  variant="outlined" defaultValue={CardValue} onBlur={cardTitleFn} />

Jeśli nie jest to konieczne, dobrym pomysłem będzie ustawienie timera.


0

Po wykryciu fokusa na polu tekstowym, po włączeniu klucza sprawdź limit czasu i zresetuj go przy każdym uruchomieniu.

Po upływie limitu czasu wykonaj żądanie ajax.


0

Jeśli szukasz określonej długości (np. Pola kodu pocztowego):

$("input").live("keyup", function( event ){
if(this.value.length == this.getAttribute('maxlength')) {
        //make ajax request here after.
    }
  });

Niezły pomysł na wykonanie ograniczonej weryfikacji przed wysłaniem żądania ajax.
chim

0

Nie jestem pewien, czy moje potrzeby są po prostu dziwne, ale potrzebowałem czegoś podobnego do tego i właśnie to wykorzystałem:

$('input.update').bind('sync', function() {
    clearTimeout($(this).data('timer'));            
    $.post($(this).attr('data-url'), {value: $(this).val()}, function(x) {
        if(x.success != true) {
            triggerError(x.message);    
        }
    }, 'json');
}).keyup(function() {
    clearTimeout($(this).data('timer'));
    var val = $.trim($(this).val());
    if(val) {
        var $this = $(this);
        var timer = setTimeout(function() {
            $this.trigger('sync');
        }, 2000);
        $(this).data('timer', timer);
    }
}).blur(function() {
    clearTimeout($(this).data('timer'));     
    $(this).trigger('sync');
});

Co pozwala mi mieć takie elementy w mojej aplikacji:

<input type="text" data-url="/controller/action/" class="update">

Które są aktualizowane, gdy użytkownik „kończy pisanie” (brak działania przez 2 sekundy) lub przechodzi do innego pola (usuwa się z elementu)


0

Jeśli potrzebujesz poczekać, aż użytkownik skończy pisać, użyj prostej:

$(document).on('change','#PageSize', function () {
    //Do something after new value in #PageSize       
});

Kompletny przykład z wywołaniem ajax - działa to na mój pager - liczba pozycji na liście:

$(document).ready(function () {
    $(document).on('change','#PageSize', function (e) {
        e.preventDefault();
        var page = 1;
        var pagesize = $("#PageSize").val();
        var q = $("#q").val();
        $.ajax({
            url: '@Url.Action("IndexAjax", "Materials", new { Area = "TenantManage" })',
            data: { q: q, pagesize: pagesize, page: page },
            type: 'post',
            datatype: "json",
            success: function (data) {
                $('#tablecontainer').html(data);
               // toastr.success('Pager has been changed', "Success!");
            },
            error: function (jqXHR, exception) {
                ShowErrorMessage(jqXHR, exception);
            }
        });  
    });
});    

0

Wiele timerów na stronie

Wszystkie pozostałe odpowiedzi działają tylko dla jednej kontroli ( moja druga odpowiedź włącznie). Jeśli masz wiele kontrolek na stronie (np. W koszyku), wywoływana będzie tylko ostatnia kontrolka, w której użytkownik wpisał coś . W moim przypadku z pewnością nie jest to pożądane zachowanie - każda kontrola powinna mieć własny licznik czasu.

Aby rozwiązać ten problem, wystarczy przekazać identyfikator funkcji i utrzymywać słownik timeoutHandles, jak w poniższym kodzie:

Deklaracja funkcji:

var delayUserInput = (function () {
    var timeoutHandles = {};    
    return function (id, callback, ms) {        
        if (timeoutHandles[id]) {
            clearTimeout(timeoutHandles[id]);
        }

        timeoutHandles[id] = setTimeout(callback, ms);             
    };
})();

Zastosowanie funkcji:

  delayUserInput('yourID', function () {
     //do some stuff
  }, 1000);

0

Prosty i łatwy do zrozumienia.

var mySearchTimeout;
$('#ctl00_mainContent_CaseSearch').keyup(function () {
   clearTimeout(mySearchTimeout);
   var filter = $(this).val();
   mySearchTimeout = setTimeout(function () { myAjaxCall(filter); }, 700);
   return true;
});

0

Do przekazywania parametrów do funkcji wraz ze składnią ES6.

$(document).ready(() => {
    let timer = null;
     $('.classSelector').keydown(() => {
     clearTimeout(timer); 
     timer = setTimeout(() => foo('params'), 500);
  });
});

const foo = (params) => {
  console.log(`In foo ${params}`);
}

-2

Wow, nawet 3 komentarze są całkiem poprawne!

  1. Puste dane wejściowe nie są powodem do pominięcia wywołania funkcji, np. Usuwam parametr odpadów z adresu URL przed przekierowaniem

  2. .on ('input', function() { ... });powinny być wykorzystywane do wyzwalania keyup, pasteoraz changeimprez

  3. zdecydowanie .val()lub .valuenależy go użyć

  4. Możesz użyć $(this)funkcji zdarzenia wewnętrznego zamiast #idpracować z wieloma wejściami

  5. (moja decyzja) Korzystam z anonimowej funkcji zamiast doneTypingw setTimeoutcelu łatwego dostępu $(this)z wersji 4, ale najpierw musisz ją zapisaćvar $currentInput = $(this);

EDYCJA Widzę, że niektórzy ludzie nie rozumieją wskazówek bez możliwości skopiowania i wklejenia gotowego kodu. Oto jesteś

var typingTimer;
//                  2
$("#myinput").on('input', function () {
    //             4     3
    var input = $(this).val();
    clearTimeout(typingTimer);
    //                           5
    typingTimer = setTimeout(function() {
        // do something with input
        alert(input);
    }, 5000);      
});

Jak to odpowiada na pytanie?
Thomas Orlita,

@ThomasOrlita ta odpowiedź uzupełnia 3 najczęściej oceniane odpowiedzi. Spójrz na zaakceptowany: 1. nie obsługuje paste, nie używa thisitp. (Myślę, że to ważne, ale nie chcę zgubić się w
mnóstwie

1
To nie odpowiada na pytanie. Jeśli chcesz skomentować inną odpowiedź, istnieje system komentowania (używam jej teraz!)
GrayedFox
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.