0

I have a JavaScript searchbox/filter on my page:

$("#show_search").on("keyup search input paste cut", function() {
    send_data["search"] = this.value;
    getAPIData();
});

It filters the results I show on the page based on the search term put into the input box. But sometimes, usually when I type a search term very quickly, it doesn't capture the final state of the input text and instead picks up an earlier state.

So, for example, if I search for "miranda", my ajax calls look like this:

[23/Oct/2020 16:12:51] "GET /api/shows/?year=&show_type=&sort_by=name&search=mir&format=json HTTP/1.1" 200 2486
[23/Oct/2020 16:12:51] "GET /api/shows/?year=&show_type=&sort_by=name&search=mira&format=json HTTP/1.1" 200 1705
[23/Oct/2020 16:12:51] "GET /api/shows/?year=&show_type=&sort_by=name&search=mir&format=json HTTP/1.1" 200 2486
[23/Oct/2020 16:12:51] "GET /api/shows/?year=&show_type=&sort_by=name&search=miran&format=json HTTP/1.1" 200 1705
[23/Oct/2020 16:12:52] "GET /api/shows/?year=&show_type=&sort_by=name&search=mira&format=json HTTP/1.1" 200 1705
[23/Oct/2020 16:12:52] "GET /api/shows/?year=&show_type=&sort_by=name&search=mirand&format=json HTTP/1.1" 200 1705
[23/Oct/2020 16:12:52] "GET /api/shows/?year=&show_type=&sort_by=name&search=miranda&format=json HTTP/1.1" 200 1705
[23/Oct/2020 16:12:52] "GET /api/shows/?year=&show_type=&sort_by=name&search=miran&format=json HTTP/1.1" 200 1705
[23/Oct/2020 16:12:52] "GET /api/shows/?year=&show_type=&sort_by=name&search=mir&format=json HTTP/1.1" 200 2486
[23/Oct/2020 16:12:52] "GET /api/shows/?year=&show_type=&sort_by=name&search=miranda&format=json HTTP/1.1" 200 1705
[23/Oct/2020 16:12:52] "GET /api/shows/?year=&show_type=&sort_by=name&search=mirand&format=json HTTP/1.1" 200 1705
[23/Oct/2020 16:12:52] "GET /api/shows/?year=&show_type=&sort_by=name&search=miranda&format=json HTTP/1.1" 200 1705
[23/Oct/2020 16:12:52] "GET /api/shows/?year=&show_type=&sort_by=name&search=mi&format=json HTTP/1.1" 200 40981
[23/Oct/2020 16:12:52] "GET /api/shows/?year=&show_type=&sort_by=name&search=m&format=json HTTP/1.1" 200 41785

You can see that the full search-term does show in that list, but it ends on filtering on "m" when "miranda" is in the search box, which is nowhere close to what I want. What gives? How can I ensure that the current input value will always be extracted from this.value and stored in send_data["search"]?

Danny
  • 470
  • 1
  • 4
  • 21

2 Answers2

2

You need to 'debounce' the search with a timeout like so:

var searchTimeout = null;

$("#show_search").on("keyup search input paste cut", function() {
    clearTimeout(searchTimeout);
    searchTimeout = setTimeout(function() {
        send_data["search"] = this.value;
        getAPIData();
    }, 200);
});

Feel free to change the 200 to however long you feel is appropriate. It will wait however long you set before actually running the code in the timeout. It will also clear any previously set timeouts so only one is executed.

jshrc
  • 187
  • 8
1

You could wait for n seconds (probably milliseconds) before sending your request to see if a new letter is typed

let timeout;
$("#show_search").on("keyup search input paste cut", function() {
  // if a new letter is typed within 400ms the previous request is canceled
  clearTimeout(timeout);
  setTimeout(_ => {
    send_data["search"] = this.value;
    getAPIData();
  }, 400);
});
Cedric Cholley
  • 1,956
  • 2
  • 9
  • 15