From 465d167ef1fb3bbe20da8c15c61bbdfc3e0935bb Mon Sep 17 00:00:00 2001 From: Jan Schneider Date: Tue, 16 Mar 2010 22:37:46 +0100 Subject: [PATCH] Add preference to limit the events per day in the month view. --- kronolith/config/prefs.php.dist | 10 +++- kronolith/docs/CHANGES | 1 + kronolith/js/kronolith.js | 110 +++++++++++++++++++++++++++++++++++++++- kronolith/lib/Kronolith.php | 8 +-- kronolith/themes/screen.css | 12 ----- 5 files changed, 124 insertions(+), 17 deletions(-) diff --git a/kronolith/config/prefs.php.dist b/kronolith/config/prefs.php.dist index 98162a919..51a81d972 100644 --- a/kronolith/config/prefs.php.dist +++ b/kronolith/config/prefs.php.dist @@ -10,7 +10,7 @@ $prefGroups['view'] = array( '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', @@ -95,6 +95,14 @@ $_prefs['defaultview'] = array( '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, diff --git a/kronolith/docs/CHANGES b/kronolith/docs/CHANGES index b4fc357f8..ae9875ddb 100644 --- a/kronolith/docs/CHANGES +++ b/kronolith/docs/CHANGES @@ -2,6 +2,7 @@ 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. diff --git a/kronolith/js/kronolith.js b/kronolith/js/kronolith.js index 965a5c34d..d8164b538 100644 --- a/kronolith/js/kronolith.js +++ b/kronolith/js/kronolith.js @@ -1276,6 +1276,88 @@ KronolithCore = { } 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': @@ -1571,12 +1653,17 @@ KronolithCore = { 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': @@ -1599,6 +1686,22 @@ KronolithCore = { .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('|'); @@ -3516,6 +3619,11 @@ KronolithCore = { 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)); diff --git a/kronolith/lib/Kronolith.php b/kronolith/lib/Kronolith.php index a28fc0752..0e7c61e9a 100644 --- a/kronolith/lib/Kronolith.php +++ b/kronolith/lib/Kronolith.php @@ -202,14 +202,15 @@ class Kronolith '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', @@ -346,6 +347,7 @@ class Kronolith '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."), diff --git a/kronolith/themes/screen.css b/kronolith/themes/screen.css index 78095a8f0..d0db1b01a 100644 --- a/kronolith/themes/screen.css +++ b/kronolith/themes/screen.css @@ -1282,18 +1282,6 @@ table.kronolithView td.kronolithFirstCol { 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; -- 2.11.0