Exploring JQuery plugin ‘FullCalendar’.

Here’s the author’s weblink on this tremendous open-source calendar based scheduler. Everything to get started with this plugin can be found here, (ie docs, demos, download etc.)
http://arshaw.com/fullcalendar/

I basically tried to run those same examples using ASP.Net/C#. Fullcalendar is extremely customizable and very easy to alter/adapt as per the application needs. As of now, Fullcalendar does not inherently support “Recurring Events”. I developed 2 examples on Recurring events on top of this calendar — one that recurs daily and another monthly. All my recurring logic is on the server. On the topic of “Recurring Events”, I actually borrowed the main idea from Telerik’s  RadScheduler. In RadScheduler, there is something called “RecurrenceRule” which basically consists of EventStartdate, EventEndDate, Frequency (ie daily or weekly or monthly), Interval of Occurance in a string variable. An example of RadScheduler Recurrence Rule:

string rRule = "{DTSTART:20120808T110000ZDTEND:20120808T113000ZRRULE:FREQ=DAILY:COUNT=3;INTERVAL=5;BYDAY=MO,TU,WE,TH,FR,SA,SU}";

Based on that, RadScheduler dynamically generates range of occurance dates at runtime. I tried to mimic exact same on fullCalendar. The main challenge was to write the recurring logic myself. Once the event occurance dates are obtained, at runtime, I generate those many events on those dates and push that complete List-array of events to client.That’s it. From there on, FullCalendar takes care of everything. Here are those examples.
Ex 1:- A basic Fullcalendar getting bunch of events from server as well as have the ability to update an event,  Events can be dragged, resized, dropped on the calendar. On any of this action a AJAX request can be sent to server to save the changes.

img1

<link rel='stylesheet' type='text/css' href='fullcalendar/fullcalendar.css' />
    <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.js" type="text/javascript"></script>
    <script src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.9/jquery-ui.js" type="text/javascript"></script>
    <link href="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.9/themes/redmond/jquery-ui.css" rel="stylesheet" type="text/css" />
    <script type='text/javascript' src='fullcalendar/fullcalendar.min.js'></script>
    <script src="https://github.com/douglascrockford/JSON-js/raw/master/json2.js" type="text/javascript"></script>
    <script src="jquery/jquery-ui-timepicker-addon-0.6.2.min.js" type="text/javascript"></script>
    <script type='text/javascript' src='Scripts/jquery.qtip-1.0.0-rc3.min.js'></script>
<script type="text/javascript">
function UpdateMyEvent(event) {
var eventToSave = new Object(); ;
eventToSave.EventID = event.id ;
eventToSave.StartDate = event.start.toLocaleString();
eventToSave.EndDate = event.end.toLocaleString();
eventToSave.EventName = event.title;
$.ajax({
type: "POST",
contentType: "application/json",
data: "{eventdata1:" + JSON.stringify(eventToSave) + "}",
url: "ExToolTip2.aspx/UpdateEvent",
dataType: "json",
error: function (XMLHttpRequest, textStatus, errorThrown) {
    debugger;
}
});
}


$(document).ready(function () {
DisplayCalendar();
});

function DisplayCalendar() {
$.ajax({
type: "POST",
contentType: "application/json",
data: "{}",
url: "ExToolTip2.aspx/GetEvents",
dataType: "json",
success: function (data) {
    $('div[id*=calendar]').fullCalendar({
        header: {
            left: 'prev,next today',
            center: 'title',
            right: 'month,agendaWeek,agendaDay'
        },
        selectable: true,
        editable: true,
        droppable: true,
        draggable: true,
        selectable: true,
        selectHelper: true,
        eventTextColor: 'Yellow',
        eventBackgroundColor: 'purple',
        events:
        $.map(data.d, function (item, i) {
            var event = new Object();
            event.id = item.EventID;
            event.start = item.StartDate;
            event.end = item.EndDate;
            event.title = item.EventName;
            event.allDay = false;
            if (event.title == 'Event_1') {
                event.color = "DarkBlue";
                event.textColor = "DarkBlue";
                event.backgroundColor = "yellow";
                event.title = "Important Meeting";
            }
            return event;
        }),
        eventRender: function (event, element) {
            element.attr("categories", event.categoryname),
            element.qtip({
                content: event.title + "<br>" + event.start,
                position: { corner: { tooltip: 'bottomLeft', target: 'topRight'} },
                style: {
                    border: {
                        width: 1,
                        radius: 3,
                        color: 'green'
                    },
                    padding: 10,
                    textAlign: 'left',
                    tip: true
                }
            });
        },
        eventAfterRender: function (event, element, view) {
        },
        eventResize: function (event, dayDelta, minuteDelta, revertFunc) {
            if ($(this).data("qtip")) $(this).qtip("destroy");
            if (!confirm("is this okay?")) {
                revertFunc();
            }
            else {
                UpdateMyEvent(event);
            }
        },
        eventDrop: function (event, dayDelta, minuteDelta, allDay, revertFunc) {
            if ($(this).data("qtip")) $(this).qtip("destroy");
        }
    });

},
error: function (XMLHttpRequest, textStatus, errorThrown) {
    debugger;
}
});
}
</script>
<body>
<form id="form1" runat="server">
<div id='calendar'></div>
</form>
public class Event
{
    public int? EventID { get; set; }
    public string EventName { get; set; }
    public string StartDate { get; set; }
    public string EndDate { get; set; }
}
[System.Web.Services.WebMethod]
public static List<Event> GetEvents()
{
    List<Event> events;
    if (HttpContext.Current.Session["events"] != null)
        events = (List<Event>)HttpContext.Current.Session["events"];
    else
    {
        events = new List<Event>();
        for (int i = 0; i < 5; i++)
        {
            Event _Event = new Event();
            _Event.EventID = i;
            _Event.EventName = "Event_" + i.ToString();
            _Event.StartDate = DateTime.Now.DayOfWeek + ", " + DateTime.Now.AddDays(i + 2).ToString();
            _Event.EndDate = DateTime.Now.DayOfWeek + ", " + DateTime.Now.AddDays(i + 2).ToString();
            events.Add(_Event);
        }
    }
    HttpContext.Current.Session["events"] = events;
    return events;
}

[System.Web.Services.WebMethod]
public static bool UpdateEvent(Event eventdata1)
{
    List<Event> events;
    if (HttpContext.Current.Session["events"] != null)
        events = (List<Event>)HttpContext.Current.Session["events"];
    else
        events = new List<Event>();
    if (events.Contains(eventdata1))
    {
        //Update DB
        Event _MyEvent = events.Find(
        delegate(Event bk)
        {
            return bk.EventID == eventdata1.EventID;
        });
        if (_MyEvent is object)
        {
            _MyEvent.StartDate = eventdata1.StartDate;
            _MyEvent.EndDate = eventdata1.EndDate;
        }
    }
    HttpContext.Current.Session["events"] = events;
    return true;
}

Ex 2:- A Daily Recurring Event

img3

<script type='text/javascript'>
$(document).ready(function () {
    DisplayCalendar();
    $('#chkRec').click(function () {
        if ($(this).is(':checked')) {
            $('#RecEvent').show();
        }
        else {
            $('#RecEvent').hide();
        }
    });
});

function DisplayCalendar() {
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();

var calendar = $('#calendar').fullCalendar({
    header: {
        left: 'prev,next today',
        center: 'title',
        right: 'month,agendaWeek,agendaDay'
    },
    eventRender: function(event, element) {
    element.qtip({
    content: event.description
    });
    },
    selectable: true,
    eventDrop: function (event, dayDelta, minuteDelta, allDay, revertFunc) {
    },
    dayClick: function(date, allDay, jsEvent, view) {
        //$(this).css('background-color', 'red');
    },
 
    selectHelper: true,
    select: function (start, end, allDay) {
        $("#StartDt").val("" + start.toLocaleString());
        $("#EvtStartDt").val("" + start.toLocaleString());

        $("#EndDt").val("" + end.toLocaleString());
        $("#EvtEndDt").val("" + end.toLocaleString());

        $("#ModalAdd").dialog(
        {
            title: "Add event",
            width: 500,
            modal: true,
            buttons: {
                "Add": function () {
                    var event = new Object(), eventToSave = new Object(); ;
                    eventToSave.EventID = event.id = Math.floor(200 * Math.random());
                    event.start = new Date($("#StartDt").val());
                    eventToSave.StartDate = $("#StartDt").val();
                    eventToSave.EndDate = $("#EndDt").val();
                    eventToSave.EventName = event.title = eventToSave.title = $("#Name").val();
                    if ($('#chkRec').is(':checked')) {
                        eventToSave.title += " (Recurring)";
                        eventToSave.IsRecurring = true;
                        eventToSave.Freq = "Daily";
                        eventToSave.Count = $("#txtCount").val();
                        eventToSave.Interval = $("#txtInterval").val();
                    }
                    $.ajax({
                        type: "POST",
                        contentType: "application/json",
                        data: "{eventdata:" + JSON.stringify(eventToSave) + "}",
                        url: "Test2.aspx/AddEvents",
                        dataType: "json",
                        success: function (data) {
                            var events = new Array();
                            $.map(data.d, function (item, i) {
                                var event = new Object();
                                event.id = item.EventID;
                                event.start = new Date(item.StartDate);
                                event.end = new Date(item.EndDate);
                                event.title = item.EventName;
                                event.allDay = false;
                                events.push(event);
                            })
                            $('div[id*=calendar]').fullCalendar('addEventSource', events);
                            $("#ModalAdd").dialog("close");
                        },
                        error: function (XMLHttpRequest, textStatus, errorThrown) {
                            debugger;
                        }
                    });
                }
            }
        });
        calendar.fullCalendar('unselect');
    },
    editable: true,
    droppable: true,
    draggable: true,
    eventTextColor: 'Yellow',
    eventBackgroundColor: 'purple'
});
}
    </script>

<div id="ModalAdd" style="display:none;width:400px;">
<div id="AddEvent" style="width:400px;" >
    Event Name:&nbsp;
    <input id="Name" type="text" style="width:200px;" /><br /><br />
    Start date:&nbsp;&nbsp;
    <input id="StartDt" type="text" style="width:360px;" /><br /><br />
    End date:&nbsp;&nbsp;
    <input id="EndDt" type="text" style="width:360px;" /><br /><br />
    Recurrence: <input type="checkbox" id="chkRec" />
    <br />
</div>

<div id="RecEvent" style="display: none; width:400px;">
    <hr />
    <b>Repeat:</b><br />
    Daily:   | &nbsp;&nbsp;&nbsp; Every <input id="txtInterval" type="text" style="width:30px;" /> day(s).
    <br /><br />
    End after <input id="txtCount" type="text" style="width:30px;" /> occurences.<br />
</div>        
</div>

<div id="calendar"></div>
</form>
[System.Web.Services.WebMethod]
public static List<MyEvent> AddEvents(MyEvent eventdata)
{
    List<MyEvent> events;
    if (HttpContext.Current.Session["events"] != null)
        events = (List<MyEvent>)HttpContext.Current.Session["events"];
    else
        events = new List<MyEvent>();
    if (eventdata.IsRecurring)
    {
        string stDate = eventdata.StartDate;
        string EndDate = eventdata.EndDate;
        DateTime dtStart = DateTime.Parse(stDate.Split(',')[1] + stDate.Split(',')[2]);
        DateTime dtEnd = DateTime.Parse(EndDate.Split(',')[1] + EndDate.Split(',')[2]);
        int i = 0;
        int TotalCnt = eventdata.Count;
        do
        {
            if (eventdata.Freq == "Daily")
            {
                MyEvent _Event = new MyEvent();
                _Event.StartDate = dtStart.DayOfWeek + ", " + dtStart;
                _Event.EndDate = dtEnd.DayOfWeek + ", " + dtEnd;
                _Event.EventName = eventdata.EventName;
                _Event.EventID = eventdata.EventID + i;

                dtStart = dtStart.AddDays(eventdata.Interval);
                dtEnd = dtEnd.AddDays(eventdata.Interval);
                events.Add(_Event);
            }
            i++;
        } while (i < TotalCnt);
    }
    else
    {
        events.Add(eventdata);
    }
    HttpContext.Current.Session["events"] = events;
    return events;
}
public class MyEvent
{
    public int? EventID { get; set; }
    public string EventName { get; set; }
    public string StartDate { get; set; }
    public string EndDate { get; set; }
    public bool IsRecurring { get; set; }
    public string Freq { get; set; }
    public string ByDay { get; set; }
    public int Count { get; set; }
    public int Interval { get; set; }
    public bool allDay = false;
}

Ex 3:- A monthly recurring Event
In this example an outside event is dragged on the calendar. On the event click that particular event is made monthly recurrent. Client side code is similar as above.

img5

img7

public class RecMthEvent
{
    public int? EventID { get; set; }
    public string EventName { get; set; }
    public string StartDate { get; set; }
    public string EndDate { get; set; }
    public bool IsRecurring { get; set; }
    public string Freq { get; set; }
    public double DayInterval { get; set; }
    public int Count { get; set; }
    public int Interval { get; set; }
    public bool allDay = false;
}

[System.Web.Services.WebMethod]
public static List<RecMthEvent> AddEvents(RecMthEvent eventdata)
{
    List<RecMthEvent> events;
    if (HttpContext.Current.Session["events"] != null)
        events = (List<RecMthEvent>)HttpContext.Current.Session["events"];
    else
        events = new List<RecMthEvent>();
    string stDate = eventdata.StartDate;
    string EndDate = eventdata.EndDate;
    DateTime dtStart = DateTime.Parse(stDate.Split(',')[1] + stDate.Split(',')[2]);
    DateTime dtEnd = DateTime.Parse(EndDate.Split(',')[1] + EndDate.Split(',')[2]);

    int TotalCnt = eventdata.Count;
    TimeSpan ts = dtEnd - dtStart;
    for (int r = 0; r < TotalCnt; r++)
    {
        RecMthEvent _MyEvent = new RecMthEvent();
        int CurrMonth = dtStart.Month;
        DateTime dtStart2 = dtStart.AddMonths(eventdata.Interval);
        int DestMonth = dtStart2.Month;
        dtStart2 = dtStart2.AddDays(-(dtStart.Day-1));
        dtStart2 = dtStart2.AddDays(eventdata.DayInterval - 1);
        DateTime dtEnd2 = dtStart2.Add(ts);
        dtStart = dtStart2;

        _MyEvent.EventID = eventdata.EventID + r;
        _MyEvent.StartDate = dtStart2.DayOfWeek + ", " + dtStart2;
        _MyEvent.EndDate = dtEnd2.DayOfWeek + ", " + dtEnd2;
        _MyEvent.EventName = eventdata.EventName;
        events.Add(_MyEvent);
    }
    return events;
}

That’s all for now. Thanks for reading.

Advertisements
This entry was posted in External Open Source APIs, JQuery and tagged , . Bookmark the permalink.

5 Responses to Exploring JQuery plugin ‘FullCalendar’.

  1. angelo says:

    Hi, is there any chance you can post a ,net project/solution showing how to accomplish this using your code snippets?

    I would love to look at this and figure out how to add custom fields as well, say like an Event has an associated cost and a status as well.

    Regards
    Angelo

  2. Ajay Panwar says:

    This is good code.But you can try implement step by step.

  3. Jefferson Ciotti says:

    Could make available for download ? Tks

  4. Justin says:

    What version of fullcalendar are you using?

    Thanks

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s