'label' => _("User Interface"),
'desc' => _("Select confirmation options, how to display the different views and choose default view."),
'members' => array('dynamic_view', 'confirm_delete', 'defaultview',
- 'time_between_days', 'week_start_monday',
+ 'max_events', 'time_between_days', 'week_start_monday',
'day_hour_start', 'day_hour_end', 'day_hour_force',
'slots_per_hour', 'show_icons', 'show_time',
'show_location', 'show_fb_legend',
'desc' => _("Select the view to display on startup:")
);
+$_prefs['max_events'] = array(
+ 'value' => 3,
+ 'locked' => false,
+ 'shared' => false,
+ 'type' => 'number',
+ 'desc' => _("How many events should be displayed per day in the month view? Set to 0 to always show all events."),
+);
+
// Display the timeslots between each day column, in week view.
$_prefs['time_between_days'] = array(
'value' => 0,
v3.0-git
--------
+[jan] Add preference to limit the events per day in the month view.
[jan] Add system calendars (Request #2059).
[jan] Add URL field to events.
[jan] Add task management capabilities to the Ajax interface.
}
this.holidays.push(event.key);
}
+ if (view == 'month' && Kronolith.conf.max_events) {
+ var events = $('kronolithMonthDay' + date).select('.kronolithEvent');
+ if (events.size() >= Kronolith.conf.max_events) {
+ if (date == (new Date().dateString())) {
+ // This is today.
+ if (event.value.al || event.value.end.isBefore()) {
+ // No room for all-day or finished events.
+ this.insertMore(date);
+ return;
+ }
+ var remove, max;
+ // Find an event that is earlier than now or
+ // later then the current event.
+ events.each(function(elm) {
+ var calendar = elm.retrieve('calendar').split('|'),
+ event = this.ecache.get(calendar[0]).get(calendar[1]).get(date).get(elm.retrieve('eventid'));
+ if (event.start.isBefore()) {
+ remove = elm;
+ throw $break;
+ }
+ if (!max || event.start.isAfter(max)) {
+ max = event.start;
+ remove = elm;
+ }
+ }, this);
+ if (remove) {
+ remove.remove();
+ } else {
+ this.insertMore(date);
+ return;
+ }
+ } else {
+ // Not today.
+ var allDays = events.findAll(function(elm) {
+ var calendar = elm.retrieve('calendar').split('|');
+ return this.ecache.get(calendar[0]).get(calendar[1]).get(date).get(elm.retrieve('eventid')).al;
+ }.bind(this));
+ if (event.value.al) {
+ // We want one all-day event.
+ if (allDays.size()) {
+ // There already is an all-day event.
+ if (event.value.x == Kronolith.conf.status.confirmed ||
+ event.value.x == Kronolith.conf.status.tentative) {
+ // But is there a less important
+ // one?
+ var status = [Kronolith.conf.status.free, Kronolith.conf.status.cancelled];
+ if (event.value.x == Kronolith.conf.status.confirmed) {
+ status.push(Kronolith.conf.status.tentative);
+ }
+ var free = allDays.detect(function(elm) {
+ var calendar = elm.retrieve('calendar').split('|');
+ return status.include(this.ecache.get(calendar[0]).get(calendar[1]).get(date).get(elm.retrieve('eventid')).x);
+ }.bind(this));
+ if (!free) {
+ this.insertMore(date);
+ return;
+ }
+ free.remove();
+ } else {
+ // No.
+ this.insertMore(date);
+ return;
+ }
+ } else {
+ // Remove the last event to make room
+ // for this one.
+ events.pop().remove();
+ }
+ } else {
+ if (allDays.size() > 1) {
+ // We don't want more than one all-day
+ // event.
+ allDays.pop().remove();
+ } else {
+ // This day is full.
+ this.insertMore(date);
+ return;
+ }
+ }
+ }
+ }
+ }
break;
case 'year':
var div = _createElement(event)
.setStyle({ backgroundColor: Kronolith.conf.calendars[calendar[0]][calendar[1]].bg,
color: Kronolith.conf.calendars[calendar[0]][calendar[1]].fg });
-
$('kronolithMonthDay' + date).insert(div);
if (event.value.pe) {
div.setStyle({ cursor: 'move' });
new Drag('kronolithEventmonth' + event.value.calendar + date + event.key, { threshold: 5, parentElement: function() { return $('kronolithViewMonthBody'); }, snapToParent: true });
}
+ if (Kronolith.conf.max_events) {
+ var more = $('kronolithMonthDay' + date).down('.kronolithMore');
+ if (more) {
+ $('kronolithMonthDay' + date).insert({ bottom: more.remove() });
+ }
+ }
break;
case 'agenda':
.observe('mouseout', div.removeClassName.curry('kronolithSelected'));
},
+ /**
+ * Adds a "more..." button to the month view cell that links to the days,
+ * or moves it to the buttom.
+ *
+ * @param string date The date string of the day cell.
+ */
+ insertMore: function(date)
+ {
+ var more = $('kronolithMonthDay' + date).down('.kronolithMore');
+ if (more) {
+ $('kronolithMonthDay' + date).insert({ bottom: more.remove() });
+ } else {
+ $('kronolithMonthDay' + date).insert({ bottom: new Element('span', { className: 'kronolithMore' }).store('date', date).insert(Kronolith.text.more) });
+ }
+ },
+
setEventText: function(div, event)
{
var calendar = event.calendar.split('|');
e.stop();
return;
+ case 'kronolithMore':
+ this.go('day:' + elt.retrieve('date'));
+ e.stop();
+ return;
+
case 'kronolithDatePicker':
id = elt.readAttribute('id');
Horde_Calendar.open(id, Date.parseExact($F(id.replace(/Picker$/, 'Date')), Kronolith.conf.date_format));
'login_view' => $prefs->getValue('defaultview') == 'workweek' ? 'week' : $prefs->getValue('defaultview'),
'default_calendar' => 'internal|' . self::getDefaultCalendar(Horde_Perms::EDIT),
'week_start' => (int)$prefs->getValue('week_start_monday'),
+ 'max_events' => (int)$prefs->getValue('max_events'),
'date_format' => str_replace(array('%e', '%d', '%a', '%A', '%m', '%h', '%b', '%B', '%y', '%Y'),
array('d', 'dd', 'ddd', 'dddd', 'MM', 'MMM', 'MMM', 'MMMM', 'yy', 'yyyy'),
Horde_Nls::getLangInfo(D_FMT)),
'time_format' => $prefs->getValue('twentyFour') ? 'HH:mm' : 'hh:mm tt',
'status' => array('tentative' => self::STATUS_TENTATIVE,
- 'confirmed' => self::STATUS_CONFIRMED,
- 'cancelled' => self::STATUS_CANCELLED,
- 'free' => self::STATUS_FREE),
+ 'confirmed' => self::STATUS_CONFIRMED,
+ 'cancelled' => self::STATUS_CANCELLED,
+ 'free' => self::STATUS_FREE),
'recur' => array(Horde_Date_Recurrence::RECUR_NONE => 'None',
Horde_Date_Recurrence::RECUR_DAILY => 'Daily',
Horde_Date_Recurrence::RECUR_WEEKLY => 'Weekly',
'agenda' => _("Agenda"),
'searching' => sprintf(_("Events matching \"%s\""), '#{term}'),
'allday' => _("All day"),
+ 'more' => _("more..."),
'prefs' => _("Options"),
'no_url' => _("You must specify a URL."),
'wrong_auth' => _("The authentication information you specified wasn't accepted."),
background-color: #ebf3fc;
border-color: #808080;
}
-.kronolithMore {
- position: absolute;
- z-index: 10;
- right: 0;
- bottom: 0;
- width: 15px;
- height: 15px;
- background: white;
- border-right: none;
- border-bottom: none;
- text-align: center;
-}
/*
.kronolithWeekend {
background: #ffc;