Re-enable/implement preference for showing events as a per-day list

This commit is contained in:
Nathan Gray 2016-01-12 23:55:59 +00:00
parent 703ed91caa
commit 15dd34edcb
8 changed files with 359 additions and 147 deletions

View File

@ -117,10 +117,11 @@ class calendar_hooks
'1' => lang('Yes'),
'0' => lang('No'),
);
$grid_views = array(
'all' => lang('all'),
'day_week' => lang('Dayview').', '.lang('Four days view').' & '.lang('Weekview'),
'day4' => lang('Dayview').' & '.lang('Four days view'),
$list_views = array(
0 => lang('None'),
'weekN' => lang('Multiple week view'),
'week' => lang('Weekview'),
'day4' => lang('Four days view'),
'day' => lang('Dayview'),
);
$updates = array(
@ -346,19 +347,16 @@ class calendar_hooks
'admin' => False,
'forced' => 'user',
),
//ATM:Disable the use_time_grid preference
//@TODO: the whole use_time_grid preference should be removed
// after we decided that is not neccessary to have it at all
/*'use_time_grid' => array(
'type' => 'select',
'label' => 'Views with fixed time intervals',
'use_time_grid' => array(
'type' => 'multiselect',
'label' => 'Views showing a list of events',
'name' => 'use_time_grid',
'values' => $grid_views,
'help' => 'For which views should calendar show distinct lines with a fixed time interval.',
'values' => $list_views,
'help' => 'For which views should calendar just a list of events instead of distinct lines with a fixed time interval.',
'xmlrpc' => True,
'admin' => False,
'forced' => 'all',
),*/
'default' => ['weekN'],
),
'link_title' => array(
'type' => 'multiselect',
'label' => 'Link title for events to show',

View File

@ -2082,6 +2082,10 @@ app.classes.calendar = AppJS.extend(
{
widget.set_show_weekend(view.show_weekend(state.state));
}
if(widget.set_granularity)
{
widget.set_granularity(view.granularity(state.state));
}
if(widget.id == value[row_index].id &&
widget.get_end_date().toJSON() == value[row_index].end_date
)
@ -2097,16 +2101,6 @@ app.classes.calendar = AppJS.extend(
widget.set_value(value[row_index++]);
}
},this, et2_calendar_view);
grid.iterateOver(function(widget) {
if(widget.set_granularity)
{
widget.set_granularity(view.granularity(state.state));
}
if(widget.resize)
{
widget.resize();
}
},this,et2_calendar_view);
// Single day with multiple owners still needs owners split to satisfy
// caching keys, otherwise they'll cache consolidated
@ -3327,7 +3321,10 @@ app.classes.calendar = AppJS.extend(
* How big or small are the displayed time chunks?
*/
granularity: function(state) {
return parseInt(egw.preference('interval','calendar')) || 30;
var list = egw.preference('use_time_grid','calendar').split(',');
return list.indexOf(state.view) >= 0 ?
0 :
parseInt(egw.preference('interval','calendar')) || 30;
},
extend: function(sub)
{
@ -3505,7 +3502,8 @@ jQuery.extend(app.classes.calendar,{
return week_start;
},
granularity: function(state) {
return 120;
// Always a list, not a grid
return 0;
},
scroll: function(delta)
{

View File

@ -160,6 +160,12 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
}
}
if(this.display_settings.granularity === 0)
{
this.div.attr('data-date', this.options.date);
}
else
{
this.display_settings.rowsToDisplay = ((this.display_settings.wd_end - this.display_settings.wd_start)/this.display_settings.granularity);
this.display_settings.rowHeight= (100/this.display_settings.rowsToDisplay).toFixed(1);
this.display_settings.titleHeight = (this.title.height()/this.div.height())*100;
@ -184,6 +190,7 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
.attr('data-minute',linkData.minute)
.appendTo(this.div);
}
}
},
/**
@ -245,7 +252,10 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
.attr('data-whole_day',true);
// Avoid redrawing if date is the same
if(new_date === this.options.date && !force_redraw)
if(new_date === this.options.date &&
this.display_settings.granularity === this._parent.options.granularity &&
!force_redraw
)
{
return;
}
@ -361,8 +371,13 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
},
set_width: function(width) {
if(this.width_timeout)
{
window.clearTimeout(this.width_timeout);
}
this.options.width = width;
window.setTimeout(jQuery.proxy(function() {
this.width_timeout = window.setTimeout(jQuery.proxy(function() {
this.width_timeout = null;
if(this.div)
{
this.div.outerWidth(this.options.width);
@ -487,7 +502,6 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
this.div.children('.hiddenEventAfter').remove();
var timegrid = this._parent;
var day = this;
// elem is jquery div of event
function isHidden(elem) {
@ -511,12 +525,16 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
// Check each event
this.iterateOver(function(event) {
// Skip whole day events and events missing value
if(!event.options || !event.options.value || event.options.value.whole_day_on_top) return;
if(this.display_settings.granularity && (
(!event.options || !event.options.value || event.options.value.whole_day_on_top))
)
{
return;
}
// Reset
event.title.css('top','');
event.body.css('padding-top','');
var hidden = isHidden.call(this,event.div);
if(!hidden)
{
@ -529,19 +547,43 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
event.title.css('top',timegrid.scrolling.scrollTop() - event.div.position().top);
event.body.css('padding-top',timegrid.scrolling.scrollTop() - event.div.position().top);
}
// Too many in list view, show indicator
else if (this.display_settings.granularity === 0 && hidden.completely)
{
var day = this;
this._hidden_indicator(event, false, function() {
app.calendar.update_state({view: 'day', date: day.date});
});
}
// Completely out of view, show indicator
else if (hidden.completely)
{
var indicator = '';
if(hidden.hidden === 'top')
this._hidden_indicator(event, hidden.hidden == 'top');
}
}, this, et2_calendar_event);
},
/**
* Show an indicator that there are hidden events
*
* @param {et2_calendar_event} event Event we're creating the indicator for
* @param {boolean} top Events hidden at the top (true) or bottom (false)
* @param {function} [onclick] Callback for when user clicks on the indicator
*/
_hidden_indicator: function _hidden_indicator(event, top, onclick)
{
if($j('.hiddenEventBefore',this.header).length == 0)
var indicator = '';
var day = this;
var timegrid = this._parent;
if(top)
{
if($j('.hiddenEventBefore',this.header).length === 0)
{
indicator = $j('<div class="hiddenEventBefore"></div>')
.appendTo(this.header)
.text(event.options.value.title)
.attr('data-hidden_count', 1)
.on('click', function() {
.on('click', typeof onclick === 'function' ? onclick : function() {
$j('.calendar_calEvent',day.div).first()[0].scrollIntoView();
return false;
});
@ -553,16 +595,16 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
indicator.text(day.egw().lang('%1 event(s) %2',indicator.attr('data-hidden_count'),''));
}
}
else if(hidden.hidden === 'bottom')
else
{
indicator = $j('.hiddenEventAfter',this.div);
if(indicator.length == 0)
if(indicator.length === 0)
{
indicator = $j('<div class="hiddenEventAfter"></div>')
.text(event.options.value.title)
.attr('data-hidden_count', 1)
.appendTo(this.div)
.on('click', function() {
.on('click', typeof onclick === 'function' ? onclick : function() {
$j('.calendar_calEvent',day.div).last()[0].scrollIntoView(false);
// Better re-run this to clean up
day._out_of_view();
@ -571,24 +613,31 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
}
else
{
indicator.attr('data-hidden_count', parseInt(indicator.attr('data-hidden_count')) + 1);
var count = parseInt(indicator.attr('data-hidden_count')) + 1
indicator.attr('data-hidden_count', count);
if(this.display_settings.granularity === 0)
{
indicator.text(indicator.text() + "\n" + event.options.value.title);
}
else
{
indicator.text(day.egw().lang('%1 event(s) %2',indicator.attr('data-hidden_count'),''));
}
indicator.css('top',timegrid.scrolling.height() + timegrid.scrolling.scrollTop()-indicator.height());
}
}
// Match color to the event
if(indicator !== '')
{
// Avoid white, which is hard to see
var color = jQuery.Color(event.div.css('border-top-color')).toString() !== jQuery.Color('white').toString() ?
event.div.css('border-top-color') : event.div.css('background-color');
// Use border-top-color, Firefox doesn't give a value with border-color
// Use border-bottom-color, Firefox doesn't give a value with border-color
var color = jQuery.Color(event.div.css('border-bottom-color')).toString() !== jQuery.Color('white').toString() ?
event.div.css('border-bottom-color') : event.div.css('background-color');
if(color !== 'rgba(0, 0, 0, 0)')
{
indicator.css('border-color', color);
}
}
}, this, et2_calendar_event);
},
/**
@ -598,6 +647,8 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
*/
_spread_events: function()
{
if(!this.date) return [];
var day_start = this.date.valueOf() / 1000;
var dst_check = new Date(this.date);
dst_check.setUTCHours(12);
@ -706,6 +757,21 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
// Calculate vertical positioning
var top = 0;
var height = 0;
// Position the event
if(this.display_settings.granularity === 0)
{
if(this.all_day.has(columns[c][i].div).length)
{
columns[c][i].div.prependTo(this.div);
}
columns[c][i].div.css('top', '');
columns[c][i].div.css('height', '');
columns[c][i].div.css('left', '');
columns[c][i].div.css('width', '');
// Strip out of view padding
columns[c][i].body.css('padding-top','');
continue;
}
if(columns[c][i].options.value.whole_day_on_top)
{
if(!this.all_day.has(columns[c][i].div).length)
@ -878,8 +944,15 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
return;
}
if(this.display_settings.granularity !== this._parent.options.granularity)
{
// Layout has changed
this._draw();
}
// Resize & position all events
this.position_event();
this._out_of_view();
}
});

View File

@ -238,8 +238,8 @@ var et2_calendar_event = et2_valueWidget.extend([et2_IDetachedDOM],
// Let timegrid always get the drag
.droppable('option','greedy',false)
// ?
.attr('data-draggable-id',event['id']+'_O'+event.owner+'_C'+(event.owner<0?'group'+Math.abs(event.owner):event.owner))
// Set full day flag
.attr('data-full_day', event.whole_day_on_top)
// Put everything we need for basic interaction here, so it's available immediately
.attr('data-id', event.id)
@ -312,6 +312,7 @@ var et2_calendar_event = et2_valueWidget.extend([et2_IDetachedDOM],
{
this.body
.html('<span class="calendar_calEventTitle">'+title+'</span>')
.append('<span class="calendar_calTimespan">'+this._get_timespan(event) + '</span>')
.append('<p>'+this.options.value.description+'</p>');
}
this.body

View File

@ -55,7 +55,7 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
name: "Granularity",
type: "integer",
default: parseInt(egw.preference('interval','calendar')) || 30,
description: "How many minutes per row"
description: "How many minutes per row, or 0 to display events as a list"
},
"onchange": {
"name": "onchange",
@ -194,6 +194,9 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
* for planner view to resize horizontally.
*/
this.div.on('mouseover', '.calendar_calEvent:not(.ui-resizable):not(.rowNoEdit)', function() {
// Only resize in timegrid
if(timegrid.options.granularity === 0) return;
// Load the event
timegrid._get_event_info(this);
var that = this;
@ -331,7 +334,7 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
{
this.scrolling.scrollTop(element.dropEnd.position().top);
}
else if (element.dropEnd.prev() && element.dropEnd.prev().position().top < this.scrolling[0].scrollTop)
else if (element.dropEnd.prev().length && element.dropEnd.prev().position().top < this.scrolling[0].scrollTop)
{
this.scrolling.scrollTop(element.dropEnd.prev().position().top);
}
@ -341,6 +344,12 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
{
time = this.egw().lang('Whole day');
}
else if (this.options.granularity === 0)
{
// No times, keep what's in the event
// Add class to helper to keep formatting
$j(helper).addClass('calendar_calTimeGridList');
}
else
{
time = jQuery.datepicker.formatTime(
@ -392,7 +401,13 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
if(event_data.app == 'calendar' && event_widget.options.value.whole_day)
{
event_widget._parent.date_helper.set_hours(0);
event_widget._parent.date_helper.set_minutes(0)
event_widget._parent.date_helper.set_minutes(0);
}
else if (timegrid.options.granularity === 0)
{
// List, not time grid - keep time
event_widget._parent.date_helper.set_hours(event_widget.options.value.start.getUTCHours());
event_widget._parent.date_helper.set_minutes(event_widget.options.value.start.getUTCMinutes());
}
else
{
@ -507,6 +522,7 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
}
this.update_timer = window.setTimeout(jQuery.proxy(function() {
this.widget.update_timer = null;
window.clearTimeout(this.resize_timer);
this.widget.loader.hide().show();
// Update actions
@ -600,11 +616,7 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
_drawTimes: function() {
$j('.calendar_calTimeRow',this.div).remove();
var wd_start = 60*this.options.day_start;
var wd_end = 60*this.options.day_end;
var granularity = this.options.granularity;
var totalDisplayMinutes = wd_end - wd_start;
var rowsToDisplay = Math.ceil((totalDisplayMinutes+60)/granularity);
this.div.toggleClass('calendar_calTimeGridList', this.options.granularity === 0);
this.gridHeader
.attr('data-date', this.options.start_date)
@ -614,13 +626,34 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
.append(this.dayHeader)
.appendTo(this.div);
// Max with 45 avoids problems when it's not shown
var header_height = Math.max(this.gridHeader.outerHeight(true), 45);
// Max with 18 avoids problems when it's not shown
var header_height = Math.max(this.gridHeader.outerHeight(true), 18);
this.scrolling
.appendTo(this.div)
.off()
// No time grid - list
if(this.options.granularity === 0)
{
this.scrolling.css('height','100%');
this.days.css('height', '100%');
this.iterateOver(function(day) {
day.resize();
},this,et2_calendar_daycol);
return;
}
var wd_start = 60*this.options.day_start;
var wd_end = 60*this.options.day_end;
var granularity = this.options.granularity;
var totalDisplayMinutes = wd_end - wd_start;
var rowsToDisplay = Math.ceil((totalDisplayMinutes+60)/granularity);
this.scrolling
.css('height', (this.div.innerHeight() - header_height)+'px')
.appendTo(this.div)
.off().on('scroll', jQuery.proxy(this._scroll, this));
.on('scroll', jQuery.proxy(this._scroll, this));
// Percent
var rowHeight = (100/rowsToDisplay).toFixed(1);
@ -701,6 +734,9 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
{
window.clearTimeout(this.resize_timer);
}
// No point if it is just going to be redone completely
if(this.upate_timer) return;
this.resize_timer = window.setTimeout(jQuery.proxy(function() {
if(this._resizeTimes)
{
@ -727,12 +763,23 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
var new_height = this.scrolling.height() / rowsToDisplay;
this.rowHeight = new_height;
var rows = $j('.calendar_calTimeRow',this.scrolling).height(this.rowHeight);
this.days.css('height', (this.rowHeight*rows.length)+'px');
if(!rows.length && this.options.granularity)
{
return this._drawTimes();
}
this.days.css('height', this.options.granularity === 0 ?
'100%' :
(this.rowHeight*rows.length)+'px'
);
$j('.calendar_calAddEvent',this.scrolling).height(this.rowHeight);
// Scroll to start of day
this._top_time = (wd_start * this.rowHeight) / this.options.granularity;
this.scrolling.scrollTop(this._top_time);
this.iterateOver(function(child) {
child.resize();
},this, et2_IResizeable);
},
/**
@ -749,7 +796,9 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
this.day_list = this._calculate_day_list(this.options.start_date, this.options.end_date, this.options.show_weekend);
}
// For a single day, we show each owner in their own daycol
var daily_owner = this.day_list.length === 1 && this.options.owner.length < parseInt(egw.preference('day_consolidate','calendar'));
var daily_owner = this.day_list.length === 1 &&
this.options.owner.length > 1 &&
this.options.owner.length < parseInt(egw.preference('day_consolidate','calendar'));
var daycols_needed = daily_owner ? this.options.owner.length : this.day_list.length;
var day_width = ( Math.min( $j(this.getInstanceManager().DOMContainer).width(),this.days.width())/daycols_needed);
if(!day_width || !this.day_list)
@ -815,6 +864,9 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
this.day_widgets.splice(delete_index--,1);
}
// Adjust and scroll to start of day
this.resizeTimes();
// Create / update day widgets with dates and data
for(var i = 0; i < this.day_widgets.length; i++)
{
@ -848,9 +900,6 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
this.set_label('');
}
// Adjust and scroll to start of day
this._resizeTimes();
// Handle not fully visible elements
this._scroll();
@ -1356,15 +1405,24 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
*/
set_granularity: function(minutes)
{
// Avoid 0 or less
minutes = Math.max(1,minutes);
// Avoid < 0
minutes = Math.max(0,minutes);
if(this.options.granularity !== minutes)
{
if(this.options.granularity === 0 || minutes === 0)
{
this.options.granularity = minutes;
// Need to re-do a bunch to make sure this is propagated
this.invalidate();
}
else
{
this.options.granularity = minutes;
this._drawTimes();
}
else
}
else if (!this.update_timer)
{
this.resizeTimes();
}
@ -1545,13 +1603,20 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
x = Math.round(x);
y = Math.round(y);
var nodes = $j('.calendar_calAddEvent[data-hour],.calendar_calDayColHeader',this.div).removeClass('drop-hover').filter(function() {
var nodes = this.options.granularity === 0 ?
$j('.calendar_calDayCol',this.div) :
$j('.calendar_calAddEvent[data-hour],.calendar_calDayColHeader',this.div);
nodes = nodes
.removeClass('drop-hover')
.filter(function() {
var offset = $j(this).offset();
var range={x:[offset.left,offset.left+$j(this).outerWidth()],y:[offset.top,offset.top+$j(this).outerHeight()]};
var i = (x >=range.x[0] && x <= range.x[1]) && (y >= range.y[0] && y <= range.y[1]);
return i;
}).addClass("drop-hover");
})
nodes.addClass("drop-hover");
return nodes;
},
@ -1626,9 +1691,9 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes
}
// Try to resize width, though animations cause problems
var total_width = ( $j(this.getInstanceManager().DOMContainer).width() - (
var total_width = Math.min(this.div.width(),( $j(this.getInstanceManager().DOMContainer).width() - (
this.days.innerWidth() ? this.div.innerWidth() - this.days.innerWidth() : 0
));
)));
var day_width = (total_width > 0 ? total_width : $j(this.getInstanceManager().DOMContainer).width())/this.day_widgets.length;
// update day widgets
for(var i = 0; i < this.day_widgets.length; i++)

View File

@ -10,7 +10,7 @@
*/
$setup_info['calendar']['name'] = 'calendar';
$setup_info['calendar']['version'] = '14.3.902';
$setup_info['calendar']['version'] = '14.3.903';
$setup_info['calendar']['app_order'] = 3;
$setup_info['calendar']['enable'] = 1;
$setup_info['calendar']['index'] = 'calendar.calendar_uiviews.index&ajax=true';

View File

@ -2683,3 +2683,23 @@ function calendar_upgrade14_3_901()
});
return $GLOBALS['setup_info']['calendar']['currentver'] = '14.3.902';
}
/**
* Change grid/list preference values to list each view
*/
function calendar_upgrade14_3_902()
{
preferences::change_preference('calendar', 'use_time_grid', function($attr, $old_value, $owner) {
switch($old_value)
{
case 'all':
return 0;
case 'day_week':
return ['day','day4','week'];
case 'day4':
return ['day','day4'];
}
return null;
});
return $GLOBALS['setup_info']['calendar']['currentver'] = '14.3.903';
}

View File

@ -191,6 +191,7 @@ e.g. the div with class calendar_calTimeGrid is generated by the timeGridWidget
width: 100%;
overflow-y: auto;
overflow-x: hidden;
cursor: default;
}
.calendar_calTimeGrid .loading,.calendar_plannerWidget .loading {
@ -298,6 +299,7 @@ e.g. the div with class calendar_calTimeGrid is generated by the timeGridWidget
border-right: 0px;
overflow: hidden;
z-index: 40;
cursor: pointer;
}
.calendar_calDayColHeader .hiddenEventBefore {
height: 2px;
@ -602,7 +604,9 @@ e.g. the div with class calendar_calTimeGrid is generated by the timeGridWidget
.calendar_calEventBody > p, .calendar_calEventBodySmall > p {
white-space: pre-wrap;
}
.calendar_calEventBody .calendar_calTimespan {
display: none;
}
.calendar_calEventBodySmall{
font-size: 95%;
}
@ -615,6 +619,59 @@ e.g. the div with class calendar_calTimeGrid is generated by the timeGridWidget
font-weight: bold;
}
/* Events as displayed in a list, not sized by time */
.calendar_calTimeGridList .calendar_calTimeGridScroll {
overflow-y: hidden;
}
.calendar_calTimeGridList .calendar_calGridHeader {
min-height: 1em;
}
.calendar_calTimeGridList .calendar_calDayColAllDay {
display: none;
}
.calendar_calTimeGridList .calendar_calDayColHeader {
min-height: initial;
padding-bottom: 0px;
}
.calendar_calTimeGridList .calendar_calEvent {
min-height: 1.1em;
position: relative;
}
.calendar_calTimeGridList .calendar_calEvent:not([data-full_day]) {
border-top: none;
border-left: none;
border-right: none;
}
.calendar_calTimeGridList .calendar_calEventHeader {
display: none !important;
}
.calendar_calTimeGridList .calendar_calEventTitle {
font-weight: normal;
display: inline-block;
max-height:2.4em;
white-space: nowrap;
}
.calendar_calTimeGridList .calendar_calEventBody:not(.calendar_calEventBodySmall) {
overflow: hidden;
}
.calendar_calTimeGridList .calendar_calEventBody .calendar_calTimespan {
display: inline-block;
float: right;
padding-left: 1em;
opacity: 0.8;
font-size: 90%
}
.calendar_calTimeGridList .calendar_calEventBody > p {
display: none;
}
.calendar_calTimeGridList .calendar_calDayCol .hiddenEventAfter:hover {
/* Need !important to override calculated height*/
top: initial !important;
bottom: 0px;
white-space: pre;
height: 100%;
}
/* table of the dayView containing 2 cols: 1) day-view, 2) todos
*/
.calendar_calDayView{