JS Newbie Here. How can I create a progress bar where I can add or subtract a count?

I need a little bit of help, I’m a newbie and can’t seem to find the right keywords to look for the answer to my question.

I wanted to add a similar “progress bar” on top of the page I’m working on like this. I would like a similar bar but with a plus and minus button next to it. It doesn’t even have to be in percentage, I just want it to say something like “You have read x out of 30 books” then the bar, then a plus and minus button, and also saves it in local storage.

How do I go about this? Thank you!

Answer

I replicated the progress bar in the screenshot you have provided. I’ve provided comments in the javascript code which should explain everything that is happening. Hopefully this helps!

var current = 0;
const min = 0;
const max = 30;

//This function is taken from: https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API#testing_for_availability
//This is used to check if localStorage is available
function storageAvailable(type) {
    var storage;
    try {
        storage = window[type];
        var x = '__storage_test__';
        storage.setItem(x, x);
        storage.removeItem(x);
        return true;
    }
    catch(e) {
        return e instanceof DOMException && (
            // everything except Firefox
            e.code === 22 ||
            // Firefox
            e.code === 1014 ||
            // test name field too, because code might not be present
            // everything except Firefox
            e.name === 'QuotaExceededError' ||
            // Firefox
            e.name === 'NS_ERROR_DOM_QUOTA_REACHED') &&
            // acknowledge QuotaExceededError only if there's something already stored
            (storage && storage.length !== 0);
    }
}

//This function should be called each time you update the progress so the display updates as well
function updateProgress()
{
    document.querySelector(".progress-text").innerText = `You have read ${current} out of ${max} books.`; //this sets the text including the variable values
    document.querySelector(".progress-bar").style.width = Math.round((current / max) * 100) + "%"; //this sets the length of the progress-bar to a percentage
    document.querySelector(".progress-percentage").innerText = Math.round((current / max) * 100) + "%"; //this displays the progress as a percentage
}

//this function is called each time the increase button is clicked
function onButtonIncreaseClicked(e)
{
    e.preventDefault(); //prevent the button from doing anything else

    //make sure the current value never goes above the max value
    if (current < max)
        current++;

    //this will set the value in the localStorage as long as it is available and accessible
    if (storageAvailable('localStorage'))
    {
        localStorage.setItem("progress", current); //our "key" is set to contain the value of current
    }

    updateProgress(); //call to update the display
}

//identical to the increase button, only decreases
function onButtonDecreaseClicked(e)
{
    e.preventDefault();

    //prevent us from going below the minimum value
    if (current > min)
        current--;

    if (storageAvailable('localStorage'))
    {
        localStorage.setItem("progress", current);
    }

    updateProgress(); //always call to update the display
}

//this function is to register the button click event handlers. This makes clicking the buttons work. You should only call this once per page load.
function registerHandlers()
{
    document.querySelector("#btnIncrease").addEventListener("click", onButtonIncreaseClicked);
    document.querySelector("#btnDecrease").addEventListener("click", onButtonDecreaseClicked);
}

//this function is to unregister the button click event handlers. This prevents the buttons from working. Just incase.
function unregisterHandlers()
{
    document.querySelector("#btnIncrease").removeEventListener("click", onButtonIncreaseClicked);
    document.querySelector("#btnDecrease").removeEventListener("click", onButtonDecreaseClicked);
}

//This is our setup function. You should call this once per page load.
function setup()
{
    //check if localstorage is available and if there's a valid number in it
    if (storageAvailable('localStorage') && localStorage.getItem("progress") != null && !isNaN(localStorage.getItem("progress")))
    {
        current = parseInt(localStorage.getItem("progress")); //load our stored value

        if (current > max) //make sure the stored value is not above our max value
            current = max;
        else if (current < min) //make sure the stored value is not below our min value
            current = min;
    }

    registerHandlers(); //make clicking buttons work
    updateProgress(); //update the display
}

setup(); //our call to setup everything, should be called once per page load.
.progression
{
    width: 300px;
    text-align: center;
}

p.progress-text
{
    font-weight: bold;
}

.progress-container
{
    display: block;
    background-color: #f4f1ea;
    height: 25px;
}

.progress-bar
{
    background-color: #927f64;
    height: 100%;
    width: 0%;
    transition: width 0.5s;
}
<div class="progression">
    <p class="progress-text">You have read 0 of 30 books.</p>
    <div class="progress-container">
        <div class="progress-bar"></div>
    </div>
    <p class="progress-percentage">0%</p>
    <button id="btnDecrease">-</button>
    <button id="btnIncrease">+</button>
</div>