tinthetub tinthetub - 1 month ago 7
jQuery Question

jQuery Counter with Max and Min Value

I'm building a counter that should increment up to a maxValue and decrement no further than 0 when I mousedown. I also have an option to reset the counter to it's initial value: 0. Also, if the maxValue is an even number it should count up to that number. However, if the maxValue is an odd number, it should count up to number-1.

The counter seems to be work fine. But sometimes it tends to stay stuck between two values. I'm pretty sure that this occurs when I mousedown on one of the buttons and then immediately mousedown on the other. Is there a way to prevent that from happening? I also wanted to know if my code is correct if if there is a simpler approach to this (perhaps with loops)?

Anyway here is my code:

$(document).ready(function(){
var maxValue = 3;
var count = 0;
// intervals used to regulate how fast the value will change on mousedown
var upInterval;
var downInterval;

$('#counter').html("<p>" + parseInt(count) + "</p>");

$('#up').mousedown(function(){
// if the maxValue is an even number
if(maxValue % 2 == 0) {
upInterval = setInterval(function(){
if(count < maxValue) {
count++;
$('#counter').html("<p>" + parseInt(count) + "</p>");
}
},180);
}
// if it's an odd number, subtract one
else {
upInterval = setInterval(function(){
if(count < maxValue-1) {
count++;
$('#counter').html("<p>" + parseInt(count) + "</p>");
}
},180);
}
}).mouseup(function() {
clearInterval(upInterval);
});

$('#down').mousedown(function(){
downInterval = setInterval(function(){
if(count > 0) {
count--;
$('#counter').html("<p>" + parseInt(count) + "</p>");
}
},180);
}).mouseup(function() {
clearInterval(downInterval);
});

$('#reset').click(function(){
count = 0;
$('#counter').html("<p>" + parseInt(count) + "</p>");
});

});


Keep in mind that the intervals are there to regulate how fast the number should change when I mousedown and to stop it from incrementing or decrementing.

Here is a fiddle

Thanks!

Answer

jsBin demo (advanced use-case)

in the demo above I've created an use-case where you can handle multiple elements. It also has a better UX cause it uses a setTimeout (instead of interval) which will gradually increase the counting speed as long as you hold it.

jsBin demo

$(document).ready(function(){

  var $counter = $("#counter p"), // Get the 'p' element
      max = 10,
      c   = 0,
      up  = true, // boolean // This will keep track of the clicked up/dn button
      itv; 

  function incDec(){
    c = up ? ++c : --c; // value of `up` is true? increment, else: decrement
    c = Math.min(Math.max(c, 0), max); // dididababaduuuu!
    $counter.text(c);                  // Set current `c` into element
  }

  $('#up, #down').on("mousedown", function(e){   
    up = this.id==="up";           // set to true if button in "up"; else: false
    incDec();                      // Trigger on sligle click
    clearInterval(itv);            // Clear some ongoing intervals
    itv=setInterval(incDec, 180);  // Do every 180 untill..
  }).on("mouseup mouseleave", function(){        //      ..mouseup or mouseleave
    clearInterval(itv); 
  });


  $('#reset').click(function(){
    c = 0;              // Reset to 0
    $counter.text(c);   // Show that "0"           
  }).click();           // Trigger a reset click on DOM ready

});
Comments