View: 3.4: Fish-Eye View For Busy Days
This commit is contained in:
parent
def64e251f
commit
0a367cbe29
7 changed files with 181 additions and 52 deletions
|
@ -25,7 +25,6 @@ function rcube_calendar_ui(settings)
|
|||
this.selected_event = null;
|
||||
this.selected_calendar = null;
|
||||
this.search_request = null;
|
||||
this.eventcount = [];
|
||||
this.saving_lock = null;
|
||||
|
||||
|
||||
|
@ -251,7 +250,7 @@ function rcube_calendar_ui(settings)
|
|||
// event details dialog (show only)
|
||||
var event_show_dialog = function(event)
|
||||
{
|
||||
var $dialog = $("#eventshow").removeClass().addClass('uidialog');
|
||||
var $dialog = $("#eventshow").dialog('close').removeClass().addClass('uidialog');
|
||||
var calendar = event.calendar && me.calendars[event.calendar] ? me.calendars[event.calendar] : { editable:false };
|
||||
me.selected_event = event;
|
||||
|
||||
|
@ -1564,9 +1563,126 @@ function rcube_calendar_ui(settings)
|
|||
return true;
|
||||
};
|
||||
|
||||
/*** fullcalendar event handlers ***/
|
||||
|
||||
var fc_event_render = function(event, element, view) {
|
||||
if (view.name != 'list' && view.name != 'table') {
|
||||
var prefix = event.sensitivity != 0 ? String(sensitivitylabels[event.sensitivity]).toUpperCase()+': ' : '';
|
||||
element.attr('title', prefix + event.title);
|
||||
}
|
||||
if (view.name == 'month') {
|
||||
// limit the number of events displayed
|
||||
var sday = event.start.getMonth()*120 + event.start.getDate();
|
||||
var eday = event.end.getMonth()*120 + event.end.getDate();
|
||||
if (!view._eventcount[sday]) view._eventcount[sday] = 1;
|
||||
else view._eventcount[sday]++;
|
||||
if (!view._eventcount[eday]) view._eventcount[eday] = 1;
|
||||
else if (eday != sday) view._eventcount[eday]++;
|
||||
|
||||
if (view._eventcount[sday] >= view._maxevents) {
|
||||
if (!view._morelink[sday]) {
|
||||
view._morelink[sday] = view._morelink[event.id] = $('<div>')
|
||||
.addClass('fc-event-more')
|
||||
.css({ position:'absolute', left:element.css('left'), width:element.css('width') })
|
||||
.appendTo(element.parent())
|
||||
.data('overflow', 1);
|
||||
}
|
||||
else {
|
||||
view._morelink[sday].data('overflow', view._eventcount[sday] - view._maxevents);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (view._eventcount[eday] >= view._maxevents || view._morelink[event.id]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (event.location) {
|
||||
element.find('div.fc-event-title').after('<div class="fc-event-location">@ ' + Q(event.location) + '</div>');
|
||||
}
|
||||
if (event.sensitivity != 0)
|
||||
element.find('div.fc-event-time').append('<i class="fc-icon-sensitive"></i>');
|
||||
if (event.recurrence)
|
||||
element.find('div.fc-event-time').append('<i class="fc-icon-recurring"></i>');
|
||||
if (event.alarms)
|
||||
element.find('div.fc-event-time').append('<i class="fc-icon-alarms"></i>');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*** public methods ***/
|
||||
|
||||
// opens calendar day-view in a popup
|
||||
this.fisheye_view = function(date)
|
||||
{
|
||||
$('#fish-eye-view').dialog('close');
|
||||
|
||||
// create list of active event sources
|
||||
var src, cals = {}, sources = [];
|
||||
for (var id in this.calendars) {
|
||||
src = $.extend({}, this.calendars[id]);
|
||||
src.editable = false;
|
||||
src.url = null;
|
||||
src.events = [];
|
||||
|
||||
if (cal.active) {
|
||||
cals[id] = src;
|
||||
sources.push(src);
|
||||
}
|
||||
}
|
||||
|
||||
// copy events already loaded
|
||||
var events = fc.fullCalendar('clientEvents');
|
||||
for (var event, i=0; i< events.length; i++) {
|
||||
event = events[i];
|
||||
if (event.source && (src = cals[event.source.id])) {
|
||||
src.events.push(event);
|
||||
}
|
||||
}
|
||||
|
||||
var h = $(window).height() - 50;
|
||||
var dialog = $('<div>')
|
||||
.attr('id', 'fish-eye-view')
|
||||
.dialog({
|
||||
modal: true,
|
||||
width: 680,
|
||||
height: h,
|
||||
title: $.fullCalendar.formatDate(date, 'dddd ' + settings['date_long']),
|
||||
close: function(){
|
||||
dialog.dialog("destroy");
|
||||
me.fisheye_date = null;
|
||||
}
|
||||
})
|
||||
.fullCalendar({
|
||||
header: { left: '', center: '', right: '' },
|
||||
height: h - 50,
|
||||
defaultView: 'agendaDay',
|
||||
date: date.getDate(),
|
||||
month: date.getMonth(),
|
||||
year: date.getFullYear(),
|
||||
ignoreTimezone: true, // will treat the given date strings as in local (browser's) timezone
|
||||
eventSources: sources,
|
||||
monthNames : settings['months'],
|
||||
monthNamesShort : settings['months_short'],
|
||||
dayNames : settings['days'],
|
||||
dayNamesShort : settings['days_short'],
|
||||
firstDay : settings['first_day'],
|
||||
firstHour : settings['first_hour'],
|
||||
slotMinutes : 60/settings['timeslots'],
|
||||
timeFormat: { '': settings['time_format'] },
|
||||
axisFormat : settings['time_format'],
|
||||
columnFormat: { day: 'dddd ' + settings['date_short'] },
|
||||
titleFormat: { day: 'dddd ' + settings['date_long'] },
|
||||
allDayText: rcmail.gettext('all-day', 'calendar'),
|
||||
eventRender: fc_event_render,
|
||||
eventClick: function(event) {
|
||||
event_show_dialog(event);
|
||||
}
|
||||
});
|
||||
|
||||
this.fisheye_date = date;
|
||||
};
|
||||
|
||||
//public method to show the print dialog.
|
||||
this.print_calendars = function(view)
|
||||
{
|
||||
|
@ -1813,6 +1929,9 @@ function rcube_calendar_ui(settings)
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fisheye_date)
|
||||
this.fisheye_view(this.fisheye_date);
|
||||
};
|
||||
|
||||
// resize and reposition (center) the dialog window
|
||||
|
@ -1955,37 +2074,19 @@ function rcube_calendar_ui(settings)
|
|||
me.events_loaded($(this).fullCalendar('clientEvents').length);
|
||||
},
|
||||
// event rendering
|
||||
eventRender: function(event, element, view) {
|
||||
if (view.name != 'list' && view.name != 'table') {
|
||||
var prefix = event.sensitivity != 0 ? String(sensitivitylabels[event.sensitivity]).toUpperCase()+': ' : '';
|
||||
element.attr('title', prefix + event.title);
|
||||
}
|
||||
if (view.name == 'month') {
|
||||
/* attempt to limit the number of events displayed
|
||||
(could also be used to init fish-eye-view)
|
||||
var max = 4; // to be derrived from window size
|
||||
var sday = event.start.getMonth()*12 + event.start.getDate();
|
||||
var eday = event.end.getMonth()*12 + event.end.getDate();
|
||||
if (!me.eventcount[sday]) me.eventcount[sday] = 1;
|
||||
else me.eventcount[sday]++;
|
||||
if (!me.eventcount[eday]) me.eventcount[eday] = 1;
|
||||
else if (eday != sday) me.eventcount[eday]++;
|
||||
|
||||
if (me.eventcount[sday] > max || me.eventcount[eday] > max)
|
||||
return false;
|
||||
*/
|
||||
}
|
||||
else {
|
||||
if (event.location) {
|
||||
element.find('div.fc-event-title').after('<div class="fc-event-location">@ ' + Q(event.location) + '</div>');
|
||||
}
|
||||
if (event.sensitivity != 0)
|
||||
element.find('div.fc-event-time').append('<i class="fc-icon-sensitive"></i>');
|
||||
if (event.recurrence)
|
||||
element.find('div.fc-event-time').append('<i class="fc-icon-recurring"></i>');
|
||||
if (event.alarms)
|
||||
element.find('div.fc-event-time').append('<i class="fc-icon-alarms"></i>');
|
||||
eventRender: fc_event_render,
|
||||
eventAfterRender: function(event, element, view) {
|
||||
// adjust position of the more... element
|
||||
var link;
|
||||
if (view.name == 'month' && (link = view._morelink[event.id]) && !link.data('date') && link.data('overflow') > 1) {
|
||||
link.html(rcmail.gettext('andnmore', 'calendar').replace('$nr', link.data('overflow')))
|
||||
.css({ left:element.css('left'), top:element.css('top') })
|
||||
.data('date', new Date(event.start.getTime()))
|
||||
.click(function(e){ me.fisheye_view($(this).data('date')); });
|
||||
element.remove();
|
||||
}
|
||||
else if (link)
|
||||
link.remove();
|
||||
},
|
||||
// callback for date range selection
|
||||
select: function(start, end, allDay, e, view) {
|
||||
|
@ -2066,14 +2167,13 @@ function rcube_calendar_ui(settings)
|
|||
update_event_confirm('resize', event, data);
|
||||
},
|
||||
viewDisplay: function(view) {
|
||||
me.eventcount = [];
|
||||
if (!bw.ie)
|
||||
window.setTimeout(function(){ $('div.fc-content').css('overflow', view.name == 'month' ? 'auto' : 'hidden') }, 10);
|
||||
if (minical)
|
||||
window.setTimeout(function(){ minical.datepicker('setDate', fc.fullCalendar('getDate')); }, exec_deferred);
|
||||
},
|
||||
windowResize: function(view) {
|
||||
me.eventcount = [];
|
||||
viewRender: function(view) {
|
||||
view._maxevents = Math.floor((view.element.parent().height()-18) / 108) - 1;
|
||||
view._eventcount = [];
|
||||
view._morelink = [];
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -2387,6 +2487,10 @@ window.rcmail && rcmail.addEventListener('init', function(evt) {
|
|||
event.source = source; // link with source
|
||||
fc.fullCalendar('renderEvent', event);
|
||||
}
|
||||
|
||||
// refresh fish-eye view
|
||||
if (cal.fisheye_date)
|
||||
cal.fisheye_view(cal.fisheye_date);
|
||||
}
|
||||
|
||||
// remove temp events
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
--- js/fullcalendar.js.orig 2011-04-09 14:13:16.000000000 +0200
|
||||
+++ js/fullcalendar.js 2011-08-07 18:43:34.000000000 +0200
|
||||
+++ js/fullcalendar.js 2011-09-07 11:53:03.000000000 +0200
|
||||
@@ -47,12 +47,16 @@
|
||||
titleFormat: {
|
||||
month: 'MMMM yyyy',
|
||||
|
@ -49,7 +49,15 @@
|
|||
|
||||
// jquery-ui theming
|
||||
theme: false,
|
||||
@@ -500,8 +524,8 @@
|
||||
@@ -424,6 +448,7 @@
|
||||
setSize();
|
||||
unselect();
|
||||
currentView.clearEvents();
|
||||
+ currentView.trigger('viewRender', currentView);
|
||||
currentView.renderEvents(events);
|
||||
currentView.sizeDirty = false;
|
||||
}
|
||||
@@ -500,8 +525,8 @@
|
||||
}
|
||||
|
||||
|
||||
|
@ -60,7 +68,15 @@
|
|||
}
|
||||
|
||||
|
||||
@@ -632,6 +656,8 @@
|
||||
@@ -523,6 +548,7 @@
|
||||
markEventsDirty();
|
||||
if (elementVisible()) {
|
||||
currentView.clearEvents();
|
||||
+ currentView.trigger('viewRender', currentView);
|
||||
currentView.renderEvents(events, modifiedEventID);
|
||||
currentView.eventsDirty = false;
|
||||
}
|
||||
@@ -632,6 +658,8 @@
|
||||
if (name == 'height' || name == 'contentHeight' || name == 'aspectRatio') {
|
||||
options[name] = value;
|
||||
updateSize();
|
||||
|
@ -69,7 +85,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
@@ -897,15 +923,16 @@
|
||||
@@ -897,15 +925,16 @@
|
||||
}
|
||||
|
||||
|
||||
|
@ -90,7 +106,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
@@ -1579,10 +1606,23 @@
|
||||
@@ -1579,10 +1608,23 @@
|
||||
return 'th';
|
||||
}
|
||||
return ['st', 'nd', 'rd'][date%10-1] || 'th';
|
||||
|
@ -115,7 +131,7 @@
|
|||
|
||||
fc.applyAll = applyAll;
|
||||
|
||||
@@ -3534,10 +3574,10 @@
|
||||
@@ -3534,10 +3576,10 @@
|
||||
function slotSelectionMousedown(ev) {
|
||||
if (ev.which == 1 && opt('selectable')) { // ev.which==1 means left mouse button
|
||||
unselect(ev);
|
||||
|
@ -128,7 +144,7 @@
|
|||
var d1 = cellDate(origCell);
|
||||
var d2 = cellDate(cell);
|
||||
dates = [
|
||||
@@ -3762,7 +3802,8 @@
|
||||
@@ -3762,7 +3804,8 @@
|
||||
height,
|
||||
slotSegmentContainer = getSlotSegmentContainer(),
|
||||
rtl, dis, dit,
|
||||
|
@ -138,7 +154,7 @@
|
|||
|
||||
if (rtl = opt('isRTL')) {
|
||||
dis = -1;
|
||||
@@ -3789,8 +3830,11 @@
|
||||
@@ -3789,8 +3832,11 @@
|
||||
outerWidth = availWidth / (levelI + forward + 1);
|
||||
}else{
|
||||
if (forward) {
|
||||
|
@ -152,7 +168,7 @@
|
|||
}else{
|
||||
// can be entire width, aligned left
|
||||
outerWidth = availWidth;
|
||||
@@ -3801,7 +3845,7 @@
|
||||
@@ -3801,7 +3847,7 @@
|
||||
* dis + (rtl ? availWidth - outerWidth : 0); // rtl
|
||||
seg.top = top;
|
||||
seg.left = left;
|
||||
|
@ -161,7 +177,7 @@
|
|||
seg.outerHeight = bottom - top;
|
||||
html += slotSegHtml(event, seg);
|
||||
}
|
||||
@@ -4260,7 +4304,7 @@
|
||||
@@ -4260,7 +4306,7 @@
|
||||
|
||||
function opt(name, viewNameOverride) {
|
||||
var v = options[name];
|
||||
|
@ -170,7 +186,7 @@
|
|||
return smartProperty(v, viewNameOverride || viewName);
|
||||
}
|
||||
return v;
|
||||
@@ -5204,5 +5248,561 @@
|
||||
@@ -5204,5 +5250,561 @@
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -448,6 +448,7 @@ function Calendar(element, options, eventSources) {
|
|||
setSize();
|
||||
unselect();
|
||||
currentView.clearEvents();
|
||||
currentView.trigger('viewRender', currentView);
|
||||
currentView.renderEvents(events);
|
||||
currentView.sizeDirty = false;
|
||||
}
|
||||
|
@ -547,6 +548,7 @@ function Calendar(element, options, eventSources) {
|
|||
markEventsDirty();
|
||||
if (elementVisible()) {
|
||||
currentView.clearEvents();
|
||||
currentView.trigger('viewRender', currentView);
|
||||
currentView.renderEvents(events, modifiedEventID);
|
||||
currentView.eventsDirty = false;
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ $labels['printdescriptions'] = 'Beschrieb drucken';
|
|||
$labels['parentcalendar'] = 'Übergeordneter Kalender';
|
||||
$labels['searchearlierdates'] = '« Frühere Termine suchen';
|
||||
$labels['searchlaterdates'] = 'Spätere Termine suchen »';
|
||||
$labels['andnmore'] = 'und $nr weitere';
|
||||
$labels['andnmore'] = '$nr weitere...';
|
||||
$labels['togglerole'] = 'Klick zum Ändern der Rolle';
|
||||
|
||||
// alarm/reminder settings
|
||||
|
|
|
@ -64,7 +64,7 @@ $labels['printdescriptions'] = 'Beschrieb drucken';
|
|||
$labels['parentcalendar'] = 'Übergeordneter Kalender';
|
||||
$labels['searchearlierdates'] = '« Frühere Termine suchen';
|
||||
$labels['searchlaterdates'] = 'Spätere Termine suchen »';
|
||||
$labels['andnmore'] = 'und $nr weitere';
|
||||
$labels['andnmore'] = '$nr weitere...';
|
||||
|
||||
// alarm/reminder settings
|
||||
$labels['showalarms'] = 'Erinnerungen anzeigen';
|
||||
|
|
|
@ -64,7 +64,7 @@ $labels['printdescriptions'] = 'Print descriptions';
|
|||
$labels['parentcalendar'] = 'Superior calendar';
|
||||
$labels['searchearlierdates'] = '« Search for earlier events';
|
||||
$labels['searchlaterdates'] = 'Search for later events »';
|
||||
$labels['andnmore'] = 'and $nr more';
|
||||
$labels['andnmore'] = '$nr more...';
|
||||
$labels['togglerole'] = 'Click to toggle role';
|
||||
|
||||
// alarm/reminder settings
|
||||
|
|
|
@ -1026,6 +1026,13 @@ div.fc-event-location {
|
|||
font-size: 90%;
|
||||
}
|
||||
|
||||
.fc-event-more {
|
||||
color: #999;
|
||||
font-size: 90%;
|
||||
padding-top: 1px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.fc-agenda-slots td div {
|
||||
height: 22px;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue