Javascript Time Tracker with Progress Bar

Time Tracker

Time Tracker

Time tracker tools help you understand how much time you spend on each task, spend your timing wisely, and increase the productivity. This article shows you how to create a simple Javascript time tracker using setInterval function. The demo presents single-tracking and multi-tracking with CSS progress bars.

View Demo

Usage:

  1. Build CSS progress bars.
  2. Create buttons, and HTML5 input form to validate the user typing.
  3. Integrate with JavaScript timing functions

To implement this easy time tracker, we need to understand how to create a simple progress bar.

#myProgress {
  width: 100%;
  height: 10px;
  position: relative;
  background-color: #ddd;
}

#single_spend_bar {
  background-color: #4CAF50;
  width: 0;
  height: 10px;
  position: absolute;
}

As above CSS code, we create a gray (#ddd) progress bar as background and a green (#4caf50) bar for time spending, the default width set to 0, so if we increase the percentage of width, the green bar will cover the gray bar to be a progress bar.

Then, we have to create a HTML file with multiple inputs and divs containers.

<p>Set you total time (sec):</p>
<!-- using HTML5 form to validate the user typing  -->
<form id="myform">
  <input type="number" id="mytotaltime" step="1" min="1" max="86400" required></input>
  <input type="submit" id="firstbutton" ></input>
  <!-- not showing this button as default -->
  <button id="resetbutton" style="display: none;">reset</button>
</form>
<span style="font-size: 10px;">1 min = 60 sec, 1 hour = 3600 sec, 1 day = 86400 sec</span> 

<h2>single-tracking </h2>

<div id="singletask">
<!-- not showing this button as default -->
<input type='button' id='task1' value='Pause' style="display: none"></input></p>
Time Spend(sec): <span id='single_spend_output'>0</span>
<div id='myProgress'><div id='single_spend_bar'></div></div></p>
Stop Time(sec): <span id='single_relax_output'>0</span>
<div id='myProgress'><div id='single_stop_bar'></div></div></p>
Real Time Spend(sec): <span id='single_real_output'>0</span>
<div id='myProgress'><div id='single_real_bar'></div></div>
</div>


<h2>multi-tracking</h2>
<div id="multitask">
<!-- not showing these buttons as default -->
<input type='button' class='selected' value='First' style="display: none"></input> <input type='button' value='Second' style="display: none"> </input><input type='button' value='Third' style="display: none"> </input><input type='button' value='Fourth' style="display: none"></input></p>
First Time Spend(sec): <span id='multi_first_output'>0</span>
<div id='myProgress'><div id='multi_first_bar'></div></div></p>
Secone Time Spend(sec): <span id='multi_second_output'>0</span>
<div id='myProgress'><div id='multi_second_bar'></div></div></p>
Third Time Spend(sec): <span id='multi_third_output'>0</span>
<div id='myProgress'><div id='multi_third_bar'></div></div></p>
Fourth Time Spend(sec): <span id='multi_fourth_output'>0</span>
<div id='myProgress'><div id='multi_fourth_bar'></div></div></p>
Real Time Spend(sec): <span id='multi_real_output'>0</span>
<div id='myProgress'><div id='multi_real_bar'></div></div>
</div>

In here, we simply use HTML5 form input to validate the user typing, must be between 1 – 86400, and be a round number.

<input type="number" id="mytotaltime" step="1" min="1" max="86400" required></input>

And we put make our progress bar code like:

<div id='myProgress'><div id='single_spend_bar'></div></div>

Also, we create some span elements like below, and set them value display as 0.

<span id='single_spend_output'>0</span>

Finally, we hide some buttons, because we do not want them display before user typing.

<!-- not showing this button as default -->
<input type='button' id='task1' value='Pause' style="display: none"></input>

Now we need to integrate with JavaScript timing functions.

function SingleTracking(){
var elem = document.getElementById("single_spend_bar");   
var elem2 = document.getElementById("single_stop_bar");   
var elem3 = document.getElementById("single_real_bar");   

var width = 0;
var isPaused = false;
var timecount = 0;
var stopcount = 0;
var totalcount = 0;

}

We get all three elements (task spending bar, stop time spending bar, and real time spending bar), and set them count as 0, so we can have time loop after.

We set a flag condition with TRUE and FALSE. because we need a button to temporarily pause the time at anytime.

$("#task1").click(function() {
    if ($(this).val() == "Play") {
      $(this).val('Pause');
	  isPaused = false;    
   	}
   else {
      $(this).val('Play');
          isPaused = true;
   }
});

Create a click function. If the button value is Play, change it to Pause. Else ,change it value to Play. In order to toggle the button with different flag conditions.

var time = setInterval(function() {

if(!isPaused) {
++timecount;
$('#single_spend_output').text(timecount);
elem.style.width = timecount*100/totaltime + '%'; 
}

if(isPaused) {
++stopcount;
$('#single_relax_output').text(stopcount);
elem2.style.width = stopcount*100/totaltime + '%'; 
}

++totalcount;
$('#single_real_output').text(totalcount);
elem3.style.width = totalcount*100/totaltime + '%'; 

if (totalcount == totaltime) {
clearInterval(time);
} 

}, 1000);

In here, we control three progress bar, set an Interval function to the JavaScript programming to run forever and forever. We also consider two conditions that if the user pause or play a button, then run different progress bars.

However, whether the user click the button or not, the total time should keep tracking on the third progress bar. Also, when the total time is reach 100%, stop the Interval timing function no matter the first progress bar and second bar haven’t finished.

Your final code should look like this:

index.html

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<!-- for mobile version -->
	<meta name="viewport" content="initial-scale=1.0">
	<title>Time Tracker</title>
	<!-- bootstrap min.css CDN -->
	<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
	<!-- jQuery CDN -->
	<script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="
  crossorigin="anonymous"></script>
	<!-- bootstrap min.js CDN -->
  	<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<style>

body {
	padding: 15px;
}

#myProgress {
  width: 100%;
  height: 10px;
  position: relative;
  background-color: #ddd;
}

/*green color bar style*/
#single_spend_bar,#single_stop_bar,#multi_first_bar,#multi_second_bar,#multi_third_bar,#multi_fourth_bar {
  background-color: #4CAF50;
  width: 0;
  height: 10px;
  position: absolute;
}
/*blue color bar style*/
#single_real_bar,#multi_real_bar {
  background-color: #286090;
  width: 0;
  height: 10px;
  position: absolute;
}

</style>

</head>
<body>

<p>Set you total time (sec):</p>
<!-- using HTML5 form to validate the user typing  -->
<form id="myform">
  <input type="number" id="mytotaltime" step="1" min="1" max="86400" required></input>
  <input type="submit" id="firstbutton" ></input>
  <!-- not showing this button as default -->
  <button id="resetbutton" style="display: none;">reset</button>
</form>
<span style="font-size: 10px;">1 min = 60 sec, 1 hour = 3600 sec, 1 day = 86400 sec</span> 

<h2>single-tracking </h2>

<div id="singletask">
<!-- not showing this button as default -->
<input type='button' id='task1' value='Pause' style="display: none"></input></p>
Time Spend(sec): <span id='single_spend_output'>0</span>
<div id='myProgress'><div id='single_spend_bar'></div></div></p>
Stop Time(sec): <span id='single_relax_output'>0</span>
<div id='myProgress'><div id='single_stop_bar'></div></div></p>
Real Time Spend(sec): <span id='single_real_output'>0</span>
<div id='myProgress'><div id='single_real_bar'></div></div>
</div>


<h2>multi-tracking</h2>
<div id="multitask">
<!-- not showing these buttons as default -->
<input type='button' class='selected' value='First' style="display: none"></input> <input type='button' value='Second' style="display: none"> </input><input type='button' value='Third' style="display: none"> </input><input type='button' value='Fourth' style="display: none"></input></p>
First Time Spend(sec): <span id='multi_first_output'>0</span>
<div id='myProgress'><div id='multi_first_bar'></div></div></p>
Secone Time Spend(sec): <span id='multi_second_output'>0</span>
<div id='myProgress'><div id='multi_second_bar'></div></div></p>
Third Time Spend(sec): <span id='multi_third_output'>0</span>
<div id='myProgress'><div id='multi_third_bar'></div></div></p>
Fourth Time Spend(sec): <span id='multi_fourth_output'>0</span>
<div id='myProgress'><div id='multi_fourth_bar'></div></div></p>
Real Time Spend(sec): <span id='multi_real_output'>0</span>
<div id='myProgress'><div id='multi_real_bar'></div></div>
</div>


<script type="text/javascript">

// when clicking this button, refresh the whole page.
$("#resetbutton").click(function () { 
      location.reload();
});

$("#myform").submit(function(e) {
   
// prevent page refresh after clicking submit.
e.preventDefault();

// hide the submit button.
$("#firstbutton").hide();
// show the reset button.
$('#resetbutton').show();
// make total time input unclickable.
$("#mytotaltime").prop('disabled', true);

// Get the total time input value, and store it as variable.
var totaltime = $('#mytotaltime').val();
// console.log(totaltime);

// call two functions right now.
SingleTracking();
MultiTracking(); 


// single-tracking function start
function SingleTracking(){

// show the Pause/Play button 
$("#task1").show();

// Get all three elements
var elem = document.getElementById("single_spend_bar");   
var elem2 = document.getElementById("single_stop_bar");   
var elem3 = document.getElementById("single_real_bar");   

// set width default as 0
var width = 0;
// set a default flag 
var isPaused = false;
var timecount = 0;
var stopcount = 0;
var totalcount = 0;

// click function
$("#task1").click(function() {

   
    // if the button value is Play, change it to Pause
    if ($(this).val() == "Play") {
      $(this).val('Pause');

	  isPaused = false;    
   	}
   else {
   	// else change it value to Play
      $(this).val('Play');

      isPaused = true;
   }
});


var time = setInterval(function() {

// if is play, time spend is running...
if(!isPaused) {
++timecount;
$('#single_spend_output').text(timecount);
elem.style.width = timecount*100/totaltime + '%'; 
// console.log(timecount+"-"+totaltime);

}

// if is pause, stop time is running...
if(isPaused) {
++stopcount;
$('#single_relax_output').text(stopcount);

elem2.style.width = stopcount*100/totaltime + '%'; 
// console.log(timecount+"-"+totaltime);
}

// whether play or pause, real time spend is running....
++totalcount;
$('#single_real_output').text(totalcount);
elem3.style.width = totalcount*100/totaltime + '%'; 

// When realtime run to 100%, stop the counter
if (totalcount == totaltime) {
clearInterval(time);
} 

// 1000 = 1 second 
}, 1000);

}

// multi-tracking function start
function MultiTracking(){

// Get all five elements
var elems1 = document.getElementById("multi_first_bar");  
var elems2 = document.getElementById("multi_second_bar");  
var elems3 = document.getElementById("multi_third_bar");  
var elems4 = document.getElementById("multi_fourth_bar");  
var elems = document.getElementById("multi_real_bar");   
var width = 0;

var multitask = $('#multitask > input');
var timearray = [0, 0, 0, 0];
// show four buttons
multitask.show();
multitask.click(function() {
    $(this).addClass('selected').siblings().removeClass('selected');
});

var grouptime = setInterval(function() {
    var idx = multitask.filter('.selected').index();
    ++timearray[idx];
    
    elems1.style.width = timearray[0]*100/totaltime + '%';
    $('#multi_first_output').text(timearray[0]);
    elems2.style.width = timearray[1]*100/totaltime + '%';
    $('#multi_second_output').text(timearray[1]);
    elems3.style.width = timearray[2]*100/totaltime + '%';
    $('#multi_third_output').text(timearray[2]);
    elems4.style.width = timearray[3]*100/totaltime + '%';
	$('#multi_fourth_output').text(timearray[3]);

    var sum = timearray.reduce(function(a, b) { return a + b; }, 0);
    elems.style.width = sum*100/totaltime + '%';
    // console.log(sum+"-"+totaltime);
    $('#multi_real_output').text(sum);

    if (sum == totaltime) {
	clearInterval(grouptime);
	} 

}, 1000);

}


});
// clicking event end
</script>
   </body>
</html>

Easy right? Now you can combine these data to Chart.js to do data analyzing and visualization.

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *