Create a spinner control on an HTML webpage with the help of JavaScript

I am attempting to create a spinner control on my webpage, and I have tried the following code:

<!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, the spinner does not behave as expected. When I click the "up" button, I want the value to increment only once, but sometimes it adds the value multiple times.

Could someone please review this and make the necessary fixes?

For a live example, visit this link

Answer №1

Utilizing an interval can streamline the code significantly, as confirmed through testing on IE9, Chrome21, and FF14. I conducted my testing using http://jsfiddle.net/KmMCE/3/, although I have yet to update the sample.

Here is the 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();" />

The JavaScript snippet is as follows:

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);
}

Answer №2

Here are the key issues that need to be addressed:

  • The handling of the onmouseup and onmousedown events needs improvement.

    • An onmousedown event in a button can still trigger even if the subsequent onmouseup event occurs outside the button. This results in inaccurate tracking of the window.rotate_start variable. Simply relying on onmouseup and onmousedown events is insufficient for achieving the desired functionality.

    • To resolve this, implement a global event handler for both onmouseup and onmousedown events that maintains the state in a variable. Additionally, use other variables to monitor the occurrence of onmouseover and onmouseout events on the buttons. This will help determine whether to update the value or not, along with how to adjust it (+1/-1).

  • Accumulation of timeouts during single clicks is causing undesired effects as mentioned in the question. To address this issue, introduce a variable that tracks whether a timeout has been set, and reset the timeout when both onmousedown and onmouseover events for a button are triggered (i.e., upon a single click, disregard any pending timer executions).

For a practical example, refer to the following 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);

}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

"Error: The property $notify is not found in the type" - Unable to utilize an npm package in Vue application

Currently integrating this npm package for notification functionalities in my Vue application. Despite following the setup instructions and adding necessary implementations in the main.ts, encountering an error message when attempting to utilize its featur ...

Personalizing text in HTML using JavaScript results

I have a modal dialog box function that pops up when a user clicks a button, triggered by a javascript/jquery script. The text displayed in the dialog is set up within an HTML div element that references the script function. My query is how to personalize ...

Ensure accurate detection of invalid values for SVG Elements in React using jest testing framework

When testing my react app, I am attempting to capture any errors that are thrown or logged to the console. If a regular HTML element such as <p> contains invalid attributes like <p color={false}></p>, react will display an error via cons ...

Creating objects that are a fraction of another's width

My goal is to create 3 responsive divs that fill the width of the window and adjust their width based on the window dimensions. However, I'm facing an issue with JavaScript where it seems to be miscalculating the window width, causing the objects to o ...

unable to insert logo into HTML

I am customizing an HTML template, but the dimensions of the logo in the template are smaller than my logo. Despite adding my logo to the template, it is not showing up. @media (max-width: 673px) { #logo { margin-left: 20px; } } #header #logo ...

Property-based Angular Material row grouping in a mat-table is a powerful feature that enhances

Is there a way to organize the data in one row with the same ID? Currently, my data looks like this: Data Set: { "id": "700", "desc": "Tempo", "richiesta": "20220087", "dataElab": &quo ...

What is the best way to implement a day timer feature using JavaScript?

I am looking for a timer that can automatically change the rows in an HTML table every day. For example, if it is Day 11, 12, or 25 and the month is February at 8 AM, the rows should display "Hello!". function time() { var xdate = new Date(); var ...

:Incorporating active hyperlinks through javascript

Hey there, I've encountered a little conundrum. I have a header.php file that contains all the header information - navigation and logo. It's super convenient because I can include this file on all my pages where needed, making editing a breeze. ...

Utilizing a JavaScript Library in your Scala.js Project: A Step-by-Step Guide

I am currently following a tutorial on setting up dependencies in my Scala.js project. Here is the link to the tutorial: First and foremost, I have organized my project setup as shown below: https://github.com/scala-js/scalajs-cross-compile-example Wi ...

Once a session is established within a route, it cannot be accessed or utilized in any other routes within the

I am currently in the process of setting up sessions for my node.js app. To achieve this, I am utilizing modules such as "express", "express-session", and "express-mysql-session" to store the sessions in a database on my server. While my code works perfect ...

A guide on incorporating a Java loop with Selenium automation

// Searching and deleting process driver.findElement(By.cssSelector("input[type='search']")).sendKeys("Diversification Rule Template"); driver.findElement(By.className("delete-template")).click(); Alert alert = driver.switchTo.alert(); Thread. ...

Is it possible to observe the website functionalities and execute them directly from the console?

Question about JavaScript: Is it safe for a script tag to be visible in the body of the developer console and for functions to be run directly on the website? It raises security concerns, and there should be measures in place to prevent this kind of displa ...

What is the best way to transform the data received from this function into a DataTable that can be used with the Google Charts API?

Is there a way to easily convert the data returned by this function into a format that Google Charts API can read? public function ajax_get_dates(){ $data = ([['date1' => '04/08/2016'], ['date2' => '05/08/2016& ...

Customize the appearance of the Vue.js datepicker starting from today's date

I am currently using the vue-datepicker component to display a date input field in my form. I want to set the default date to the current day and disable the selection of past dates. Additionally, I need to change the language of the component but it seems ...

An element in CSS that has a position of fixed and a width of 100% surpasses the dimensions of its

My element has the CSS properties position:fixed and width:100%, causing it to be larger than its parent elements. Despite the complexity of my code, I have attempted to simplify it for better understanding. Below, you can see that the green box exceeds ...

What is the best way to display user input within a paragraph using React?

I've been working on a To-Do list and I have successfully implemented the functionality to add new tasks. The issue I'm facing is that when I try to add a task, it doesn't show up in the paragraph within my Todo component, even though I can ...

The Vue Watch feature fails to trigger when incorporating axios

Hello everyone, I am facing an issue with my code that involves fetching data from a database using axios. The problem is that the watch function is not triggering in the .then() block. Below is the snippet of code I am currently working with. Thank you ...

What is the best way to initiate a fresh AJAX request whenever the submit button is pressed?

Every time the submit button is clicked on my form, a modal appears and gets filled with JSON data from the application /addresschecker. If I receive an error message with a code return number of 2003, it indicates an issue with the addresses provided. Oth ...

Executing React Fetch API Twice upon loading the page

Double-fetching Issue with React Fetch API on Initial Page Load import React, { useState, useEffect } from 'react' import axios from 'axios'; import { Grid, Paper, TextField } from '@mui/material' import PersonOut ...

Enhance with Laravel combined with AngularJS

I've encountered some issues with the "edit" part while working on a Laravel + AngularJS CRUD application. An internal server error is being displayed, and I'm seeking assistance to understand its cause. Error "GET localhost/crudtcc/public/ap ...