Age Calculator Project

July 12, 2020 | ~12 Minute Read

Motivation

I watched a time video a while back and it really struck me. The way they explained the amount of time we have and how we use it resonated with me. I have also been watching a Netflix series lately that deals with time, Dark.

Both of these along with the current search for a programming / web development project led me to come up with an idea of representing our age in a way that provides better perspective of how much time we actually have.

The HTML

I started with a simple HTML file, only the necessary items on the page. I did add a few ids to the HTML for the Javascript of the page. This is what I came up with:

<!DOCTYPE HTML>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <link rel="stylesheet" href="css/style.css">
        <link rel="icon" href="/favicon.ico">
        <title>Age Calculator</title>
    </head>
    <body>
        <header>
            <h1>Age Calculator</h1>
        </header>
        <main>
            <h2>Select your Birthdate</h2>
            <form id="birthdayForm">
                <label for="birthday">Birthday</label>
                <input id="birthdate" type="date" name="birthday">
                <input type="submit" value="Calculate">
            </form>
        </main>
        <summary id="timeCurrent">
            <h3></h3>
        </summary>
        <section>
            <p id="weeks"></p>
            <p id="days"></p>
            <p id="hours"></p>
        </section>
        <summary id="timeLeft">
            <h3></h3>
        </summary>
        <article>
            <p id="weeksLeft"></p>
            <p id="daysLeft"></p>
            <p id="hoursLeft"></p>
        </article>
        <aside>
            <blockquote>
            </blockquote>
        </aside>
        <script src="js/main.js"></script>
    </body>
</html>

The CSS

I used the core Basic.css for the styling of the page with a few additions for the Grid layout. The Grid layout looks like the following:

/* Grid Layout */
body {
    display:                                grid;
    grid-template-columns:                  1fr 50% 1fr;
    justify-items:                          center;
}
header {
    grid-column:                            2;
    grid-row:                               1;
}
main {
    grid-column:                            2;
    grid-row:                               2;
}   
#timeCurrent {
    grid-column:                            2;
    grid-row:                               3;
}   
section {
    grid-column:                            2;
    grid-row:                               4;
}
#timeLeft {
    grid-column:                            2;
    grid-row:                               5;
}
article {
    grid-column:                            2;
    grid-row:                               6;
}
aside {
    grid-column:                            2;
    grid-row:                               7;
}   

This is what is left of the original Basic.css style.css file for this project:

/* Basic.css  */
* {box-sizing: border-box} 

:root{
    --sans:                                 1em/1.6 system-ui, -apple-system, Blin
kMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Droid Sans, Helvetica
 Neue, Fira Sans, sans-serif;
    --mono:                                 SFMono-Regular, Consolas, 'Liberation 
Mono', Menlo, Courier, 'Courier New', monospace;
    --c1:                                   #0074d9;
    --c2:                                   #eee;
    --c3:                                   #fff;
    --c4:                                   #000;
    --c5:                                   #fff;
    --m1:                                    8px;
    --rc:                                    8px;
}

@media (prefers-color-scheme: dark) {
    :root {
    --c2:                                   #333;
    --c3:                                   #1e1f20;
    --c4:                                   #fff;
    }
}

html {  
    -ms-text-size-adjust:                   100%;
    -webkit-text-size-adjust:               100%;

}

/* General settings */
body {                                                                            
    margin:                                 0;                                    
    font:                                   var(--sans);                          
    font-weight:                            400;                                  
    font-style:                             normal;                               
    text-rendering:                         optimizeLegibility;                   
    -webkit-font-smoothing:                 antialiased;                          
    background-color:                       var(--c3);                            
    color:                                  var(--c4);                            
}                                                                                 

blockquote {                                                                      
    border-left:                            5px solid var(--c2);                  
    padding:                                1em 1.5em;                            
    margin:                                 0;                                    
}                                                                                 

/* Headlines */                                                                   
h1,h2,h3,h4,h5,h6 {                                                               
    margin:                                 0.6em 0;                              
    font-weight:                            normal;                               
}                                                                                 

h1 {                                                                              
    font-size:                              2.625em;                              
    line-height:                            1.2;                                  
    margin-top:                             1.5em;                                
}                                                                                 

h2 {                                                                              
    font-size:                              1.625em;                              
    line-height:                            1.2;                                  
}                                                                                 

h3 {                                                                              
    font-size:                              1.3125em;                             
    line-height:                            1.24;                                 
}                                                                                 

h4 {                                                                              
    font-size:                              1.1875em;                             
    line-height:                            1.23;                                 
}                                                                                 

h5,h6 {                                                                           
    font-size:                              1em;                                  
    font-weight:                            bold;                                 
}                                                                                 

/* Rounded Corners*/                                                              
pre,code,input,select,textarea,button,img {                                       
    border-radius:                          var(--rc);                            
}                                                                                 

/* Forms */                                                                       
input, select, textarea {                                                         
    font-size:                              1em;                                  
    color:                                  var(--c4);                            
    background:                             var(--c2);                            
    border:                                 0;                                    
    padding:                                0.6em;                                
}                                                                                 
button, input[type=submit], input[type=reset], input[type="button"] {             
    -webkit-appearance:                     none;                                 
    font-size:                              1em;                                  
    display:                                inline-block;                         
    color:                                  var(--c5);                            
    background:                             var(--c1);                            
    border:                                 0;                                    
    margin:                                 4px;                                  
    padding:                                0.6em;                                
    cursor:                                 pointer;                              
    text-align:                             center;                               
}                                                                                 

button:hover, button:focus, input:hover, textarea:hover, select:hover {           
    opacity:                                0.8;                                  
}                                                                                 

I then added the responsive support to the page, this section is very similar to what I did for the blog.

/* Tablet Sized Screens */                                                        
/* Grid Layout */                                                                 
@media (max-width: 1200px) {                                                      
    body {                                                                        
        grid-template-columns:              1fr 70% 1fr;                          
    }                                                                             
}                                                                                 

/* Mobile Sized Screens */                                                        
/* Grid Layout */                                                                 
@media (max-width: 599px) {                                                       
    body {                                                                        
        grid-template-columns:              1fr 95% 1fr;                          
    }                                                                             
}                                                                                                                                                                   

With that we have the CSS covered for this small project.

The Javascript

This is the part that I really wanted to get to practice while doing this project. I had never dealt with the Date object from Javascript. This was the perfect time to get a bit more familiar with some of the methods that this object has.

When I initially started the project I thought that I would use something like a timer, I actually grabbed the sample code from W3’s How-to. But I later realized that the way the code is set up on the sample is for counting backwards, which is a little different from what I wanted to accomplish.

I then started by creating the main.js file by making the DOM available to the script:

// Define the birthdayForm constant from the html form labeled birthdayForm
const birthdayForm = document.getElementById("birthdayForm");

// Define the birthdate constant from the html date input labeled birthdate
const birthdate = document.getElementById("birthdate");

Once we had access to the DOM elements I created a single function that would be triggered upon click of the form submit button.

The first thing I did was to add the preventDefault method for the event constructor so that the form submission will not reload the page:

// Prevent the page from reloading on submit
e.preventDefault

First we need to know the current time, so we use the Date object for the first time and it’s getTime method to get the current date upon the form submission:

// Define the currentDate constant with today's date in epoch time format
const currentDate = new Date().getTime();

At that point I’ll use the same method to get the epoch time for the date the user selects on the UI like so:

// Define the inputDate variable with the epoch time from the birth date entered by the user
let inputDate = new Date(birthdate).getTime();

We can then subtract the current time from the time the user choose. This assumes that the current time is greater than the time the user selects. I may add a mechanism to prevent the user from selecting a date in the future, however for now I haven’t implemented it.

// Define the timeAge variable with the remainder from the birthdate entered by the user
let timeAge = currentDate - inputDate;

From that difference in epoch time I converted it to a value that I could use for the rest of the math in the calculation, days.

// Define the days variable from the conversion of timeAge's epochs time to 24 hour intervals
let days = Math.floor(timeAge / (1000 * 60 * 60 * 24));

From there it was just defining the weeks and hours based on the days variable:

// Define the weeks variable from the days variable value divided by 7
let weeks = Math.round(days / 7);

// Define the hours variable from the days variable value multiplied by 24
let hours = Math.round(days * 24);

With that little bit of math done, we now have the necessary data to update the DOM of the HTML document. I wrote the header and three paragraphs in the HTML but left them empty so that they could be filled via Javascript.

First we’ll add the header content by using the getElementsByTagName method from the document object and the textContent property from the node interface, also from the document object, so that we can have access to all h3 elements in the page which are only two in our case, so we access the first one like so:

//Update HTML elements with the heading for the current age details
document.getElementsByTagName("h3")[0].textContent = "Current Age";

Next I update the three paragraphs with the text I thought appropriate and calculated data. For this I chose to use the getElementById method from the document object. I could have done the same as before, but I want to practice with as many methods as possible. One thing I noticed is that I was getting unformatted numbers as results for the data so I used the toLocalString method from the number object in order to have the formatting setup up correctly. At the end this is how it looks:

// Update HTML elements with the calculated time values from the birthdate selected
document.getElementById("weeks").textContent = weeks.toLocalString() + " weeks of age";
document.getElementById("days").textContent = days.toLocaleString() + " days of age"
document.getElementById("hours").textContent = hours.toLocaleString() + " hours of age"

At this point I was pretty much done with the project, but during the testing I felt like it wasn’t complete. I decided to do something similar to what was done in the initial video I mentioned earlier. They showed how much time we have and then they bring awareness to the thought of how you may want to spend it, so I thought I would do something similar.

I decided to add a section where you would see how much time you have until you reach the age of 90 years old in the same units of measurement as before, weeks, days and hours.

The first thing I had to do was to define what 90 years of age was in days:

// Define the ageNinety constant
const ageNinety = 32850;

Next we subtract the current age in days we had earlier from the ageNinety constant:

// Define the timeLeft variable with the remainder of the ageNinety and days variables
let timeLeft = ageNinety - days;

Now that we have the number of days until the age of 90 is reached we do the same simple math we did before but with the new values:

// Define the weeks variable fro the days variable value divided by 7
let weeksLeft = Math.round(timeLeft / 7);

// Define the hours variable from th edays variable value multiplied by 24
let hoursLeft = timeLeft * 24;

The next step is to update the DOM so that the user may see the results, we do that in the very same way we did before:

// Update HTML elements with the heading for the time left to reach 90 years of age
document.getElementsByTagName("h3")[1].textContent = "Time until 90 years of age";

// Update HTML elements with the calculated time values to reach 90 years of age
document.getElementById("weeksLeft").textContent = weeksLeft.toLocaleString() + " weeks to reach 90 years of age";
document.getElementById("daysLeft").textContent = daysLeft.toLocaleString() + " days to reach 90 years of age";
document.getElementById("hoursLeft").textContent = hoursLeft.toLocaleString() + " days to reach 90 years of age";

With that done, the functionality was complete, but I decided to add a quote from the Buddha related to time and the perception we sometimes have that it’s unlimited. This was the cherry on top that, to me, provokes thought and hopefully inspires the user to make wise use of their time:

// Update HTML elements with a quote
document.getElementsByTagName("blockquote")[0].textContent = '"The trouble is, you think you have time" - Buddha';

The only special note to add here would be that since I’m adding a quote with the " characters in it and I’m using Javascript to add it I used a single quote ' to delimit the text to be added by the textContent property so the two wouldn’t clash.

Conclusion

This is my very small attempt to create a tool that will help keep me motivated whenever the programming path, or any other objective I have at the time, gets though for any reason. I hope for it to serve as a reminder to try and keep a proper level of urgency and get things done.

I hope you enjoy the application as well!