Saturday, 12 July 2025

Web Tutorial: The Cigarette Break Browser-based Screensaver

Following the one-year anniversary of having quit smoking, now that I no longer take smoke breaks, I do the next best thing - I make my browser take smoke breaks. Heh heh. For real, though. This occasion's web tutorial is centered around the idea of browser idle time. When the browser is left alone for a suitable amount of time, a screensaver comes up! And in this case, I want it to feature a smoking cigarette.

And the more time passes, the shorter I want the cigarette to get. Oh, and there needs to be animation.

Can I squeeze all of that into a single-part web tutorial? Let's find out!

Some HTML as usual. There's some Lorem Ipsum text, and a div with the id overlay. In the CSS, we want to set the outline for all divs to red.
<!DOCTYPE html>
  <html>
  <head>
    <title>Screensaver</title>
    <style>
      div { outline: 1px solid red; }
    </style>
    <script>
    </script>
  </head>

  <body>
    <h1>Some sample text. Leave this screen alone for 5 seconds to see the popup!</h1>    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque et justo sit amet libero interdum bibendum at nec dui. Mauris lacinia sapien nec blandit dapibus. Nunc suscipit in nunc in finibus. Praesent mi arcu, convallis auctor auctor luctus, gravida eget enim. Nunc quis finibus nisl, semper hendrerit nisl. Curabitur faucibus, velit varius efficitur suscipit, nibh ipsum bibendum turpis, placerat elementum nulla lorem eget diam. Phasellus lobortis aliquet leo, non aliquet mauris volutpat vel. Aliquam facilisis dui id sapien dignissim vulputate. Nullam cursus convallis sem vel maximus. Sed ac sollicitudin justo, at vehicula ligula. Praesent sit amet tellus massa. Nam nec varius ipsum.</p>
    <p>Cras varius, nisl vitae lobortis sodales, purus ligula dictum eros, volutpat finibus neque sem et ligula. Vivamus id odio varius, blandit elit sit amet, scelerisque enim. Sed luctus molestie leo, suscipit ultricies nisl elementum id. Donec lacus erat, laoreet vel viverra vel, aliquam vitae elit. Vestibulum venenatis congue lacus a facilisis. Nulla condimentum, metus volutpat rhoncus maximus, purus mauris imperdiet dolor, at bibendum lacus justo nec risus. Praesent scelerisque libero magna, at lobortis justo convallis vel. Suspendisse cursus, odio ultricies auctor laoreet, ligula leo vulputate diam, et efficitur mauris nisl et urna. Quisque sit amet rutrum magna. Aenean at vestibulum urna. Nam ornare justo a tortor molestie auctor. Quisque at malesuada mi, volutpat feugiat sem.</p>
    <p>Vestibulum luctus tempor ligula. Nulla id tortor ut est rutrum viverra. Etiam nec sapien id massa egestas dapibus at ut ipsum. Nunc sed tortor euismod, aliquet arcu et, commodo justo. Proin pretium vel neque sed maximus. In vitae vestibulum quam. Integer quis ex in ligula varius tempus. Donec diam arcu, faucibus eu aliquet nec, dapibus at sem. Sed convallis urna neque, tristique condimentum mauris condimentum vel. Praesent eu interdum quam, at ullamcorper augue. Mauris euismod odio libero, vel pharetra lorem egestas et. Nam laoreet ultricies venenatis. Integer ante risus, commodo nec eros ac, convallis tempus magna. Maecenas dictum lacus magna.</p>
    <p>Proin eu iaculis felis, sed lobortis lectus. Pellentesque malesuada diam eu porttitor aliquam. Fusce posuere dapibus odio vitae suscipit. Mauris consectetur, tortor et pulvinar auctor, ante eros ornare nunc, non fringilla neque quam sed erat. In velit turpis, ultricies ut egestas in, porttitor eget erat. Sed et risus molestie, maximus mauris eu, accumsan sem. Sed pellentesque feugiat elit. Integer nisl nulla, condimentum eu purus id, vestibulum commodo ligula. Phasellus consectetur, justo in mollis egestas, nisl felis laoreet ipsum, ac feugiat nunc ante sit amet risus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nulla in enim lacus. Proin nulla dui, dictum at porttitor et, consectetur ac augue. Aliquam fringilla ex nec diam efficitur, vel vehicula mi molestie. Phasellus pellentesque in sem vitae porta. Nulla ut ultricies enim. Duis eu mauris sit amet lectus mattis efficitur molestie non magna.</p>

    <div id="overlay">
    </div>  </body>
</html>


Now, the modal popup is going to be visible by default - for now. For that we have the styling for overlay. position will be absolute, and we will set height and width properties to cover the entire screen with a translucent black background. left and top properties will be at 0px so as to begin on the top left corner of the screen. And of course, display is set to block to be visible by default.
<style>
  div { outline: 0px solid red; }

  #overlay
  {
    width: 100%;
 
    height: 100%;
 
    position: absolute;
 
    left: 0px;
    top: 0px;
    background-color: rgba(0, 0, 0, 0.5);
    display: block; 
 }

</style>


The first step of many steps!


Let's follow up by adding a div, styled with the CSS class content, in there.
<div id="overlay">
  <div class="content">

  </div>

</div>


We'll style it like this - a square with a black background and rounded corners set in the middle of overlay.
<style>
  div { outline: 0px solid red; }

  #overlay
  {
    width: 100%;    height: 100%;    position: absolute;    left: 0px;    top: 0px;    background-color: rgba(0, 0, 0, 0.5);    display: block;  }

  .content
  {
    width: 500px;
    height: 500px;
    margin: 5% auto 0 auto;
    background-color: rgba(0, 0, 0, 1);
    border-radius: 30px;
  }
</style>


Yep, here's that black square. Impossible to miss.


We introduce a new div inside that one, and style it using the CSS class cigarette.
<div id="overlay">
  <div class="content">
    <div class="cigarette">
    </div>
  </div>
</div>


This is how we style cigarette. It is a long vertical rectangle set in the middle of its parent, content. Think of it as a holder for all the divs that will make up the components of the cigarette.
.content
{
  width: 500px;
  height: 500px;
  margin: 5% auto 0 auto;
  background-color: rgba(0, 0, 0, 1);
  border-radius: 30px;
}

.cigarette
{
  width: 50px;
  height: 400px;
  margin: 10% auto 0 auto;
}


All in position, so far!



Now we'll do the individual parts of the cigarette. We have two divs - the first styled using body and the second styled using butt.
<div class="cigarette">
  <div class="body">

  </div>

  <div class="butt">
  
  </div>

</div>


body takes up full width but only 300 out of the 400 pixels on offer. There is explicitly no background.
.cigarette
{
  width: 50px;
  height: 400px;
  margin: 10% auto 0 auto;
}

.body
{
  width: 100%;
  height: 300px;
  background-color: none;
}


butt, similarly, takes up fill width and has only 100 pixels height. We have as its background a linear gradient, going from brown, yellow, then brown again.
.cigarette
{
  width: 50px;
  height: 400px;
  margin: 10% auto 0 auto;
}

.butt
{
  width: 100%;
  height: 100px;
  background-color: rgba(255, 170, 0, 1);
  background: linear-gradient(90deg,rgba(255, 170, 0, 1) 0%, rgba(255, 255, 170, 1) 50%, rgba(255, 170, 0, 1) 100%);
}


.body
{
  width: 100%;
  height: 300px;
  background-color: none;
}


This is what it looks like now. We'll be working on the empty-looking div next.


In body, we nest two more divs. Instead of classes, they will have ids because this will make them easier to manipulate via JavaScript later. The ids are empty (because that div represents "empty" space) and burnable (because it's the part of the cigarette that gets "burned").
<div class="body">
  <div id="empty">

  </div>

  <div id="burnable">

  </div>

</div>


body has 300 pixels in height, so empty takes up 50 and burnable takes up 250. burnable has a linear background that goes from light grey, white, then light grey again.
.body
{
  width: 100%;
  height: 300px;
  background-color: none;
}

#empty
{
  width: 100%;
  height: 50px;
}

#burnable
{
  width: 100%;
  height: 250px;
  background-color: rgba(255, 255, 255, 1);
  background: linear-gradient(90deg, rgba(230, 230, 230, 1) 0%, rgba(255, 255, 255, 1) 50%, rgba(230, 230, 230, 1) 100%);
}


So now we have an unlit cigarette.


In burnable, we have a div styled using the tip CSS class.
<div id="burnable">
  <div class="tip">

  </div>

</div>


tip has a height of 5 pixels and takes up full width; that's all there is to it.
#burnable
{
  width: 100%;
  height: 250px;
  background-color: rgba(255, 255, 255, 1);
  background: linear-gradient(90deg, rgba(230, 230, 230, 1) 0%, rgba(255, 255, 255, 1) 50%, rgba(230, 230, 230, 1) 100%);
}

.tip
{
  width: 100%;
  height: 5px;
}


In that div, let's add three divs, each styled using the ember CSS class.
<div id="burnable">
  <div class="tip">
    <div class="ember"></div>
    <div class="ember"></div>
    <div class="ember"></div>  </div>
</div>


ember is floated left and has an orange background.
.tip
{
  width: 100%;
  height: 5px;
}

.ember
{
  float: left;
  background-color: rgba(250, 150, 0, 1);
}


However, height and width vary according to their order. There are three divs in there, styled using ember, and we use the nth-of-type pseudoselector, passing in either "odd" or "even" and then adjusting the width and height accordingly. The middle (or second) "ember" is supposed to be the largest one.
.ember
{
  float: left;
  background-color: rgba(250, 150, 0, 1);
}

.ember:nth-of-type(odd)
{
  width:15px;
  height:3px;
}

.ember:nth-of-type(even)
{
  width:20px;
  height:5px;
}


Just for fun, let's add a bit of animation. This is totally superfluous. The animation name is emberglow and we want it to last for 2 seconds, run forever, and alternate smoothly between states. You'll see that for emberglow, I basically have background go from orange to red.
.ember
{
  float: left;
  background-color: rgba(250, 150, 0, 1);
  animation-name: emberglow;
  animation-duration: 2s;
  animation-iteration-count: infinite;
  animation-direction: alternate;

}

.ember:nth-of-type(odd)
{
  width:15px;
  height:3px;
}

.ember:nth-of-type(even)
{
  width:20px;
  height:5px;
}

@keyframes emberglow
{
  from { background-color: rgba(250, 150, 0, 1); }
  to { background-color: rgba(255, 0, 0, 1); }
}


There you go, a glowing tip! I feel like there's a filthy joke I could insert here, but let's move on...


In empty, we insert divs. Several divs. But let's just start with three. Style them using the CSS class smoke.
<div id="empty">
  <div class="smoke"></div>
  <div class="smoke"></div>
  <div class="smoke"></div>

</div>


Give each of them a random height, weight, margin-top and margin-left property. Do bear in mind that the effective width of empty is 50 pixels due to its parents, so the sum of margin-left and half of width shouldn't exceed 50, otherwise we'll have an overflow problem. Similarly, if we subtract half of width from margin-left, it should not be less than 0. width and height should be the same. You can have negative values for margin-top if you want the divs to overlap.
<div id="empty">
  <div class="smoke" style="width:15px;height:15px;margin-top:5px;margin-left:25px;"></div>
  <div class="smoke" style="width:20px;height:20px;margin-top:-2px;margin-left:10px;"></div>
  <div class="smoke" style="width:18px;height:18px;margin-top:0px;margin-left:5px;"></div>
</div>


smoke has a translucent white background and a nice fuzzy grey outline by way of the box-shadow property.
#empty
{
  width: 100%;
  height: 50px;
  background-color: rgba(0, 0, 0, 1);
}

.smoke
{
  background-color: rgba(255, 255, 255, 0.2);
  border-radius: 50%;
  box-shadow: 0 0 15px rgba(255, 255, 255, 0.5);
}

#burnable
{
  width: 100%;
  height: 250px;
  background-color: rgba(255, 255, 255, 1);
  background: linear-gradient(90deg, rgba(230, 230, 230, 1) 0%, rgba(255, 255, 255, 1) 50%, rgba(230, 230, 230, 1) 100%);
}


And that's how the first three divs would look like.


Add several more! Make sure width, height, margin-top and margin-left properties vary.
<div id="empty">
  <div class="smoke" style="width:15px;height:15px;margin-top:5px;margin-left:25px;"></div>
  <div class="smoke" style="width:20px;height:20px;margin-top:-2px;margin-left:10px;"></div>
  <div class="smoke" style="width:18px;height:18px;margin-top:0px;margin-left:5px;"></div>
  <div class="smoke" style="width:10px;height:10px;margin-top:-5px;margin-left:30px;"></div>
  <div class="smoke" style="width:15px;height:15px;margin-top:0px;margin-left:20px;"></div>
  <div class="smoke" style="width:20px;height:20px;margin-top:-2px;margin-left:15px;"></div>
  <div class="smoke" style="width:8px;height:8px;margin-top:-5px;margin-left:13px;"></div>
  <div class="smoke" style="width:12px;height:12px;margin-top:-5px;margin-left:8px;"></div>
  <div class="smoke" style="width:8px;height:8px;margin-top:0px;margin-left:22px;"></div>
  <div class="smoke" style="width:15px;height:15px;margin-top:-2px;margin-left:5px;"></div>
  <div class="smoke" style="width:20px;height:20px;margin-top:-5px;margin-left:15px;"></div>
  <div class="smoke" style="width:15px;height:15px;margin-top:-2px;margin-left:5px;"></div>
  <div class="smoke" style="width:12px;height:12px;margin-top:-5px;margin-left:8px;"></div>
  <div class="smoke" style="width:8px;height:8px;margin-top:0px;margin-left:30px;"></div>
  <div class="smoke" style="width:20px;height:20px;margin-top:-2px;margin-left:10px;"></div>
  <div class="smoke" style="width:8px;height:8px;margin-top:0px;margin-left:10px;"></div>
  <div class="smoke" style="width:15px;height:15px;margin-top:0px;margin-left:15px;"></div>
  <div class="smoke" style="width:20px;height:20px;margin-top:-5px;margin-left:10px;"></div>
  <div class="smoke" style="width:8px;height:8px;margin-top:-2px;margin-left:30px;"></div>
  <div class="smoke" style="width:10px;height:10px;margin-top:-2px;margin-left:15px;"></div>
  <div class="smoke" style="width:15px;height:15px;margin-top:-0px;margin-left:20px;"></div>

</div>


And you'll see their red outlines even if they're not visible after the glowing tip otherwise.


Now, at random, have each div styled using smoke1 or smoke2.
<div id="empty">
  <div class="smoke smoke1" style="width:15px;height:15px;margin-top:5px;margin-left:25px;"></div>
  <div class="smoke smoke1" style="width:20px;height:20px;margin-top:-2px;margin-left:10px;"></div>
  <div class="smoke smoke2" style="width:18px;height:18px;margin-top:0px;margin-left:5px;"></div>
  <div class="smoke smoke1" style="width:10px;height:10px;margin-top:-5px;margin-left:30px;"></div>
  <div class="smoke smoke2" style="width:15px;height:15px;margin-top:0px;margin-left:20px;"></div>
  <div class="smoke smoke2" style="width:20px;height:20px;margin-top:-2px;margin-left:15px;"></div>
  <div class="smoke smoke1" style="width:8px;height:8px;margin-top:-5px;margin-left:13px;"></div>
  <div class="smoke smoke2" style="width:12px;height:12px;margin-top:-5px;margin-left:8px;"></div>
  <div class="smoke smoke1" style="width:8px;height:8px;margin-top:0px;margin-left:22px;"></div>
  <div class="smoke smoke2" style="width:15px;height:15px;margin-top:-2px;margin-left:5px;"></div>
  <div class="smoke smoke2" style="width:20px;height:20px;margin-top:-5px;margin-left:15px;"></div>
  <div class="smoke smoke1" style="width:15px;height:15px;margin-top:-2px;margin-left:5px;"></div>
  <div class="smoke smoke2" style="width:12px;height:12px;margin-top:-5px;margin-left:8px;"></div>
  <div class="smoke smoke1" style="width:8px;height:8px;margin-top:0px;margin-left:30px;"></div>
  <div class="smoke smoke2" style="width:20px;height:20px;margin-top:-2px;margin-left:10px;"></div>
  <div class="smoke smoke2" style="width:8px;height:8px;margin-top:0px;margin-left:10px;"></div>
  <div class="smoke smoke1" style="width:15px;height:15px;margin-top:0px;margin-left:15px;"></div>
  <div class="smoke smoke2" style="width:20px;height:20px;margin-top:-5px;margin-left:10px;"></div>
  <div class="smoke smoke1" style="width:8px;height:8px;margin-top:-2px;margin-left:30px;"></div>
  <div class="smoke smoke2" style="width:10px;height:10px;margin-top:-2px;margin-left:15px;"></div>
  <div class="smoke smoke1" style="width:15px;height:15px;margin-top:-0px;margin-left:20px;"></div>
</div>


This is for more animation. These CSS classes each call an animation, with different durations. However, both of these animations will run forever, and alternate back and forth.
.smoke
{
  background-color: rgba(255, 255, 255, 0.2);
  border-radius: 50%;
  box-shadow: 0 0 15px rgba(255, 255, 255, 0.5);
}

.smoke1
{
  animation-name: smokebubble1;
  animation-duration: 1s;
  animation-iteration-count: infinite;
  animation-direction: alternate;
}

.smoke2
{
  animation-name: smokebubble2;
  animation-duration: 3s;
  animation-iteration-count: infinite;
  animation-direction: alternate;
}


#burnable
{
  width: 100%;
  height: 250px;
  background-color: rgba(255, 255, 255, 1);
  background: linear-gradient(90deg, rgba(230, 230, 230, 1) 0%, rgba(255, 255, 255, 1) 50%, rgba(230, 230, 230, 1) 100%);
}


Here are their animations. The box-shadow and margin-left properties are animated. I won't bother showing screenshots because the range of motion is rather limited.
.smoke1
{
  animation-name: smokebubble1;
  animation-duration: 1s;
  animation-iteration-count: infinite;
  animation-direction: alternate;
}

.smoke2
{
  animation-name: smokebubble2;
  animation-duration: 3s;
  animation-iteration-count: infinite;
  animation-direction: alternate;
}

@keyframes smokebubble1
{
  from { box-shadow: 0 0 11px rgba(255, 255, 255, 1); margin-left: 26px; }
}

@keyframes smokebubble2
{
  from { box-shadow: 0 0 12px rgba(255, 255, 255, 0.8); margin-left: 24px; }
}


#burnable
{
  width: 100%;
  height: 250px;
  background-color: rgba(255, 255, 255, 1);
  background: linear-gradient(90deg, rgba(230, 230, 230, 1) 0%, rgba(255, 255, 255, 1) 50%, rgba(230, 230, 230, 1) 100%);
}


In the JavaScript, we define the object idleCounter. In it, there are the properties lastActivity and msToPopup. lastActivity is a timestamp and defaults to null. msToPopup is an integer, defaults to 5, and defines the number of seconds of idle time encountered before the popup happens.
<script>
  var idleCounter =
  {
    lastActivity: null,
    msToPopup: 5
  };

</script>


We then have the method, startTimer(). What it does is set the observeLastActivity() method to run every second.
<script>
  var idleCounter =
  {
    lastActivity: null,
    msToPopup: 5,
    startTimer: function()
    {
      setInterval(
        () =>
        {
          this.observeLastActivity();
        }, 
       1000
      );
    }
  };
</script>


And we want this method to run as soon as the page is loaded.
<script>
  var idleCounter =
  {
    lastActivity: null,
    msToPopup: 5,
    startTimer: function()
    {
      setInterval(
        () =>
        {
          this.observeLastActivity();
        },
        5000
      );
    }
  };

  window.onload = () =>
  {
    idleCounter.startTimer();
  };
</script>


Create observeLastActivity(). If lastActivity is falsy (not defined or just null) then we run the setLastActivity() method. We'll run the popup() method regardless.
var idleCounter =
{
  lastActivity: null,
  msToPopup: 5,
  popupOpen: false,
  observeLastActivity: function()
  {
    if (!this.lastActivity) this.setLastActivity();
    this.popup();
  },

  startTimer: function()
  {
    setInterval(
      () =>
      {
        this.observeLastActivity();
      },
      5000
    );
  }
};


So we have two new methods to create. Start with setLastActivity(). This basically involves setting lastActivity to the current time, then running popup().
var idleCounter =
{
  lastActivity: null,
  msToPopup: 5,
  setLastActivity: function()
  {
    this.lastActivity = new Date();
    this.popup();
  },
  observeLastActivity: function()
  {
    if (!this.lastActivity) this.setLastActivity();
    this.popup();
  },
  startTimer: function()
  {
    setInterval(
      () => 
      {
        this.observeLastActivity(); 
     }, 
     5000
    );
  }
};


Now for the popup() method. Define d as the current time. Then use the getTime() method on d and lastActivity to get the number of milliseconds since the first day of 1970, for each timestamp, and subtract to get diff. Of course d will always be greater than lastActivity, even if by a couple milliseconds.
var idleCounter =
{
  lastActivity: null,
  msToPopup: 5,
  popupOpen: false,
  setLastActivity: function()
  {
    this.lastActivity = new Date();
    this.popup();
  },
  observeLastActivity: function()
  {
    if (!this.lastActivity) this.setLastActivity();
    this.popup();
  },
  startTimer: function()
  {
    setInterval(
      () => 
      {
        this.observeLastActivity(); 
     }, 
     5000
    );
  }
  popup: function()
  {
    var d = new Date();
    var diff = d.getTime() - this.lastActivity.getTime();
  }
};


Then divide diff (which is in milliseconds) by 1000 to get the number of seconds. And create a conditional to check if diff is now greater or equal to msToPopup.
popup: function()
{
  var d = new Date();
  var diff = d.getTime() - this.lastActivity.getTime();
  diff = diff / 1000;

  if (diff >= this.msToPopup)
  {

  }
  else
  {

  }

}


Define overlay as the modal, empty as the empty div and burnable as the burnable div. This is where it gets exciting.
popup: function()
{
  var d = new Date();
  var diff = d.getTime() - this.lastActivity.getTime();
  diff = diff / 1000;

  var overlay = document.getElementById("overlay");
  var empty = document.getElementById("empty");
  var burnable = document.getElementById("burnable");


  if (diff >= this.msToPopup)
  {

  }
  else
  {

  }
}


Now if diff is greater or equal to msToPopup, we want to display the modal by setting the display property of its style object to block. By default, we will set empty's height to 50 pixels and burnable's height to 250 pixels. If not, we hide overlay.
popup: function()
{
  var d = new Date();
  var diff = d.getTime() - this.lastActivity.getTime();
  diff = diff / 1000;

  var overlay = document.getElementById("overlay");
  var empty = document.getElementById("empty");
  var burnable = document.getElementById("burnable");

  if (diff >= this.msToPopup)
  {
    overlay.style.display = "block";
    empty.style.height = "50px";
    burnable.style.height = "250px";

  }
  else
  {
    overlay.style.display = "none";
  }
}


Here's the fun part. If diff is greater or equal to twice msToPopup, set empty's height to 80 pixels and burnable's height to 220 pixels. It will still add up to 300 pixels. The effect is that if more idle time has passed, empty will be taller and burnable will be shorter.
popup: function()
{
  var d = new Date();
  var diff = d.getTime() - this.lastActivity.getTime();
  diff = diff / 1000;

  var overlay = document.getElementById("overlay");
  var empty = document.getElementById("empty");
  var burnable = document.getElementById("burnable");

  if (diff >= this.msToPopup)
  {
    overlay.style.display = "block"; 
    empty.style.height = "50px";
    burnable.style.height = "250px";

    if (diff >= (this.msToPopup * 2))
    {
       empty.style.height = "80px";
       burnable.style.height = "220px";
    }
  }
  else
  {
    overlay.style.display = "none";
  }
}


And so on, and so forth. I've set a few cases here and you should feel free to add more.
popup: function()
{
  var d = new Date();
  var diff = d.getTime() - this.lastActivity.getTime();
  diff = diff / 1000;

  var overlay = document.getElementById("overlay");
  var empty = document.getElementById("empty");
  var burnable = document.getElementById("burnable");

  if (diff >= this.msToPopup)
  {
    overlay.style.display = "block";
    empty.style.height = "50px";
    burnable.style.height = "250px";

    if (diff >= (this.msToPopup * 2))
    {
       empty.style.height = "80px";
       burnable.style.height = "220px";
    }

    if (diff >= (this.msToPopup * 3))
    {
       empty.style.height = "100px";
       burnable.style.height = "200px";
    }

    if (diff >= (this.msToPopup * 5))
    {
       empty.style.height = "200px";
       burnable.style.height = "100px";
    }

    if (diff >= (this.msToPopup * 10))
    {
       empty.style.height = "250px";
      burnable.style.height = "50px";
    }

  }
  else
  {
    overlay.style.display = "none";
  }
}


And while we're at it, disable the red outline.
div { outline: 0px solid red; }


When you first refresh the browser, there should be no modal because the popup() method detects that 5 seconds of inactivity have not passed, so the modal remains invisible. Wait for 5 seconds, and it should come up!


At 10 seconds, the cigarette grows shorter.


At 15 seconds...


At 25 seconds...


At 50 seconds...


For the final touch, add these two lines. This ensures that if you move the mouse or press a keyboard button, setLastActivity() gets run and will result in the modal disappearing until another 5 seconds of inactivity passes.
window.onload = () =>
{
  idleCounter.startTimer();

  document.body.addEventListener("keypress", ()=> { idleCounter.setLastActivity(); });
  document.body.addEventListener("mousemove", ()=> { idleCounter.setLastActivity(); });

};


Well done!

We just implemented a browser screen saver. Cool, right?!

Don't be idle now!
T___T

No comments:

Post a Comment