This tutorial shows how to create a simple Java web application that displays an AJAX event calendar using the open-source DayPilot Lite for Java library. It supports drag and drop operations (event creating, moving, resizing).
Included
- Full Java and JavaScript source code
- DayPilot Lite for Java 1.0.453
- Compiled war file ready for deployment
Requirements
- JRE 5 or higher
- J2EE web container (Tomcat 6 or higher)
1. HTML
Create a new HTML file (index.jsp) and add the references to jQuery and the DayPilot JavaScript libraries to the header or to the body:
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.3.2.min.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/js/daypilot/common.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/js/daypilot/calendar.js"></script>
Put a placeholder for the Calendar in the <body> :
<div id="dpc"></div>
Add the jQuery plugin initialization code:
<script type="text/javascript"> $(document).ready(function() { var dpc = $("#dpc").daypilotCalendar({ backendUrl : '${pageContext.request.contextPath}/dpc', viewType : "Week" }); }); </script>
It is necessary to specify the backendUrl property. That's the URL which handles the AJAX callback requests.
2. Libraries
JavaScript libraries
- Copy common.js and calendar.js to js/daypilot directory of your web application.
Java libraries
- Copy daypilot-lite-1.0.453.jar to WEB-INF/lib directory of your web application.
3. Servlet
We need to create the backend servlet that will supply the calendar event data and handler user actions (such as event drag and drop) on the server side.
Create a new servlet and map it to "/dpc" Url. You can do it by adding the following declaration to web.xml file:
<servlet> <description /> <display-name>DpcServlet</display-name> <servlet-name>DpcServlet</servlet-name> <servlet-class>org.daypilot.tutorial.calendar.DpcServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>DpcServlet</servlet-name> <url-pattern>/dpc</url-pattern> </servlet-mapping>
The servlet class will be very simple:
package org.daypilot.tutorial.calendar; import java.io.IOException; import java.util.Locale; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.daypilot.demo.db.Db; import org.daypilot.ui.DayPilotCalendar; import org.daypilot.ui.args.calendar.EventMoveArgs; import org.daypilot.ui.args.calendar.EventResizeArgs; import org.daypilot.ui.args.calendar.TimeRangeSelectedArgs; import org.daypilot.ui.enums.UpdateType; public class DpcServlet extends HttpServlet { private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); DayPilotCalendar dpc = new Dpc(); dpc.process(request, response); } }
This will forward the POST request to a special Dpc class (see the next step).
4. Dpc Class
Create a new Dpc class (it must inherit from org.daypilot.ui.DayPilotCalendar):
public class Dpc extends DayPilotCalendar { @Override public void onInit() throws Exception { // map the database column names setDataIdField("event_id"); setDataTextField("event_name"); setDataStartField("event_start"); setDataEndField("event_end"); // assign the collection of events setEvents(Db.getEvents(getRequest(), getStartDate().toDate(), getStartDate().addDays(getDays()).toDate())); // request an update of the event set on the client side update(); } }
The onInit() method is called using an AJAX callback right after the Calendar is initialized on the client side.
5. Event Moving
In order to handle event move action, we need to override onEventMove() method. The event arguments are available in EventMoveArgs class (ea parameter).
@Override public void eventMove(EventMoveArgs ea) throws Exception { // update the DB Db.moveEvent(getRequest(), ea.getValue(), ea.getNewStart().toTimeStamp(), ea.getNewEnd().toTimeStamp()); update(); }
Db is a helper class that will handle database access.
It has to be enabled on the client-side as well (eventMoveHandling):
<script type="text/javascript"> $(document).ready(function() { var dpc = $("#dpc").daypilotCalendar({ backendUrl : '${pageContext.request.contextPath}/dpc', viewType : "Week", eventMoveHandling : "CallBack" }); }); </script>
6. Prepare and Finish
There are two special callback lifecycle methods available:
- onPrepare()
- onFinish()
They are called during every AJAX callback request (before and after the main event method).
We will use onPrepare() to initialize an in-memory instance of a HSQLDB embedded database (which we will use for testing purposes):
public void onPrepare() throws Exception { // create the in-memory DB if it's not ready if (!Db.tableExists("EVENTS")) { Db.createTable(); } }
We will also move the event loading code there to the onFinish() method:
@Override public void onFinish() throws Exception { if (getUpdateType() == UpdateType.NONE) { return; } // set the database fields setDataIdField("event_id"); setDataTextField("event_name"); setDataStartField("event_start"); setDataEndField("event_end"); // reload events setEvents(Db.getEvents(getRequest(), getStartDate().toDate(), getStartDate().addDays(getDays()).toDate())); }
7. Event Resizing, Event Creating
Implementing event handlers is very similar to onEventMove. Just add the required database changes. Since we already added onFinish() method, you don't need to care about refreshing the events.
Our new onEventResize handler:
@Override public void onEventResize(EventResizeArgs ea) throws Exception { Db.resizeEvent(getRequest(), ea.getValue(), ea.getNewStart().toTimeStamp(), ea.getNewEnd().toTimeStamp()); update(); }
And onTimeRangeSelected handler:
@Override public void timeRangeSelected(TimeRangeSelectedArgs ea) throws Exception { Db.insertEvent(getRequest(), "New event", ea.getStart().toTimeStamp(), ea.getEnd().toTimeStamp()); update(); }
Both events need to be enabled on the client side:
<script type="text/javascript"> $(document).ready(function() { var dpc = $("#dpc").daypilotCalendar({ backendUrl : '${pageContext.request.contextPath}/dpc', viewType : "Week", eventMoveHandling : "CallBack", eventResizeHandling: "CallBack", timeRangeSelectedHandling : "CallBack" }); }); </script>