Thought I’d throw another option in here as I’m working on something like this right now… though ours is more scoped for payroll data than appointments … UI is similar.
I learned this technique at ServoyWorld 2012 in a session with Patrick about Solution Model:
Done 100% with solution model… I’ve attached a sample (this is Patrick’s code from sw2012 he shared as a demo, so I think it’s probably OK to share here?)
there’s a LOT more utility code (getting the time / date from an x-y co-ordinate for example) in the sample (and our production implementation extends it a lot further) but the basic idea is :
Draw a new calendar with solution model :
function setupCalendar_week() {
//remove any old forms
elements.calendar.removeAllTabs();
history.removeForm("calendar_week");
solutionModel.removeForm("calendar_week");
//create a new solution model form
var _jsForm = solutionModel.newForm("calendar_week", null, "calendar", false, 770, 1040);
_jsForm.navigator = SM_DEFAULTS.NONE;
//add some variables to needed to render the calendar
var _jsVariable = _jsForm.newVariable("_formWidth",JSVariable.INTEGER);
_jsVariable.defaultValue = 780;
_jsVariable = _jsForm.newVariable("_startDate",JSVariable.DATETIME);
_jsVariable.defaultValue = _startDate;
//create a couple of solution model methods to track events
_jsForm.onResize = _jsForm.newMethod("function onResize(event) { forms.calendar_base.onResize_weekCalendar(event); }");
_jsForm.newMethod("function onDoubleClick(event) { forms.calendar_base.onDoubleClick(event); }");
//start from a point on the screen...
var _initialY = 35;
//draw the time labels
for (var t = 1; t <= 24; t++) {
var _lblTime = _jsForm.newLabel(utils.dateFormat(new Date(0,0,0,t-1,0,0),"HH:mm"), 10, _initialY + ((t-1)*40), 50, 40);
_lblTime.name = "lbl_times_" + (t-1);
if (t == 24) {
_lblTime.styleClass = "times_bottom";
} else {
_lblTime.styleClass = "times";
}
}
//draw the calendar grid
var _initialX = 60;
var _onActionGridCell = _jsForm.newMethod("function onAction_grid(event) { forms.calendar_base.onCellClicked(event); }");
for (var d = 1; d <= 7; d++) {
var _lblHeader = _jsForm.newLabel(utils.dateFormat(new Date(_startDate.getFullYear(),_startDate.getMonth(),_startDate.getDate() + (d-1),0,0,0),"EEE dd.MM."), _initialX + (100*(d-1)), _initialY - 20, 100, 20);
_lblHeader.name = "lbl_header_day_" + d;
_lblHeader.styleClass = "day_header";
for (var dt = 1; dt <= 48; dt++) {
var _lblGrid = _jsForm.newLabel("", _initialX + (100*(d-1)), _initialY + ((dt-1)*20), 100, 20);
_lblGrid.name = "lbl_grid_" + d + "_" + (dt%2==0 ? (dt-2)/2 : (dt-1)/2) + "_" + (dt%2==0 ? 2 : 1);
if (dt == 48) {
_lblGrid.styleClass = "grid_absolute_bottom";
} else if (dt%2==0) {
_lblGrid.styleClass = "grid_bottom";
} else {
_lblGrid.styleClass = "grid_top";
}
if (d == 7) {
_lblGrid.styleClass += "_right";
}
_lblGrid.onAction = _onActionGridCell;
_lblGrid.showClick = false;
}
}
//enable resizing of elements
setClientDesignHandles();
if (!forms["calendar_week"].controller.getDesignMode()) {
forms["calendar_week"].controller.setDesignMode(onDrag, onDrop, onSelected, onResize);
}
elements.calendar.addTab("calendar_week");
}
to add events :
//get the top left grid element for x-y references
var _startElement = _jsForm.getComponent("lbl_grid_1_0_1");
var _startX = _startElement.x;
var _startY = _startElement.y;
var _elementWidth = _startElement.width;
var _dayOfWeek;
var _columnsPerDay;
for (i = 0; i < _eventsToAdd.length; i++) {
var _event = _eventsToAdd[i];
if (_dayOfWeek != _event.getDayOfWeek() || !_columnsPerDay) {
_dayOfWeek = _event.getDayOfWeek();
_columnsPerDay = getMaxColumnsPerDay(_dayOfWeek, _eventsToAdd);
}
var _x = _startX + _elementWidth * (_event.getDayOfWeek() - 1);
var _height = Math.ceil((_event.end - _event.start) / 1000 / 60 * (20 / 30));
var _y = _startY + _event.start.getHours() * 40 + _event.start.getMinutes() * (20 / 30);
var _displayText = "<html><body>" + utils.dateFormat(_event.start,"HH:mm") + " - " + utils.dateFormat(_event.end,"HH:mm") + "
" + _event.subject + "</body></html>";
var _eventWidth = (_elementWidth - _eventRightOffset) * (1 / (_event.overlappingEvents.length > 0 ? _columnsPerDay : 1));
var _eventX = _x + (_columnsPerDay > 1 && _event.overlappingEvents.length > 0 ? (_event.overlapColumn - 1) * _eventWidth : 0);
// create the element
var _eventElement = _jsForm.newLabel(_displayText, _eventX, _y, _eventWidth, _height);
_eventElement.name = "event_" + _event.uuid;
_eventElement.background = _event.color;
_eventElement.styleClass = "event";
_eventElement.formIndex = 99999;
_eventElement.borderType = _event.border;
_eventElement.toolTipText = _event.getTooltip();
_event.x = _eventX;
_event.width = _eventWidth;
// add event to _events array
_events.push(_event);
}
//redraw the screen once the events are added
forms["calendar_week"].controller.recreateUI();
the sample data is again from SW2012 so you’ll probably have to click back to may 2012 before you see any data on screen!
calendar.servoy (23.1 KB)