user2970050 user2970050 - 1 month ago 6
CoffeeScript Question

how do I add time delay to coffeescript search

When the User searches for a Last Name, the response is jumping.

Here's what's happening. My example is to search on the name Moon.

Because Moon is most specific, it runs fastest search (e.g 15.08)

Because M is least specific it runs slowest search (e.g 22.47)

Mo & Moo also run.

As a result, the search finds Moon but is then overwritten by the search results for 'Moo', 'Mo' & 'M' (and causing the jump and also the search not to work properly).

Here is the code (using coffeescript).

class @ContactsSearch

constructor: ->

SearchUtils.configCheckBoxSelectAll('contacts-checkbox-select-all', 'contacts-container','contacts-delete-button')

SearchUtils.configBtnGroup('contacts-btn-group-grade', doSearch)
SearchUtils.configBtnGroup('contacts-btn-group-order-by', doSearch)
SearchUtils.configBtnGroup('contact-btn-group', doSearch)
SearchUtils.configSortDirBtn('contacts-sort-order-toggle', doSearch)


search_box = $('#contacts-search-input')'search-url')
search_box.bind 'input', (e, data) ->

doSearch = ->
search_box = $('#contacts-search-input')

btn_group_grade = $('#contacts-btn-group-grade')
btn_group_order_by = $('#contacts-btn-group-order-by')
sort_order_toggle = $('#contacts-sort-order-toggle')
contact_btn_group = $('#contact-btn-group')

SearchUtils.resetMasterCheckbox('contacts-checkbox-select-all', 'contacts-delete-button')

ajaxCall('search-url') + "?search_term=" + search_box.val() + "&order_by=" +'value') + "&sort_direction=" +'value') + "&grade=" +'value') + "&group=" +'value'))

ajaxCall = (finalUrl) ->
search_box = $('#contacts-search-input')
contacts_table = $('#contacts-container')
url: finalUrl
type: "GET"
error: (data, status, xhr) ->
# do nothing
success: (data, status, xhr) =>

SearchUtils.configContainerCheckBoxs('contacts-checkbox-select-all', 'contacts-container','contacts-delete-button')

configDeleteButton = ->
$("#contacts-delete-button").click (event) ->
bootbox.confirm "Are you sure?", (result) ->
if result

configAjaxPaginationLinks = ->
$('#contacts-container').find(".pagination a").click (event) ->
search_box = $('#contacts-search-input')
finalUrl ='search-url') + "?" + $(this).attr("href").split("?").slice(1)

deleteSelectedContacts = ->
url = $("#contacts-delete-button").data('url')

deleteIDs = $(".contact-search-item:checked").map(->

url: url
type: "POST"
data: JSON.stringify({ ids: deleteIDs }),
contentType: "application/json; charset=utf-8",
dataType: "json"
error: (data, status, xhr) ->
# do nothing
success: (data, status, xhr) =>

document.addEventListener "turbolinks:load", ->
new ContactsSearch()

I am a novice with coffeescript but think i need to change the logic. Specifically, i think i need to add a time delay to this:

search_box.bind 'input', (e, data) ->

I tried just changing 'input' to 'keyup' to have it search whenever the fingers came off the keyboard but that did not work. Not sure if the syntax is wrong or if that is not a coffeescript convention.

Alternatively, I think I need to add some sort of time delay on the cofeescript but not sure the syntax?

Any ideas?

Many thanks.


You are correct with your comment in that you need to debounce your input. You only want to start searching when the user has stopped typing for a moment.

The best way of doing this is via setTimout.

setTimeout will call a method in X miliseconds. It also returns an id, by which you can cancel the timeout. You will need to use both of these features:

# We want to wait for the user to stop typing for 1 second

# here we will save the timeout id so we can cancel the search early
#   if the user keeps on typing
searchTimeoutId = null

search_box.bind 'input', ->
  # First clear the old search timeout if it exists
  clearTimeout searchTimeoutId
  # Then set a new timeout to search the text box contents if the user
  #   doesn't continue typing within 1 second
  searchTimeoutId = setTimeout doSearch, SEARCH_DELAY

Please ask if you need anything explained further.

Side note:

This will work just fine while developing locally, but there are some real world scenarios which it won't cover.

Say a user is typing in moon landing, with a 1 second pause between moon and landing This means two separate searches will be sent to the server. Locally this is fine, and they should come back in the correct order. But with a complex network in between, the order isn't guaranteed.

I would suggest you send a timestamp along with every query. Then you can check if you already received & rendered a more recent request, and drop old responses which were too slow without rendering them.