How to keep button disabled even if user refreshes the page? Javascript

Viewed 71

I have this little app that generates numbers between 1 and 90. I do it as I'm practicing with my early JS skills.

It's written in italian so for better understanding, well the title doesn't matter that much, it just says "wanna try your luck?" bla-bla.

Then I set a timeout that disables the "Genera Numeri" button for 1 hour after it's clicked (I set it to 3 seconds for the post), and a message pops up ("You can use it once every hour") but if you refresh the page, of course, you can click it again.

I was wondering, how can I make it that even if I refresh, the countdown would be still going?

I read another similar question where they were talking about Mongo (which I have no clue what it is, I suppose back end (?) ), and they mentioned the use of cookies to do that, which in my inexperienced eyes, could make sense.

Anyways, HERE the Javascript

let button = document.querySelector('.button')
let clear = document.querySelector('.clear')
let message = document.querySelector('.message')
let first = document.querySelector('.first')
let second = document.querySelector('.second')
let third = document.querySelector('.third')
let fourth = document.querySelector('.fourth')
let fifth = document.querySelector('.fifth')
let sixth = document.querySelector('.sixth')

button.addEventListener('click', ()=> {
  first.innerText = Math.floor(Math.random() * (90 - 1) + 1)
  second.innerText = Math.floor(Math.random() * (90 - 1) + 1)
  third.innerText = Math.floor(Math.random() * (90 - 1) + 1)
  fourth.innerText = Math.floor(Math.random() * (90 - 1) + 1)
  fifth.innerText = Math.floor(Math.random() * (90 - 1) + 1)
  sixth.innerText = Math.floor(Math.random() * (90 - 1) + 1)

  message.classList.add('show')

  button.disabled = true

  setTimeout(function(){
    button.disabled = false
    message.classList.remove('show')
  }, 1000 * 3) 

})


clear.addEventListener('click', ()=> {
  first.innerText = ''
  second.innerText = ''
  third.innerText = ''
  fourth.innerText = ''
  fifth.innerText = ''
  sixth.innerText = ''
})

And HERE the snippet

let button = document.querySelector('.button')
let clear = document.querySelector('.clear')
let message = document.querySelector('.message')
let first = document.querySelector('.first')
let second = document.querySelector('.second')
let third = document.querySelector('.third')
let fourth = document.querySelector('.fourth')
let fifth = document.querySelector('.fifth')
let sixth = document.querySelector('.sixth')

button.addEventListener('click', ()=> {
  first.innerText = Math.floor(Math.random() * (90 - 1) + 1)
  second.innerText = Math.floor(Math.random() * (90 - 1) + 1)
  third.innerText = Math.floor(Math.random() * (90 - 1) + 1)
  fourth.innerText = Math.floor(Math.random() * (90 - 1) + 1)
  fifth.innerText = Math.floor(Math.random() * (90 - 1) + 1)
  sixth.innerText = Math.floor(Math.random() * (90 - 1) + 1)

  message.classList.add('show')

  button.disabled = true

  setTimeout(function(){
    button.disabled = false
    message.classList.remove('show')
  }, 1000 * 3) 

})


clear.addEventListener('click', ()=> {
  first.innerText = ''
  second.innerText = ''
  third.innerText = ''
  fourth.innerText = ''
  fifth.innerText = ''
  sixth.innerText = ''
})
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  background-image: url('conf.jpg');
  background-size: cover;
  background-repeat: no-repeat;
  height: 100vh;
  background-position-x: right;
}

.overlay {
  width: 100vw;
  height: 100vh;
  background: rgba(0,0,0,.3);
}

.container {
  width: 95vw;
  height: 420px;
  margin: auto;
  display: flex;
  flex-direction: column;
  border: 1px solid black;
  justify-content: space-around;
  align-items: center;
  text-align: center;
  font-family: helvetica;
  position: absolute;
  top: 40vh;
  left: 50vw;
  transform: translate(-50%, -50%);
  background: rgba(0,0,0,.75);
  color: white;
  border-radius: 15px;
  box-shadow: 0 0 15px black;
  padding-bottom: 1em;
}

.title {
  height: 50%;
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  align-items: center;
  text-align: center;

  letter-spacing: .5px;
}

h1 {
  font-family: verdana;
  border-bottom: 1px solid white;
}

.tenta {
  font-size: 1.25em;
}

.numbers {
  display: flex;
  width: 100%;
  justify-content: space-around;
}

.number {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  border: 1px solid white;
  text-align: center;
  vertical-align: center;
  display: flex;
  justify-content: center;
  align-items: center;
  color: white;
  font-family: tahoma;
  font-size: 1.2em;
  background: black;
}

.button {
  padding: .5em 1.5em;
  font-size: 1.1em;
  border: none;
  background: white;
  border-radius: 5px;
  box-shadow: 0 0 10px black;
  transition: .2s linear;
  outline: none;
  background: rgb(0,255,117)
}

.button:active {
  transform: scale(.95);
}

.clear {
  padding: .2em .5em;
  position: absolute;
  bottom: 20px;
  right: 20px;
  border: none;
  background: white;
  border-radius: 5px;
  box-shadow: 0 0 10px black;
  transition: .2s linear;
  outline: none;
}

.clear:active {
  transform: scale(.95);
}

p {
  color: white;
  text-align: center;
  position: relative;
  top: calc(450px + 20vw);
  font-family: helvetica;
  font-size: 1.1em;
  margin: auto;
  background: rgba(0,0,0,.45);
  padding: .5em 1em;
  display: none;
}

p.show {
  display: block;
}
  <div class="overlay">
    <div class="container">
      <div class="title">
        <h1>Number Generator</h1>
        <h3 class="nonsai">Non sai quali numeri giocare?</h3>
        <h3 class="tenta">Tenta la fortuna con l'algoritmo di<br> Number Generator!</h3>
      </div>

      <div class="numbers">
        <div class="first number"></div>
        <div class="second number"></div>
        <div class="third number"></div>
        <div class="fourth number"></div>
        <div class="fifth number"></div>
        <div class="sixth number"></div>
      </div>

      <button class="button">Genera Numeri</button>
      <button class="clear">Refresh</button>

    </div>
    <p class="message">Puoi usare Number Generator una volta ogni ora</p>
  </div>

  <script src="main.js"></script>

2 Answers

I didn't read all your code but from the explanation it seems like you have wrong approach in general if you want to restrict the user from clicking the button. I think you are aware of the client and server side computation.

So, first of all. Surely you can restrict button clicks on client side and even in a consistent way (saving it after refresh) but you should keep in mind that an advanced internet user will be able to hack it easily because you have just some standart options to achieve it. One of them is using cookies: When user clicks a button save a cookie with name butttonClicked or smth with value true and a lifetime of 1 hour. Its easy googlable how to do it. On page load always check if the cookies is set and attach attribute disabled to button. but cookies are visible and user can delete it himself.

To really restrict it you should make some checks on the server side so that even if user was able to send a request somehow, no matter the button was disabled or no on the front end, you should stop performing an action and send back an error message.

One way to do this would be using the browser's built-in capability to store data for a particular domain by utilizing the local storage. In general it can be used to store any kind of data but in your case it should hold the time your button gets 'reactivated'.

Let me outline what needs to be done:

  • at page load, start a timer which continuously checks the time stored in the local storage in a short interval of e.g. 1 second.

  • if there is no time stored yet, store the current time

  • if there is a time stored and it's in the future, disable the button

  • if there is a time stored and it's in the past, enable the button

  • If the user presses the button, update the value in the local storage and disable the button.

Here's an example. If you click on the button, it will disable it for 3 seconds:

<html>
    <head>  
    </head>
    <body>
        <button id="button">click me</button>
    </body>
    <script type="text/javascript">
        var myButton=document.getElementById("button");
        function storeTime(theTime)
        {
            localStorage.setItem("time", theTime);
        }
        
        function check()
        {
            var now=new Date().getTime();
            if(!localStorage.getItem("time"))
            {
                storeTime(now);
            }
            var storedTime=parseInt(localStorage.getItem("time"));
            
            if(storedTime>now)
            {
                myButton.disabled=true;
            }
            else
            {
                myButton.disabled=false;
            }
        }
        
        function buttonClicked()
        {
            var now=new Date().getTime() + 3000;
            storeTime(now);
            myButton.disabled=true;
        }
        
        setInterval(check, 1000);
        check();
        myButton.addEventListener("click", buttonClicked);
    </script>
</html>
Related