How do I implement press and hold button javascript?

15,914

Solution 1

This code should do everything you're looking for; it's based very loosely on tj111's example. I tried to make it as reusable as possible, and it doesn't need JavaScript mixed in with the HTML.

You do need to add IDs to the buttons (btnUP and btnDOWN) and text field (amount). You can change these IDs in the window.onload statement.

// This function creates a closure and puts a mousedown handler on the element specified in the "button" parameter.
function makeButtonIncrement(button, action, target, initialDelay, multiplier){
    var holdTimer, changeValue, timerIsRunning = false, delay = initialDelay;
    changeValue = function(){
        if(action == "add" && target.value < 1000)
            target.value++;
        else if(action == "subtract" && target.value > 0)
            target.value--;
        holdTimer = setTimeout(changeValue, delay);
        if(delay > 20) delay = delay * multiplier;
        if(!timerIsRunning){
            // When the function is first called, it puts an onmouseup handler on the whole document 
            // that stops the process when the mouse is released. This is important if the user moves
            // the cursor off of the button.
            document.onmouseup = function(){
                clearTimeout(holdTimer);
                document.onmouseup = null;
                timerIsRunning = false;
                delay = initialDelay;
            }
            timerIsRunning = true;
        }
    }
    button.onmousedown = changeValue;
}

//should only be called after the window/DOM has been loaded
window.onload = function() {
    makeButtonIncrement(document.getElementById('btnUP'), "add", document.getElementById('amount'), 500, 0.7);
    makeButtonIncrement(document.getElementById('btnDOWN'), "subtract", document.getElementById('amount'), 500, 0.7);
}

Solution 2

This is kind of quick and dirty, but it should give you a start. Basically you want to set up a few initial "constants" that you can play with to get the desired behavior. The initial time between increments is 1000 ms, and on each iteration if become 90% of that (1000, 990, 891, ... 100) and stops getting smaller at 100 ms. You can tweak this factor to get faster or slower acceleration. The rest I believe is pretty close to what I think you were going for. It seems like you were just missing the event assignments. In the window.onload you'll see that i assign the onmouseup, and onmousedown events to functions that just call the increment() or decrement() functions with your initial timeout, or the ClearTimeout() function to stop the counter.

EDIT: I changed this slightly to fix the bug. Now if you move your mouse pointer off the button and release it will stop the counter.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
    <title><!-- Insert your title here --></title>
    <script>

      // Fake Constants
      var INITIAL_TIME = 1000;
      var ACCELERATION = .9;
      var MIN_TIME = 100;

      // create global variables to hold DOM objects, and timer
      var up = null,
        down = null,
        count = null,
        timer = null;

      // Increment the counter
      function increment (time) {
        // decrease timeout by our acceleration factor, unless it's at the minimum
        time = (time * ACCELERATION > MIN_TIME) ? (time * ACCELERATION) : MIN_TIME;
        count.value ++ ;
        // set the timeout for the next round, and pass in the new smaller timeout
        timer = setTimeout(
                  function () {
                    increment(time);
                  }, time);
      }
      // Same as increment only subtracts one instead of adding.
      // -- could easily make one function and pass an pos/neg factor instead
      function decrement (time) {
        time = time * ACCELERATION > MIN_TIME ? (time * ACCELERATION) : MIN_TIME;
        count.value --;
        timer = setTimeout(
                  function () {
                    decrement(time);
                  }, time);
     }

     // Initialize the page after all the forms load
     window.onload = function () {
       // initialization function

       // assign DOM objects to our vars for ease of use.
       up = document.getElementById('up_btn');
       down = document.getElementById('dwn_btn');
       count = document.getElementById('count');

       // create event handlers for mouse up and down
       up.onmousedown = function () {
         increment(INITIAL_TIME);
       }
        down.onmousedown = function () {
         decrement(INITIAL_TIME);
       }

       document.onmouseup = function () {
         clearTimeout(timer);
       }

     }

  </script>
</head>
<body>
  <!-- Insert your content here -->

  <form name="the_form">
    <input type="button" value="Up" id="up_btn" /><br />
    <input type="button" value="Down" id="dwn_btn" /></br>

    <br />
    Count: 
    <input type="text" value="0" id="count" />

  </form> 

</body>
</html>
Share:
15,914

Related videos on Youtube

couchua
Author by

couchua

Updated on April 19, 2022

Comments

  • couchua
    couchua about 2 years

    I'm a complete novice, looking for instructions on implementing javascript. I am attempting to replace a YUI slider with buttons and a text field. I am trying to achieve buttons that, when held down, will continue to make the text field increase, preferably at a faster and faster rate. (http://www.blackbird502.com/white.htm)I have this in the java tag in the head:

    function holdit(btn, action, start, speedup) {
    var t;
    
    var repeat = function () {
        action();
        t = setTimeout(repeat, start);
        start = start / speedup;
    }
    
    btn.mousedown = function() {
        repeat();
    }
    
    btn.mouseup = function () {
        clearTimeout(t);
    }
    
    /* to use */
    holdit(btn, function () { }, 1000, 2); 
    /* x..1000ms..x..500ms..x..250ms..x */
    

    I have no clue how to implement the press and hold into the following in the body:

    <form><input type=button value="UP"  class="btn" onClick="javascript:this.form.amount.value++;"><br /><input type=text name=amount value=5 class="text"><br /> <input type=button value="DOWN"  class="btn" onClick="javascript:this.form.amount.value--;" ></form>
    

    Is it possible? Thanks.

  • Jesse Brown
    Jesse Brown about 15 years
    Ooops, my code sets the onmouseup event to the button so has the bug that SydneySM refers to in his solution.
  • couchua
    couchua about 15 years
    I just worked this into the page, and it works perfectly: blackbird502.com/white1.htm I will try out SidneySM's below to try and avoid the 'bug,' though there is no evidence of a 'bug' from a novice's stand point. THANKS!
  • Jesse Brown
    Jesse Brown about 15 years
    I changed the code to fix the bug. I just attached the onmouseup event to the document. Credit goes to SidneySM for catching that.