--- js/fullcalendar.js.orig 2011-06-04 13:45:44.000000000 -0600 +++ js/fullcalendar.js 2011-06-10 09:27:50.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 @@ } - function refetchEvents() { - fetchEvents(currentView.visStart, currentView.visEnd); // will call reportEvents + function refetchEvents(source) { + fetchEvents(currentView.visStart, currentView.visEnd, source); // will call reportEvents } @@ -897,15 +912,16 @@ } - function fetchEvents(start, end) { + function fetchEvents(start, end, src) { rangeStart = start; rangeEnd = end; - cache = []; + cache = typeof src != 'undefined' ? $.grep(cache, function(e) { return !isSourcesEqual(e.source, src); }) : []; var fetchID = ++currentFetchID; var len = sources.length; - pendingSourceCnt = len; + pendingSourceCnt = typeof src == 'undefined' ? len : 1; for (var i=0; i 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 = $('
' + htmlEscape(seg.title) + '
').appendTo(getListContainer()); + segContainer = $('
').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 += + "
" + + "
" + + "
" + + "
" + + htmlEscape(times.join(' ')) + + "
" + + "
" + + "
" + + "
" + + htmlEscape(event.title) + + "
" + + "
" + + "
" + + "
" + // close inner + "
"; // 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); + } + + markFirstLast(getListContainer()); + } + + 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 = $('
').addClass('fc-list-content').appendTo(element); + } + + function setHeight(height, dateChanged) { + body.css('height', (height-1)+'px').css('overflow', 'auto'); + } + + function setWidth(width) { + // nothing to be done here + } + + function dummy() { + // Stub. + } + +} + + })(jQuery); \ No newline at end of file