0

I have such a function on my website:

$("#search-label").on("keypress", function(e) {
  if(e.which == 13) {
    $('html, body').animate({
      scrollTop: $("#content").offset().top
    }, 2000);   
  }
});

Its task is to scroll to the selected element after press enter and it works fine, but the problem is that it can be called repeatedly in a short time and then the page gets stuck.

How to limit the possibility of calling it up to once every 10 seconds?

Thanks

Martin
  • 126
  • 1
  • 11
Dakifiz
  • 13
  • 7
  • Search for "debouncing". – Barmar Apr 15 '21 at 22:19
  • "use 10 seconds instead of 2 seconds" this is the rewind time, not the pause between calling the function – Dakifiz Apr 15 '21 at 22:20
  • 1
    I think you are looking for throttling, I would recommend lodash's `throttle` function: https://lodash.com/docs/4.17.15#throttle - or see this question for a solution with no dependencies: https://stackoverflow.com/questions/27078285/simple-throttle-in-js – nbokmans Apr 15 '21 at 22:24
  • Why is `html` in the query selector? That seems rather backwards. – Nora Apr 15 '21 at 22:37

1 Answers1

3

You can use a mix of a variable and a setTimeout to do this:

var scrollOK = true;

$("#search-label").on("keypress", function(e) {
  if((e.which == 13) && scrollOK) {
    $('html, body').animate({
      scrollTop: $("#content").offset().top
    }, 2000);   
    scrollOK = false;
    setTimeout(function(){ scrollOK=true; }, 10000);
  }
});

It uses scrollOK to make sure that scrolling is OK, and when it scrolls, then it sets it to false temporarily (temporarily because the setTimeout sets it back to true after 10 seconds, or 10000 milliseconds).

Edit: as @ChloeAnderson said, this may take up more resources than it should. This is a version that should be better:

var lastScrolled = 0;

$("#search-label").on("keypress", function(e) {
  if((e.which == 13) && (Date.now() >= (lastScrolled + 10000))) {
    $('html, body').animate({
      scrollTop: $("#content").offset().top
    }, 2000);   
    lastScrolled = Date.now();
  }
});
Lakshya Raj
  • 1,669
  • 3
  • 10
  • 34
  • Please refrain from using intervals (or timeouts) for cooldowns, there's nothing wrong with using timestamps such as `performance.now()`, as they will only be evaluated upon request. – Nora Apr 15 '21 at 22:58
  • @ChloeAnderson: I don't understand what is wrong with using a `setTimeout`. It seems perfect for this situation. – Lakshya Raj Apr 15 '21 at 22:59
  • It seems, and may be, but a much more performance setting is to use timestamps. You're using more resources by relying on an interval than to compare two integers, being timestamps. – Nora Apr 15 '21 at 23:01
  • 1
    @ChloeAnderson: OK. I added your solution in my question. Thank you! – Lakshya Raj Apr 15 '21 at 23:02