Monday, January 16, 2012

Implement drag drop events from outside in Full Calender for an ajax based data source

Introduction
With this post I will try to describe Full Calender plugin with drag and drop feature where we can drag and drop events from an Ajax based event data source outside the calender. For this to implement we need to know basics about jQuery and full calender plugin. We can get the plugin detail form this URL.

Details goes here-
CSS used in this post goes here-
   <style type='text/css'>
        body
        {
            margin-top: 40px;
            text-align: center;
            font-size: 14px;
            font-family: "Lucida Grande" ,Helvetica,Arial,Verdana,sans-serif;
        }
        #wrap
        {
            width: 1100px;
            margin: 0 auto;
        }
        #external-events
        {
            float: left;
            width: 150px;
            padding: 0 10px;
            border: 1px solid #ccc;
            background: #eee;
            text-align: left;
        }
        #external-events h4
        {
            font-size: 16px;
            margin-top: 0;
            padding-top: 1em;
        }
        .external-event
        {
            margin: 10px 0;
            padding: 2px 4px;
            background: #3366CC;
            color: #fff;
            font-size: .85em;
            cursor: pointer;
        }
        #external-events p
        {
            margin: 1.5em 0;
            font-size: 11px;
            color: #666;
        }
        #external-events p input
        {
            margin: 0;
            vertical-align: middle;
        }
        #calendar
        {
            float: right;
            width: 900px;
        }
    </style>
For this to work we need to take some CSS and JS files as a reference as follows-
    <link rel='stylesheet' type='text/css' href='http://arshaw.com/js/fullcalendar-1.5.2/fullcalendar/fullcalendar.css' />
    <link rel='stylesheet' type='text/css' href='http://arshaw.com/js/fullcalendar-1.5.2/fullcalendar/fullcalendar.print.css'
        media='print' />

    <script type='text/javascript' src='http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.js'></script>

    <script type='text/javascript' src='http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.9/jquery-ui.js'></script>

    <script type='text/javascript' src='http://arshaw.com/js/fullcalendar-1.5.2/fullcalendar/fullcalendar.min.js'></script>
We can implement a full calender in a div like container as follows-
    <div id='calendar'>
    </div>
            $('#calendar').fullCalendar({
                header: {
                    left: 'prev,next today',
                    center: 'title',
                    right: 'month,agendaWeek,agendaDay'
                },
                editable: true,
                droppable: true,
                drop: function(date, allDay) {
                //drop functionality goes here
                }
            });
Now the basic construct for the problem is done. Lets add a div in the page as a container and list all the events on the div using Ajax. We will now implement drag and drop such that we can drag an event form the list of events and add the events to calender by dropping it into the full calender. To list the events in a div using Ajax we can use page method like below-
    <div id='external-events'>
        <h4>
            Draggable Events</h4>
        
        <p id="events">
            <input type='checkbox' id='drop-remove' />
            <label for='drop-remove'>
                remove after drop</label>
        </p>
    </div> 
            $.ajax({
                url: "Fill draggable events area of FullCalendar.aspx/GetEvents",
                type: "POST",
                dataType: "json",
                contentType: "application/json; charset=utf-8",
                success: function(data) {
                    $(data.d).each(function(i, item) {
                        $("#events").before($("<div class='external-event'></div>").html(item.EventName));
                    });
                },
                error: function(XMLHttpRequest, textStatus, errorThrown) {
                    debugger;
                    alert(textStatus);
                }
            });
    [System.Web.Services.WebMethod]
    public static object GetEvents()
    {
        var obj = new { EventName = "My Event 1"};
        var objList = (new[] { obj }).ToList();
        objList.Add(new { EventName = "My Event 2" });
        objList.Add(new { EventName = "My Event 3" });
        objList.Add(new { EventName = "My Event 4" });
        objList.Add(new { EventName = "My Event 5" });
        objList.Add(new { EventName = "My Event 6" });
        objList.Add(new { EventName = "My Event 7" });
        return objList;
    }
In the above code we have some in memory object as event datasource. We can change to any data source as we need.
Now we need to make the event divs, constructed in the above js code, as draggable. We can do this by implementing the draggable UI plugin by modifying the success method of the Ajax call like below-
                success: function(data) {
                    $(data.d).each(function(i, item) {
                        $("#events").before($("<div class='external-event'></div>").html(item.EventName));
                    });
                    $('#external-events div.external-event').each(function() {
                        var eventObject = {
                            title: $.trim($(this).text())
                        };

                        $(this).data('eventObject', eventObject);

                        $(this).draggable({
                            zIndex: 999,
                            revert: true,
                            revertDuration: 0
                        });
                    });
                }
And finally we can implement drop functionality of the full calender plugin to accept the draggable events and we can achieve this by modifying the full calender jquery call as below-
            $('#calendar').fullCalendar({
                header: {
                    left: 'prev,next today',
                    center: 'title',
                    right: 'month,agendaWeek,agendaDay'
                },
                editable: true,
                droppable: true,
                drop: function(date, allDay) {

                    var originalEventObject = $(this).data('eventObject');

                    var copiedEventObject = $.extend({}, originalEventObject);

                    copiedEventObject.start = date;
                    copiedEventObject.allDay = allDay;

                    $('#calendar').fullCalendar('renderEvent', copiedEventObject, true);

                    if ($('#drop-remove').is(':checked')) {
                        $(this).remove();
                    }

                }
            });

2 comments:

  1. Great help! How can I include unique background colors for the drag-and-drop events, specified with the ajax fetch?

    ReplyDelete
  2. Anup,

    Your blog on integrating MySQL and PHP with FullCalendar has been very to me. I came across this blog which further helped me with dragging and dropping external events. I have success with populating external events of varying number and color. I understand how the above code will replicate the properties of dragged events onto the calendar. I am not able to assign multiple object properties to the external events. I implemented your '$("#events").before($("").html(item.EventName));', and it is great.

    My question is, how can I attach more properties in this, or a similar fashion.

    Thanks in advance,
    Jack

    ReplyDelete