Handling events with new data before previous event has completed
javascript, jquery
Solution
SomeKittens of years ago: You've learned a lot since you asked this, particularly about managing state & multiple events (not to mention how to properly ask a StackOverflow question). A simple answer would be something like this:
var rolling = false;
function rollNum(div, target) {
if (rolling) { return; }
rolling = true;
// Set rolling to false when done
}
That's all well and good but it ignores any events that are fired while we're rolling. The above won't adjust to changes on the slider made after the first adjustment, but before the numbers have finished rolling. Now, I (we?) would use Angular (`$scope.$watch` would come in handy here) but that didn't exist when you were working on this. Instead of passing a target number, why don't we check against the live value on the slider? (Note the use of vanilla JS, it's much faster).
var rollNum = function(textarea) {
var content = parseInt(textarea.value.substring(1), 10)
, target = parseInt(document.getElementById('sliderId').value, 10);
if (content === target) {
return;
}
// Roll up/down logic
setTimeout(function() { rollNum(textarea); }, 60);
};
A few other misc changes:
- Use brackets after `if` statements. Waaaay easier to debug
- Don't forget the radix param in `parseInt`
Unfortunately, you didn't think to include a JSFiddle, so I can't provide a live demonstration.
Problem
This code takes two inputs: div, the div (actually a textbox) and target (a number). It'll then try and in/decrement the number in a pseudo-animated way. The problem is that I'm using jQuery sliders as one form of input, which can result in multiple calls before the first call finished. This isn't a problem unless the slider is quickly increased, and then decreased before the increase rollUp finishes, resulting in an eternal decrementing div. I can't figure out what's causing it. Thoughts? ``` function rollNum(div, target) { var contentString = $(div).val(); content = parseInt(contentString.substring(1)); if(content === target) return; else if(div !== "#costMinusMSP" && div !== "#savingsWithMSP") { var total = rollNumTotalCost(div, target); rollNum("#costMinusMSP", total); rollNum("#savingsWithMSP", total /*- somehow find the cost here*/) } if(isNaN(content)) content = 0; var remainingChange = target - content; if(remainingChange > 0) loopUp(); else loopDown(); function loopUp() { var length = remainingChange.toString().length; var incrementBy = 1; //Find how far away we are from target for(var i=0;i<length-1;i++) incrementBy *= 10; content += incrementBy; remainingChange -= incrementBy; $(div).val("$" + (content)) if(content === target) return; else if(content > target) { $(div).val("$" + (target)); return; } setTimeout(loopUp, 60); } function loopDown() { remainingChange = Math.abs(remainingChange); var length = remainingChange.toString().length; var decrementBy = 1; //Find how far away we are from target for(var i=0;i<length-1;i++) decrementBy *= 10; content -= decrementBy; remainingChange -= decrementBy; if(content < target) { $(div).val("$" + (target)); return; } //This ensures we won't promise our clients negative values. if(content <= 0) { $(div).val("$0"); return; } $(div).val("$" + (content)) if(content === target) return; setTimeout(loopDown, 60); } } ``` Strangely enough, adjusting another slider (that modifies an unrelated div) fixes the eternal decrement. Things I have tried: -Creating a boolean "running" that the function sets to true, then false before it returns. If running was true, then the function would wait until it was false to continue executing. This killed the browser or achieved maximum stack.