Fixed smart event segmentation in list view; added table view (derived from list view) as alternative

This commit is contained in:
Thomas Bruederli 2011-06-11 13:31:24 -06:00
parent 5f7e3b6029
commit b45566de9e
7 changed files with 405 additions and 72 deletions

View file

@ -739,7 +739,7 @@ function rcube_calendar(settings)
header: { header: {
left: 'prev,next today', left: 'prev,next today',
center: 'title', center: 'title',
right: 'agendaDay,agendaWeek,month,list' right: 'agendaDay,agendaWeek,month,list,table'
}, },
aspectRatio: 1, aspectRatio: 1,
ignoreTimezone: false, // will translate event dates to the client's timezone ignoreTimezone: false, // will translate event dates to the client's timezone
@ -754,20 +754,25 @@ function rcube_calendar(settings)
slotMinutes : 60/settings['timeslots'], slotMinutes : 60/settings['timeslots'],
timeFormat: { timeFormat: {
'': settings['time_format'], '': settings['time_format'],
list: settings['time_format'] + '{ - ' + settings['time_format'] + '}' list: settings['time_format'] + '{ - ' + settings['time_format'] + '}',
table: settings['time_format'] + '{ - ' + settings['time_format'] + '}'
}, },
axisFormat : settings['time_format'], axisFormat : settings['time_format'],
columnFormat: { columnFormat: {
month: 'ddd', // Mon month: 'ddd', // Mon
week: 'ddd ' + settings['date_short'], // Mon 9/7 week: 'ddd ' + settings['date_short'], // Mon 9/7
day: 'dddd ' + settings['date_short'] // Monday 9/7 day: 'dddd ' + settings['date_short'], // Monday 9/7
list: settings['date_agena'],
table: settings['date_agena']
}, },
titleFormat: { titleFormat: {
month: 'MMMM yyyy', month: 'MMMM yyyy',
week: settings['date_long'].replace(/ yyyy/, '[ yyyy]') + "{ '—' " + settings['date_long'] + "}", week: settings['date_long'].replace(/ yyyy/, '[ yyyy]') + "{ '—' " + settings['date_long'] + "}",
day: 'dddd ' + settings['date_long'], day: 'dddd ' + settings['date_long'],
list: settings['date_long'] list: settings['date_long'],
table: settings['date_long']
}, },
smartSections: true,
defaultView: settings['default_view'], defaultView: settings['default_view'],
allDayText: rcmail.gettext('all-day', 'calendar'), allDayText: rcmail.gettext('all-day', 'calendar'),
buttonText: { buttonText: {
@ -776,7 +781,7 @@ function rcube_calendar(settings)
week: rcmail.gettext('week', 'calendar'), week: rcmail.gettext('week', 'calendar'),
month: rcmail.gettext('month', 'calendar'), month: rcmail.gettext('month', 'calendar'),
list: rcmail.gettext('agenda', 'calendar'), list: rcmail.gettext('agenda', 'calendar'),
basicDay: 'basic' table: rcmail.gettext('table', 'calendar')
}, },
selectable: true, selectable: true,
selectHelper: true, selectHelper: true,
@ -785,7 +790,7 @@ function rcube_calendar(settings)
}, },
// event rendering // event rendering
eventRender: function(event, element, view) { eventRender: function(event, element, view) {
if (view.name != 'list') if (view.name != 'list' && view.name != 'table')
element.attr('title', event.title); element.attr('title', event.title);
if (view.name == 'month') { if (view.name == 'month') {
/* attempt to limit the number of events displayed /* attempt to limit the number of events displayed
@ -940,7 +945,7 @@ function rcube_calendar(settings)
var shift_enddate = function(dateText) { var shift_enddate = function(dateText) {
var newstart = parse_datetime('0', dateText); var newstart = parse_datetime('0', dateText);
var newend = new Date(newstart.getTime() + $('#edit-startdate').data('duration') * 1000); var newend = new Date(newstart.getTime() + $('#edit-startdate').data('duration') * 1000);
$('#edit-enddate').val($.fullCalendar.formatDate(newend, cal.settings['date_format'])); $('#edit-enddate').val($.fullCalendar.formatDate(newend, me.settings['date_format']));
}; };
// init event dialog // init event dialog

View file

@ -370,6 +370,7 @@ class calendar extends rcube_plugin
else else
$this->rc->output->show_message('calendar.errorsaving', 'error'); $this->rc->output->show_message('calendar.errorsaving', 'error');
// TODO: keep view and date selection
if ($success && $reload) if ($success && $reload)
$this->rc->output->redirect(''); $this->rc->output->redirect('');
} }
@ -478,6 +479,7 @@ class calendar extends rcube_plugin
$settings['date_format'] = (string)$this->rc->config->get('calendar_date_format', "yyyy/MM/dd"); $settings['date_format'] = (string)$this->rc->config->get('calendar_date_format', "yyyy/MM/dd");
$settings['date_short'] = (string)$this->rc->config->get('calendar_date_short', "M/d"); $settings['date_short'] = (string)$this->rc->config->get('calendar_date_short', "M/d");
$settings['date_long'] = (string)$this->rc->config->get('calendar_date_long', "M d yyyy"); $settings['date_long'] = (string)$this->rc->config->get('calendar_date_long', "M d yyyy");
$settings['date_agena'] = (string)$this->rc->config->get('calendar_date_agenda', "ddd M d");
$settings['time_format'] = (string)$this->rc->config->get('calendar_time_format', "HH:mm"); $settings['time_format'] = (string)$this->rc->config->get('calendar_time_format', "HH:mm");
$settings['timeslots'] = (int)$this->rc->config->get('calendar_timeslots', 2); $settings['timeslots'] = (int)$this->rc->config->get('calendar_timeslots', 2);
$settings['first_day'] = (int)$this->rc->config->get('calendar_first_day', 1); $settings['first_day'] = (int)$this->rc->config->get('calendar_first_day', 1);

View file

@ -40,6 +40,9 @@ $rcmail_config['calendar_date_short'] = 'M-d';
// long date format (used for calendar title) // long date format (used for calendar title)
$rcmail_config['calendar_date_long'] = 'MMM d yyyy'; $rcmail_config['calendar_date_long'] = 'MMM d yyyy';
// date format used for agenda view
$rcmail_config['calendar_date_agenda'] = 'ddd MM-dd';
// timeslots per hour (1, 2, 3, 4, 6) // timeslots per hour (1, 2, 3, 4, 6)
$rcmail_config['calendar_timeslots'] = 2; $rcmail_config['calendar_timeslots'] = 2;

View file

@ -1,5 +1,5 @@
--- js/fullcalendar.js.orig 2011-06-04 13:45:44.000000000 -0600 --- js/fullcalendar.js.orig 2011-06-04 13:45:44.000000000 -0600
+++ js/fullcalendar.js 2011-06-08 14:30:33.000000000 -0600 +++ js/fullcalendar.js 2011-06-10 09:27:50.000000000 -0600
@@ -47,12 +47,14 @@ @@ -47,12 +47,14 @@
titleFormat: { titleFormat: {
month: 'MMMM yyyy', month: 'MMMM yyyy',
@ -34,7 +34,7 @@
+ thisWeek: 'This week', + thisWeek: 'This week',
+ nextWeek: 'Next week', + nextWeek: 'Next week',
+ thisMonth: 'This month', + thisMonth: 'This month',
+ nextMonth: 'Next Month', + nextMonth: 'Next month',
+ future: 'Future events' + future: 'Future events'
}, },
@ -59,19 +59,19 @@
rangeStart = start; rangeStart = start;
rangeEnd = end; rangeEnd = end;
- cache = []; - cache = [];
+ cache = typeof src != 'undefined' ? $.grep(cache, function(e) { return !isSourcesEqual(e.source, source); }) : []; + cache = typeof src != 'undefined' ? $.grep(cache, function(e) { return !isSourcesEqual(e.source, src); }) : [];
var fetchID = ++currentFetchID; var fetchID = ++currentFetchID;
var len = sources.length; var len = sources.length;
- pendingSourceCnt = len; - pendingSourceCnt = len;
+ pendingSourceCnt = typeof src == 'undefined' ? len : 1; + pendingSourceCnt = typeof src == 'undefined' ? len : 1;
for (var i=0; i<len; i++) { for (var i=0; i<len; i++) {
- fetchEventSource(sources[i], fetchID); - fetchEventSource(sources[i], fetchID);
+ if (typeof src == 'undefined' || src == sources[i]) + if (typeof src == 'undefined' || isSourcesEqual(sources[i], src))
+ fetchEventSource(sources[i], fetchID); + fetchEventSource(sources[i], fetchID);
} }
} }
@@ -5205,4 +5221,307 @@ @@ -5205,4 +5221,309 @@
} }
@ -269,6 +269,8 @@
+ +
+ lazySegBind(segContainer, seg, bindSeg); + lazySegBind(segContainer, seg, bindSeg);
+ } + }
+
+ markFirstLast(getListContainer());
+ } + }
+ +
+ function bindSeg(event, eventElement, seg) { + function bindSeg(event, eventElement, seg) {
@ -364,7 +366,7 @@
+ } + }
+ +
+ function setHeight(height, dateChanged) { + function setHeight(height, dateChanged) {
+ body.css('height', height+'px').css('overflow', 'auto'); + body.css('height', (height-1)+'px').css('overflow', 'auto');
+ } + }
+ +
+ function setWidth(width) { + function setWidth(width) {

View file

@ -48,13 +48,15 @@ var defaults = {
month: 'MMMM yyyy', month: 'MMMM yyyy',
week: "MMM d[ yyyy]{ '&#8212;'[ MMM] d yyyy}", week: "MMM d[ yyyy]{ '&#8212;'[ MMM] d yyyy}",
day: 'dddd, MMM d, yyyy', day: 'dddd, MMM d, yyyy',
list: 'MMM d, yyyy' list: 'MMM d, yyyy',
table: 'MMM d, yyyy'
}, },
columnFormat: { columnFormat: {
month: 'ddd', month: 'ddd',
week: 'ddd M/d', week: 'ddd M/d',
day: 'dddd M/d', day: 'dddd M/d',
list: 'dddd, yyyy' list: 'dddd, MMM d, yyyy',
table: 'dddd, MMM d, yyyy'
}, },
timeFormat: { // for event elements timeFormat: { // for event elements
'': 'h(:mm)t' // default '': 'h(:mm)t' // default
@ -76,7 +78,8 @@ var defaults = {
month: 'month', month: 'month',
week: 'week', week: 'week',
day: 'day', day: 'day',
list: 'list' list: 'list',
table: 'table'
}, },
listTexts: { listTexts: {
from: 'from', from: 'from',
@ -91,6 +94,9 @@ var defaults = {
future: 'Future events' future: 'Future events'
}, },
// list options
smartSections: false,
// jquery-ui theming // jquery-ui theming
theme: false, theme: false,
buttonIcons: { buttonIcons: {
@ -5230,8 +5236,11 @@ function ListEventRenderer() {
// exports // exports
t.renderEvents = renderEvents; t.renderEvents = renderEvents;
t.renderEventTime = renderEventTime;
t.compileDaySegs = compileSegs; // for DayEventRenderer t.compileDaySegs = compileSegs; // for DayEventRenderer
t.clearEvents = clearEvents; t.clearEvents = clearEvents;
t.lazySegBind = lazySegBind;
t.sortCmp = sortCmp;
// imports // imports
DayEventRenderer.call(t); DayEventRenderer.call(t);
@ -5265,9 +5274,12 @@ function ListEventRenderer() {
function compileSegs(events) { function compileSegs(events) {
var segs = []; var segs = [];
var colFormat = opt('columnFormat', 'day'); var colFormat = opt('titleFormat', 'day');
var event, i, dd, md, seg, segHash, curSegHash, segDate, curSeg = -1; var firstDay = opt('firstDay');
var smartSegs = opt('smartSections');
var event, i, dd, wd, md, seg, segHash, curSegHash, segDate, curSeg = -1;
var today = clearTime(new Date()); var today = clearTime(new Date());
var weekstart = addDays(cloneDate(today), -((today.getDay() - firstDay + 7) % 7));
for (i=0; i < events.length; i++) { for (i=0; i < events.length; i++) {
event = events[i]; event = events[i];
@ -5280,40 +5292,33 @@ function ListEventRenderer() {
// create smart sections such as today, tomorrow, this week, next week, next month, ect. // create smart sections such as today, tomorrow, this week, next week, next month, ect.
segDate = cloneDate(event.start < t.start && event.end > t.start ? t.start : event.start, true); segDate = cloneDate(event.start < t.start && event.end > t.start ? t.start : event.start, true);
dd = dayDiff(segDate, today); dd = dayDiff(segDate, today);
wd = Math.floor(dayDiff(segDate, weekstart) / 7);
md = segDate.getMonth() + ((segDate.getYear() - today.getYear()) * 12) - today.getMonth(); md = segDate.getMonth() + ((segDate.getYear() - today.getYear()) * 12) - today.getMonth();
// past events // build section title
if (dd < 0) { if (!smartSegs) {
segHash = formatDate(segDate, colFormat);
} else if (dd < 0) {
segHash = opt('listTexts', 'past'); segHash = opt('listTexts', 'past');
} } else if (dd == 0) {
// today
else if (dd == 0) {
segHash = opt('listTexts', 'today'); segHash = opt('listTexts', 'today');
} } else if (dd == 1) {
else if (dd == 1) {
segHash = opt('listTexts', 'tomorrow'); segHash = opt('listTexts', 'tomorrow');
} } else if (wd == 0) {
// this week
else if (dd < 7) {
segHash = opt('listTexts', 'thisWeek'); segHash = opt('listTexts', 'thisWeek');
} } else if (wd == 1) {
// next week
else if (dd >= 7 && dd < 14 && md == 0) {
segHash = opt('listTexts', 'nextWeek'); segHash = opt('listTexts', 'nextWeek');
} } else if (md == 0) {
else if (md == 0) {
segHash = opt('listTexts', 'thisMonth'); segHash = opt('listTexts', 'thisMonth');
} } else if (md == 1) {
else if (md == 1) {
segHash = opt('listTexts', 'nextMonth'); segHash = opt('listTexts', 'nextMonth');
} } else {
else {
segHash = formatDate(segDate, colFormat); segHash = formatDate(segDate, colFormat);
} }
// start new segment // start new segment
if (segHash != curSegHash) { if (segHash != curSegHash) {
segs[++curSeg] = { events: [], start: segDate, title: segHash, daydiff: dd }; segs[++curSeg] = { events: [], start: segDate, title: segHash, daydiff: dd, weekdiff: wd, monthdiff: md };
curSegHash = segHash; curSegHash = segHash;
} }
@ -5329,11 +5334,9 @@ function ListEventRenderer() {
function renderSegs(segs, modifiedEventId) { function renderSegs(segs, modifiedEventId) {
var tm = opt('theme') ? 'ui' : 'fc'; var tm = opt('theme') ? 'ui' : 'fc';
var timeFormat = opt('timeFormat');
var dateFormat = opt('titleFormat');
var headerClass = tm + "-widget-header"; var headerClass = tm + "-widget-header";
var contentClass = tm + "-widget-content"; var contentClass = tm + "-widget-content";
var i, j, seg, event, duration, s, skinCss, skinCssAttr, classes, time, segHeader, segContainer, eventElements; var i, j, seg, event, times, s, skinCss, skinCssAttr, classes, segHeader, segContainer, eventElements;
for (j=0; j < segs.length; j++) { for (j=0; j < segs.length; j++) {
seg = segs[j]; seg = segs[j];
@ -5344,7 +5347,7 @@ function ListEventRenderer() {
for (i=0; i < seg.events.length; i++) { for (i=0; i < seg.events.length; i++) {
event = seg.events[i]; event = seg.events[i];
times = renderEventTime(event, seg);
skinCss = getSkinCss(event, opt); skinCss = getSkinCss(event, opt);
skinCssAttr = (skinCss ? " style='" + skinCss + "'" : ''); skinCssAttr = (skinCss ? " style='" + skinCss + "'" : '');
classes = ['fc-event', 'fc-event-skin', 'fc-event-vert', 'fc-corner-left', 'fc-corner-right', 'fc-corner-top', 'fc-corner-bottom']; classes = ['fc-event', 'fc-event-skin', 'fc-event-vert', 'fc-corner-left', 'fc-corner-right', 'fc-corner-top', 'fc-corner-bottom'];
@ -5352,31 +5355,13 @@ function ListEventRenderer() {
classes = classes.concat(event.source.className); classes = classes.concat(event.source.className);
} }
// event time/date range to display
times = [];
duration = event.end.getTime() - event.start.getTime();
if (event.start < seg.start) {
times.push(opt('listTexts', 'until') + ' ' + formatDate(event.end, (event.allDay || event.end.getDate() != seg.start.getDate()) ? dateFormat : timeFormat));
} else if (duration > DAY_MS) {
times.push(formatDates(event.start, event.end, dateFormat + '[ - ' + dateFormat + ']'));
} else if (seg.daydiff > 1 && seg.daydiff < 7) {
times.push(formatDate(event.start, 'ddd'));
} else if (seg.daydiff > 1 || seg.daydiff < 0) {
times.push(formatDate(event.start, dateFormat));
}
if (!times.length && event.allDay) {
times.push(opt('allDayText'));
} else if (duration < DAY_MS && !event.allDay) {
times.push(formatDates(event.start, event.end, timeFormat))
}
s += s +=
"<div class='" + classes.join(' ') + "'" + skinCssAttr + ">" + "<div class='" + classes.join(' ') + "'" + skinCssAttr + ">" +
"<div class='fc-event-inner fc-event-skin'" + skinCssAttr + ">" + "<div class='fc-event-inner fc-event-skin'" + skinCssAttr + ">" +
"<div class='fc-event-head fc-event-skin'" + skinCssAttr + ">" + "<div class='fc-event-head fc-event-skin'" + skinCssAttr + ">" +
"<div class='fc-event-time'>" + "<div class='fc-event-time'>" +
htmlEscape(times.join(' ')) + (times[0] ? '<span class="fc-col-date">' + times[0] + '</span> ' : '') +
(times[1] ? '<span class="fc-col-time">' + times[1] + '</span>' : '') +
"</div>" + "</div>" +
"</div>" + "</div>" +
"<div class='fc-event-content'>" + "<div class='fc-event-content'>" +
@ -5405,7 +5390,7 @@ function ListEventRenderer() {
eventElement = $(triggerRes).appendTo(segContainer); eventElement = $(triggerRes).appendTo(segContainer);
} }
if (event._id === modifiedEventId) { if (event._id === modifiedEventId) {
bindSeg(event, eventElement, seg); eventElementHandlers(event, eventElement, seg);
} else { } else {
eventElement[0]._fci = i; // for lazySegBind eventElement[0]._fci = i; // for lazySegBind
} }
@ -5413,14 +5398,42 @@ function ListEventRenderer() {
} }
} }
lazySegBind(segContainer, seg, bindSeg); lazySegBind(segContainer, seg, eventElementHandlers);
} }
markFirstLast(getListContainer()); markFirstLast(getListContainer());
} }
function bindSeg(event, eventElement, seg) { // event time/date range to display
eventElementHandlers(event, eventElement); function renderEventTime(event, seg) {
var timeFormat = opt('timeFormat');
var dateFormat = opt('columnFormat');
var duration = event.end.getTime() - event.start.getTime();
var datestr = '', timestr = '';
if (!opt('smartSections')) {
// no date display if grouped by day
} else if (event.start < seg.start) {
datestr = opt('listTexts', 'until') + ' ' + formatDate(event.end, (event.allDay || event.end.getDate() != seg.start.getDate()) ? dateFormat : timeFormat);
} else if (duration > DAY_MS) {
datestr = formatDates(event.start, event.end, dateFormat + '[ - ' + dateFormat + ']');
} else if (seg.daydiff == 0) {
datestr = opt('listTexts', 'today');
} else if (seg.daydiff == 1) {
datestr = opt('listTexts', 'tomorrow');
} else if (seg.weekdiff == 0 || seg.weekdiff == 1) {
datestr = formatDate(event.start, 'dddd');
} else if (seg.daydiff > 1 || seg.daydiff < 0) {
datestr = formatDate(event.start, dateFormat);
}
if (!datestr && event.allDay) {
timestr = opt('allDayText');
} else if (duration < DAY_MS && !event.allDay) {
timestr = formatDates(event.start, event.end, timeFormat);
}
return [datestr, timestr];
} }
function lazySegBind(container, seg, bindHandlers) { function lazySegBind(container, seg, bindHandlers) {
@ -5526,4 +5539,226 @@ function ListView(element, calendar) {
} }
/* Additional view: table (by bruederli@kolabsys.com)
---------------------------------------------------------------------------------*/
function TableEventRenderer() {
var t = this;
// imports
ListEventRenderer.call(t);
var opt = t.opt;
var sortCmp = t.sortCmp;
var trigger = t.trigger;
var compileSegs = t.compileDaySegs;
var reportEvents = t.reportEvents;
var reportEventClear = t.reportEventClear;
var reportEventElement = t.reportEventElement;
var eventElementHandlers = t.eventElementHandlers;
var renderEventTime = t.renderEventTime;
var showEvents = t.showEvents;
var hideEvents = t.hideEvents;
var getListContainer = t.getDaySegmentContainer;
var lazySegBind = t.lazySegBind;
var calendar = t.calendar;
var formatDate = calendar.formatDate;
var formatDates = calendar.formatDates;
// exports
t.renderEvents = renderEvents;
t.clearEvents = clearEvents;
/* Rendering
--------------------------------------------------------------------*/
function clearEvents() {
reportEventClear();
getListContainer().children('tbody').remove();
}
function renderEvents(events, modifiedEventId) {
events.sort(sortCmp);
reportEvents(events);
renderSegs(compileSegs(events), modifiedEventId);
}
function renderSegs(segs, modifiedEventId) {
var tm = opt('theme') ? 'ui' : 'fc';
var table = getListContainer();
var headerClass = tm + "-widget-header";
var contentClass = tm + "-widget-content";
var i, j, seg, event, times, s, skinCss, skinCssAttr, skinClasses, rowClasses, segHeader, segContainer, eventElements;
for (j=0; j < segs.length; j++) {
seg = segs[j];
segHeader = $('<tbody class="fc-list-header"><tr><td class="fc-list-header ' + headerClass + '" colspan="5">' + htmlEscape(seg.title) + '</td></tr></tbody>').appendTo(table);
segContainer = $('<tbody>').addClass('fc-list-section ' + contentClass).appendTo(table);
s = '';
for (i=0; i < seg.events.length; i++) {
event = seg.events[i];
times = renderEventTime(event, seg);
skinCss = getSkinCss(event, opt);
skinCssAttr = (skinCss ? " style='" + skinCss + "'" : '');
skinClasses = ['fc-event-skin', 'fc-corner-left', 'fc-corner-right', 'fc-corner-top', 'fc-corner-bottom'];
if (event.source && event.source.className) {
skinClasses = skinClasses.concat(event.source.className);
}
rowClasses = ['fc-event', 'fc-event-row', 'fc-'+dayIDs[event.start.getDay()]];
if (seg.daydiff == 0) {
rowClasses.push('fc-today');
}
s +=
"<tr class='" + rowClasses.join(' ') + "'>" +
"<td class='fc-event-handle'>" +
"<div class='" + skinClasses.join(' ') + "'" + skinCssAttr + ">" +
"<span class='fc-event-inner'></span>" +
"</div></td>" +
"<td class='fc-event-date'>" +
htmlEscape(times[0]) +
"</td>" +
"<td class='fc-event-time'>" +
htmlEscape(times[1]) +
"</td>" +
"<td class='fc-event-title'>" +
htmlEscape(event.title) +
"</td>" +
"<td class='fc-event-location'>" +
htmlEscape(event.location) +
"</td>" +
"</tr>";
}
segContainer[0].innerHTML = s;
eventElements = segContainer.children();
// retrieve elements, run through eventRender callback, bind event handlers
for (i=0; i < seg.events.length; i++) {
event = seg.events[i];
eventElement = $(eventElements[i]); // faster than eq()
triggerRes = trigger('eventRender', event, event, eventElement);
if (triggerRes === false) {
eventElement.remove();
} else {
if (triggerRes && triggerRes !== true) {
eventElement.remove();
eventElement = $(triggerRes).appendTo(segContainer);
}
if (event._id === modifiedEventId) {
eventElementHandlers(event, eventElement, seg);
} else {
eventElement[0]._fci = i; // for lazySegBind
}
reportEventElement(event, eventElement);
}
}
lazySegBind(segContainer, seg, eventElementHandlers);
markFirstLast(segContainer);
}
//markFirstLast(table);
}
}
fcViews.table = TableView;
function TableView(element, calendar) {
var t = this;
// exports
t.render = render;
t.select = dummy;
t.unselect = dummy;
t.getDaySegmentContainer = function(){ return table; };
// imports
View.call(t, element, calendar, 'table');
TableEventRenderer.call(t);
var opt = t.opt;
var trigger = t.trigger;
var clearEvents = t.clearEvents;
var reportEventClear = t.reportEventClear;
var formatDates = calendar.formatDates;
var formatDate = calendar.formatDate;
// overrides
t.setWidth = setWidth;
t.setHeight = setHeight;
// locals
var div;
var table;
var firstDay;
var nwe;
var tm;
var colFormat;
function render(date, delta) {
if (delta) {
addDays(date, delta);
if (!opt('weekends')) {
skipWeekend(date, delta < 0 ? -1 : 1);
}
}
t.title = opt('listTexts', 'from') + ' ' + formatDate(date, opt('titleFormat'));
t.start = t.visStart = cloneDate(date, true);
t.end = addDays(cloneDate(t.start), 1);
t.visEnd = addMonths(cloneDate(t.start), 1); // show events one month ahead. Enough?
updateOptions();
if (!table) {
buildSkeleton();
} else {
clearEvents();
}
}
function updateOptions() {
firstDay = opt('firstDay');
nwe = opt('weekends') ? 0 : 1;
tm = opt('theme') ? 'ui' : 'fc';
colFormat = opt('columnFormat');
}
function buildSkeleton() {
var s =
"<table class='fc-border-separate' style='width:100%' cellspacing='0'>" +
"<colgroup>" +
"<col class='fc-event-handle' />" +
"<col class='fc-event-date' />" +
"<col class='fc-event-time' />" +
"<col class='fc-event-title' />" +
"<col class='fc-event-location' />" +
"</colgroup>" +
"</table>";
div = $('<div>').addClass('fc-list-content').appendTo(element);
table = $(s).appendTo(div);
}
function setHeight(height, dateChanged) {
div.css('height', (height-1)+'px').css('overflow', 'auto');
}
function setWidth(width) {
// nothing to be done here
}
function dummy() {
// Stub.
}
}
})(jQuery); })(jQuery);

View file

@ -461,16 +461,21 @@ a.alarm-action-snooze:after {
.fc-event-hori .fc-event-time { .fc-event-hori .fc-event-time {
white-space: nowrap; white-space: nowrap;
font-weight: normal; font-weight: normal !important;
font-size: 10px; font-size: 10px;
padding-right: 0.6em; padding-right: 0.6em;
} }
.fc-grid .fc-event-time {
font-weight: normal !important;
padding-right: 0.3em;
}
.fc-event-cateories { .fc-event-cateories {
font-style:italic; font-style:italic;
} }
.fc-event-location { div.fc-event-location {
font-size: 90%; font-size: 90%;
} }
@ -504,6 +509,27 @@ a.alarm-action-snooze:after {
cursor: pointer; cursor: pointer;
} }
.fc-view-list div.fc-list-header,
.fc-view-table td.fc-list-header {
padding: 3px;
background: #dddddd;
background-image: -moz-linear-gradient(center top, #f4f4f4, #d2d2d2);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0.00, #f4f4f4), color-stop(1.00, #d2d2d2));
filter: progid:DXImageTransform.Microsoft.gradient(enabled='true', startColorstr=#f4f4f4, endColorstr=#d2d2d2, GradientType=1);
font-weight: bold;
color: #333;
}
.fc-view-list .fc-event-skin .fc-event-content {
background: #F6F6F6;
padding: 2px;
}
.fc-view-list .fc-event-skin .fc-event-title,
.fc-view-list .fc-event-skin .fc-event-location {
color: #333;
}
/* Settings section */ /* Settings section */
fieldset #calendarcategories div { fieldset #calendarcategories div {

View file

@ -619,18 +619,28 @@ table.fc-border-separate {
/* List view (by bruederli@kolabsys.com) /* List view (by bruederli@kolabsys.com)
------------------------------------------------------------------------*/ ------------------------------------------------------------------------*/
.fc-view-list { .fc-view-list,
.fc-view-table {
border: 1px solid #ccc; border: 1px solid #ccc;
width: 99%; width: 99%;
} }
.fc-view-list .fc-list-header { .fc-view-list .fc-list-header,
.fc-view-table td.fc-list-header {
border-width: 0; border-width: 0;
border-bottom-width: 1px; border-bottom-width: 1px;
padding: 2px; padding: 3px;
text-align: center; text-align: center;
} }
.fc-view-table td.fc-list-header {
_border-top-width: 1px;
}
.fc-view-table .fc-first td.fc-list-header {
border-top-width: 0;
}
.fc-list-section { .fc-list-section {
padding: 4px 2px; padding: 4px 2px;
border-width: 0; border-width: 0;
@ -645,3 +655,53 @@ table.fc-border-separate {
position: relative; position: relative;
margin: 1px 2px 3px 2px; margin: 1px 2px 3px 2px;
} }
.fc-view-table tr.fc-event td {
padding: 2px;
border-bottom: 1px solid #ccc;
}
.fc-view-table tr.fc-event td.fc-event-handle {
padding: 3px 8px 3px 3px;
}
.fc-view-table .fc-event-handle .fc-event-skin {
border-radius: 2px;
-moz-border-radius: 2px;
}
.fc-view-table .fc-event-handle .fc-event-inner {
display: block;
width: 8px;
height: 10px;
border-radius: 2px;
-moz-border-radius: 2px;
}
.fc-view-table table {
table-layout: fixed;
width: 100%;
}
.fc-view-table col.fc-event-handle {
width: 18px;
}
.fc-view-table col.fc-event-date {
width: 7em;
}
.fc-view-table col.fc-event-time {
width: 8em;
}
.fc-view-table col.fc-event-location {
width: 20%;
}
.fc-view-table td.fc-event-date,
.fc-view-table td.fc-event-time {
white-space: nowrap;
padding-right: 1em;
}