0
\$\begingroup\$

In my web application, there is a search input field, and when the user empties all of the text inside the input field, there is an API call made for a default-list of results, which are displayed in a dropdown right underneath the input field.

I'm using the keyup event to try to capture when the user will have completed deleting text, but I've not been able to re-create the desired behavior without using setTimeout(). I've been told to use a throttle or debounce method (no third party modules or plugins, although plain jQuery is ok).

Could someone please give me some advice on how to recreate this code without using setTimeout? I've been on this for a couple days no with no luck, any help is appreciated!

(function () {
  var desktopInput = document.getElementById('someId');
  var desktopResults = document.getElementsByClassName('someClass')[0];

  function getSuggestedSearchResults(cb) {
    $.ajax({
      url: url,
      data: {},
      timeout: REQ_TIMEOUT,
      xhrFields: {
        withCredentials: true
      },
      success: function (data) {
        cb(data);
      }
    });
  }

  function handleEmptyInputDesktop() {
    if (desktopInput.value === '') {
      setTimeout(function () {
        getSuggestedSearchResults(function (data) {
          var model = transformResults(data);
          var results = nunjucks.render('_fullscreenSearchResults', {
            results: model,
            source: 'suggested'
          });
          desktopResults.innerHTML = results;
        });
      }, 500);
    }
  }

  function init() {
    desktopInput.addEventListener('keyup', handleEmptyInputDesktop);
  }

  init();
})();

Without the setTimeout(), the dropdown menu will disappear if the key isn't pressed long enough on the first stroke that deletes all the text.

I've omitted some extraneous code from this snippet, but I'm happy to give more details if you like.

\$\endgroup\$
0
\$\begingroup\$

I ended up using window.requestAnimationFrame and it worked really well, just thought I'd share my solution based on the linked article.

 function requestAnimationTimeout(callback, delay) {
    var dateNow = Date.now;
    var requestAnimation = window.requestAnimationFrame;
    var start = dateNow();
    var stop;

    var timeoutFunc = function () {
      if (dateNow() - start < delay) {
       return stop || requestAnimation(timeoutFunc);
      } else {
       return callback();
      }
    };

    requestAnimation(timeoutFunc);

  }

And then simply use requestAnimationTimeout in place of the native setTimeout.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.