Steven Steven - 5 months ago 31
Javascript Question

Modify checkbox change() event to wait for other actions

I have a pretty big list of checkboxes that all perform an action when you check/uncheck one:

$("input[type='checkbox']").change(function () {
DoSomething();
});


The
DoSomething()
method is actually pretty heavy. I've run into a problem where if someone starts clicking multiple checkboxes in a short period of time, it causes the method to be called every single time,

I'd like to limit that so that if the user clicks several of those checkboxes within the span of a second or two, that it will only call
DoSomething()
once.

Is there a way to wait for a couple seconds until the user is done checking checkboxes before I call
DoSomething()
?

Answer

Moving my comment to an answer.

Check out the _.throttle/_.debounce methods in underscore.js. If you're fine with using that as a library, that's exactly what you need. Otherwise you could just look at the source code and copy the methods you need.

The following example will wait one second since the last checkbox was checked before executing the function:

Example Here

var debouncedFunction = _.debounce(function() {
  console.log('Debounced');
}, 1000);

$("input[type='checkbox']").change(debouncedFunction);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<input type="checkbox" />
<input type="checkbox" />
<input type="checkbox" />
<input type="checkbox" />
<input type="checkbox" />

As stated above, if you don't want to include underscore in your project, then you could simply scrape the _.debounce method. Take a look at this example.

var debouncedFunction = debounce(function() {
  console.log('Debounced');
}, 1000);

$("input[type='checkbox']").change(debouncedFunction);

function debounce(func, wait, immediate) {
  var timeout, args, context, timestamp, result;

  var later = function() {
    var last = new Date().getTime() - timestamp;

    if (last < wait && last >= 0) {
      timeout = setTimeout(later, wait - last);
    } else {
      timeout = null;
      if (!immediate) {
        result = func.apply(context, args);
        if (!timeout) context = args = null;
      }
    }
  };

  return function() {
    context = this;
    args = arguments;
    timestamp = new Date().getTime();
    var callNow = immediate && !timeout;
    if (!timeout) timeout = setTimeout(later, wait);
    if (callNow) {
      result = func.apply(context, args);
      context = args = null;
    }

    return result;
  };
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="checkbox" />
<input type="checkbox" />
<input type="checkbox" />
<input type="checkbox" />
<input type="checkbox" />