|
|
Theme:
Description & Source Code
ZK Calendar is an Ajax component readily embeddable into any Java
web application. In this demo, it's shown as a standalone, Google
Calendar like application; offering functionalities such as filtering,
detailed scheduling, multiple time zones, and daily/weekly/monthly view.
Properties such as format and style can be easily configured by setting
the calendar component's attributes. The main task for the developers is
to handle the calendar events and preparing the event data model;
similar to how other data components work in ZK. zk_calendar.zul
<zk> <style src="/widgets/application/zk_calendar/style.css" /> <window> <!-- Calendars Body --> <div apply="demo.app.zk_calendar.CalendarController"> <!-- Control Menu --> <hlayout sclass="z-valign-middle"> <button id="today" label="Today" /> <button id="prev" image="/widgets/application/zk_calendar/img/arrow-180.png"/> <button id="next" image="/widgets/application/zk_calendar/img/arrow.png"/> <separator width="50px" /> <button id="pageDay" label="Day" width="55px" /> <button id="pageWeek" label="Week" width="55px"/> <button id="pageMonth" label="Month" width="55px"/> <separator width="50px" /> Filter : <textbox id="filter"/> <button id="applyFilter" label="Apply"/> <button id="resetFilter" label="Reset"/> </hlayout> <separator bar="true" height="20px"/> <calendars id="calendars" firstDayOfWeek="Sunday" height="600px" timeZone="Main=GMT+0" mold="month"/> </div> <!-- Create/Update Event Popup --> <include src="/widgets/application/zk_calendar/calendar_editor.zul" /> <!-- Server+Client Fusion - Mouse Scroll Handling --> <script type="text/javascript" src="/js/lib/jquery.mousewheel.min.js" /> <script type="text/javascript" src="/widgets/application/zk_calendar/scroll.js" /> </window> </zk> calendar_editor.zul
<div apply="org.zkoss.bind.BindComposer"
viewModel="@id('vm') @init('demo.app.zk_calendar.CalendarEditorViewModel')"
validationMessages="@id('vmsgs')">
<window title="Create Calendar Event" border="normal" width="400px"
form="@id('fx') @load(vm.calendarEvent) @save(vm.calendarEvent, before='ok') @validator(vm.dateValidator)"
allDay="@ref(vm.isAllDay(fx.beginDate,fx.endDate))"
mode="popup" visible="@load(vm.visible)" position="center,center" >
<caption>
Lock this event : <checkbox checked="@bind(fx.locked)" />
All Day: <checkbox checked="@load(allDay)" disabled="true" />
</caption>
<grid hflex='1'>
<columns>
<column width="100px" align="right" />
<column />
</columns>
<rows>
<row>
BeginDate:
<div>
<datebox hflex="true" locale="en" timeZone="GMT+0"
format="@load(allDay ? 'long' : 'long+medium')"
value="@bind(fx.beginDate)" errorMessage="@load(vmsgs.beginDate)" />
</div>
</row>
<row>
EndDate:
<div>
<datebox hflex="true" locale="en" timeZone="GMT+0"
format="@load(allDay ? 'long' : 'long+medium')"
value="@bind(fx.endDate)" errorMessage="@load(vmsgs.endDate)"/>
</div>
</row>
<row>
Color:
<hlayout sclass="z-valign-middle">
Border -
<colorbox value="@bind(fx.headerColor)" height="20px" />
Content -
<colorbox value="@bind(fx.contentColor)" height="20px" />
</hlayout>
</row>
<row>
Title:
<textbox multiline="true" rows="3" width="97%"
value="@bind(fx.content)" />
</row>
<row>
<cell colspan="2" style="text-align:center;">
<button label="OK" onClick="@command('ok')" width="80px" />
<button label="Cancel" onClick="@command('cancel')" width="80px" />
<button label="Delete" onClick="@command('delete')" width="80px" />
</cell>
</row>
</rows>
</grid>
</window>
</div>
style.css
.selectedButton .z-button-cm {
font-weight: bold;
}
.chooser-popup div.z-popup-cl {
border: none;
}
.chooser-popup .z-popup-cnt {
padding: 0;
}
.chooser-popup .z-groupbox {
-moz-border-radius: 1px 1px 1px 1px;
}scroll.js
var calenderWidget; //ZK Calendar client side widget
zk.afterMount(function() {
calenderWidget = zk.Widget.$(jq("$calendars")); // ZK id selector
//Mouse wheel Handle - change month
jq('$calendars').bind(
'mousewheel',
function(event, delta) {
if (calenderWidget.getMold() == "month") { //Only month mold need this
zAu.send(new zk.Event(calenderWidget, 'onMoveViewDate',delta > 0 ? 1 : -1));
return false;
}
return true;
}
);
});CalendarController.java
package demo.app.zk_calendar;
import java.util.Calendar;
import java.util.TimeZone;
import org.zkoss.calendar.Calendars;
import org.zkoss.calendar.event.CalendarsEvent;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.select.SelectorComposer;
import org.zkoss.zk.ui.select.annotation.Listen;
import org.zkoss.zk.ui.select.annotation.Wire;
import org.zkoss.zkmax.ui.select.annotation.Subscribe;
import org.zkoss.zul.Textbox;
public class CalendarController extends SelectorComposer<Component> {
private static final long serialVersionUID = 1L;
@Wire
private Calendars calendars;
@Wire
private Textbox filter;
private DemoCalendarModel calendarModel;
//the in editing calendar ui event
private CalendarsEvent calendarsEvent = null;
@Override
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
calendarModel = new DemoCalendarModel(new DemoCalendarData().getCalendarEvents());
calendars.setModel(this.calendarModel);
}
//control the calendar position
@Listen("onClick = #today")
public void gotoToday(){
TimeZone timeZone = calendars.getDefaultTimeZone();
calendars.setCurrentDate(Calendar.getInstance(timeZone).getTime());
}
@Listen("onClick = #next")
public void gotoNext(){
calendars.nextPage();
}
@Listen("onClick = #prev")
public void gotoPrev(){
calendars.previousPage();
}
//control page display
@Listen("onClick = #pageDay")
public void changeToDay(){
calendars.setMold("default");
calendars.setDays(1);
}
@Listen("onClick = #pageWeek")
public void changeToWeek(){
calendars.setMold("default");
calendars.setDays(7);
}
@Listen("onClick = #pageMonth")
public void changeToYear(){
calendars.setMold("month");
}
//control the filter
@Listen("onClick = #applyFilter")
public void applyFilter(){
calendarModel.setFilterText(filter.getValue());
calendars.setModel(calendarModel);
}
@Listen("onClick = #resetFilter")
public void resetFilter(){
filter.setText("");
calendarModel.setFilterText("");
calendars.setModel(calendarModel);
}
//listen to the calendar-create and edit of a event data
@Listen("onEventCreate = #calendars; onEventEdit = #calendars")
public void createEvent(CalendarsEvent event) {
calendarsEvent = event;
//to display a shadow when editing
calendarsEvent.stopClearGhost();
DemoCalendarEvent data = (DemoCalendarEvent)event.getCalendarEvent();
if(data == null) {
data = new DemoCalendarEvent();
data.setHeaderColor("#3366ff");
data.setContentColor("#6699ff");
data.setBeginDate(event.getBeginDate());
data.setEndDate(event.getEndDate());
} else {
data = (DemoCalendarEvent) event.getCalendarEvent();
}
//notify the editor
QueueUtil.lookupQueue().publish(
new QueueMessage(QueueMessage.Type.EDIT,data));
}
//listen to the calendar-update of event data, usually send when user drag the event data
@Listen("onEventUpdate = #calendars")
public void updateEvent(CalendarsEvent event) {
DemoCalendarEvent data = (DemoCalendarEvent) event.getCalendarEvent();
data.setBeginDate(event.getBeginDate());
data.setEndDate(event.getEndDate());
calendarModel.update(data);
}
//listen to queue message from other controller
@Subscribe(value = QueueUtil.QUEUE_NAME)
public void handleQueueMessage(QueueMessage message) {
switch(message.getType()){
case DELETE:
calendarModel.remove((DemoCalendarEvent)message.getData());
//clear the shadow of the event after editing
calendarsEvent.clearGhost();
calendarsEvent = null;
break;
case OK:
if (calendarModel.indexOf((DemoCalendarEvent)message.getData()) >= 0) {
calendarModel.update((DemoCalendarEvent)message.getData());
} else {
calendarModel.add((DemoCalendarEvent)message.getData());
}
case CANCEL:
//clear the shadow of the event after editing
calendarsEvent.clearGhost();
calendarsEvent = null;
break;
}
}
}
CalendarEditorViewModel.java
package demo.app.zk_calendar;
import java.util.Date;
import java.util.Map;
import org.zkoss.bind.BindUtils;
import org.zkoss.bind.Property;
import org.zkoss.bind.ValidationContext;
import org.zkoss.bind.Validator;
import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.Init;
import org.zkoss.bind.annotation.NotifyChange;
import org.zkoss.bind.validator.AbstractValidator;
import org.zkoss.zk.ui.event.EventListener;
public class CalendarEditorViewModel {
private DemoCalendarEvent calendarEventData = new DemoCalendarEvent();
private boolean visible = false;
public DemoCalendarEvent getCalendarEvent() {
return calendarEventData;
}
public boolean isVisible() {
return visible;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
@Init
public void init() {
//subscribe a queue, listen to other controller
QueueUtil.lookupQueue().subscribe(new QueueListener());
}
private void startEditing(DemoCalendarEvent calendarEventData) {
this.calendarEventData = calendarEventData;
visible = true;
//reload entire view-model data when going to edit
BindUtils.postNotifyChange(null, null, this, "*");
}
public boolean isAllDay(Date beginDate,Date endDate) {
int M_IN_DAY = 1000 * 60 * 60 * 24;
boolean allDay = false;
if(beginDate != null && endDate != null) {
long between = endDate.getTime() - beginDate.getTime();
allDay = between > M_IN_DAY;
}
return allDay;
}
public Validator getDateValidator(){
return new AbstractValidator(){
@Override
public void validate(ValidationContext ctx) {
Map<String,Property> formData = ctx.getProperties(ctx.getProperty().getValue());
Date beginDate = (Date)formData.get("beginDate").getValue();
Date endDate = (Date)formData.get("endDate").getValue();
if(beginDate==null){
addInvalidMessage(ctx, "beginDate","Begin date is empty");
}
if(endDate==null){
addInvalidMessage(ctx, "endDate","End date is empty");
}
if(beginDate!=null && endDate!=null && beginDate.compareTo(endDate) >= 0){
addInvalidMessage(ctx, "endDate","End date is before begin date");
}
}
};
}
@Command
@NotifyChange("visible")
public void cancel() {
QueueMessage message = new QueueMessage(QueueMessage.Type.CANCEL);
QueueUtil.lookupQueue().publish(message);
this.visible = false;
}
@Command
@NotifyChange("visible")
public void delete() {
QueueMessage message = new QueueMessage(QueueMessage.Type.DELETE, calendarEventData);
QueueUtil.lookupQueue().publish(message);
this.visible = false;
}
@Command
@NotifyChange("visible")
public void ok() {
QueueMessage message = new QueueMessage(QueueMessage.Type.OK, calendarEventData);
QueueUtil.lookupQueue().publish(message);
this.visible = false;
}
private class QueueListener implements
EventListener<QueueMessage> {
@Override
public void onEvent(QueueMessage message)
throws Exception {
if (QueueMessage.Type.EDIT.equals(message.getType())){
CalendarEditorViewModel.this.startEditing((DemoCalendarEvent)message.getData());
}
}
}
}
QueueMessage.java
package demo.app.zk_calendar;
import org.zkoss.zk.ui.event.Event;
public class QueueMessage extends Event {
private static final long serialVersionUID = 1L;
static public enum Type {
EDIT, OK, DELETE, CANCEL;
}
private Type type;
private Object data;
public QueueMessage(Type type) {
super("onCalendarMessage");
this.type = type;
}
public QueueMessage(Type type, Object data) {
this(type);
this.data = data;
}
public Type getType() {
return type;
}
public Object getData() {
return data;
}
}
DemoCalendarData.java
package demo.app.zk_calendar;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import org.zkoss.calendar.api.CalendarEvent;
public class DemoCalendarData {
private List<CalendarEvent> calendarEvents = new LinkedList<CalendarEvent>();
private final SimpleDateFormat DATA_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm");
private Calendar cal = Calendar.getInstance();
public DemoCalendarData() {
init();
}
private void init() {
int mod = cal.get(Calendar.MONTH) + 1;
int year = cal.get(Calendar.YEAR);
String date2 = mod > 9 ? year + "/" + mod + "" : year + "/" + "0" + mod;
String date1 = --mod > 9 ? year + "/" + mod + "" : year + "/" + "0" + mod;
++mod;
String date3 = ++mod > 9 ? year + "/" + mod + "" : year + "/" + "0" + mod;
// Red Events
calendarEvents.add(new DemoCalendarEvent(getDate(date1 + "/28 00:00"), getDate(date1 + "/29 00:00"), "#A32929", "#D96666", "ZK Jet Released"));
calendarEvents.add(new DemoCalendarEvent(getDate(date1 + "/04 02:00"), getDate(date1 + "/05 03:00"), "#A32929", "#D96666", "Experience ZK SpreadSheet Live Demo!"));
calendarEvents.add(new DemoCalendarEvent(getDate(date2 + "/21 05:00"), getDate(date2 + "/21 07:00"), "#A32929", "#D96666", "New Features of ZK Spreadsheet"));
calendarEvents.add(new DemoCalendarEvent(getDate(date2 + "/08 00:00"), getDate(date2 + "/09 00:00"), "#A32929", "#D96666", "ZK Spreadsheet Released"));
// Blue Events
calendarEvents.add(new DemoCalendarEvent(getDate(date1 + "/29 03:00"), getDate(date2 + "/02 06:00"), "#3467CE", "#668CD9", "ZK Released"));
calendarEvents.add(new DemoCalendarEvent(getDate(date2 + "/02 10:00"), getDate(date2 + "/02 12:30"), "#3467CE", "#668CD9", "New Feature of ZK "));
calendarEvents.add(new DemoCalendarEvent(getDate(date2 + "/17 14:00"), getDate(date2 + "/18 16:00"), "#3467CE", "#668CD9", "Case Study - Mecatena"));
calendarEvents.add(new DemoCalendarEvent(getDate(date3 + "/01 14:30"), getDate(date3 + "/01 17:30"), "#3467CE", "#668CD9", "ZK Unit Testing Project - zunit"));
// Purple Events
calendarEvents.add(new DemoCalendarEvent(getDate(date1 + "/29 08:00"), getDate(date2 + "/03 12:00"), "#7A367A", "#B373B3", "ZK Studio released"));
calendarEvents.add(new DemoCalendarEvent(getDate(date2 + "/07 08:00"), getDate(date2 + "/07 12:00"), "#7A367A", "#B373B3", "Tutorial : Reading from the DB with Netbeans and ZK"));
calendarEvents.add(new DemoCalendarEvent(getDate(date2 + "/13 11:00"), getDate(date2 + "/13 14:30"), "#7A367A", "#B373B3", "Small talk - ZK Charts"));
calendarEvents.add(new DemoCalendarEvent(getDate(date2 + "/16 14:00"), getDate(date2 + "/18 16:00"), "#7A367A", "#B373B3", "Style Guide for ZK released !"));
calendarEvents.add(new DemoCalendarEvent(getDate(date3 + "/02 12:00"), getDate(date3 + "/02 17:00"), "#7A367A", "#B373B3", "Small talk -- Simple Database Access From ZK"));
// Khaki Events
calendarEvents.add(new DemoCalendarEvent(getDate(date1 + "/03 00:00"), getDate(date1 + "/04 00:00"), "#88880E", "#BFBF4D", "ZK UK User Group"));
calendarEvents.add(new DemoCalendarEvent(getDate(date2 + "/13 05:00"), getDate(date2 + "/13 07:00"), "#88880E", "#BFBF4D", "How to Test ZK Application with Selenium"));
calendarEvents.add(new DemoCalendarEvent(getDate(date2 + "/24 19:30"), getDate(date2 + "/24 20:00"), "#88880E", "#BFBF4D", "ZK Alfresco Talk"));
calendarEvents.add(new DemoCalendarEvent(getDate(date3 + "/03 00:00"), getDate(date3 + "/04 00:00"), "#88880E", "#BFBF4D", "ZK selected as SourceForge.net Project of the Month"));
// Green Events
calendarEvents.add(new DemoCalendarEvent(getDate(date1 + "/28 10:00"), getDate(date1 + "/28 12:30"), "#0D7813", "#4CB052", "ZK Mobile Released"));
calendarEvents.add(new DemoCalendarEvent(getDate(date2 + "/03 00:00"), getDate(date2 + "/03 05:30"), "#0D7813", "#4CB052", "ZK Gmaps released"));
calendarEvents.add(new DemoCalendarEvent(getDate(date2 + "/05 20:30"), getDate(date2 + "/06 00:00"), "#0D7813", "#4CB052", "Refresh with Five New ZK Themes!"));
calendarEvents.add(new DemoCalendarEvent(getDate(date2 + "/23 00:00"), getDate(date2 + "/25 16:30"), "#0D7813", "#4CB052", "ZK Roadmap Announced"));
calendarEvents.add(new DemoCalendarEvent(getDate(date3 + "/01 08:30"), getDate(date3 + "/01 19:30"), "#0D7813", "#4CB052", "Build Database CRUD Application in 6 Steps"));
}
private Date getDate(String dateText) {
try {
return DATA_FORMAT.parse(dateText);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
public List<CalendarEvent> getCalendarEvents() {
return calendarEvents;
}
}
DemoCalendarEvent.java
package demo.app.zk_calendar;
import java.util.Date;
import org.zkoss.calendar.impl.SimpleCalendarEvent;
public class DemoCalendarEvent extends SimpleCalendarEvent {
private static final long serialVersionUID = 1L;
public DemoCalendarEvent(Date beginDate, Date endDate, String headerColor, String contentColor, String content) {
setHeaderColor(headerColor);
setContentColor(contentColor);
setContent(content);
setBeginDate(beginDate);
setEndDate(endDate);
}
public DemoCalendarEvent(Date beginDate, Date endDate, String headerColor, String contentColor, String content,
String title) {
setHeaderColor(headerColor);
setContentColor(contentColor);
setContent(content);
setTitle(title);
setBeginDate(beginDate);
setEndDate(endDate);
}
public DemoCalendarEvent(Date beginDate, Date endDate, String headerColor, String contentColor, String content,
String title, boolean locked) {
setHeaderColor(headerColor);
setContentColor(contentColor);
setContent(content);
setTitle(title);
setBeginDate(beginDate);
setEndDate(endDate);
setLocked(locked);
}
public DemoCalendarEvent() {
setHeaderColor("#FFFFFF");
setContentColor("#000000");
}
}
DemoCalendarModel.java
package demo.app.zk_calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.zkoss.calendar.api.CalendarEvent;
import org.zkoss.calendar.api.RenderContext;
import org.zkoss.calendar.impl.SimpleCalendarModel;
public class DemoCalendarModel extends SimpleCalendarModel {
private static final long serialVersionUID = 1L;
private String filterText = "";
public DemoCalendarModel(List<CalendarEvent> calendarEvents) {
super(calendarEvents);
}
public void setFilterText(String filterText) {
this.filterText = filterText;
}
@Override
public List<CalendarEvent> get(Date beginDate, Date endDate, RenderContext rc) {
List<CalendarEvent> list = new LinkedList<CalendarEvent>();
long begin = beginDate.getTime();
long end = endDate.getTime();
for (Iterator<?> itr = _list.iterator(); itr.hasNext();) {
Object obj = itr.next();
CalendarEvent ce = obj instanceof CalendarEvent ? (CalendarEvent)obj : null;
if(ce == null) break;
long b = ce.getBeginDate().getTime();
long e = ce.getEndDate().getTime();
if (e >= begin && b < end && ce.getContent().toLowerCase().contains(filterText.toLowerCase()))
list.add(ce);
}
return list;
}
}
|
|
|
|
|
Theme:
|