Snippets

Michael Riddle Calendar jQuery UI Widget

Created by Michael Riddle
$.widget('riddlemd.calendarize', {
        options : {
            select : function(value) {},
            className : 'calendarize',
            menuClassName : 'calendarize-menu',
            dayListClassName : 'calendarize-days',
            dayClassName : 'calendarize-day',
            headerClassName : 'calendarize-header',
            monthSelectClassName : 'calendarize-month',
            yearSelectClassName : 'calendarize-year',
            showMenu : true,
            daysOfWeek : ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'],
            months : ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
            currentDate : null
        },
        _create : function() {
            var currentWidget = this;

            currentWidget.options.currentDate = currentWidget.options.currentDate instanceof Date ? currentWidget.options.currentDate : new Date();

            currentWidget.element.addClass('calendarize');

            currentWidget._createMenu();

            currentWidget._createHeader();

            currentWidget._createDaysList();

            var currentDate = currentWidget.options.currentDate;
            currentWidget.displayMonth();
        },
         _createMenu : function() {
            var currentWidget = this;

            var $menu =  $('<ul>')
                .addClass(currentWidget.options.menuClassName)
                .appendTo(currentWidget.element);

            if(!currentWidget.options.showMenu) {
                $menu.hide();
            }

            var $monthSelectWrapper = $('<li>')
                .addClass('input select')
                .appendTo($menu);

            var $monthSelectLabel = $('<label>')
                .html('Month')
                .appendTo($monthSelectWrapper);

            var $monthSelect = $('<select>')
                .addClass(currentWidget.options.monthSelectClassName)
                .change(function() {
                    currentWidget.displayMonth($monthSelect.val(), $yearSelect.val());
                })
                .appendTo($monthSelectWrapper);

            for(var i = 0; i < currentWidget.options.months.length; i++) {
                var monthName = currentWidget.options.months[i];
                var $monthOption = $('<option>')
                    .val(i+1)
                    .html(monthName)
                    .appendTo($monthSelect);
            }

            var $yearSelectWrapper = $('<li>')
                .addClass('input select')
                .appendTo($menu);

            var $yearSelectLabel = $('<label>')
                .html('Year')
                .appendTo($yearSelectWrapper);
            
            var $yearSelect = $('<select>')
                .addClass(currentWidget.options.yearSelectClassName)
                .change(function() {
                    currentWidget.displayMonth($monthSelect.val(), $yearSelect.val());
                })
                .appendTo($yearSelectWrapper);

            for(var i = currentWidget.options.currentDate.getFullYear(); i < currentWidget.options.currentDate.getFullYear() + 40; i++) {
                var $monthOption = $('<option>')
                    .val(i)
                    .html(i)
                    .appendTo($yearSelect);
            }
        },
        _createHeader : function() {
            var currentWidget = this;

            var $header = $('<ul>')
                .addClass(currentWidget.options.headerClassName)
                .appendTo(currentWidget.element);

            for(var i = 0; i < currentWidget.options.daysOfWeek.length; i++) {
                var $day = $('<li>')
                    .html(currentWidget.options.daysOfWeek[i])
                    .addClass(currentWidget.options.dayHeaderClassName)
                    .appendTo($header);
            }
        },
        _createDaysList : function() {
            var currentWidget = this;

            var $daysList = $('<ul>')
                .addClass(currentWidget.options.dayListClassName)
                .appendTo(currentWidget.element);
        },
        getDaysList : function() {
            var currentWidget = this;
            return currentWidget.element.find('.' + currentWidget.options.dayListClassName);
        },
        getYearSelect : function() {
            var currentWidget = this;
            return currentWidget.element.find('.' + currentWidget.options.yearSelectClassName);
        },
        getMonthSelect : function() {
            var currentWidget = this;
            return currentWidget.element.find('.' + currentWidget.options.monthSelectClassName);
        },
        displayMonth : function(month, year) {
            var currentWidget = this;

            year = parseInt(year);
            if(isNaN(year)) {
                year = this.options.currentDate.getFullYear();
            }
            month = parseInt(month);
            if(isNaN(month)) {
                month = this.options.currentDate.getMonth();
            } else {
                month--; // Remove one from month, since humans count them 1-12 and not 0-11...
            }

            currentWidget.getMonthSelect().val(month+1);
            currentWidget.getYearSelect().val(year);

            var firstDayOfMonth = new Date(year, month, 1);
            var totalDaysInMonth = new Date(year, month, 0).getDate();
            var offsetDays = firstDayOfMonth.getDay();

            currentWidget.getDaysList().empty();
            
            for(var i = 1; i <= 42; i++) {
                var dayDate = new Date(year, month, i - offsetDays);

                var $day = $('<li>')
                    .addClass(currentWidget.options.dayClassName)
                    .data('date', dayDate)
                    .click(function(e) {
                        var $currentElement = $(this);
                        currentWidget.clearSelection();
                        $currentElement.addClass('selected');
                        currentWidget.onDateSelected({date:$currentElement.data('date'),valid:!$currentElement.hasClass('different-month')})
                    })
                    .appendTo(currentWidget.getDaysList());

                var event = currentWidget.onDrawDate({element:$day,date:dayDate});
                $day.html(event.html);

                if(dayDate.getMonth() != month) {
                    $day.addClass('different-month')
                }
            }

            currentWidget.element.trigger('monthDisplayed', {month:month+1,year:year});
        },
        clearSelection : function() {
            var currentWidget = this;
            currentWidget.getDaysList().children().removeClass('selected');
        },
        onMonthDisplayed : function(args) {
            var event = new jQuery.Event('monthDisplayed');
            $(this.element).trigger(event, args);
            return event;
        },
        onDrawDate : function(args) {
            var event = new jQuery.Event('drawDate', {html:''});
            $(this.element).trigger(event, args);
            return event;
        },
        onDateSelected : function(args) {
            var event = new jQuery.Event('dateSelected');
            $(this.element).trigger(event, args);
            return event;
        }
    });

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.