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.

Walter G. is a software engineer, startup co-founder, former CTO of several tech companies and currently teaches programming for a coding bootcamp. He has been blogging for the past 5 years and is an avid BMX rider, bio-hacker and performance enthusiast.
If you read this far, then I hope you enjoyed this post and found it useful! Consider adding to my daily coffee funds to continue to provide better and more helpful articles in the future!
Maybe later

Add a comment

Send me your weekly newsletter filled with awesome ideas
Post comment