最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Incrementing value continuously on mouse hold - Stack Overflow

programmeradmin2浏览0评论

I have an HTML5 'range' control to which I want to add a plus (+) and minus (-) buttons on either sides.

The fiddle works fine, except that the value increase (or decrease) only once on 'click and hold'. While I want is it should increase (or decrease) continuously.

Fiddle

HTML,

<input type='button' id='minus'/>
<div class='range-container'>
    <input id='range' type='range' min='0' max='100' step='1'/>
</div>
<input type='button' id='plus'/>

JavaScript,

$('#plus').click(function() {
    $('#range').val(parseInt($('#range').val()) + 1);
});

$('#minus').click(function() {
    $('#range').val(parseInt($('#range').val()) - 1);
});

HTML5 'number' control have this experience natively.

Looked through SO, couldn't find this question anywhere. Closest I got is, this, which again does only one click.

I have an HTML5 'range' control to which I want to add a plus (+) and minus (-) buttons on either sides.

The fiddle works fine, except that the value increase (or decrease) only once on 'click and hold'. While I want is it should increase (or decrease) continuously.

Fiddle

HTML,

<input type='button' id='minus'/>
<div class='range-container'>
    <input id='range' type='range' min='0' max='100' step='1'/>
</div>
<input type='button' id='plus'/>

JavaScript,

$('#plus').click(function() {
    $('#range').val(parseInt($('#range').val()) + 1);
});

$('#minus').click(function() {
    $('#range').val(parseInt($('#range').val()) - 1);
});

HTML5 'number' control have this experience natively.

Looked through SO, couldn't find this question anywhere. Closest I got is, this, which again does only one click.

Share Improve this question edited May 23, 2017 at 11:59 CommunityBot 11 silver badge asked Jan 24, 2015 at 16:19 anoopeliasanoopelias 9,5487 gold badges27 silver badges40 bronze badges 4
  • Use setInterval to run a function continuously while the mouse is down. Increment in that function. clear the interval on mouseup and start it on mousedown. – Sergiu Paraschiv Commented Jan 24, 2015 at 16:25
  • @SergiuParaschiv Thanks, will try. Though, I was hoping for a more 'native'/jQuery solution, since it is supported on number control. – anoopelias Commented Jan 24, 2015 at 16:44
  • @SergiuParaschiv Actually it's not as simple as that. There are many strings attached. Primarily detecting a click vs. a mousedown and doing the right thing when there is no mouseup event because the mouse has moved outside of the button. Secondly there would be finding a delays and an easing that works and making the whole thing work independently of the number range. – Tomalak Commented Jan 24, 2015 at 16:51
  • Obviously. That's why I did not post that as an answer. It's a starting point. – Sergiu Paraschiv Commented Jan 24, 2015 at 16:53
Add a comment  | 

5 Answers 5

Reset to default 7

You can use requestAnimationFrame to constantly check if any button is still pressed. If still pressed, you can increment or decrement your value.

  • Create a 'number' variable that starts at zero.
  • If the Add button is pressed, set an 'isDown' variable to 1.
  • If the Subtract button is pressed, set the 'isDown' variable to -1.
  • If any button is released, set the 'isDown' variable to 0;
  • Start a requestAnimationFrame loop that constantly checks if 'isDown' is not zero. If not zero, requestAnimationFrame changes the 'number' variable by the isDown value.

Here's example code and a Demo:

var $result=$('#result');
var number=0;
var isDown=0;
var delay=250;
var nextTime=0;

requestAnimationFrame(watcher);

$("button").mousedown(function(e){handleMouseDown(e);});
$("button").mouseup(function(e){handleMouseUp(e);});
$("button").mouseout(function(e){handleMouseUp(e);});


function handleMouseDown(e){
  // tell the browser we're handling this event
  e.preventDefault();
  e.stopPropagation();

  // Put your mousedown stuff here
  isDown=(e.target.id=='Add')?1:-1;
}

function handleMouseUp(e){
  // tell the browser we're handling this event
  e.preventDefault();
  e.stopPropagation();

  // Put your mouseup stuff here
  isDown=0;
}

function watcher(time){
  requestAnimationFrame(watcher);
  if(time<nextTime){return;}
  nextTime=time+delay;
  if(isDown!==0){
    number+=isDown;
    $result.text(number);
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<button id=Add>Add</button>
<button id=Subtract>Subtract</button>
<span id='result'>0</span>

Edit, Updated

Try

var range = $("#range")
, fx = function(elem, prop) {
  return elem
    .animate({
      value: range.prop(prop)
    }, {
      duration: 3000,
      easing: "linear",
      step: function(now) {
             elem.val(now + prop === ("max","+"||"min","-") + elem.prop("step"))
      }
    })
};

$('#plus').mousedown(function(e) {
  fx(range, "max")
});

$('#minus').mousedown(function minus(e) {
  fx(range, "min")
});

$(document).mouseup(function(e) {
  range.stop(true, false)
});

jsfiddle http://jsfiddle.net/bnesu3h9/3/

var range = $("#range")
, fx = function(elem, prop) {
  return elem
    .animate({
      value: range.prop(prop)
    }, {
      duration: 3000,
      easing: "linear",
      step: function(now) {
        elem.val(now + prop === ("max","+"||"min","-") + elem.prop("step"))
      }
    })
};

$('#plus').mousedown(function(e) {
  fx(range, "max")
});

$('#minus').mousedown(function minus(e) {
  fx(range, "min")
});

$(document).mouseup(function(e) {
  range.stop(true, false)
});
#plus {
  width: 15px;
  height: 15px;
  background-color: red;
  float: left;
}
#minus {
  width: 15px;
  height: 15px;
  background-color: blue;
  float: left;
}
.range-container {
  float: left;
  overflow: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input type='button' id='minus' />
<div class='range-container'>
  <input id='range' type='range' min='0' max='100' step='1' />
</div>
<input type='button' id='plus' />

This answer should help.

The click event includes mouseup and mousedown. You'll want to handle mousedown alone at first, and continuously check to see if the mouse is still down. You can stop checking on document mouseup.

The very basic approach to this is to start looping at certain interval while one of buttons is pressed, doing value changes at each tick. Start when button is clicked, stop when it's released. Here's simplistic code for concept demonstration purpose only:

// Store the reference
var range = $('#range');

// These functions will change the value
function increment () {
    range.val(parseInt(range.val()) + 1)
}

function decrement () {
    range.val(parseInt(range.val()) - 1)
}

// Attaches polling function to element
function poll (el, interval, fn) {
    var isHeldDown = false;

    return el
    .on("mousedown", function() {
        isHeldDown = true;

        (function loop (range) {
            if (!isHeldDown) return; // Stop if it was released
            fn();
            setTimeout(loop, interval); // Run the function again       
        })();
    })
    .on("mouseup mouseleave", function () {
        isHeldDown = false; // Stop polling on leave or key release
    });
}

poll($("#plus"), 40, increment);
poll($("#minus"), 40, decrement);

JSFiddle.

In production grade version you'd want to apply timing function instead of constant interval; think about all possible events that should start and stop the polling so it won't stuck forever when user moves pointer away or something; use requestAnimationFrame to control timing function more precisely.

this is a question that is asked a lot. I have answered on a duplicate thread with a working snippet that exactly does what you are looking for.

https://stackoverflow.com/a/70957862/13795525

function imposeMinMax(el) {
    if (el.value != '') {
        if (parseInt(el.value) < parseInt(el.min)) {
            el.value = el.min;
        }
        if (parseInt(el.value) > parseInt(el.max)) {
            el.value = el.max;
        }
    }
}


var index = 0;
var interval;
var timeout;
var stopFlag=false;

function clearAll(){
   clearTimeout(timeout);
   clearInterval(interval);
}


function modIn(el) {
   var inId = el.id;
   if (inId.charAt(0) == 'p') {
      var targetId = inId.charAt(2);      
      var maxValue = Number(document.getElementById(targetId).max);
      var actValue = Number(document.getElementById(targetId).value);
      index = actValue;
      if(actValue < maxValue){
         stopFlag=false;
         document.getElementById(targetId).value++;
      }else{
      stopFlag=true;
      }
      timeout = setTimeout(function(){
      interval = setInterval(function(){        
         if(index+1 >= maxValue){
            index=0;
            stopFlag=true;
         }  
         if(stopFlag==false){
            document.getElementById(targetId).value++;
         } 
         index++;
      }, 100);
      }, 500);      
   imposeMinMax(document.getElementById(targetId));
   }
   if (inId.charAt(0) == 'm') {
      var targetId = inId.charAt(2);
      var minValue = Number(document.getElementById(targetId).min);
      var actValue = Number(document.getElementById(targetId).value);
      index = actValue;
      if(actValue > minValue){
         stopFlag=false;
         document.getElementById(targetId).value--;
      }else{
         stopFlag=true;
      }
      timeout = setTimeout(function(){
         interval = setInterval(function(){        
            if(index-1 <= minValue){
               index=0;
               stopFlag=true;
            }  
            if(stopFlag==false){
               document.getElementById(targetId).value--;
            } 
            index--;
         }, 100);
         }, 500);      
      imposeMinMax(document.getElementById(targetId));
   }
}
<!DOCTYPE html>
<html lang="en">
<head>
  <title>Button example</title>
  <meta charset="utf-8">
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
</head>
<body>

  <button type='button' class='btn btn-danger btn-sm ' id='mbA' onmousedown='modIn(this)' onmouseup='clearAll()' onmouseleave='clearAll()'>-</button>
  <input type='number' id='A'  onchange='imposeMinMax(this)' value='200' max='350' min='150' step='1' style='width: 50px;'>                 
  <button type='button' class='btn btn-danger btn-sm ' id='pbA' onmousedown='modIn(this)' onmouseup='clearAll()' onmouseleave='clearAll()'>+</button>&nbsp;

  <button type='button' class='btn btn-danger btn-sm signBut' id='mbB' onmousedown='modIn(this)' onmouseup='clearAll()' onmouseleave='clearAll()'>-</button>
  <input type='number'  id='B'  onchange='imposeMinMax(this)' value='250' max='450' min='150' step='1' style='width: 50px;'>                 
  <button type='button' class='btn btn-danger btn-sm ' id='pbB' onmousedown='modIn(this)' onmouseup='clearAll()' onmouseleave='clearAll()'>+</button>&ensp;

  <button type='button' class='btn btn-danger btn-sm signBut' id='mbC' onmousedown='modIn(this)' onmouseup='clearAll()' onmouseleave='clearAll()'>-</button>
  <input type='number'  id='C'  onchange='imposeMinMax(this)' value='3' max='10' min='1' step='1' style='width: 50px;'>                 
  <button type='button' class='btn btn-danger btn-sm ' id='pbC' onmousedown='modIn(this)' onmouseup='clearAll()' onmouseleave='clearAll()'>+</button>

</body>



</html>

发布评论

评论列表(0)

  1. 暂无评论