Pomodoro Hourglass

In this example below you will see how to do a Pomodoro Hourglass with some HTML / CSS and Javascript

This is my Pomodoro Clock, I am the one yelling !https://www.freecodecamp.com/challenges/build-a-pomodoro-clock

Thumbnail
This awesome code was written by captnstarburst, you can see more from this user in the personal repository.
You can find the original code on Codepen.io
Copyright captnstarburst ©

Technologies

  • HTML
  • CSS
  • JavaScript
<!DOCTYPE html>
<html lang="en" >

<head>
  <meta charset="UTF-8">
  <title>Pomodoro Hourglass</title>
  <link href="https://fonts.googleapis.com/css?family=Leckerli+One" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Lobster" rel="stylesheet">


  
  <link rel='stylesheet prefetch' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css'>

      <link rel="stylesheet" href="css/style.css">

  
</head>

<body>

  
<div class="container-fluid background">
  
  <div class="topPusher"></div>

  <div class="row title">
    <div class="col-xs-12">
      <h1 class="text-center"> Pomodoro Clock </h1>
      
      <div class="topPusher"></div>
      
      <h4 class="text-center"> I want to work for  
        <input type = "number" min = "1" max ="999" value="45" id="work"> minutes followed by a 
        <input type = "number" min = "1" max ="999" value = "15" id="break"> minute break.         </h4>
    </div>
  </div>  
  
  <div class="topPusher"></div>

  <div class="row buttons">
    <div class="col-xs-12">
      <button class="btn btn-warning" id="start">Start</button>
      <button class="btn btn-primary" id ="stop">Stop</button>
      <button class="btn btn-danger" id="reset">Reset</button>
   </div>
  </div>  
  
  <div class="topPusher"></div>
  <h3 class="text-center" id="state"> Stopped </h3>
  
  
  <div class="row timer">
   <div class="col-xs-12">
    
         <div class="clock" ><h1 class="text-center" id="clock"> 00:00</h1></div>
      
          
    </div>  
  </div>  

  <div class="topPusher"></div>
  
  <div class="row hourglass" id="hourglass">
    <div class="col-xs-12">
      <div class="top"></div>
    
    <div class="topBubble">
      <div class="drainer" id="drainer"></div>
      <div class="topSand" id="topSand"></div>
    </div>
    
     <div class="connector" id ="connector"> </div>
    
     <div class="bottomBubble">
       <div class="filler" id="filler"></div>
       <div class="bottomSand" id="bottomSand"></div>
      
     </div>
    <div class="bottom"></div>
    </div>  
  </div>  
  
  
</div>

<div class="text-center footer"> Coded by Conor Hinchee </div>
  <script src='https://code.jquery.com/jquery-2.2.4.min.js'></script>

  

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




</body>

</html>

/*Downloaded from https://www.codeseek.co/captnstarburst/pomodoro-hourglass-xOZmyX */
.background {
  background-color: #D99A6C;
  min-height: 800px;
}

.buttons {
  text-align: center;
}

.btn {
  border: solid;
}

.timer {
  background-color: white;
  height: 60px;
  width: 200px;
  border-radius: 20px;
  margin: 0px auto;
}

.topPusher {
  padding-bottom: 45px;
}

.footer {
  background-color: #56887D;
  margin: 0 auto;
}

.hourglass {
  height: 500px;
  background: #D99A6C;
  -moz-border-radius: 50px;
  -webkit-border-radius: 50px;
  border-radius: 50px;
  margin: 0 auto;
  padding-top: 2%;
  text-align: center;
}


.top {
  width: 240px;
  height: 65px;
  background: #87421F;
  -moz-border-radius: 100px / 50px;
  -webkit-border-radius: 100px / 50px;
  border-radius: 100px / 50px;
  border: #87421F solid;
  box-shadow: 1px 0 0 black, 0 -10px 0 black;
  margin: 25px auto;
}

.bottom {
  width: 240px;
  height: 65px;
  background: #87421F;
  -moz-border-radius: 100px / 50px;
  -webkit-border-radius: 100px / 50px;
  border-radius: 100px / 50px;
  border-style: solid;
  box-shadow: 0 10px 0 black;
  margin: 37px auto;
}

.topBubble {
  width: 186px;
  height: 157px;
  background-color: white;
  border-top-left-radius: 12px;
  border-top-right-radius: 12px;
  border-bottom-left-radius: 97px;
  border-bottom-right-radius: 97px;
  margin: -70px auto;
  box-shadow: inset 0 0 15px 2px rgba(0, 0, 0, .2), 0 0 2px 2px rgba(255, 255, 255, .03);
  position: relative;
}

.bottomBubble {
  width: 186px;
  height: 157px;
  background-color: white;
  border-top-left-radius: 97px;
  border-top-right-radius: 97px;
  border-bottom-left-radius: 12px;
  border-bottom-right-radius: 12px;
  border-left: 3px solid #BCEAFF;
  border-right: 1px solid #BCEAFF;
  margin: -80px auto;
  position: relative;
}

.connector {
  width: 40px;
  height: 40px;
  background: white;
  border-radius: 50px;
  margin: 65px auto;
  box-shadow: inset 0 0 15px 2px rgba(0, 0, 0, .2), 0 0 2px 2px rgba(255, 255, 255, .03);
}

.topSand {
  background-color: grey;
  background-image: url('http://oi67.tinypic.com/4k9ute.jpg');
  background-size: 50px;
  background-repeat: repeat;
  image-rendering: pixelated;
  height: 98%;
  width: 99%;
  border-top-left-radius: 12px;
  border-top-right-radius: 12px;
  border-bottom-left-radius: 100px;
  border-bottom-right-radius: 100px;
  margin: 0 auto;
}

.bottomSand {
  background-color: grey;
  background-image: url('http://oi67.tinypic.com/4k9ute.jpg');
  background-size: 100px;
  background-repeat: repeat;
  image-rendering: pixelated;
  height: 99%;
  width: 99%;
  border-top-left-radius: 100px;
  border-top-right-radius: 100px;
  border-bottom-left-radius: 12px;
  border-bottom-right-radius: 12px;
}

.rotated {
  -webkit-transform: rotate(180deg);
  /* Chrome, Safari 3.1+ */
  -moz-transform: rotate(180deg);
  /* Firefox 3.5-15 */
  -ms-transform: rotate(180deg);
  /* IE 9 */
  -o-transform: rotate(180deg);
  /* Opera 10.50-12.00 */
  transform: rotate(180deg);
  /* Firefox 16+, IE 10+, Opera 12.10+ */
}

.filler {
  margin: 0 auto;
  width: 10px;
  height: 0;
  background-size: 100px;
  background-repeat: repeat;
  image-rendering: pixelated;
}

.drainer {
  width: 186px;
  height: 0;
}

.connector {
  background-repeat: repeat;
  image-rendering: pixelated;
  background-size: 100px;
}

.clock {
  display: block;
  text-align: center;
}
h1{
  font-family: 'Leckerli One', cursive;
}
h4{
  font-family: 'Leckerli One', cursive;
}
h3{
  font-family: 'Lobster', cursive;
}
input{
  width: 60px;
   text-align: center;
  border-radius: 40px;
  border: solid''
}

/*Downloaded from https://www.codeseek.co/captnstarburst/pomodoro-hourglass-xOZmyX */
$(document).ready(function() {

  $("#topSand").hide();
  var timeArr;
  var timerInterval;
  var state = "initial";
  var lastState;
  var count = 0;
  var pps = 0;
  var moveSandCount = 0;
  var height = 0;

  $("#start").on("click", function() {

    if (state === "initial" || state ==="Stopped") {
      
      if(state === "initial"){
        timeArr = getTimes();
        setTimer(timeArr[0]);
        startDrain();
        playWorkSound();
      }
      
      state = "Working";
      changeState(state);
      

      timerInterval = setInterval(function() {
        var arr = getCurrent();

        count++;

        if (arr[0] === "00" && arr[1] === "00") {
          //$.playSound("https://res.cloudinary.com/dgogbqs6e/video/upload/v1468781999/164090__hypocore__buzzer_ugk6nc");
          
          if (state === "Working") {
 
            state = "Breaking";
            count = 0;
            moveSandCount = 0;
            setTimer(timeArr[1]);
            changeState(state);
            startScreen();
            startDrain();
            playBreakSound();            
          } else {
           
            alert("Get Back To Work!");
            state = "Working";
            count = 0;
            moveSandCount = 0;
            setTimer(timeArr[0]);
            changeState(state);
            startScreen();
            startDrain();
            playWorkSound();
          }
        } else {
          if (state === "Working") {
            pps = ppsMath(timeArr[0]);
            if (pps >= 1) {
              height = Math.ceil(pps * count);
              moveSand(height);
            } else {
              if (sandInterval(pps, count)) {
                moveSandCount++;
                moveSand(moveSandCount);
              }
            }
          } else {
            pps = ppsMath(timeArr[1]);
            if (pps >= 1) {
              height = Math.ceil(pps * count);
              moveSand(height);
            } else {
              if (sandInterval(pps, count)) {
                moveSandCount++;
                moveSand(moveSandCount);
              }
            }
          }
          countDown(pps, count);
        }
      }, 1000);

    }
  });

  $("#stop").on("click", function() {
    clearInterval(timerInterval);
    lastState = state;
    state = "Stopped";
    changeState(state);
  });

  $("#reset").on("click", function(){
  clearInterval(timerInterval);
   state = "initial" ;
    changeState("Stopped");
    setTimer("00");
   document.getElementById("work").value = 45;
    document.getElementById("break").value = 15;
    startScreen();
  });
  
});

function getTimes() {
  return [$("#work").val(), $("#break").val()];
}

function startDrain() {
  $("#topSand").show();
  $("#bottomSand").css("height", "0%");
  $("#topSand").css("width", "99%");
  $("#connector").css("background-image", "url('http://oi67.tinypic.com/4k9ute.jpg')");
  $("#filler").css("background-image", "url('http://oi67.tinypic.com/4k9ute.jpg')");
}

function changeState(state) {
  $("#state").text(state);
}

function setTimer(minutes) {
  $("#clock").text(minutes + ":00");
}

function getCurrent() {
  var str = $("#clock").text();
  var arr = str.split(":");
  return arr;
}

function countDown() {

  var arr = getCurrent();
  var int;
  var toStr;
  var rtnStr;
  if (arr[1] !== "00") {
    int = parseInt(arr[1]) - 1;
    toStr = int.toString();
    if (toStr.length === 1) {
      toStr = "0" + toStr;
    }
    rtnStr = arr[0] + ":" + toStr;
  } else {
    int = parseInt(arr[0]) - 1;
    toStr = int.toString();
    if (toStr.length === 1) {
      toStr = "0" + toStr;
    }

    rtnStr = toStr + ":59";
  }

  changeText(rtnStr);
}

function changeText(str) {
  $("#clock").text(str);
}

function ppsMath(initialTime) {
  var seconds = parseInt(initialTime) * 60;
  var pps = 157 / seconds;
  return pps;
}

function sandInterval(pps, count) {

  var movement = Math.ceil(1 / pps);
  if (count % movement === 0) {
    return true;
  } else {
    return false;
  }
}

function moveSand(height) {
  var drain = height.toString() + "px";
  var fillInt = 157 - height;
  var fill = fillInt.toString() + "px";
  console.log(height);

  $("#drainer").css("height", drain);
  $("#bottomSand").css("height", drain);
  $("#filler").css("height", fill);
  $("#topSand").css("height", fill);
  $("#bottomSand").show();

  if (height >= 80) {
    $("#topSand").css("width", "90%");
  }
  if (height >= 90) {
    $("#topSand").css("width", "80%");
  }
  if (height >= 100) {
    $("#topSand").css("width", "70%");
  }

  if (height >= 120) {
    $("#topSand").css("width", "60%");
  }
  if (height >= 130) {
    $("#topSand").css("width", "50%");
  }

  if (height >= 140) {
    $("#topSand").css("width", "30%");
  }
}

function startScreen() {
  $("#drainer").css("height", "0px");
  $("#bottomSand").css("height", "99%");
  $("#filler").css("height", "0px");
  $("#topSand").css("height", "99%");
  $("#topSand").hide();
}

function playWorkSound(){
  // var audio = document.createElement('audio');
  // audio.style.display = "none";
  // audio.src = " http://conorhinchee.tech/getToWork.mp3";
  // audio.autoplay = true;
  // audio.onended = function(){
  //   audio.remove() //Remove when played.
  // };
  // document.body.appendChild(audio);
}

function playBreakSound(){
  // var audio = document.createElement('audio');
  // audio.style.display = "none";
  // audio.src = " http://conorhinchee.tech/takeABreak.mp3";
  // audio.autoplay = true;
  // audio.onended = function(){
  //   audio.remove() //Remove when played.
  // };
  // document.body.appendChild(audio);
}

Comments