4 commits - plugins/calendar plugins/libkolab plugins/tasklist
Thomas Brüderli
bruederli at kolabsys.com
Thu Jun 26 17:44:19 CEST 2014
plugins/calendar/calendar.php | 7
plugins/calendar/calendar_ui.js | 304 ++++++++++-------
plugins/calendar/drivers/kolab/kolab_user_calendar.php | 9
plugins/calendar/lib/calendar_ui.php | 1
plugins/calendar/lib/js/fullcalendar.js | 13
plugins/calendar/localization/en_US.inc | 1
plugins/calendar/skins/larry/calendar.css | 124 +++++-
plugins/calendar/skins/larry/images/calendars.png |binary
plugins/libkolab/js/folderlist.js | 14
plugins/tasklist/tasklist.js | 3
10 files changed, 309 insertions(+), 167 deletions(-)
New commits:
commit 3b80a73456ab025e12114f17d06b595a5e41449d
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Thu Jun 26 17:44:10 2014 +0200
Minor codestyle fix
diff --git a/plugins/tasklist/tasklist.js b/plugins/tasklist/tasklist.js
index fb7c4ac..5994381 100644
--- a/plugins/tasklist/tasklist.js
+++ b/plugins/tasklist/tasklist.js
@@ -207,8 +207,9 @@ function rcube_tasklist_ui(settings)
// handler for clicks on quickview buttons
tasklists_widget.container.on('click', '.quickview', function(e){
var id = $(this).closest('li').attr('id').replace(/^rcmlitasklist/, '');
- set_focusview(focusview == id ? null : id)
+ set_focusview(focusview == id ? null : id);
e.stopPropagation();
+ return false;
});
// register dbl-click handler to open calendar edit dialog
commit ab43057b1fa5104da744fc2deb6264d0524d2965
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Thu Jun 26 17:42:32 2014 +0200
Implement quickview for calendars, showing free-busy data for other user's calendars (#3043)
diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php
index f863580..0313bb1 100644
--- a/plugins/calendar/calendar.php
+++ b/plugins/calendar/calendar.php
@@ -3,12 +3,11 @@
/**
* Calendar plugin for Roundcube webmail
*
- * @version @package_version@
* @author Lazlo Westerhof <hello at lazlo.me>
* @author Thomas Bruederli <bruederli at kolabsys.com>
*
* Copyright (C) 2010, Lazlo Westerhof <hello at lazlo.me>
- * Copyright (C) 2012, Kolab Systems AG <contact at kolabsys.com>
+ * Copyright (C) 2014, Kolab Systems AG <contact at kolabsys.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
@@ -1397,7 +1396,9 @@ class calendar extends rcube_plugin
'title' => strval($event['title']),
'description' => strval($event['description']),
'location' => strval($event['location']),
- 'className' => ($addcss ? 'fc-event-cal-'.asciiwords($event['calendar'], true).' ' : '') . 'fc-event-cat-' . asciiwords(strtolower(join('-', (array)$event['categories'])), true),
+ 'className' => ($addcss ? 'fc-event-cal-'.asciiwords($event['calendar'], true).' ' : '') .
+ 'fc-event-cat-' . asciiwords(strtolower(join('-', (array)$event['categories'])), true) .
+ rtrim(' ' . $event['className']),
'allDay' => ($event['allday'] == 1),
) + $event;
}
diff --git a/plugins/calendar/calendar_ui.js b/plugins/calendar/calendar_ui.js
index 3558d91..985a3b6 100644
--- a/plugins/calendar/calendar_ui.js
+++ b/plugins/calendar/calendar_ui.js
@@ -8,7 +8,7 @@
* JavaScript code in this file.
*
* Copyright (C) 2010, Lazlo Westerhof <hello at lazlo.me>
- * Copyright (C) 2012, Kolab Systems AG <contact at kolabsys.com>
+ * Copyright (C) 2014, Kolab Systems AG <contact at kolabsys.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
@@ -83,6 +83,78 @@ function rcube_calendar_ui(settings)
selectOtherMonths: true
};
+ // global fullcalendar settings
+ var fullcalendar_defaults = {
+ aspectRatio: 1,
+ ignoreTimezone: true, // will treat the given date strings as in local (browser's) timezone
+ 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,
+ agenda: settings.time_format + '{ - ' + settings.time_format + '}',
+ list: settings.time_format + '{ - ' + settings.time_format + '}',
+ table: settings.time_format + '{ - ' + settings.time_format + '}'
+ },
+ axisFormat : settings.time_format,
+ columnFormat: {
+ month: 'ddd', // Mon
+ week: 'ddd ' + settings.date_short, // Mon 9/7
+ day: 'dddd ' + settings.date_short, // Monday 9/7
+ table: settings.date_agenda
+ },
+ titleFormat: {
+ month: 'MMMM yyyy',
+ week: settings.dates_long,
+ day: 'dddd ' + settings['date_long'],
+ table: settings.dates_long
+ },
+ listPage: 1, // advance one day in agenda view
+ listRange: settings.agenda_range,
+ listSections: settings.agenda_sections,
+ tableCols: ['handle', 'date', 'time', 'title', 'location'],
+ defaultView: rcmail.env.view || settings.default_view,
+ allDayText: rcmail.gettext('all-day', 'calendar'),
+ buttonText: {
+ prev: ' ◄ ',
+ next: ' ► ',
+ today: settings['today'],
+ day: rcmail.gettext('day', 'calendar'),
+ week: rcmail.gettext('week', 'calendar'),
+ month: rcmail.gettext('month', 'calendar'),
+ table: rcmail.gettext('agenda', 'calendar')
+ },
+ listTexts: {
+ until: rcmail.gettext('until', 'calendar'),
+ past: rcmail.gettext('pastevents', 'calendar'),
+ today: rcmail.gettext('today', 'calendar'),
+ tomorrow: rcmail.gettext('tomorrow', 'calendar'),
+ thisWeek: rcmail.gettext('thisweek', 'calendar'),
+ nextWeek: rcmail.gettext('nextweek', 'calendar'),
+ thisMonth: rcmail.gettext('thismonth', 'calendar'),
+ nextMonth: rcmail.gettext('nextmonth', 'calendar'),
+ future: rcmail.gettext('futureevents', 'calendar'),
+ week: rcmail.gettext('weekofyear', 'calendar')
+ },
+ currentTimeIndicator: settings.time_indicator,
+ // event rendering
+ eventRender: fc_event_render,
+ // render element indicating more (invisible) events
+ overflowRender: function(data, element) {
+ element.html(rcmail.gettext('andnmore', 'calendar').replace('$nr', data.count))
+ .click(function(e){ me.fisheye_view(data.date); });
+ },
+ // callback when a specific event is clicked
+ eventClick: function(event, ev, view) {
+ if (!event.temp && String(event.className).indexOf('fc-type-freebusy') < 0)
+ event_show_dialog(event, ev);
+ }
+ };
+
/*** imports ***/
var Q = this.quote_html;
var text2html = this.text2html;
@@ -1598,25 +1670,13 @@ function rcube_calendar_ui(settings)
// initialize resource calendar display
var resource_cal = $(rcmail.gui_objects.resourceinfocalendar);
- resource_cal.fullCalendar({
+ resource_cal.fullCalendar($.extend({}, fullcalendar_defaults, {
header: { left: '', center: '', right: '' },
height: resource_cal.height() + 4,
defaultView: 'agendaWeek',
- ignoreTimezone: true,
eventSources: [],
- monthNames: settings['months'],
- monthNamesShort: settings['months_short'],
- dayNames: settings['days'],
- dayNamesShort : settings['days_short'],
- firstDay: settings['first_day'],
- firstHour: settings['first_hour'],
slotMinutes: 60,
allDaySlot: false,
- timeFormat: { '': settings['time_format'] },
- axisFormat: settings['time_format'],
- columnFormat: { day: 'dddd ' + settings['date_short'] },
- titleFormat: { day: 'dddd ' + settings['date_long'] },
- currentTimeIndicator: settings.time_indicator,
eventRender: function(event, element, view) {
var title = rcmail.get_label(event.status, 'calendar');
element.addClass('status-' + event.status);
@@ -1624,7 +1684,7 @@ function rcube_calendar_ui(settings)
element.find('.fc-event-title').text(title);
element.attr('aria-label', me.event_date_text(event, true) + ': ' + title);
}
- });
+ }));
$('#resource-calendar-prev').click(function(){
resource_cal.fullCalendar('prev');
@@ -2107,37 +2167,69 @@ function rcube_calendar_ui(settings)
me.fisheye_date = null;
}
})
- .fullCalendar({
+ .fullCalendar($.extend({}, fullcalendar_defaults, {
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'),
- currentTimeIndicator: settings.time_indicator,
- eventRender: fc_event_render,
- eventClick: function(event, ev, view) {
- event_show_dialog(event, ev);
- }
- });
+ eventSources: sources
+ }));
this.fisheye_date = date;
};
+ // opens the given calendar in a popup dialog
+ this.quickview = function(id)
+ {
+ $('#quickview-calendar:ui-dialog').dialog('close');
+
+ var dialog, src, cal = this.calendars[id], date = fc.fullCalendar('getDate'),
+ h = $(window).height() - 50,
+ me = this;
+
+ // clone and modify calendar properties
+ src = $.extend({}, cal);
+ src.editable = false;
+ src.url += '&_quickview=1';
+
+ dialog = $('<div>')
+ .attr('id', 'quickview-calendar')
+ .dialog({
+ modal: true,
+ width: Math.min(1000, $(window).width() - 100),
+ height: h,
+ title: cal.name.replace('»', '»').replace(' ', ' '),
+ open: function() {
+ setTimeout(function() { dialog.find('.fc-button-next').first().focus(); }, 10);
+ },
+ close: function() {
+ dialog.dialog('destroy').fullCalendar('destroy').remove();
+ me.quickview_active = null;
+ },
+ resize: function(e) {
+ // adjust height when dialog resizes
+ dialog.fullCalendar('option', 'height', dialog.height() + 8);
+ }
+ })
+ .fullCalendar($.extend({}, fullcalendar_defaults, {
+ header: {
+ left: 'agendaDay,agendaWeek,month,table',
+ center: 'title',
+ right: 'prev,next today'
+ },
+ height: h - 50,
+ defaultView: fc.fullCalendar('getView').name || fullcalendar_defaults.defaultView,
+ date: date.getDate(),
+ month: date.getMonth(),
+ year: date.getFullYear(),
+ slotMinutes: 60,
+ eventSources: [ src ]
+ }));
+
+ me.quickview_active = id;
+ };
+
//public method to show the print dialog.
this.print_calendars = function(view)
{
@@ -2464,6 +2556,22 @@ function rcube_calendar_ui(settings)
{
var source = me.calendars[p.source];
+ // helper function to update the given fullcalendar view
+ function update_view(view, event, source) {
+ var existing = view.fullCalendar('clientEvents', event._id);
+ if (existing.length) {
+ $.extend(existing[0], event);
+ view.fullCalendar('updateEvent', existing[0]);
+ // remove old recurrence instances
+ if (event.recurrence && !event.recurrence_id)
+ view.fullCalendar('removeEvents', function(e){ return e._id.indexOf(event._id+'-') == 0; });
+ }
+ else {
+ event.source = source; // link with source
+ view.fullCalendar('renderEvent', event);
+ }
+ }
+
if (source && (p.refetch || (p.update && !source.active))) {
// activate event source if new event was added to an invisible calendar
if (!source.active) {
@@ -2473,31 +2581,31 @@ function rcube_calendar_ui(settings)
}
else
fc.fullCalendar('refetchEvents', source);
+
+ if (this.quickview_active)
+ $('#quickview-calendar').fullCalendar('refetchEvents');
}
// add/update single event object
else if (source && p.update) {
var event = p.update;
event.temp = false;
+
+ // update quickview
+ if (this.quickview_active)
+ update_view($('#quickview-calendar'), event, source);
+ // update fish-eye view
+ if (this.fisheye_date)
+ update_view($('#fish-eye-view'), event, source);
+
+ // update main view
event.editable = source.editable;
- var existing = fc.fullCalendar('clientEvents', event._id);
- if (existing.length) {
- $.extend(existing[0], event);
- fc.fullCalendar('updateEvent', existing[0]);
- // remove old recurrence instances
- if (event.recurrence && !event.recurrence_id)
- fc.fullCalendar('removeEvents', function(e){ return e._id.indexOf(event._id+'-') == 0; });
- }
- else {
- event.source = source; // link with source
- fc.fullCalendar('renderEvent', event);
- }
- // refresh fish-eye view
- if (me.fisheye_date)
- me.fisheye_view(me.fisheye_date);
+ update_view(fc, event, source);
}
// refetch all calendars
else if (p.refetch) {
fc.fullCalendar('refetchEvents');
+ if (this.quickview_active)
+ $('#quickview-calendar').fullCalendar('refetchEvents');
}
// remove temp events
@@ -2811,6 +2919,18 @@ function rcube_calendar_ui(settings)
else
rcmail.display_message(rcmail.gettext('nocalendarsfound','calendar'), 'info');
});
+ calendars_list.addEventListener('click-item', function(event) {
+ // handle clicks on quickview icon: temprarily add this source and open in quickview
+ if ($(event.target).hasClass('quickview') && event.data) {
+ if (!me.calendars[event.data.id]) {
+ event.data.readonly = true;
+ event.data.active = false;
+ event.data.subscribed = false;
+ add_calendar_source(event.data);
+ }
+ me.quickview(event.data.id);
+ }
+ });
// init (delegate) event handler on calendar list checkboxes
$(rcmail.gui_objects.calendarslist).on('click', 'input[type=checkbox]', function(e){
@@ -2839,6 +2959,14 @@ function rcube_calendar_ui(settings)
calendars_list.select(this.value);
return rcube_event.cancel(e);
}
+ })
+ // init (delegate) event handler on quickview links
+ .on('click', 'a.quickview', function(e) {
+ var id = $(this).closest('li').attr('id').replace(/^rcmlical/, '');
+ if (me.calendars[id])
+ me.quickview(id);
+ e.stopPropagation();
+ return false;
});
// register dbl-click handler to open calendar edit dialog
@@ -2859,75 +2987,19 @@ function rcube_calendar_ui(settings)
viewdate.setTime(fromunixtime(rcmail.env.date));
// initalize the fullCalendar plugin
- var fc = $('#calendar').fullCalendar({
+ var fc = $('#calendar').fullCalendar($.extend({}, fullcalendar_defaults, {
header: {
right: 'prev,next today',
center: 'title',
left: 'agendaDay,agendaWeek,month,table'
},
- aspectRatio: 1,
date: viewdate.getDate(),
month: viewdate.getMonth(),
year: viewdate.getFullYear(),
- ignoreTimezone: true, // will treat the given date strings as in local (browser's) timezone
height: $('#calendar').height(),
eventSources: event_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'],
- agenda: settings['time_format'] + '{ - ' + settings['time_format'] + '}',
- list: settings['time_format'] + '{ - ' + settings['time_format'] + '}',
- table: settings['time_format'] + '{ - ' + settings['time_format'] + '}'
- },
- axisFormat : settings['time_format'],
- columnFormat: {
- month: 'ddd', // Mon
- week: 'ddd ' + settings['date_short'], // Mon 9/7
- day: 'dddd ' + settings['date_short'], // Monday 9/7
- table: settings['date_agenda']
- },
- titleFormat: {
- month: 'MMMM yyyy',
- week: settings['dates_long'],
- day: 'dddd ' + settings['date_long'],
- table: settings['dates_long']
- },
- listPage: 1, // advance one day in agenda view
- listRange: settings['agenda_range'],
- listSections: settings['agenda_sections'],
- tableCols: ['handle', 'date', 'time', 'title', 'location'],
- defaultView: rcmail.env.view || settings['default_view'],
- allDayText: rcmail.gettext('all-day', 'calendar'),
- buttonText: {
- prev: (bw.ie6 ? ' << ' : ' ◄ '),
- next: (bw.ie6 ? ' >> ' : ' ► '),
- today: settings['today'],
- day: rcmail.gettext('day', 'calendar'),
- week: rcmail.gettext('week', 'calendar'),
- month: rcmail.gettext('month', 'calendar'),
- table: rcmail.gettext('agenda', 'calendar')
- },
- listTexts: {
- until: rcmail.gettext('until', 'calendar'),
- past: rcmail.gettext('pastevents', 'calendar'),
- today: rcmail.gettext('today', 'calendar'),
- tomorrow: rcmail.gettext('tomorrow', 'calendar'),
- thisWeek: rcmail.gettext('thisweek', 'calendar'),
- nextWeek: rcmail.gettext('nextweek', 'calendar'),
- thisMonth: rcmail.gettext('thismonth', 'calendar'),
- nextMonth: rcmail.gettext('nextmonth', 'calendar'),
- future: rcmail.gettext('futureevents', 'calendar'),
- week: rcmail.gettext('weekofyear', 'calendar')
- },
selectable: true,
selectHelper: false,
- currentTimeIndicator: settings.time_indicator,
loading: function(isLoading) {
me.is_loading = isLoading;
this._rc_loading = rcmail.set_busy(isLoading, 'loading', this._rc_loading);
@@ -2935,13 +3007,6 @@ function rcube_calendar_ui(settings)
if (!isLoading)
me.events_loaded($(this).fullCalendar('clientEvents').length);
},
- // event rendering
- eventRender: fc_event_render,
- // render element indicating more (invisible) events
- overflowRender: function(data, element) {
- element.html(rcmail.gettext('andnmore', 'calendar').replace('$nr', data.count))
- .click(function(e){ me.fisheye_view(data.date); });
- },
// callback for date range selection
select: function(start, end, allDay, e, view) {
var range_select = (!allDay || start.getDate() != end.getDate())
@@ -2966,11 +3031,6 @@ function rcube_calendar_ui(settings)
day_clicked = date.getTime();
day_clicked_ts = now;
},
- // callback when a specific event is clicked
- eventClick: function(event, ev, view) {
- if (!event.temp)
- event_show_dialog(event, ev);
- },
// callback when an event was dragged and finally dropped
eventDrop: function(event, dayDelta, minuteDelta, allDay, revertFunc) {
if (event.end == null || event.end.getTime() < event.start.getTime()) {
@@ -3040,7 +3100,7 @@ function rcube_calendar_ui(settings)
if (fc && view.name == 'month')
fc.fullCalendar('option', 'maxHeight', Math.floor((view.element.parent().height()-18) / 6) - 35);
}
- });
+ }));
// format time string
var formattime = function(hour, minutes, start) {
diff --git a/plugins/calendar/drivers/kolab/kolab_user_calendar.php b/plugins/calendar/drivers/kolab/kolab_user_calendar.php
index c52bfd7..bcfc772 100644
--- a/plugins/calendar/drivers/kolab/kolab_user_calendar.php
+++ b/plugins/calendar/drivers/kolab/kolab_user_calendar.php
@@ -210,8 +210,10 @@ class kolab_user_calendar extends kolab_calendar
}
}
- // get events from the user's free/busy feed
- $this->fetch_freebusy($limit_changed);
+ // get events from the user's free/busy feed (for quickview only)
+ if (!empty($_REQUEST['_quickview']) && empty($search)) {
+ $this->fetch_freebusy($limit_changed);
+ }
$events = array();
foreach ($this->events as $id => $event) {
@@ -281,7 +283,7 @@ class kolab_user_calendar extends kolab_calendar
// console('_fetch_freebusy', kolab_storage::get_freebusy_url($this->userdata['mail']), $fbdata);
- // parse free-busy information using Horde classes
+ // parse free-busy information
$count = 0;
if ($fbdata) {
$ical = $this->cal->get_ical();
@@ -304,6 +306,7 @@ class kolab_user_calendar extends kolab_calendar
'start' => $from,
'end' => $to,
'free_busy' => $statusmap[$type] ?: 'busy',
+ 'className' => 'fc-type-freebusy',
'organizer' => array(
'email' => $this->userdata['mail'],
'name' => $this->userdata['displayname'],
diff --git a/plugins/calendar/lib/calendar_ui.php b/plugins/calendar/lib/calendar_ui.php
index 5e1bd44..4fef691 100644
--- a/plugins/calendar/lib/calendar_ui.php
+++ b/plugins/calendar/lib/calendar_ui.php
@@ -308,6 +308,7 @@ class calendar_ui
html::span(array('class' => 'calname', 'id' => $label_id, 'title' => $title), $prop['editname'] ? Q($prop['editname']) : $prop['listname']) .
($prop['virtual'] ? '' :
html::tag('input', array('type' => 'checkbox', 'name' => '_cal[]', 'value' => $id, 'checked' => $prop['active'], 'aria-labelledby' => $label_id), '') .
+ html::a(array('href' => '#', 'class' => 'quickview', 'title' => $this->cal->gettext('quickview'), 'role' => 'checkbox', 'aria-checked' => 'false'), '') .
(isset($prop['subscribed']) ? html::a(array('href' => '#', 'class' => 'subscribed', 'title' => $this->cal->gettext('calendarsubscribe'), 'role' => 'checkbox', 'aria-checked' => $prop['subscribed'] ? 'true' : 'false'), ' ') : '') .
html::span(array('class' => 'handle', 'style' => "background-color: #" . ($prop['color'] ?: 'f00')), ' ')
)
diff --git a/plugins/calendar/localization/en_US.inc b/plugins/calendar/localization/en_US.inc
index 80d36cb..87a3e65 100644
--- a/plugins/calendar/localization/en_US.inc
+++ b/plugins/calendar/localization/en_US.inc
@@ -94,6 +94,7 @@ $labels['calsearchresults'] = 'Available Calendars';
$labels['calendarsubscribe'] = 'List permanently';
$labels['nocalendarsfound'] = 'No calendars found';
$labels['nrcalendarsfound'] = '$nr calendars found';
+$labels['quickview'] = 'View only this calendar';
// agenda view
$labels['listrange'] = 'Range to display:';
diff --git a/plugins/calendar/skins/larry/calendar.css b/plugins/calendar/skins/larry/calendar.css
index d78d9ec..de6aab5 100644
--- a/plugins/calendar/skins/larry/calendar.css
+++ b/plugins/calendar/skins/larry/calendar.css
@@ -219,11 +219,11 @@ pre {
#calendars .treelist li span.calname {
display: block;
- padding: 0px 30px 2px 2px;
+ padding: 0px 18px 2px 2px;
position: absolute;
top: 7px;
left: 38px;
- right: 40px;
+ right: 60px;
cursor: default;
background: url(images/calendars.png) right 20px no-repeat;
overflow: hidden;
@@ -240,7 +240,7 @@ pre {
#calendars .treelist.flat li span.calname {
left: 24px;
- right: 22px;
+ right: 42px;
}
#calendars .treelist li span.handle {
@@ -288,6 +288,29 @@ pre {
background-position: -16px -110px;
}
+#calendars .treelist li a.quickview {
+ display: inline-block;
+ position: absolute;
+ top: 6px;
+ right: 42px;
+ width: 16px;
+ height: 16px;
+ padding: 0;
+ background: url(images/calendars.png) -100px 0 no-repeat;
+ overflow: hidden;
+ text-indent: -5000px;
+ cursor: pointer;
+}
+
+#calendars .treelist div > a.quickview:focus,
+#calendars .treelist li div:hover > a.quickview {
+ background-position: 0 -128px;
+}
+
+#calendars .treelist li div.focusview > a.quickview {
+ background-position: -18px -128px;
+}
+
#calendars .treelist li input {
position: absolute;
top: 5px;
@@ -1316,9 +1339,26 @@ a.dropdown-link:after {
bottom: 2px;
}
+#quickview-calendar {
+ padding: 8px;
+ overflow: hidden;
+}
+
.calendarmain .fc-button,
.calendarmain .fc-button.fc-state-default,
.calendarmain .fc-button.fc-state-hover {
+ background-color: #f5f5f5;
+ background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));
+ background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);
+ background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);
+ background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);
+ background-position: 0 0;
+}
+
+.calendarmain #calendar .fc-button,
+.calendarmain #calendar .fc-button.fc-state-default,
+.calendarmain #calendar .fc-button.fc-state-hover {
margin: 0 0 0 0;
height: 20px;
line-height: 20px;
@@ -1338,22 +1378,15 @@ a.dropdown-link:after {
text-decoration: none;
}
-.calendarmain .fc-button.fc-state-disabled {
+.calendarmain #calendar .fc-button.fc-state-disabled {
color: #999;
background: #d8d8d8;
}
-.calendarmain .fc-button.fc-state-down {
- margin: 0;
- background: #bababa;
- background: -moz-linear-gradient(top, #bababa 0%, #d8d8d8 100%);
- background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#bababa), color-stop(100%,#d8d8d8));
- background: -o-linear-gradient(top, #bababa 0%, #d8d8d8 100%);
- background: -ms-linear-gradient(top, #bababa 0%, #d8d8d8 100%);
- background: linear-gradient(top, #bababa 0%, #d8d8d8 100%);
-}
-
-.calendarmain .fc-button.fc-state-active {
+.calendarmain .fc-button.fc-state-active,
+.calendarmain .fc-button.fc-state-down,
+.calendarmain #calendar .fc-button.fc-state-active,
+.calendarmain #calendar .fc-button.fc-state-down {
color: #333;
background: #bababa;
background: -moz-linear-gradient(top, #bababa 0%, #d8d8d8 100%);
@@ -1363,12 +1396,12 @@ a.dropdown-link:after {
background: linear-gradient(top, #bababa 0%, #d8d8d8 100%);
}
-.calendarmain .fc-header .fc-button {
+.calendarmain #calendar .fc-header .fc-button {
margin-left: -1px;
margin-right: 0;
}
-.calendarmain .fc-header-left .fc-button {
+.calendarmain #calendar .fc-header-left .fc-button {
display: inline-block;
margin: 0;
text-align: center;
@@ -1393,58 +1426,58 @@ a.dropdown-link:after {
outline: none;
}
-.calendarmain .fc-header-left .fc-button:focus {
+.calendarmain #calendar .fc-header-left .fc-button:focus {
color: #fff;
text-shadow: 0px 1px 1px #666;
background-color: rgba(30,150,192, 0.5);
border-radius: 3px;
}
-.calendarmain .fc-header-left .fc-button.fc-state-active {
+.calendarmain #calendar .fc-header-left .fc-button.fc-state-active {
font-weight: bold;
color: #222;
text-shadow: none;
background-color: transparent;
}
-.calendarmain .fc-header-left .fc-button-agendaDay {
+.calendarmain #calendar .fc-header-left .fc-button-agendaDay {
background-position: center -120px;
}
-.calendarmain .fc-header-left .fc-button-agendaDay.fc-state-active {
+.calendarmain #calendar .fc-header-left .fc-button-agendaDay.fc-state-active {
background-position: center -160px;
}
-.calendarmain .fc-header-left .fc-button-agendaWeek {
+.calendarmain #calendar .fc-header-left .fc-button-agendaWeek {
background-position: center -200px;
}
-.calendarmain .fc-header-left .fc-button-agendaWeek.fc-state-active {
+.calendarmain #calendar .fc-header-left .fc-button-agendaWeek.fc-state-active {
background-position: center -240px;
}
-.calendarmain .fc-header-left .fc-button-month {
+.calendarmain #calendar .fc-header-left .fc-button-month {
background-position: center -280px;
}
-.calendarmain .fc-header-left .fc-button-month.fc-state-active {
+.calendarmain #calendar .fc-header-left .fc-button-month.fc-state-active {
background-position: center -320px;
}
-.calendarmain .fc-header-left .fc-button-table {
+.calendarmain #calendar .fc-header-left .fc-button-table {
background-position: center -360px;
}
-.calendarmain .fc-header-left .fc-button-table.fc-state-active {
+.calendarmain #calendar .fc-header-left .fc-button-table.fc-state-active {
background-position: center -400px;
}
-.calendarmain .fc-header-right {
+.calendarmain #calendar .fc-header-right {
padding-right: 252px;
padding-top: 4px;
}
-.fc-header-title {
+.calendarmain #calendar .fc-header-title {
padding-top: 5px;
}
@@ -1452,6 +1485,39 @@ a.dropdown-link:after {
font-size: 1em !important;
}
+.fc-type-freebusy {
+ opacity: 0.55;
+ color: #fff !important;
+
+ background: rgba(80,80,80,0.85) !important;
+ background: -moz-linear-gradient(top, rgba(80,80,80,0.85) 0%, rgba(48,48,48,0.9) 100%) !important;
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(80,80,80,0.85)), color-stop(100%,rgba(48,48,48,0.9))) !important;
+ background: -webkit-linear-gradient(top, rgba(80,80,80,0.85) 0%, rgba(48,48,48,0.85) 100%) !important;
+ background: -o-linear-gradient(top, rgba(80,80,80,0.85) 0%, rgba(48,48,48,0.85) 100%) !important;
+ background: -ms-linear-gradient(top, rgba(80,80,80,0.85) 0%, rgba(48,48,48,0.85) 100%) !important;
+ background: linear-gradient(to bottom, rgba(80,80,80,0.85) 0%, rgba(48,48,48,0.85) 100%) !important;
+
+ -moz-box-shadow: inset 0px 1px 0 0px #888;
+ -webkit-box-shadow: inset 0px 1px 0 0px #888;
+ -o-box-shadow: inset 0px 1px 0 0px #888;
+ box-shadow: inset 0px 1px 0 0px #888;
+
+ border-color: #444 !important;
+ cursor: default !important;
+}
+
+.fc-type-freebusy .fc-event-skin,
+.fc-type-freebusy .fc-event-inner {
+ background-color: transparent !important;
+ border-color: #444 !important;
+ color: #fff !important;
+ text-shadow: 0 1px 1px #000;
+}
+
+.fc-type-freebusy .fc-event-title {
+ display: none;
+}
+
.calendarmain .fc-event:focus {
outline: 1px solid rgba(71,135,177, 0.4);
-webkit-box-shadow: 0 0 2px 3px rgba(71,135,177, 0.6);
diff --git a/plugins/calendar/skins/larry/images/calendars.png b/plugins/calendar/skins/larry/images/calendars.png
index 117d329..bf84f3a 100644
Binary files a/plugins/calendar/skins/larry/images/calendars.png and b/plugins/calendar/skins/larry/images/calendars.png differ
commit 30c684026953722e48052eae387ec53bcdabc7dd
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Thu Jun 26 17:40:19 2014 +0200
Forward clicks on folderlist search results with full node data
diff --git a/plugins/libkolab/js/folderlist.js b/plugins/libkolab/js/folderlist.js
index 543673b..6caf419 100644
--- a/plugins/libkolab/js/folderlist.js
+++ b/plugins/libkolab/js/folderlist.js
@@ -71,6 +71,9 @@ function kolab_folderlist(node, p)
node = search_results_widget.get_node(id),
has_children = node.children && node.children.length;
+ e.stopPropagation();
+ e.bubbles = false;
+
// activate + subscribe
if ($(e.target).hasClass('subscribed')) {
search_results[id].subscribed = true;
@@ -98,6 +101,17 @@ function kolab_folderlist(node, p)
if (rcube_event.is_keyboard(e)) {
$(me.get_item(id, true)).find('input[type=checkbox]').first().focus();
}
+ })
+ .on('click', function(e) {
+ var prop, id = String($(e.target).closest('li').attr('id')).replace(new RegExp('^'+p.id_prefix), '');
+ if (p.id_decode)
+ id = p.id_decode(id);
+
+ // forward event
+ if (prop = search_results[id]) {
+ e.data = prop;
+ me.triggerEvent('click-item', e);
+ }
});
}
commit dd2ad15cdcee4a4f4fd608846b3990685dfba623
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Thu Jun 26 15:28:17 2014 +0200
Remove duplicate function
diff --git a/plugins/calendar/lib/js/fullcalendar.js b/plugins/calendar/lib/js/fullcalendar.js
index dc2fe10..e286310 100644
--- a/plugins/calendar/lib/js/fullcalendar.js
+++ b/plugins/calendar/lib/js/fullcalendar.js
@@ -509,9 +509,9 @@ function Calendar(element, options, eventSources) {
// TODO: going forward, most of this stuff should be directly handled by the view
- function refetchEvents() { // can be called as an API method
+ function refetchEvents(source) { // can be called as an API method
clearEvents();
- fetchAndRenderEvents();
+ fetchAndRenderEvents(source);
}
@@ -547,18 +547,13 @@ function Calendar(element, options, eventSources) {
}
- function fetchAndRenderEvents() {
- fetchEvents(currentView.visStart, currentView.visEnd);
+ function fetchAndRenderEvents(source) {
+ fetchEvents(currentView.visStart, currentView.visEnd, source);
// ... will call reportEvents
// ... which will call renderEvents
}
- function refetchEvents(source) {
- fetchEvents(currentView.visStart, currentView.visEnd, source); // will call reportEvents
- }
-
-
// called when event data arrives
function reportEvents(_events) {
events = _events;
More information about the commits
mailing list