Making a Calendar in Vanilla Javascript
Tags: javascript, beginners, webdev, tutorial
Published: 2019-04-16 19:11:07

---
title: Making a Calendar in Vanilla Javascript
published: true
description: Manipulate the HTML using the power of Vanilla Javascript
tags: #javascript #beginner #webdev #tutorial
---
Arguably, time is the best and worst built-in function in Javascript.  For my most recent project, I had the idea to make a bastardized Google calendars.  I naively figured that making a general, functional calendar would be straightforward and allow me plenty of time to build out my site. I **so** was wrong. 

<h3> Where to Start? </h3>
Pretty early on, with guidance from my instructor, I decided to hard code a month into the HTML. This allowed me to build out the general structure and style I wanted for my calendar. There was conflicting literature on whether using `<div>` or `<table>` would be better practice. I ultimately decided to go with a table. 

If you have ever taken the time to really study a month calendar, the structure is pretty simple. There is a header at the top, usually, that indicates the month and year. Below that are 7 columns outlining the individual days of the week. Finally, there is a maximum of 6 rows to populate the number of days for a given month. 

Below is a snapshot of my hardcoded HTML.

![Hard-coded HTML Calendar](https://i.imgur.com/vU5ethQ.jpg)

Again, this allowed me to mess with the CSS style sheet to render the overall look and feel I wanted for my calendar.

<h3> Harnessing the Power of Time </h3>
Now came the hard part. I needed to use the built-in time function to populate the accurate number of days in a given month and year. After doing some research, I learned that Javascript will return a number that corresponds to a months relative index in a year: i.e. January is 0, February is 1, etc.  This can be called using the `getMonth()` function built-in to Javascript.

Javascript also does the same thing with days of the week and starts with Sunday. That makes Sunday - 0, Monday - 1, etc. This is called using the `getDay()` function from Javascript.

So, the question became how do I use this two crucial pieces of information: 1. How do I figure out what day of the week is the start of the month? 2. How do I calculate how many days are in a month?

Answering the first questions was simple enough. [Javascript literature](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) helped outline the various options for built-in functions. Miraculously, `new Date(year, month)` is incredibly powerful and will automatically render the first day of a given year and month argument. Using the `.getDay()` function on this allowed me to get the day index for the start of the month.

![Start of Month Code](https://i.imgur.com/ZBTvzTd.jpg)

Next, I needed to get the number of days in a given month. Again, I used the all-powerful `new Date()` to get me started, and using some high school algebra, I reverse engineered a way to calculate the total days. The `new Date()` function can accept a large number of arguments, down to the millisecond. I did not need to get granular with my calendar, but thought I could use the month, year and day arguments. Given that the maximum number of days in any month is 31, putting in 32 days into `new Date()` would give me the relative date that would actually be in the next month. For example, July(index 6 of a year) has 31 days in a month. If I entered `new Date(2019, 6, 32)` into my console, I would expect the console to return August 1, 2019.
![July Snapshot of Console](https://i.imgur.com/NyFABME.jpg)

The `new Date()` function also has a `getDate()` function that will return the day number from a given date. Using this returned number, I subtracted this from 32 to get the accurate number of days in a given month. 

![End of Month Code](https://i.imgur.com/eDSgUJP.jpg)

To further prove my concept, I used February 2019 in my console. Passing in 2019 for year, 1 for month, and 32 for days, I should expect the above equation to return 28, as there were 28 days in February 2019.

![Feb Snapshot Console](https://i.imgur.com/AW2bhi7.jpg)

One hurdle down, now I had to use this data to populate and render my table.

<h3> Populating the Beast </h3>

After removing the hardcoded HTML data from my table, I needed to populate the *month* span and the *year* span with the currently rendered month and year. This was fairly straightforward as I left a majority of my HTML code in the header. After finding the individual span elements using `document.findElementById()`, I changed the `textContent` to the given *month* and *year*.

![Populating Month Year](https://i.imgur.com/fzJ0ZJR.jpg)

After grabbing the table element, again using `document.getElementById()`, I then needed to add some `for` loops to render my rows and columns. I also knew that I would need to print the actual day number on the calendar. For obvious reasons, I started the count at 1 and assigned this 1 to a usable variable called `renderNum`. (Note: This variable will be incremented up by one with each column loop. But I’ll get to that in a bit)

![Get The Variables](https://i.imgur.com/CGvy8GC.jpg)

Next, I generated the row `for` loop, as this was going to hold all the individual date tiles. (To be more proper, I will append my row `<tr>` with my table data `<td>` elements.) Since I knew that I would need at maximum 6 rows, I started my `for` loop at the traditional 0 and had it stop when *i* reached 6. Seeing as there was no text content for the row, all I needed was to create the `<tr>` element and assign this to a usable variable.

![First For Loop](https://i.imgur.com/8Zne8uO.jpg)

As stated before, I wanted to append each row with 7 table data elements. This meant that I needed a nested `for` loop. This 2nd `for` loop also started at 0 and ended when the count (c in this case) reached 7. This was simple enough, but the next step took some logical reasoning. Remembering that the `new Date(month, year).getDay()` gave me the index of day of the week, I needed to setup empty `<td>`s so that the count and calendar rendering started on the correct day. To do this, I added an `if` statement in my column `for` loop that would check if: <sub>1.</sub> The loop was on the first row (aka `i===0`), and <sub>2. </sub> The value of count loop was less than the `new Date(month, year).getDay()` value (aka `c < startOfMonth`).

If both those conditions were true, I wanted the loop to create a `<td>` element, add an *empty* class to the newly rendered `<td>` and append this to the current row element. 

![Empty Column Data](https://i.imgur.com/scpykiX.jpg)

Next, I wanted to make sure that I was populating the correct day number on each one of the new table data elements. Modifying my *empty td element* method, I added a `<td>` element for each new day, added the `textContent`, and appended the row. The `textContent` in this case would be the `renderNum` variable defined earlier. To make sure that the `renderNum` printed the correct date, I incremented the variable by 1. 

![Populated Column Data](https://i.imgur.com/ehYSSyh.jpg)

Using the power of *truthiness*, I used an `else if` statement to stop the calendar from incrementing and adding data past the last day of the month. 

![Else If Statement](https://i.imgur.com/IRQMv0B.jpg)

Once I reached the `break` and was out of the `for` loops, I needed to make sure that to append the table body with the newly formed and populated row. (*I did rearrange and group the code according to variables, and my personal preference. Obviously, this is not necessary. It was just a personal preference.*)

![Final Code](https://i.imgur.com/c1kWv4W.jpg)

Finally, I added `EventListeners` on the click of the arrows to toggle to the month before and after a calendar snapshot. Given the length of this post already, I will spare you. But there is plenty of [literature on `EventListeners`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener) that I recommend reading if you have trouble with that step.

Below is a snapshot of the rendered calendar. I will be sure to update this post with the github link, once the project is complete.

Next up, appointments, time zones and scheduling. Wish me luck!

![Final Calendar](https://i.imgur.com/3dlwWWo.jpg)