Calendar Grouping


In the Calendar Grouping, you can display data in a calendar view. You can customize the style of the calendar by changing the style or the layout of the group items using a row template. In the following example, the calendar grouping strategy is used with the Grid Layout to present a data set in a form of a calendar. This calendar is editable.

Use the following steps to implement the Calendar Grouping.

Sample Code

  1. Add the following references after the Dataview reference.

    <link rel="stylesheet" type="text/css" href="[Your Stylesheet Path]/gc.spread.views.dataview.10.1.1.css">
    <link rel="stylesheet" type="text/css" href="[Your Stylesheet Path]/bootstrap-snippet.min.css">
        <link rel="stylesheet" type="text/css" href="[Your Stylesheet Path]/gc.spread.views.calendargrouping.10.1.1.css">
    <script src="[Your Script Path]/gc.spread.views.calendargrouping.10.1.1.min.js" type="text/javascript"></script>
    <script src="data/timetable.js" type="text/javascript"></script>
  2. Add a div tag within the body tag to include the DOM element as the container in the page.

    <div class="wrapper">
            <div class="button-container " id="calendarCommandPanel">
                <div class="calendar-left-div">
                    <div id="commandPanel" class="btn-group" role="group">
                        <button id="dayView" type="button" class="btn btn-default" onclick="changeToDayView()">Day</button>
                        <button id="weekView" type="button" class="btn btn-default" onclick="changeToWeekView()">Week</button>
                        <button id="monthView" type="button" class="btn btn-default active" onclick="changeToMonthView()">
                        Month
                    </button>
                    </div>
                </div>
                <div class="calendar-middle-div">
                    <div id="title" style="font:400 18px arial,sans-serif;text-align: center;">20 Aug 2012-26 Aug 2012
                    </div>
                </div>
                <div class="calendar-right-div">
                    <div class="btn-group" role="group" style="float:right;">
                        <div class="btn btn-default" onclick="previous();">
                            <i class="demo-icon icon-left-big"></i>
                        </div>
                        <div class="btn btn-default" onclick="next();">
                            <i class="demo-icon icon-right-big"></i>
                        </div>
                    </div>
                </div>
            </div>
            <div id="gridContainer" style="height:620px;min-width: 800px">
                <div id="grid1" style="height:100%;position: relative"></div>
            </div>
    </div>
  3. Add the template definition and calendar definition followed by the column definition. ``` var editData;

        var columns = [{
            id: 'topic',
            dataField: 'topic'
        }, {
            id: 'start',
            dataField: 'start',
            format: 'HH:mm'
        }, {
            id: 'end',
            dataField: 'end',
            format: 'HH:mm'
        }, {
            id: 'speaker',
            dataField: 'speaker'
        }];
    
        var monthEventTemplate = '<div style="padding-left: 5px;padding-right: 5px;"><div class="event-title"><span style="color:white;background-color: #157fcc;border-radius: 5px;padding-left: 5px;padding-right: 5px">{{=it.start}}</span> <span style="padding-left: 5px;">{{=it.topic}}</span></div><div>';
        var dayEventTemplate = '<div><div>{{=it.topic}}</div></div>';
        $.each(data, function(key, val) {
            for (var prop in val) {
                if (prop === 'start' || prop === 'end') {
                    val[prop] = new Date(val[prop]);
                }
            }
        });

        var calendaryStrategy = new GC.Spread.Views.Plugins.CalendarGrouping({
            viewMode: 'Month',
            daysEventStartField: 'start',
            daysEventEndField: 'end',
            startDate: new Date(2015, 5, 1, 8, 0, 0),
            daysStartTime: new Date(2015, 5, 1, 8, 0, 0),
            daysEndTime: new Date(2015, 5, 1, 23, 0, 0)
        });

        calendaryStrategy.eventClick.addHandler(function(sender, args) {
            var dialog = ($('#editDialog').length > 0) ? ($('#editDialog')[0]) : createEditEventDialog();
            if (dialog) {
                setTimeout(function() {
                    var popoverDialog = $('.popover-dialog');
                    if (popoverDialog.length > 0) {
                        popoverDialog.remove();
                    }
                    dataView.container.parentElement.appendChild(dialog);
                    var left = parseInt(($(window).width() - $(dialog).width()) / 2 + $(window).scrollLeft());
                    var top = parseInt(($(window).height() - $(dialog).height()) / 2 + $(window).scrollTop());
                    $(dialog).css({
                        left: left,
                        top: top
                    });

                    if (!args.data) {
                        var start = new Date();
                        var end = new Date(start.getFullYear(), start.getMonth(), start.getDate(),
                            start.getHours() + 2, start.getMinutes(), start.getSeconds());
                        args.data = {
                            topic: '',
                            start: start,
                            end: end
                        };
                    }

                    editData = args.data;
                    var excelFormatter = new GC.Spread.Formatter.GeneralFormatter('hh:mm:ss');

                    $('#eventTitleContent')[0].value = editData.topic;
                    $('#datetimepicker1')[0].value = excelFormatter.format(editData.start);
                    $('#datetimepicker2')[0].value = excelFormatter.format(editData.end);
                }, 100);
            }
    });

4.  Initialize the code by calling the Grid ID from the DIV tag.
var dataView = new GC.Spread.Views.DataView(document.getElementById('grid1'), data, columns, new GC.Spread.Views.Plugins.GridLayout({
            grouping: {
                field: 'start',
                converter: function(field) {
                    return field.toDateString();
                }
            },
            rowTemplate: monthEventTemplate,
            groupStrategy: calendaryStrategy
        }));

    updateTitle();
5.  Add functions to switch between Day, Week, and Month views.
function previous() {
            var options = calendaryStrategy.options;
            var currentDate = options.startDate;

            if (options.viewMode === 'Month') {
                currentDate = getMonth(currentDate, -1);
            } else if (options.viewMode === 'Week') {
                currentDate = getDay(currentDate, -7);
            } else {
                currentDate = getDay(currentDate, -1);
            }

            calendaryStrategy.options.startDate = currentDate;
            updateTitle();
            dataView.invalidate();
        }

        function next() {
            var options = calendaryStrategy.options;
            var currentDate = options.startDate;
            if (options.viewMode === 'Month') {
                currentDate = getMonth(currentDate, 1);
            } else if (options.viewMode === 'Week') {
                currentDate = getDay(currentDate, 7);
            } else {
                currentDate = getDay(currentDate, 1);
            }

            calendaryStrategy.options.startDate = currentDate;
            updateTitle();
            dataView.invalidate();
        }

        function changeToDayView() {
            $('#commandPanel .btn').removeClass('active');
            $('#dayView').addClass('active');
            var options = dataView.options;
            options.rowHeight = 50;
            options.rowTemplate = dayEventTemplate;
            calendaryStrategy.options.viewMode = 'Day';
            dataView.invalidate();
            updateTitle();
        }

        function changeToWeekView() {
            $('#commandPanel .btn').removeClass('active');
            $('#weekView').addClass('active');
            var options = dataView.options;
            options.rowHeight = 50;
            options.rowTemplate = dayEventTemplate;
            calendaryStrategy.options.viewMode = 'Week';
            dataView.invalidate();
            updateTitle();
        }

        function changeToMonthView() {
            $('#commandPanel .btn').removeClass('active');
            $('#monthView').addClass('active');
            var options = dataView.options;
            options.rowHeight = 24;
            options.rowTemplate = monthEventTemplate;
            calendaryStrategy.options.viewMode = 'Month';
            dataView.invalidate();
            updateTitle();
        }

        function createEditEventDialog() {
            var rect = getPopDialogLocation();
            var left = rect.width - 450;
            left = left > 0 ? left / 2 : 0;
            var top = rect.height - 170;
            top = top > 0 ? top / 2 : 0;
            var eventDialog = '<div id="editDialog" class="editEventDialog">' +
                '<div class="editEventBackground">' +
                '<div class="editEventHeaderInner">' +
                '<div style="display: inline-block">Edit Event</div>' +
                '<div class="gc-editing-close gc-float-right" onclick="removeDialog(event)"><span class="close-icon"></span></div>' +
                '</div>' +
                '</div>' +
                '<div class="editEventContent">' +
                '<div class="contentItem"><div class="title"><label>Title</label></div><div class="titleInput" style="width:calc(100% - 50px);"><input id="eventTitleContent"style="width: 100%"/></div></div>' +
                '<div class="contentItem"><div class="itemContainer"><div class="title"><label>When</label></div>' +
                '<div class="titleInput" style="width:calc(100% - 50px)"><div class="input-group date" style="width: 100%;">' +
                '<input type="time" id="datetimepicker1" style="width: 100%">' +
                '</div></div></div>' +
                '<div class="itemContainer"><div class="title"><label style="margin-left: 20px;margin-right: 15px;">to</label></div>' +
                '<div class="titleInput"  style="width:calc(100% - 50px)" ><div class="input-group date" style="width: 100%" >' +
                '<input type="time" id="datetimepicker2" style="width: 100%">' +
                '</div></div></div>' +
                '</div>' +
                '</div>' +
                '<div class="editEventBackground">' +
                '<div class="btn-group pull-right editEventBtnInner" rol="group">' +
                '<button  type="button" class="btn btn-default editBtn" onclick="deleteEvent(event)">Delete Event</button>' +
                '<button  type="button" class="btn btn-default editBtn" onclick="saveEvent(event)">Save</button>' +
                '<button  type="button" class="btn btn-default editBtn" onclick="cancelEditEvent(event)">Cancel</button>' +
                '</div>' +
                '</div>' +
                '</div>';

            var div = document.createElement('div');
            div.innerHTML = eventDialog;
            var r = div.children[0];
            div = null;
            return r;
        }

        function saveEvent() {
            if (editData) {
                var oldStart = editData.start;
                var oldEnd = editData.end;
                editData.topic = $('#eventTitleContent')[0].value;
                var newStartValue = $('#datetimepicker1')[0].value;
                var newEndValue = $('#datetimepicker2')[0].value;
                if (newStartValue && newEndValue) {
                    var newStart = newStartValue.split(':');
                    var newEnd = newEndValue.split(':');
                    while (newStart.length < 3) {
                        newStart.push('0');
                    }
                    while (newEnd.length < 3) {
                        newEnd.push('0');
                    }

                    editData.start = new Date(oldStart.getFullYear(), oldStart.getMonth(), oldStart.getDate(),
                        parseInt(newStart[0]), parseInt(newStart[1]), parseInt(newStart[2]));
                    editData.end = new Date(oldEnd.getFullYear(), oldEnd.getMonth(), oldEnd.getDate(),
                        parseInt(newEnd[0]), parseInt(newEnd[1]), parseInt(newEnd[2]));
                    dataView.invalidate();
                }

                removeDialog();
            }
        }

        function deleteEvent(sender, e) {
            dataView.data.removeDataItems(editData.sourceIndex, 1);
            removeDialog();
        }

        function cancelEditEvent() {
            removeDialog();
        }

        function removeDialog(e) {
            var dialog = document.getElementById('editDialog');
            if (dialog) {
                dataView.container.parentElement.removeChild(dialog);
            }
        }

        function getPopDialogLocation() {
            var container = document.getElementById('grid1');
            if (container) {
                return container.getBoundingClientRect();
            }
        }

        function getDay(currentDate, daysCount) {
            var date = new Date(currentDate);
            var timeSpan = 1000 * 60 * 60 * 24 * (daysCount ? daysCount : 1);
            date.setTime(date.getTime() + timeSpan);

            return date;
        }

        function getMonth(currentDate, monthCount) {
            var year = currentDate.getFullYear();
            var month = currentDate.getMonth() + monthCount;
            var day = currentDate.getDate();

            if (month == 12) {
                month = 0;
                year += 1;
            } else if (month == -1) {
                month = 11;
                year -= 1;
            }

            return new Date(year, month, day, 0, 0, 0);
        }

        function updateTitle() {
            var options = calendaryStrategy.options;
            var date = options.startDate;
            var title = document.getElementById("title");
            var dateFormatter;
            if (options.viewMode === 'Month') {
                dateFormatter = new GC.Spread.Formatter.GeneralFormatter('mmmm yyyy');
                title.innerText = dateFormatter.format(date);
            } else if (options.viewMode === 'Week') {
                dateFormatter = new GC.Spread.Formatter.GeneralFormatter('d mmm yyyy');
                title.innerText = dateFormatter.format(date) + '-' + dateFormatter.format(getDay(date, 6));
            } else {
                dateFormatter = new GC.Spread.Formatter.GeneralFormatter('d mmm yyyy');
                title.innerText = dateFormatter.format(date) + '-' + dateFormatter.format(getDay(date, 1));
            }
    }

```