hguser
hguser

Reputation: 36028

build a spinner controll in html page using javascript

I want to make a spinner controll in my page,I tried it like this:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Simple spinner</title>

    <script type="text/javascript">
        function RotateSpinner(spinnerId, up) {
            var ele=document.getElementById(spinnerId);
            ele.value=parseInt(ele.value)+up;
                var t=setTimeout(function(){
                    if(window.rotate_start)
                        RotateSpinner(spinnerId,up);
                    else
                        clearTimeout(t);
                },500);

        }


    </script>

    <style>
        *
        {
            padding: 0;
            margin: 0;
        }
        .spinner
        {
            list-style: none;
            display: inline-block;
            line-height: 0;
            vertical-align: middle;
        }
        .spinner input
        {
            font-size: .45em;
            border-width: .5px;
            height: 1.5em;
            width: 2em;
        }
    </style>
</head>
<body>
    <input id="spinner" type="text" value="0" />
    <ul class="spinner">
        <li>
            <input type="button" value="&#9650;" onmousedown="window.rotate_start=true;RotateSpinner('spinner', 1)" onmouseup="window.rotate_start=false;"/>
        </li>
        <li>
            <input type="button" value="&#9660;" onmousedown="window.rotate_start=true;RotateSpinner('spinner', -1)" onmouseup="window.rotate_start=false;"/>
        </li>
    </ul>
</body>
</html>

However,it does not work as what I want, when I click the "up" button,I want the value only add once,but sometime it will add the value many times.

Can anyone have a check and fix it?

Here is the live example

Upvotes: 0

Views: 1703

Answers (2)

user1661268
user1661268

Reputation: 121

Using an interval shortens and simplifies the code a lot. (tested on IE9, Chrome21, FF14) I used http://jsfiddle.net/KmMCE/3/ for testing but I haven't updated the sample though.

Markup:

    <input id="spinner" type="text" value="0" />
    <input type="button" value="&#9650;"
      onmousedown="spinnerMouseDown('spinner', 1);" 
onmouseup="stopSpinner();" onmouseout="stopSpinner();" />

    <input type="button" value="&#9660;"
      onmousedown="spinnerMouseDown('spinner', -1);" 
onmouseup="stopSpinner();" onmouseout="stopSpinner();" />

JavaScript:

function spinnerMouseDown(id, value) {
    var el = document.getElementById(id);
    window.spinnerTimer = window.setInterval(function(){
      el.value = parseInt(el.value) + value;
    }, 100);
}

function stopSpinner() {
    window.clearInterval(window.spinnerTimer);
}

Upvotes: 2

Xavi L&#243;pez
Xavi L&#243;pez

Reputation: 27880

There are two main problems here:

  • Management of the onmouseup and onmousedown events.

    • You can get an onmousedown in a button, and if the onmouseup is outside the button, window.rotate_start will still be true. onmouseup and onmousedown alone are not enough to accomplish what you want.

    • Address this by using a global onmouseup and onmousedown event handler that will track the state in a variable. Keep other variables to check for onmouseover and onmouseout on the buttons to know wheter to update the value or not and how (+1/-1).

  • Timeouts running when doing single clicks accumulate. This is what's causing the effect described in the question. Use a variable that'll hold if the timeout is set, and clear the timeout when the onmousedown and onmouseover for a button are set (i.e. when a single click is made, forget about all pending timer executions).

See an example in this fiddle: http://jsfiddle.net/KmMCE/3/

<input type="button" value="&#9650;" onmouseover="window.upfocus = 1;" onmouseout="window.upfocus = 0;" />

<input type="button" value="&#9660;" onmouseover="window.downfocus = 1;" onmouseout="window.downfocus = 0;" />

var timingOut = false;
var upfocus = 0;
var downfocus = 0;
var mouseDown = 0;
document.body.onmousedown = function() {

    mouseDown = 1;
    if (window.upfocus == 1) {
        if (timingOut) {
            clearTimeout(t);
            timingOut = false;
        }
        RotateSpinner('spinner', 1);
    }
    else if (window.downfocus == 1) {
        if (timingOut) {
            clearTimeout(t);
            timingOut = false;
        }
        RotateSpinner('spinner', -1);
    }
}
document.body.onmouseup = function() {
    mouseDown = 0;
}

function RotateSpinner(spinnerId, up) {
    var ele = document.getElementById(spinnerId);
    ele.value = parseInt(ele.value) + up;
    timingOut = true;
    t = setTimeout(function() {
        if (mouseDown == 1 && up == 1 && window.upfocus == 1) {
            RotateSpinner(spinnerId, up);
        }
        else if (mouseDown == 1 && up == -1 && window.downfocus == 1) {
            RotateSpinner(spinnerId, up);
        }
        else {
            clearTimeout(t);
            timingOut = false;
        }
    }, 500);

}

Upvotes: 1

Related Questions