Click here to Skip to main content
Click here to Skip to main content
Technical Blog

Tagged as

Creating a professional looking calendar control using jQuery

, 24 Jan 2014 CPOL
Rate this:
Please Sign up or sign in to vote.
One of the most used controls in a web page is the Calendar control. I’m sure you have seen so many and irritating ones as me. Let’s see how to create a professional calendar control using jQuery and Javascript. As … Continue reading →

One of the most used controls in a web page is the Calendar control. I’m sure you have seen so many and irritating ones as me.
Let’s see how to create a professional calendar control using jQuery and Javascript.

calendar

As with any other control development, we start with plain HTML. We can render this from server, taking into account the locale of the user request, however, that concept is outside from this article.

The HTML part

We’re going to create one div that will serve as the container, then 3 divs inside, header, body and footer.

<div class="mopCalendar">

	<div class="mopCalendarHeader"></div>

	<div class="mopCalendarBody"></div>

	<div class="mopCalendarFooter"></div>

</div>

Header
For the header, we need 4 buttons, and one label to display the current month, so we write the markup accordingly, insigde our header div

<div class="mopCalendarBtnFirst"></div>
	    <div class="mopCalendarBtnPrevious"></div>
	    <div class="mopCalendarMonth"></div>
	    <div class="mopCalendarBtnNext"></div>
	    <div class="mopCalendarBtnLast"></div>

Body
For the body, we’re going to write a table that will show the days. We could write this table using javascript, but for easing purposes we put the markup directly

<table style="width:100%;">
	    <thead>
	        <tr>
	            <th class="mopCalendarDayRed">Sun</th>
	            <th>Mon</th>
	            <th>Tue</th>
	            <th>Wed</th>
	            <th>Thu</th>
	            <th>Fri</th>
	            <th class="mopCalendarDayRed">Sat</th>    
	        </tr>
	    </thead>
    	    
	    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
	    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
	    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
	    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
	    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
	    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>

	    </table>

The table basically contains a header, with the day names. The mopCalendarDayRed style displays the weekend days with red forecolor. Then we have 7 rows, to display the whole month. Don’t worry about the styles, we’ll take care of that later.

Footer
The footer is the easiest one. We’ll have two buttons, one to clear the selected value and other to set current date. We place these buttons inside our footer div

<button class="mopCalendarBtnToday">Today</button>
<button class="mopCalendarBtnClear">Clear</button>

That’s all! We have the HTML markup ready.

JavaScriptize It!

We will follow jQuery pattern for plugin authorize, so we start with the following skeleton :

(function($)
{
    //global properties, depending on current language
    var MonthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
    var FirstDayOfWeek = 0;

    $.fn.mopCalendar = function(initialDate)
    {
        var $this = $(this);
        var selectedDate = initialDate || new Date();
        var selectedMonth = selectedDate.getMonth();
        var selectedYear = selectedDate.getFullYear();

        return this.each(function()
        {
        });
    };

} (jQuery));

We name our plugin mopCalendar, and we set several global properties for our plugin, like the month names and the first day of week. We can setup this accordingly to the current user language.

GetValue and SetValue functions

var getValue = function()
            {
                return selectedDate;
            };

            var setValue = function(date)
            {
                if (date == null)
                {
                    selectedDate = null;
                    return;
                }

                selectedDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
                selectedMonth = getMonth();
                selectedYear = getYear();
                refreshMonthTitle();
                refreshDayTable();
            };

We start setting different variables, that will hold current selected date, month and year. Also, the getValue functions returns the currently selected date, and the important piece, setValue function, will update selected date, and also will call the refresh functions we’re going to describe next.

var getDay = function()
            {
                return selectedDate.getDate();
            };

            var getWeekDay = function()
            {
                return selectedDate.getDay();
            };

            var getMonth = function()
            {
                return selectedDate.getMonth();
            };

            var getYear = function()
            {
                return selectedDate.getFullYear();
            };

            var setSelectedMonth = function(monthNum)
            {
                if (monthNum == -1 && selectedMonth == 0)
                {
                    selectedYear--;
                    selectedMonth = 11;
                }
                else if (monthNum == 12 && selectedMonth == 11)
                {
                    selectedYear++;
                    selectedMonth = 0;
                }
                else if (monthNum >= 0 && monthNum <= 11)
                    selectedMonth = monthNum;
                else
                    return;

                refreshMonthTitle();
                refreshDayTable();
            };

            var setSelectedYear = function(yearNum)
            {
                selectedYear = yearNum;
                refreshMonthTitle();
                refreshDayTable();
            };
            var getContentTable = function () {
                return $this.find('table');
            };

We continue with the supporting functions, that quickly return us the current day number, week day, month, etc, from the selected date. Also, the setSelectedMonth and setSelectedYear will help us when the different buttons are clicked. Notice the two important functions we’re going to describe, refreshMonthTitle and refreshDayTable

var refreshMonthTitle = function()
            {
                var monthTitle = $('.mopCalendarMonth').text(MonthNames[selectedMonth] + ', ' + selectedYear);
            };

            var refreshDayTable = function () {
                var table = getContentTable();
                var month = selectedMonth;
                var year = selectedYear;

                var startd = new Date(year, month, 1);
                var d1 = FirstDayOfWeek;
                var d2 = startd.getDay();
                var diff = d1 < d2 ? d2 - d1 : d1 + 7;
                startd.setDate(startd.getDate() - diff);

                for (var j = 1; j < 7; j++) {
                    var row = table[0].rows[j];
                    for (var i = 0; i < 7; i++) {
                        var dy = startd.getDate();
                        var wd = startd.getDay();
                        var md = startd.getMonth();
                        var cell = $(row.cells[i]).text(dy);

                        cell.removeClass();
                        if (startd.valueOf() == selectedDate.valueOf())
                            cell.addClass('mopCalendarDaySelected');
                        else if (md != month)
                            cell.addClass('mopCalendarDayOdd');
                        else if (wd == 0 || wd == 6)
                            cell.addClass('mopCalendarDayRed');

                        dy++;
                        startd.setDate(dy);
                    }
                }
            };

refreshMonthTitle function is pretty straightforward. It basically updates the month title with the current selected month.

The most important function is refreshDayTable. This function cleans the whole table and updates it with the month days, drawing also the last days from the previous month and the first days of the next month, all of them in gray color. Also, if the week day is Sunday or Saturday, the color will be red. The trick here is knowing which is the very first day to start with, then it’s a simply add one more until all rows and cells have been drawn.

Put those buttons to work!
And the final part is making the buttons to give some interactivity, so our super Calendar control will be finished.

On Header Click
We attach a single click event to the whole header, and then depending on the target, we’ll know which section the user has clicked on. Depending on that, we call one function or other.

var onHeaderClick = function(e)
            {
                if (e.target)
                {
                    var target = $(e.target);
                    if (target.hasClass('mopCalendarBtnFirst'))
                        setSelectedYear(selectedYear - 1);
                    else if (target.hasClass('mopCalendarBtnPrevious'))
                        setSelectedMonth(selectedMonth - 1);
                    else if (target.hasClass('mopCalendarBtnNext'))
                        setSelectedMonth(selectedMonth + 1);
                    else if (target.hasClass('mopCalendarBtnLast'))
                        setSelectedYear(selectedYear + 1);
                }
                return false;
            };

On Body Click
The same for the days. In this case, we only care if user clicks on a cell, so we update the selected day.

var onBodyClick = function(e)
            {
                if (e.target && e.target.tagName == 'TD')
                {
                    var rowIndex = e.target.parentElement.rowIndex;
                    var month = selectedMonth;
                    var year = selectedYear;
                    var day = parseInt($(e.target).text());

                    if (rowIndex <= 1 && day >= 20)
                        month--;
                    else if (rowIndex >= 5 && day <= 15)
                        month++;

                    setValue(new Date(year, month, day));
                }
            };

On footer click
And our footer buttons, to set the current value to either current date or empty value.

var onFooterClick = function(e)
            {
                if (e.target && e.target.tagName == 'BUTTON')
                {
                    var $target = $(e.target);
                    if ($target.hasClass('mopCalendarBtnToday'))
                        setValue(new Date());
                    else if ($target.hasClass('mopCalendarBtnClear'))
                        setValue(null);
                }
                return false;
            };

To attach the events, we have used this :

$('.mopCalendarHeader').on('click', onHeaderClick);
            $('.mopCalendarBody').on('click', onBodyClick);
            $('.mopCalendarFooter').on('click', onFooterClick);

            //disable drag
            $this.on('selectstart dragstart', function (e) { e.preventDefault(); });

And finally, public function access and auto-set to the received initial date

this.setValue = (function (value) {
                setValue(value);
            })(initialDate);

To start with, simply put the initialization on our html page :

<script type="text/javascript">

        $(document).ready(
            function()
            {
                $(".mopCalendar").mopCalendar(new Date());
            }
        );
    
    </script>

That’s all! You can download attached source code, which contains the CSS used also.
Thanks for your reading!

Download Source

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

mopicus
Software Developer (Senior) Ford Motor Company
Spain Spain
No Biography provided
Follow on   Twitter   LinkedIn

Comments and Discussions

 
QuestionCode usage PinmemberOlter26-Jan-14 20:41 
AnswerRe: Code usage Pinprofessionalmopicus26-Jan-14 22:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.141223.1 | Last Updated 25 Jan 2014
Article Copyright 2014 by mopicus
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid