More articles

Coding A Calendar In JavaScript: Part 2

Written by
Filed under
Published on
Modified on

The following is the follow up to the ever so popular Coding a Calendar in JavaScript, in which I created a calendar widget in JavaScript.

SUN
MON
TUE
WED
THUR
FRI
SAT

Before you continue with this post, you should head on over to that post and get familiar with that process as I will be using the same code to render the following.

I will be continuing the implementation by allowing users to select multiple days, both by clicking on date regions and by dragging multiple dates at once.

1. New variables

We are going to need to add the following variables to our calendar script.


        var selectedDays = new Array();
        var mousedown = false;
    

The selectedDays array will be used to keep track of the currently selected dates on the calendar and the mousedown boolean expression will be used to monitor the current state of the mouse. Essentially, we want to know if we are currently mid-drag or not.

2. Single Day Selection

Let's begin by allowing users to select single days on our calendar, which is most often than not the most required feature for an online calendar. The following is the loadCalendarDays function from part 1. It has 2 new additions that you will need to make, and those are adding a new dataset to our 'day' div, to make it simpler to retrieve the selected date. And we will be adding the click event handler, that will take care of adding/removing the selected date from our array.

function loadCalendarDays() {
    document.getElementById("calendarDays").innerHTML = "";

    var tmpDate = new Date(year, month, 0);
    var num = daysInMonth(month, year);
    var dayofweek = tmpDate.getDay();       // find where to start calendar day of week

    for (var i = 0; i <= dayofweek; i++) {
        var d = document.createElement("div");
        d.classList.add("day");
        d.classList.add("blank");
        document.getElementById("calendarDays").appendChild(d);
    }

    for (var i = 0; i < num; i++) {
        var tmp = i + 1;
        var d = document.createElement("div");
        d.id = "calendarday_" + tmp;
        d.className = "day";
        d.innerHTML = tmp;
        d.dataset.day = tmp;              // easier to retrieve the date


/* ****************** Click Event ********************** */ d.addEventListener('click', function(){ this.classList.toggle('selected'); if (!selectedDays.includes(this.dataset.day)) selectedDays.push(this.dataset.day); else selectedDays.splice(selectedDays.indexOf(this.dataset.day), 1); });
/* **************************************************** */

document.getElementById("calendarDays").appendChild(d); } var clear = document.createElement("div"); clear.className = "clear"; document.getElementById("calendarDays").appendChild(clear); }

Let's take a look at the click event in more detail. Essentially, we're adding or removing a class to the day element, that shows that it is selected. And we'll be checking if the currently selected date exists already in our array. If it does not, it is pushed to the array, otherwise, it is spliced out.


        /* ****************** Click Event ********************** */
        d.addEventListener('click', function(){
            this.classList.toggle('selected');

            if (!selectedDays.includes(this.dataset.day))
                selectedDays.push(this.dataset.day);

            else
                selectedDays.splice(selectedDays.indexOf(this.dataset.day), 1);
        });
/* **************************************************** */

Multiple Day Selection

We are going to be selecting multiple days by dragging our mouse through the calendar, selecting the desired days along the way. And for that we're going to be needing a few of the mouse event handlers that JavaScript provides, starting with the mousedown event, following along with the mousemove event and finishing off with the mouseup event.

mousedown - The mousedown event will simply keep track of when the mouse key is being held down. This will help ensure that we only select the days if the mouse key is indeed pressed down.


         d.addEventListener('mousedown', function(e){
            e.preventDefault();
            mousedown = true;
        });
    

mouseup - The mouseup event is essentially the same as the mousedown event. Once the mouse key has been depressed, we want to reset the mousedown variable so that it can stop selecting days.


        d.addEventListener('mouseup', function(e){
            e.preventDefault();
            mousedown = false;
        });
    

mousemove - The mousemove event is where the selection actually happens. It is very similar to the click event. The first thing we want to do is to check if the mouse key is currently pressed, which if it is, it means we are dragging our move around. In which, we will want to pretty much replicate the click event, except we don't want to toggle the selections, we just want to make sure that they get selected.


         d.addEventListener('mousemove', function(e){
           e.preventDefault();
            if (mousedown)
            {
                this.classList.add('selected');

                if (!selectedDays.includes(this.dataset.day))
                    selectedDays.push(this.dataset.day);
            }
        });
    

Note that if you wanted to, you could likely have the days deselected on mousemove as well.

Upgrades

There's plenty that you can do with a calendar widget. While this was a good start into creating a realistically functional version of a calendar, you can go further and build out any of the following.

  • Select based on 'number of day' ranges
  • Select whole months
  • Select whole weeks

In a future post, I will be addressing these features and more.

Land your next big coding job. Search through 1000's of job listings.

Discussion / Comments / Questions

C
Coder
9/27/2019 9:09:51 AM
Thank you for this . would you please to a tutorial on how to add custom events on the calendar. Thank you
S
Seege
10/4/2019 2:46:50 PM
How would you add functionality for events?
Walter G.
10/10/2019 12:43:11 PM
Hey there. Many thanks for checking out the post and for the question. The best route I would say is to create a collection of objects. And each object item can represent a list of events + a calendar date. This would only be local of course, and long term storage would depend on your tech stack. Perhaps something I can cover in a part 3! If you would like a further breakdown feel free to let me know and I would be happy to extend the functionality on the calendar. Many thanks!
S
Seege
10/10/2019 12:51:17 PM
If you could do a part 3 on this subject, that would be AWESOME!!! :)
Walter G.
10/17/2019 3:23:26 PM
Part 3 is on its way and should be published shortly. Will cover local event storage.
R
Robert
10/27/2019 3:43:53 AM
Hi! Great stuff. I might have a dumb question, but I cannot run the source code from the part 1. It spits out an error while trying to go through the lines with c("div"). I can't find any function like this in the code or am I doing something wrong? I've included script into index file and created new object with an id of a DIV for the constructor parameter and then called render() method.
Walter G.
10/27/2019 9:04:37 AM
Hey there Robert. Many thanks for the words and for catching that! I have updated the .js file to include the c(el) function. It's really just a wrapper to the document.createElement function. I shorthanded it to c(el) for ease of use. Thanks again!
R
Robert
10/29/2019 11:39:39 PM
Thank You, that worked :D .. though now I got problem with how its being displayed, but I will figure it out :) *using bootstrap 4 and latest stable jQuery version
Walter G.
10/30/2019 12:32:18 PM
Awesome to hear Robert! Feel free to send me a link if you post it online dude. Always enjoy looking at people's custom implementations!

Add a comment

Send me your weekly newsletter filled with awesome ideas
Post comment