0

I have come accros this problem before. This time it is an HTML5 color input giving the problem. Here's the issue. I want to use an onChange event to send the user selected value from a color input to the server via Ajax - for an almost real time update to a database. However, when the user drags his mouse over the color swatch, it will trigger loads of onChange events in rapid succession, for each value change, so the server will get inundated with hundreds of pointless requests until the user stops sliding their mouse!

I could use onMouseOut for this particular issue, but I have had this issue with other things like detecting browser window resizing when a user click/drags to resize and the event is triggered with every pixel change. So I'm looking for an answer that will trigger on the final value only, for all similar scenarios.

What is the best method for dealing with this and just triggering when the data has finished changing. I.e. ignore every change until user has settled on a final value. An onAfterChange method event would be nice, but I can't find one!

Ally
  • 955
  • 1
  • 15
  • 33
  • Possible duplicate of [Throttle event calls in jQuery](http://stackoverflow.com/questions/7373023/throttle-event-calls-in-jquery) – jmoerdyk Mar 10 '16 at 00:23
  • See http://stackoverflow.com/questions/8380804/issue-with-adding-hint-text-in-jquery-data-table-search-box/ – guest271314 Mar 10 '16 at 00:37

2 Answers2

1

You can prevent this by debouncing your event handler function.

Every time a debounced function is called, it "pushes back" its execution by nms. This means that while triggered numerous times within t ms (eg: while the mouse is moving), it will only execute the handler after not being triggered for t ms (eg: when the mouse has stopped moving).

Edit:

Ok, the jquery link was a bit out-of-date.. a better example of how to debounce can be found in the Underscore.js source here.

Alex McMillan
  • 17,096
  • 12
  • 55
  • 88
  • This could be a possible option, but jquery-debounce hasn't been updated for 6 years, so is not actively maintained and is therefore likely to break at some upcoming release of jQuery. I would ideally prefer to find a way of doing this natively, without requiring plugins. – Ally Mar 10 '16 at 01:49
  • The link to jQuery-debounce was just an example.. the concept of debouncing is what I was getting at. It's a simple function you could write yourself. Check out the Underscore.js implementation [here](https://github.com/jashkenas/underscore/blob/0a5ddc81795909be5d38984408f7141ad240e9c9/underscore.js#L854) for inspiration :) – Alex McMillan Mar 10 '16 at 02:07
  • OK I was a little hasty. I checked out the jquery-debounce link, but didn't take a look at the source. It's only a few lines with two methods. So granted, it's a good example in jQuery. I also just stuffed it into my main js file and the `$.throttle` works like a charm for my color picker issue! +1 also for Unserscore.js. I have been looking at fitting Underscore in to my app, but haven't really found a reason to yet, but I didn't know it had this feature. Choosing an accepted answer is a tough one because yours wins, but so also does @Yanhui Zhou's although I haven't tested it. – Ally Mar 10 '16 at 02:25
0

How about this:

  1. Set a timeout to send request to server, after the first onChange triggering, and change the first flag to false.

  2. Every onChange is triggered, reset the timeout count.

  3. After sending request, reset the first flag.

Edit: This is the sample code:

$(document).ready(function(){
   var myInterval = undefined;
   var mytimeoutcount = NaN;
   var i =0; // for debug
   
   $("#myinput").keyup(function(){
      console.log("event trigger"); // for debug
      mytimeoutcount = 300;
      if(myInterval == undefined){
          myInterval = setInterval(function(){
              mytimeoutcount -= 10;
              if(mytimeoutcount <= 0){
                // do request, for debug
                i+=1; 
                console.log(i); 
                window.clearInterval(myInterval);
                myInterval = undefined;
              }
          }, 10);
      }
      
   });
});
#myinput{
  width:100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input id="myinput" type="text" value="test" />
Yanhui Zhou
  • 872
  • 6
  • 20
  • @Ally I edit it, add a sample code. Hope it is helpful to you. – Yanhui Zhou Mar 10 '16 at 02:14
  • Thank you Yanui Zhou for your time in providing an example! I am preffering @Alex McMillan's answer as jquery-debounce works well, however I wish I could accept both your s and his answers, as they are both good! – Ally Mar 10 '16 at 02:34