使用 Grails 与 jQuery 创建 Web Calendar

红薯 发布于 2010/06/25 14:02
阅读 1K+
收藏 6

Grails 是一套用于快速 Web 应用开发的开源框架,它基于 Groovy 编程语言,并构建于 Spring、Hibernate 和其它标准 Java 框架之上,从而为大家带来一套能实现超高生产力的一站式框架。

jQuery 是一个 JavaScript 库,它有助于简化 JavaScript™ 以及 Asynchronous JavaScript + XML (Ajax) 编程。与类似的 JavaScript 库不同,jQuery 具有独特的基本原理,可以简洁地表示常见的复杂代码。

jQuery Plugin(jQuery 插件)是对于 jQuery 框架现有功能的一种标准扩展方式。开发人员可以通过这种方式去扩展 jQuery 的现有功能,并可通过 jQuery 社区发布。jQuery Plugin 大大扩展了 jQuery 的功能,并有利于其他开发者重复使用。一些功能强大 jQuery Plugin,如本文将要使用 FullCalendar、qTip 更是大大简化了复杂 Web 应用程序开发,缩短了开发周期。

示例程序

本文将要利用 Grails, jQuery 及其插件创建一个 Ajax 的 Web Calendar。用户可以通过使用 Ajax 的日程表界面的去直观地查看管理日程。本文就如何灵活使用 Grails 这种快速开发框架,发布成 JSON 数据服务,并结合 jQuery 及其插件动态展现日程数据将进行介绍和讨论。

背景介绍

目前很多著名的互联网公司都发布了 Web Calendar,如 Google、Yahoo、微软等。相对于传统的 Web Calendar,最新的程序将用户日程都以日程表这种直观的方式展现给终端用户,并可以按月、周、日等不同周期展示。同时配合 Ajax 技术,使用局部内容动态更新,大大提高了用户体验。

如果使用传统的 Web 开发框架,开发一个这样的 Web Calendar 的周期会相对较长。从持久层的数据模型和数据源,业务逻辑层的服务和控制器,到 Web 的前端展示,传统开发方式需要花费较大精力分别开发各个组件。而 Grails 这种新的 Web 开发框架出现,解决上述问题。它采用了类似于 Ruby on Rails 框架的开发方式,并使用 Groovy 语言作为开发语言,使得程序代码简洁,并可以通过 Grails 本身提供的功能方便地将数据服务发布为 JSON 格式。对于很多 Ajax 程序来说,JSON 格式数据相对于 XML 格式更容易在浏览器端解析和处理。对于完成类似于在线日历这种复杂的 Ajax 应用,jQuery 作为一个功能强大的轻量级 javascript 框架,可以大大简化复杂的 DOM 操作和 javascript 编程。其丰富强大的插件库更是进一步简化方便了开发工作。本文就将使用 jQuery 的 FullCalendar 和 qTip 插件,来辅助 Web 前端开发。

整体构架图,如下图所示:


图 1. 构架图
图 1. 构架图

主要步骤

本文所涉及的示例程序开发将包含以下主要步骤:

  1. 使用 Grails 创建日程管理相关的页面和服务。
    1. 创建 Grails 项目 MyCalendar。
    2. 创建领域对象 CalendarEvent,并使用 Grails 自动产生该领域对象的 Controller 和 View 代码,以实现对该领域对象的 CRUD 的操作页面及服务。
    3. 添加更多服务,并以 JSON 数据格式发布。
  2. 使用 jQuery 及其插件定义日历用户界面。
    1. 创建 Grails 页面并安装配置 jQuery 及其插件,包括 FullCalendar、qTip。
    2. 使用 FullCalendar 插件调用 JSON 数据格式发布的服务,并展现为日历界面。
    3. 使用 qTip 插件展示日程详细信息。
  3. 运行示例程序。

创建 Grails 项目 MyCalendar

首先下载 Grails(参见参考资源),本文示例代码是基于 Grails 1.1.1 的。对于编辑器,使用 Eclipse 或者一般的文本编辑器都可以。

将 grails-bin-1.1.1.zip 解压到 c:\ grails-1.1.1 下。设置环境变量 GRAILS_HOME 为 c:\ grails-1.1.1,并添加 grails 命令(%GRAILS_HOME%/bin 目录)到 PATH 变量中。

打开命令行窗口,进入工作目录,并运行命令 grails create-app MyCalendar创建一个 新的 Grails 项目。运行后,Grails 会在当前目录下创建 MyCalendar 目录,并产生其它项目相关文件。

创建领域对象(Domain Class)

进入 MyCalendar 目录,运行命令 grails create-domain-class CalendarEvent,Grails 将会产生 grails-app/domain/CalendarEvent.groovy 文件。用文本编辑器打开 CalendarEvent.groovy,添加成员变量 description,startDate, endDate, allDay(见清单 1)。


清单 1. Domain Class CalendarEvent

				
class CalendarEvent {
String description //description of the event
Date startDate //event start date
Date endDate //event end date
Boolean allDay //is all day event?

static constraints = {
}
}

 

继续创建 Controller 和 Views,在 MyCalendar 目录下运行命令 grails generate-all CalendarEvent。Grails 将会产生如下 controller 文件。

  • grails-app\controllers\CalendarEventController.groovy

和 views 文件

  • grails-app\views\calendarEvent\create.gsp
  • grails-app\views\calendarEvent\edit.gsp
  • grails-app\views\calendarEvent\list.gsp
  • grails-app\views\calendarEvent\show.gsp

运行命令 grails run-app,并打开浏览器访问 http://localhost:8080/MyCalendar

在 Grails 生成的 Web 应用中,用户可以创建、编辑、查看 CalendarEvent,完成 CRUD 的操作。

通过上述步骤可以看到,使用 Grails 创建一个完整可运行的 Web 程序非常的方便。对于示例程序来说,上述步骤基本实现了程序的持久层、业务逻辑层和展现层,为业务对象 CalendarEvent 建立了 CRUD 的基本操作。在接下来的步骤中,本文将基于刚才生成的代码,添加更多日程管理相关的服务。

添加日程查看和管理服务

在 Grails 项目中 , 修改 Grails Controller 对象 grails-app/controllers/CalendarEventController.groovy 并添加下列服务。

查看日程服务

首先为 CalendarEventController.groovy 添加 listAsJson 方法。该方法将为 FullCalendar 插件提供日程数据查询服务,以 JSON 数据格式返回日程查询结果。由于 Grails 提供了从 java 到 JSON 数据转换的方法 render <java object> as JSON,大大简化了开发任务。 代码清单如下:


清单 2. 查看日程服务方法

				
def listAsJson = {
def fcal = Calendar.getInstance()
if(params.start) fcal.setTime(new Date(Long.parseLong(params.start)))
def lcal = Calendar.getInstance()
if(params.end) lcal.setTime(new Date(Long.parseLong(params.end)))

def listOfEvents = CalendarEvent.findAll("from CalendarEvent as \
ce where ce.startDate>:startDate AND ce.endDate<:endDate", \
[startDate: fcal.getTime(), endDate: lcal.getTime()])

def listOfJsEvents = []
listOfEvents.each{ event->
def jsEvent = [:]
jsEvent.id = event.id
jsEvent.title = event.description?.length()>15? \
event.description?.substring(0, 14)+"..." : event.description
jsEvent.description = event.description
jsEvent.start = event.startDate
jsEvent.end = event.endDate
jsEvent.showTime = true
jsEvent.url = "show?id=${event.id}"
jsEvent.className = "scheduled"
jsEvent.allDay = event.allDay
listOfJsEvents.add(jsEvent)
}
render listOfJsEvents as JSON
}

 

当 FullCalendar 插件运行在用户的浏览器上的时候,将会异步地发送 HTTP 查询请求到服务器,查询并展示某时间范围内的日程数据。

  • 服务发布的 URL:http://localhost:8080/MyCalendar/calendarEvent/listAsJson,
  • 参数:
    • start:查询起始时间
    • end:查询结束时间

服务器将查询结果以 JSON 数据格式返回给用户的浏览器。FullCalendar 插件接收并解析返回 JSON 数据,并图形化地将用户日程展现在用户浏览器上。

日程管理服务

为了让用户可以在 FullCalendar 图形化的日程界面上很直观地管理日程。MyCalendar 将提供相应日程管理服务。由于篇幅有限,本文仅以取消日程服务为例,示例开发过程。

在 Grails Controller 中添加 deletedWithJson 方法,并实现取消删除日程服务逻辑。运行在用户浏览器端的 jQuery 及 FullCalendar 插件可以发送取消日程 HTTP 请求到服务器端,服务器接受请求并删除相关日程,并以 JSON 格式数据返回服务器执行结果。代码清单如下:


清单 3. 取消日程服务方法

				
def deletedWithJson = {
def resultAsJson = [result: "success", message: "The event has been deleted."]
def calendarEventInstance = CalendarEvent.get( params.id )
if(calendarEventInstance) {
try {
calendarEventInstance.delete()
flash.message = "CalendarEvent ${params.id} deleted"
redirect(action:list)
} catch(org.springframework.dao.DataIntegrityViolationException e) {
resultAsJson.result = "fail"
resultAsJson.message = "Database error, failed to delete the event."
}
} else {
resultAsJson.result = "fail"
resultAsJson.message = "CalendarEvent not found in database."
}
render resultAsJson as JSON
}

 

发布服务如下:

  • 服务发布 URL:http://localhost:8080/MyCalendar/calendarEvent/deletedWithJson
  • 参数:
    • id:要取消的日程 id

当服务请求完成完毕,将会返回执行结果。

定义日历用户界面

前面文章中,我们利用 Grails,快速创建了一个完整可用的 Web Calendar 程序。通过该程序,用户可以管理查看日程。但是该程序采用了传统的方式展示和管理页面,并没有使用 Ajax 等技术,对于 Web 2.0 时代的 Web 应用程序来说,用户体验并不友好。本文将使用 jQuery 及其插件对程序前端进行改造,为用户提供全新的直观友好的界面,以提高程序的可用性和用户体验。

添加 listAsCalendar 方法到 CalendarEventController.groovy,内容为空。在 grails-app\views\calendarEvent 目录下创建 listAsCalendar.gsp 页面(建议拷贝同目录下 show.gsp,在该页面基础上修改)。

  • 定义日历界面显示 div 位置
    添加 <div id='calendar'></div>到 页面中。
  • 定义日历 loading 信息提示
    添加 <div id='loading' style='display:none'>loading...</div>到页面中。
  • 添加样式定义,确定日历与 loading 信息的位置与大小。

安装配置 jQuery 和 FullCalendar 插件

首先安装 jQuery 到 MyCalendar 项目中,运行命令 grails install-plugin jquery。运行该命令后,Grails 将会更新插件列表,并下载 plugin zip 包到 <user home>\.grails\<version>\plugins\ 下。建立并解压 plugin zip 包到目录 <user home>/.grails/<version>/projects/MyCalendar/plugins/jquery-1.3.2.4 下。自动执行 post-install 脚本,脚本将会下载 jQuery 最新 js 文件并拷贝到 <project home>/web-app/js 目录。

安装 FullCalendar 和 qTip 插件。

  • 下载 FullCalendar 的 zip 文件(见参考资源),并解压。
  • 下载 qTip 插件 ( 见参考资料 ),并解压。
  • 把解压所得 js 文件拷贝到 web-app\js\jquery 目录。
  • 将 css 文件拷贝到 web-app\css 目录。

因为 Grails 采用 siteMesh( 见参考资源 ) 作为页面底层布局框架,所以可以通过修改项目的 MyCalendar\grails-app\views\layouts\main.gsp 文件将 jQuery 引用到各个页面中。因为本示例程序只在 listAsCalendar.gsp 页面使用 jQuery 及其插件,所以只需在该页面引用 jQuery 及相关资源。编辑 listAsCalendar.gsp,添加对该页面使用的 js 和 css 资源的引用。如清单 4 所示:


清单 4. 添加对 js、css 资源引用

				
<head>
. . .
<g:javascript src="jquery/jquery-1.3.2.min.js" />
<g:javascript src="jquery/fullcalendar.min.js" />
<g:javascript src="jquery/jquery.ui.core.js" />
<g:javascript src="jquery/jquery.ui.draggable.js" />
<g:javascript src="jquery/qtip-1.0.0-rc3.min.js" />
<link rel="stylesheet" href="${createLinkTo(dir:'css',file:'fullcalendar.css')}" />
. . .
</head>

 

使用 FullCalendar 生成日历界面

在 jQuery 框架中,$(document).ready() 方法所定义的 function 将会在整个页面被浏览器读取完毕时调用。初始化 FullCalendar 对象的工作可以在该方法中定义。初始化 FullCalendar 将调用 $('#calendar').fullCalendar({})函 数。

FullCalendar 主要的配置选项有:

  • draggable: boolean
    日程项是否可拖拽。
  • timeFormat: string
    日程项的日期显示格式。具体参数可以参考 FullCalendar 文档(见参考资源)。
  • loading: function(isLoading)
    当 FullCalendar 正在读取日程列表时,isLoading 为 true。当完成时,为 false。
  • eventRender: function(calEvent, element)
    每个日程项被渲染的时候,都会被调用该方法。 calEvent 是日程项的 javascript 数据对象,element 是一个 jQuery 元素,它是最终显示在页面上的对象。
  • events: array/string/function(start, end, callback)
    通过 array、string 或 function 的方式设置将展示的日程项数据。如需要将以 Ajax 的方式动态获取日程,则可使用 function 来实现。本示例使用了 function 来动态获取日程数据。

示例代码清单如下:


清单 5. 配置实例化 FullCalendar

				
$(document).ready(function() {
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
events: function(start, end, callback) {
// do some asynchronous ajax
$.getJSON("listAsJson",
{
start: start.getTime(),
end: end.getTime()
},
function(result) {
//reset timezone from server
for(var i=0;i<result.length; i++){
result[i].start = \
$.fullCalendar.parseISO8601(result[i].start, false);
result[i].end = \
$.fullCalendar.parseISO8601(result[i].end, false);
}
callback(result);
});
},
loading: function(bool) {
if (bool) $('#loading').show();
else $('#loading').hide();
},
eventRender: function(calEvent, element) {

//render event details as Qtip tooltip
}
});
});

 

上面代码中 FullCalendar() 方法将会初始化日历组件,并

  • 查询 JSON 数据格式的日程数据,在日历界面上展现查询结果;
  • 定义 eventRender 事件 , 当鼠标移动到相关日程上时,显示日程详细信息,并提供取消该日程的按钮;
  • 定义 loading 事件,当页面读取时显示“loading”。

使用 qTip 展示日程详细信息

为了展现详细的日程信息并提供管理按钮,本文采用了 jQuery qTip 插件。qTip 主要可配置项如下:

  • content:
    显示的 tooltip html 内容。
  • position:
    指定 tooltip 显示的位置,如当前位置的右上角、左下角等。
  • show:
    如何显示 tooltip 以及其显示效果,时间等。
  • hide:
    如何隐藏 tooltip 以及其显示效果,时间等。
  • style:
    设置 tooltip 的显示效果如宽度、边长、css 等。

在 FullCalendar eventRender 中添加 qTip 的展示代码。如下清单所示:


清单 6. 配置并实例化 qTip

				
eventRender: function(calEvent, element) {
element.qtip({
content:
'<p><b>Description</b>:<br/>'+calEvent.description+'</p><br/>\
<p><b>Start</b>:<br/>'+calEvent.start+'</p><br/>\
<p><b>End</b>:<br/>'+calEvent.end+'</p><br/>\
<p><input type="button" onclick=\"cancelEvent('+calEvent.id+');\"\
value=\"Cancel\"></p>',
position: {
corner: {
target:'rightTop',
tooltip:'leftBottom'
}
},
show: {solo: true},
hide: {
delay: 800
},
style: {
border:{
radius: 8,
width: 3
},
padding: '5px 15px', // Give it some extra padding
tip: true,
name: 'cream' // And style it with the preset dark theme
}
});
return element;
}

 

上述代码清单中,当用户点击“Cancel”按钮时,将会触发 cancelEvent() 事件。该方法将会发送请求到服务器,调用取消日程服务,取消指定日程。代码清单如下:

清单 7. 取消日程方法

 function cancelEvent(id) { 
$.ajax({
url: 'deletedWithJson',
type: 'GET',
data: {id:id},
dataType: 'json',
timeout: 1000,
error: function(){
alert('Error can not connect to server.');
},
success: function(data){
if(data.result=='fail'){
alert('Error delete event in database');
}else {
$('#calendar').fullCalendar('removeEvents', id);
}
}
});
}

示例运行结果

运行 grails run-app。访问 http://localhost:8080/MyCalendar,访问创建日程事件页面。


图 2. 创建日程表单页面
图 2. 创建日程表单页面

查看日程列表,该日程项已经被创建。如下图:


图 3. 日程列表页面
图 3. 日程列表页面

访问 calendar 展示页面 http://localhost:8080/MyCalendar/calendarEvent/listAsCalendar

, 即可查看用户日程(可按月、周、日查看)。


图 4. 日程展示页面(按月展示)
图 4. 日程展示页面(按月展示)

查看本周日程。


图 5. 日程展示页面(按周展示)
图 5. 日程展示页面(按周展示)

将鼠标移动到各个日程项上,将会得到 qTip 的日程信息提示,以便即时查看具体日程的详细信息。


图 6. 日程详细信息
图 6. 日程详细信息

点击“Cancel”可以取消并删除该日程。


图 7. 取消日程
图 7. 取消日程

不需要刷新当前页面,已取消的日程将会自动消失。


图 8. 取消后的日程展示页面
图 8. 取消后的日程展示页面

通过 Grails 日程项列表页面查看,该日程已经被取消。


图 9. 日程列表页面
图 9. 日程列表页面

结束语

本文使用了 Grails,介绍了如何结合 jQuery 及 FullCalendar 插件开发 Ajax 效果的 Web Calendar。通过本文示例程序开发过程,大家可以看到,Grails 可以方便的使用流行的 Javascript 开发框架,如 jQuery,快速开发 Ajax 应用程序。并且 Grails 能够很方便的将服务发布为 JSON 或其他数据交换格式,使得 Grails 和 Javascript 框架之间能够方便地交互。

加载中
OSCHINA
登录后可查看更多优质内容
返回顶部
顶部