First shot on agenda view: hacked into fullcalendar script
This commit is contained in:
parent
1bab608d2c
commit
830db74112
7 changed files with 724 additions and 18 deletions
|
@ -31,6 +31,8 @@ function rcube_calendar(settings)
|
|||
this.alarm_dialog = null;
|
||||
this.snooze_popup = null;
|
||||
this.dismiss_link = null;
|
||||
this.selected_event = null;
|
||||
this.selected_calendar = null;
|
||||
this.eventcount = [];
|
||||
|
||||
|
||||
|
@ -82,7 +84,7 @@ function rcube_calendar(settings)
|
|||
{
|
||||
var fromto, duration = event.end.getTime() / 1000 - event.start.getTime() / 1000;
|
||||
if (event.allDay)
|
||||
fromto = $.fullCalendar.formatDate(event.start, settings['date_format']) + (duration > 86400 ? ' — ' + $.fullCalendar.formatDate(event.end, settings['date_format']) : '');
|
||||
fromto = $.fullCalendar.formatDate(event.start, settings['date_format']) + (duration > 86400 || event.start.getDay() != event.end.getDay() ? ' — ' + $.fullCalendar.formatDate(event.end, settings['date_format']) : '');
|
||||
else if (duration < 86400 && event.start.getDay() == event.end.getDay())
|
||||
fromto = $.fullCalendar.formatDate(event.start, settings['date_format']) + ' ' + $.fullCalendar.formatDate(event.start, settings['time_format']) + ' — '
|
||||
+ $.fullCalendar.formatDate(event.end, settings['time_format']);
|
||||
|
@ -178,6 +180,7 @@ function rcube_calendar(settings)
|
|||
|
||||
var $dialog = $("#eventedit");
|
||||
var calendar = event.calendar && me.calendars[event.calendar] ? me.calendars[event.calendar] : { editable:action=='new' };
|
||||
me.selected_event = event;
|
||||
|
||||
// reset dialog first, enable/disable fields according to editable state
|
||||
$('#eventtabs').get(0).reset();
|
||||
|
@ -613,9 +616,10 @@ function rcube_calendar(settings)
|
|||
calendar = { name:'', color:'cc0000' };
|
||||
|
||||
// reset form first
|
||||
$('#calendarform > form').get(0).reset();
|
||||
var form = $('#calendarform > form');
|
||||
form.get(0).reset();
|
||||
|
||||
var name = $('#calendar-name').val(calendar.name);
|
||||
var name = $('#calendar-name').val(calendar.editname || calendar.name);
|
||||
var color = $('#calendar-color').val(calendar.color).miniColors('value', calendar.color);
|
||||
|
||||
// dialog buttons
|
||||
|
@ -735,7 +739,7 @@ function rcube_calendar(settings)
|
|||
header: {
|
||||
left: 'prev,next today',
|
||||
center: 'title',
|
||||
right: 'agendaDay,agendaWeek,month'
|
||||
right: 'agendaDay,agendaWeek,month,list'
|
||||
},
|
||||
aspectRatio: 1,
|
||||
ignoreTimezone: false, // will translate event dates to the client's timezone
|
||||
|
@ -748,7 +752,10 @@ function rcube_calendar(settings)
|
|||
firstDay : settings['first_day'],
|
||||
firstHour : settings['first_hour'],
|
||||
slotMinutes : 60/settings['timeslots'],
|
||||
timeFormat: settings['time_format'],
|
||||
timeFormat: {
|
||||
'': settings['time_format'],
|
||||
list: settings['time_format'] + '{ - ' + settings['time_format'] + '}'
|
||||
},
|
||||
axisFormat : settings['time_format'],
|
||||
columnFormat: {
|
||||
month: 'ddd', // Mon
|
||||
|
@ -758,7 +765,8 @@ function rcube_calendar(settings)
|
|||
titleFormat: {
|
||||
month: 'MMMM yyyy',
|
||||
week: settings['date_long'].replace(/ yyyy/, '[ yyyy]') + "{ '—' " + settings['date_long'] + "}",
|
||||
day: 'dddd ' + settings['date_long']
|
||||
day: 'dddd ' + settings['date_long'],
|
||||
list: settings['date_long']
|
||||
},
|
||||
defaultView: settings['default_view'],
|
||||
allDayText: rcmail.gettext('all-day', 'calendar'),
|
||||
|
@ -766,7 +774,9 @@ function rcube_calendar(settings)
|
|||
today: settings['today'],
|
||||
day: rcmail.gettext('day', 'calendar'),
|
||||
week: rcmail.gettext('week', 'calendar'),
|
||||
month: rcmail.gettext('month', 'calendar')
|
||||
month: rcmail.gettext('month', 'calendar'),
|
||||
list: rcmail.gettext('agenda', 'calendar'),
|
||||
basicDay: 'basic'
|
||||
},
|
||||
selectable: true,
|
||||
selectHelper: true,
|
||||
|
@ -775,7 +785,8 @@ function rcube_calendar(settings)
|
|||
},
|
||||
// event rendering
|
||||
eventRender: function(event, element, view) {
|
||||
element.attr('title', event.title);
|
||||
if (view.name != 'list')
|
||||
element.attr('title', event.title);
|
||||
if (view.name == 'month') {
|
||||
/* attempt to limit the number of events displayed
|
||||
(could also be used to init fish-eye-view)
|
||||
|
|
|
@ -416,6 +416,7 @@ class calendar extends rcube_plugin
|
|||
else
|
||||
$this->rc->output->show_message('calendar.errorsaving', 'error');
|
||||
|
||||
// FIXME: update a single event object on the client instead of reloading the entire source
|
||||
if ($success && $reload)
|
||||
$this->rc->output->command('plugin.reload_calendar', array('source' => $event['calendar']));
|
||||
}
|
||||
|
|
|
@ -1,6 +1,45 @@
|
|||
--- js/fullcalendar.js.orig 2011-06-04 13:45:44.000000000 -0600
|
||||
+++ js/fullcalendar.js 2011-06-05 18:58:59.000000000 -0600
|
||||
@@ -500,8 +500,8 @@
|
||||
+++ js/fullcalendar.js 2011-06-08 14:30:33.000000000 -0600
|
||||
@@ -47,12 +47,14 @@
|
||||
titleFormat: {
|
||||
month: 'MMMM yyyy',
|
||||
week: "MMM d[ yyyy]{ '—'[ MMM] d yyyy}",
|
||||
- day: 'dddd, MMM d, yyyy'
|
||||
+ day: 'dddd, MMM d, yyyy',
|
||||
+ list: 'MMM d, yyyy'
|
||||
},
|
||||
columnFormat: {
|
||||
month: 'ddd',
|
||||
week: 'ddd M/d',
|
||||
- day: 'dddd M/d'
|
||||
+ day: 'dddd M/d',
|
||||
+ list: 'dddd, yyyy'
|
||||
},
|
||||
timeFormat: { // for event elements
|
||||
'': 'h(:mm)t' // default
|
||||
@@ -73,7 +75,20 @@
|
||||
today: 'today',
|
||||
month: 'month',
|
||||
week: 'week',
|
||||
- day: 'day'
|
||||
+ day: 'day',
|
||||
+ list: 'list'
|
||||
+ },
|
||||
+ listTexts: {
|
||||
+ from: 'from',
|
||||
+ until: 'until',
|
||||
+ past: 'Past events',
|
||||
+ today: 'Today',
|
||||
+ tomorrow: 'Tomorrow',
|
||||
+ thisWeek: 'This week',
|
||||
+ nextWeek: 'Next week',
|
||||
+ thisMonth: 'This month',
|
||||
+ nextMonth: 'Next Month',
|
||||
+ future: 'Future events'
|
||||
},
|
||||
|
||||
// jquery-ui theming
|
||||
@@ -500,8 +515,8 @@
|
||||
}
|
||||
|
||||
|
||||
|
@ -11,7 +50,7 @@
|
|||
}
|
||||
|
||||
|
||||
@@ -897,15 +897,16 @@
|
||||
@@ -897,15 +912,16 @@
|
||||
}
|
||||
|
||||
|
||||
|
@ -19,7 +58,8 @@
|
|||
+ function fetchEvents(start, end, src) {
|
||||
rangeStart = start;
|
||||
rangeEnd = end;
|
||||
cache = [];
|
||||
- cache = [];
|
||||
+ cache = typeof src != 'undefined' ? $.grep(cache, function(e) { return !isSourcesEqual(e.source, source); }) : [];
|
||||
var fetchID = ++currentFetchID;
|
||||
var len = sources.length;
|
||||
- pendingSourceCnt = len;
|
||||
|
@ -31,3 +71,312 @@
|
|||
}
|
||||
}
|
||||
|
||||
@@ -5205,4 +5221,307 @@
|
||||
|
||||
}
|
||||
|
||||
+
|
||||
+/* Additional view: list (by bruederli@kolabsys.com)
|
||||
+---------------------------------------------------------------------------------*/
|
||||
+
|
||||
+function ListEventRenderer() {
|
||||
+ var t = this;
|
||||
+
|
||||
+ // exports
|
||||
+ t.renderEvents = renderEvents;
|
||||
+ t.compileDaySegs = compileSegs; // for DayEventRenderer
|
||||
+ t.clearEvents = clearEvents;
|
||||
+
|
||||
+ // imports
|
||||
+ DayEventRenderer.call(t);
|
||||
+ var opt = t.opt;
|
||||
+ var trigger = t.trigger;
|
||||
+ var reportEvents = t.reportEvents;
|
||||
+ var reportEventClear = t.reportEventClear;
|
||||
+ var reportEventElement = t.reportEventElement;
|
||||
+ var eventElementHandlers = t.eventElementHandlers;
|
||||
+ var showEvents = t.showEvents;
|
||||
+ var hideEvents = t.hideEvents;
|
||||
+ var getListContainer = t.getDaySegmentContainer;
|
||||
+ var calendar = t.calendar;
|
||||
+ var formatDate = calendar.formatDate;
|
||||
+ var formatDates = calendar.formatDates;
|
||||
+
|
||||
+
|
||||
+ /* Rendering
|
||||
+ --------------------------------------------------------------------*/
|
||||
+
|
||||
+ function clearEvents() {
|
||||
+ reportEventClear();
|
||||
+ getListContainer().empty();
|
||||
+ }
|
||||
+
|
||||
+ function renderEvents(events, modifiedEventId) {
|
||||
+ events.sort(sortCmp);
|
||||
+ reportEvents(events);
|
||||
+ renderSegs(compileSegs(events), modifiedEventId);
|
||||
+ }
|
||||
+
|
||||
+ function compileSegs(events) {
|
||||
+ var segs = [];
|
||||
+ var colFormat = opt('columnFormat', 'day');
|
||||
+ var event, i, dd, md, seg, segHash, curSegHash, segDate, curSeg = -1;
|
||||
+ var today = clearTime(new Date());
|
||||
+
|
||||
+ for (i=0; i < events.length; i++) {
|
||||
+ event = events[i];
|
||||
+
|
||||
+ // skip events < t.start
|
||||
+ if (event.end < t.start)
|
||||
+ continue;
|
||||
+
|
||||
+ // define sections of this event
|
||||
+ // 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);
|
||||
+ dd = dayDiff(segDate, today);
|
||||
+ md = segDate.getMonth() + ((segDate.getYear() - today.getYear()) * 12) - today.getMonth();
|
||||
+
|
||||
+ // past events
|
||||
+ if (dd < 0) {
|
||||
+ segHash = opt('listTexts', 'past');
|
||||
+ }
|
||||
+ // today
|
||||
+ else if (dd == 0) {
|
||||
+ segHash = opt('listTexts', 'today');
|
||||
+ }
|
||||
+ else if (dd == 1) {
|
||||
+ segHash = opt('listTexts', 'tomorrow');
|
||||
+ }
|
||||
+ // this week
|
||||
+ else if (dd < 7) {
|
||||
+ segHash = opt('listTexts', 'thisWeek');
|
||||
+ }
|
||||
+ // next week
|
||||
+ else if (dd >= 7 && dd < 14 && md == 0) {
|
||||
+ segHash = opt('listTexts', 'nextWeek');
|
||||
+ }
|
||||
+ else if (md == 0) {
|
||||
+ segHash = opt('listTexts', 'thisMonth');
|
||||
+ }
|
||||
+ else if (md == 1) {
|
||||
+ segHash = opt('listTexts', 'nextMonth');
|
||||
+ }
|
||||
+ else {
|
||||
+ segHash = formatDate(segDate, colFormat);
|
||||
+ }
|
||||
+
|
||||
+ // start new segment
|
||||
+ if (segHash != curSegHash) {
|
||||
+ segs[++curSeg] = { events: [], start: segDate, title: segHash, daydiff: dd };
|
||||
+ curSegHash = segHash;
|
||||
+ }
|
||||
+
|
||||
+ segs[curSeg].events.push(event);
|
||||
+ }
|
||||
+
|
||||
+ return segs;
|
||||
+ }
|
||||
+
|
||||
+ function sortCmp(a, b) {
|
||||
+ return (a.start.getTime() - b.start.getTime()) + (a.end.getTime() - b.end.getTime());
|
||||
+ }
|
||||
+
|
||||
+ function renderSegs(segs, modifiedEventId) {
|
||||
+ var tm = opt('theme') ? 'ui' : 'fc';
|
||||
+ var timeFormat = opt('timeFormat');
|
||||
+ var dateFormat = opt('titleFormat');
|
||||
+ var headerClass = tm + "-widget-header";
|
||||
+ var contentClass = tm + "-widget-content";
|
||||
+ var i, j, seg, event, duration, s, skinCss, skinCssAttr, classes, time, segHeader, segContainer, eventElements;
|
||||
+
|
||||
+ for (j=0; j < segs.length; j++) {
|
||||
+ seg = segs[j];
|
||||
+
|
||||
+ segHeader = $('<div class="fc-list-header ' + headerClass + '">' + htmlEscape(seg.title) + '</div>').appendTo(getListContainer());
|
||||
+ segContainer = $('<div>').addClass('fc-list-section ' + contentClass).appendTo(getListContainer());
|
||||
+ s = '';
|
||||
+
|
||||
+ for (i=0; i < seg.events.length; i++) {
|
||||
+ event = seg.events[i];
|
||||
+
|
||||
+ skinCss = getSkinCss(event, opt);
|
||||
+ 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'];
|
||||
+ if (event.source && 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 +=
|
||||
+ "<div class='" + classes.join(' ') + "'" + skinCssAttr + ">" +
|
||||
+ "<div class='fc-event-inner fc-event-skin'" + skinCssAttr + ">" +
|
||||
+ "<div class='fc-event-head fc-event-skin'" + skinCssAttr + ">" +
|
||||
+ "<div class='fc-event-time'>" +
|
||||
+ htmlEscape(times.join(' ')) +
|
||||
+ "</div>" +
|
||||
+ "</div>" +
|
||||
+ "<div class='fc-event-content'>" +
|
||||
+ "<div class='fc-event-title'>" +
|
||||
+ htmlEscape(event.title) +
|
||||
+ "</div>" +
|
||||
+ "</div>" +
|
||||
+ "<div class='fc-event-bg'></div>" +
|
||||
+ "</div>" + // close inner
|
||||
+ "</div>"; // close outer
|
||||
+ }
|
||||
+
|
||||
+ 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) {
|
||||
+ bindSeg(event, eventElement, seg);
|
||||
+ } else {
|
||||
+ eventElement[0]._fci = i; // for lazySegBind
|
||||
+ }
|
||||
+ reportEventElement(event, eventElement);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ lazySegBind(segContainer, seg, bindSeg);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ function bindSeg(event, eventElement, seg) {
|
||||
+ eventElementHandlers(event, eventElement);
|
||||
+ }
|
||||
+
|
||||
+ function lazySegBind(container, seg, bindHandlers) {
|
||||
+ container.unbind('mouseover').mouseover(function(ev) {
|
||||
+ var parent = ev.target, e = parent, i, event;
|
||||
+ while (parent != this) {
|
||||
+ e = parent;
|
||||
+ parent = parent.parentNode;
|
||||
+ }
|
||||
+ if ((i = e._fci) !== undefined) {
|
||||
+ e._fci = undefined;
|
||||
+ event = seg.events[i];
|
||||
+ bindHandlers(event, container.children().eq(i), seg);
|
||||
+ $(ev.target).trigger(ev);
|
||||
+ }
|
||||
+ ev.stopPropagation();
|
||||
+ });
|
||||
+ }
|
||||
+
|
||||
+}
|
||||
+
|
||||
+
|
||||
+fcViews.list = ListView;
|
||||
+
|
||||
+
|
||||
+function ListView(element, calendar) {
|
||||
+ var t = this;
|
||||
+
|
||||
+ // exports
|
||||
+ t.render = render;
|
||||
+ t.select = dummy;
|
||||
+ t.unselect = dummy;
|
||||
+ t.getDaySegmentContainer = function(){ return body; };
|
||||
+
|
||||
+ // imports
|
||||
+ View.call(t, element, calendar, 'list');
|
||||
+ ListEventRenderer.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 body;
|
||||
+ 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 (!body) {
|
||||
+ buildSkeleton();
|
||||
+ } else {
|
||||
+ clearEvents();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ function updateOptions() {
|
||||
+ firstDay = opt('firstDay');
|
||||
+ nwe = opt('weekends') ? 0 : 1;
|
||||
+ tm = opt('theme') ? 'ui' : 'fc';
|
||||
+ colFormat = opt('columnFormat', 'day');
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ function buildSkeleton() {
|
||||
+ body = $('<div>').addClass('fc-list-content').appendTo(element);
|
||||
+ }
|
||||
+
|
||||
+ function setHeight(height, dateChanged) {
|
||||
+ body.css('height', height+'px').css('overflow', 'auto');
|
||||
+ }
|
||||
+
|
||||
+ function setWidth(width) {
|
||||
+ // nothing to be done here
|
||||
+ }
|
||||
+
|
||||
+ function dummy() {
|
||||
+ // Stub.
|
||||
+ }
|
||||
+
|
||||
+}
|
||||
+
|
||||
+
|
||||
})(jQuery);
|
||||
\ No newline at end of file
|
||||
|
|
|
@ -47,12 +47,14 @@ var defaults = {
|
|||
titleFormat: {
|
||||
month: 'MMMM yyyy',
|
||||
week: "MMM d[ yyyy]{ '—'[ MMM] d yyyy}",
|
||||
day: 'dddd, MMM d, yyyy'
|
||||
day: 'dddd, MMM d, yyyy',
|
||||
list: 'MMM d, yyyy'
|
||||
},
|
||||
columnFormat: {
|
||||
month: 'ddd',
|
||||
week: 'ddd M/d',
|
||||
day: 'dddd M/d'
|
||||
day: 'dddd M/d',
|
||||
list: 'dddd, yyyy'
|
||||
},
|
||||
timeFormat: { // for event elements
|
||||
'': 'h(:mm)t' // default
|
||||
|
@ -73,7 +75,20 @@ var defaults = {
|
|||
today: 'today',
|
||||
month: 'month',
|
||||
week: 'week',
|
||||
day: 'day'
|
||||
day: 'day',
|
||||
list: 'list'
|
||||
},
|
||||
listTexts: {
|
||||
from: 'from',
|
||||
until: 'until',
|
||||
past: 'Past events',
|
||||
today: 'Today',
|
||||
tomorrow: 'Tomorrow',
|
||||
thisWeek: 'This week',
|
||||
nextWeek: 'Next week',
|
||||
thisMonth: 'This month',
|
||||
nextMonth: 'Next Month',
|
||||
future: 'Future events'
|
||||
},
|
||||
|
||||
// jquery-ui theming
|
||||
|
@ -900,7 +915,7 @@ function EventManager(options, _sources) {
|
|||
function fetchEvents(start, end, src) {
|
||||
rangeStart = start;
|
||||
rangeEnd = end;
|
||||
cache = [];
|
||||
cache = typeof src != 'undefined' ? $.grep(cache, function(e) { return !isSourcesEqual(e.source, source); }) : [];
|
||||
var fetchID = ++currentFetchID;
|
||||
var len = sources.length;
|
||||
pendingSourceCnt = typeof src == 'undefined' ? len : 1;
|
||||
|
@ -5206,4 +5221,307 @@ function HorizontalPositionCache(getElement) {
|
|||
|
||||
}
|
||||
|
||||
|
||||
/* Additional view: list (by bruederli@kolabsys.com)
|
||||
---------------------------------------------------------------------------------*/
|
||||
|
||||
function ListEventRenderer() {
|
||||
var t = this;
|
||||
|
||||
// exports
|
||||
t.renderEvents = renderEvents;
|
||||
t.compileDaySegs = compileSegs; // for DayEventRenderer
|
||||
t.clearEvents = clearEvents;
|
||||
|
||||
// imports
|
||||
DayEventRenderer.call(t);
|
||||
var opt = t.opt;
|
||||
var trigger = t.trigger;
|
||||
var reportEvents = t.reportEvents;
|
||||
var reportEventClear = t.reportEventClear;
|
||||
var reportEventElement = t.reportEventElement;
|
||||
var eventElementHandlers = t.eventElementHandlers;
|
||||
var showEvents = t.showEvents;
|
||||
var hideEvents = t.hideEvents;
|
||||
var getListContainer = t.getDaySegmentContainer;
|
||||
var calendar = t.calendar;
|
||||
var formatDate = calendar.formatDate;
|
||||
var formatDates = calendar.formatDates;
|
||||
|
||||
|
||||
/* Rendering
|
||||
--------------------------------------------------------------------*/
|
||||
|
||||
function clearEvents() {
|
||||
reportEventClear();
|
||||
getListContainer().empty();
|
||||
}
|
||||
|
||||
function renderEvents(events, modifiedEventId) {
|
||||
events.sort(sortCmp);
|
||||
reportEvents(events);
|
||||
renderSegs(compileSegs(events), modifiedEventId);
|
||||
}
|
||||
|
||||
function compileSegs(events) {
|
||||
var segs = [];
|
||||
var colFormat = opt('columnFormat', 'day');
|
||||
var event, i, dd, md, seg, segHash, curSegHash, segDate, curSeg = -1;
|
||||
var today = clearTime(new Date());
|
||||
|
||||
for (i=0; i < events.length; i++) {
|
||||
event = events[i];
|
||||
|
||||
// skip events < t.start
|
||||
if (event.end < t.start)
|
||||
continue;
|
||||
|
||||
// define sections of this event
|
||||
// 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);
|
||||
dd = dayDiff(segDate, today);
|
||||
md = segDate.getMonth() + ((segDate.getYear() - today.getYear()) * 12) - today.getMonth();
|
||||
|
||||
// past events
|
||||
if (dd < 0) {
|
||||
segHash = opt('listTexts', 'past');
|
||||
}
|
||||
// today
|
||||
else if (dd == 0) {
|
||||
segHash = opt('listTexts', 'today');
|
||||
}
|
||||
else if (dd == 1) {
|
||||
segHash = opt('listTexts', 'tomorrow');
|
||||
}
|
||||
// this week
|
||||
else if (dd < 7) {
|
||||
segHash = opt('listTexts', 'thisWeek');
|
||||
}
|
||||
// next week
|
||||
else if (dd >= 7 && dd < 14 && md == 0) {
|
||||
segHash = opt('listTexts', 'nextWeek');
|
||||
}
|
||||
else if (md == 0) {
|
||||
segHash = opt('listTexts', 'thisMonth');
|
||||
}
|
||||
else if (md == 1) {
|
||||
segHash = opt('listTexts', 'nextMonth');
|
||||
}
|
||||
else {
|
||||
segHash = formatDate(segDate, colFormat);
|
||||
}
|
||||
|
||||
// start new segment
|
||||
if (segHash != curSegHash) {
|
||||
segs[++curSeg] = { events: [], start: segDate, title: segHash, daydiff: dd };
|
||||
curSegHash = segHash;
|
||||
}
|
||||
|
||||
segs[curSeg].events.push(event);
|
||||
}
|
||||
|
||||
return segs;
|
||||
}
|
||||
|
||||
function sortCmp(a, b) {
|
||||
return (a.start.getTime() - b.start.getTime()) + (a.end.getTime() - b.end.getTime());
|
||||
}
|
||||
|
||||
function renderSegs(segs, modifiedEventId) {
|
||||
var tm = opt('theme') ? 'ui' : 'fc';
|
||||
var timeFormat = opt('timeFormat');
|
||||
var dateFormat = opt('titleFormat');
|
||||
var headerClass = tm + "-widget-header";
|
||||
var contentClass = tm + "-widget-content";
|
||||
var i, j, seg, event, duration, s, skinCss, skinCssAttr, classes, time, segHeader, segContainer, eventElements;
|
||||
|
||||
for (j=0; j < segs.length; j++) {
|
||||
seg = segs[j];
|
||||
|
||||
segHeader = $('<div class="fc-list-header ' + headerClass + '">' + htmlEscape(seg.title) + '</div>').appendTo(getListContainer());
|
||||
segContainer = $('<div>').addClass('fc-list-section ' + contentClass).appendTo(getListContainer());
|
||||
s = '';
|
||||
|
||||
for (i=0; i < seg.events.length; i++) {
|
||||
event = seg.events[i];
|
||||
|
||||
skinCss = getSkinCss(event, opt);
|
||||
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'];
|
||||
if (event.source && 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 +=
|
||||
"<div class='" + classes.join(' ') + "'" + skinCssAttr + ">" +
|
||||
"<div class='fc-event-inner fc-event-skin'" + skinCssAttr + ">" +
|
||||
"<div class='fc-event-head fc-event-skin'" + skinCssAttr + ">" +
|
||||
"<div class='fc-event-time'>" +
|
||||
htmlEscape(times.join(' ')) +
|
||||
"</div>" +
|
||||
"</div>" +
|
||||
"<div class='fc-event-content'>" +
|
||||
"<div class='fc-event-title'>" +
|
||||
htmlEscape(event.title) +
|
||||
"</div>" +
|
||||
"</div>" +
|
||||
"<div class='fc-event-bg'></div>" +
|
||||
"</div>" + // close inner
|
||||
"</div>"; // close outer
|
||||
}
|
||||
|
||||
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) {
|
||||
bindSeg(event, eventElement, seg);
|
||||
} else {
|
||||
eventElement[0]._fci = i; // for lazySegBind
|
||||
}
|
||||
reportEventElement(event, eventElement);
|
||||
}
|
||||
}
|
||||
|
||||
lazySegBind(segContainer, seg, bindSeg);
|
||||
}
|
||||
}
|
||||
|
||||
function bindSeg(event, eventElement, seg) {
|
||||
eventElementHandlers(event, eventElement);
|
||||
}
|
||||
|
||||
function lazySegBind(container, seg, bindHandlers) {
|
||||
container.unbind('mouseover').mouseover(function(ev) {
|
||||
var parent = ev.target, e = parent, i, event;
|
||||
while (parent != this) {
|
||||
e = parent;
|
||||
parent = parent.parentNode;
|
||||
}
|
||||
if ((i = e._fci) !== undefined) {
|
||||
e._fci = undefined;
|
||||
event = seg.events[i];
|
||||
bindHandlers(event, container.children().eq(i), seg);
|
||||
$(ev.target).trigger(ev);
|
||||
}
|
||||
ev.stopPropagation();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
fcViews.list = ListView;
|
||||
|
||||
|
||||
function ListView(element, calendar) {
|
||||
var t = this;
|
||||
|
||||
// exports
|
||||
t.render = render;
|
||||
t.select = dummy;
|
||||
t.unselect = dummy;
|
||||
t.getDaySegmentContainer = function(){ return body; };
|
||||
|
||||
// imports
|
||||
View.call(t, element, calendar, 'list');
|
||||
ListEventRenderer.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 body;
|
||||
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 (!body) {
|
||||
buildSkeleton();
|
||||
} else {
|
||||
clearEvents();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function updateOptions() {
|
||||
firstDay = opt('firstDay');
|
||||
nwe = opt('weekends') ? 0 : 1;
|
||||
tm = opt('theme') ? 'ui' : 'fc';
|
||||
colFormat = opt('columnFormat', 'day');
|
||||
}
|
||||
|
||||
|
||||
function buildSkeleton() {
|
||||
body = $('<div>').addClass('fc-list-content').appendTo(element);
|
||||
}
|
||||
|
||||
function setHeight(height, dateChanged) {
|
||||
body.css('height', height+'px').css('overflow', 'auto');
|
||||
}
|
||||
|
||||
function setWidth(width) {
|
||||
// nothing to be done here
|
||||
}
|
||||
|
||||
function dummy() {
|
||||
// Stub.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
})(jQuery);
|
|
@ -23,6 +23,7 @@ $labels['color'] = 'Color';
|
|||
$labels['day'] = 'Day';
|
||||
$labels['week'] = 'Week';
|
||||
$labels['month'] = 'Month';
|
||||
$labels['agenda'] = 'Agenda';
|
||||
$labels['new_event'] = 'New event';
|
||||
$labels['edit_event'] = 'Edit event';
|
||||
$labels['edit'] = 'Edit';
|
||||
|
|
|
@ -500,6 +500,10 @@ a.alarm-action-snooze:after {
|
|||
background-position: 0 -13px;
|
||||
}
|
||||
|
||||
.fc-list-section .fc-event {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Settings section */
|
||||
|
||||
fieldset #calendarcategories div {
|
||||
|
|
|
@ -614,5 +614,27 @@ table.fc-border-separate {
|
|||
.fc-agenda .ui-resizable-resizing { /* TODO: better selector */
|
||||
_overflow: hidden;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* List view (by bruederli@kolabsys.com)
|
||||
------------------------------------------------------------------------*/
|
||||
|
||||
.fc-view-list {
|
||||
border-top: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.fc-view-list .fc-list-header {
|
||||
border-top-width: 0;
|
||||
border-bottom-width: 0;
|
||||
padding: 2px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.fc-list-section {
|
||||
padding: 4px 2px;
|
||||
}
|
||||
|
||||
.fc-list-section .fc-event {
|
||||
position: relative;
|
||||
margin: 1px 2px 3px 2px;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue