This is my hacked up event list view template for the built in Calendar in v8.5 . It casts the info in a nice Bootstrap 3 layout, (styling will vary from my screenshot according to your CSS, but the basic layout should stick), with some font awesome icons.
The list pulls some custom event attributes that are not part of the default setup:
The notable revisions are this event list shows the time of the event and distinguishes All Day from times for multiday events.
It also moves the View All to the top and makes it a button with a count of events shown. Which may not work correctly. You'll see my comments within. If anyone wants to correct or improve on it, please share back.
<?php
defined('C5_EXECUTE') or die("Access Denied.");
// >>> ^^^ <<< >>> View for Event List 2020
if ($calendar) {
$pagination = $list->getPagination();
$pagination->setMaxPerPage($totalToRetrieve);
$events = $pagination->getCurrentPageResults();
//count all events, not just what is shown on page so we can make a number badge. This may not function as events drop off list, will have to watch it. -td
$allEvents = $list->getPagination();
$allEvents->setMaxPerPage(100);
$totEvents = $allEvents->getTotalResults();
if ($canViewCalendar) {
$service = Core::make('helper/date');
$c = Page::getCurrentPage();
$cID = $c->getCollectionID();
$numEvents = count($events);
?>
<div class="ccm-block-calendar-event-list-wrapper widget-featured-events unbound" data-page="<?= $totalPerPage ?: 3 ?>">
<?php if (!$linkToPage) { ?>
<?php if ($eventListTitle) { ?>
<div class="bottomborder-wrap">
<h3 class="bottomborder2 font-weight-normal" ><?=$eventListTitle?></h3>
</div>
<?php } } ?>
<?php if ($linkToPage) { ?>
<?php if ($eventListTitle) { ?>
<div class="col-xs-9">
<div class="bottomborder-wrap">
<h3 class="bottomborder2 font-weight-normal" ><?=$eventListTitle?></h3>
</div>
</div>
<div class="col-xs-3">
<div class="ccm-block-calendar-event-list-link">
<a class="btn btn-danger " href="<?=$linkToPage->getCollectionLink()?>"><?=t('View All Events <span class="badge">' . $numEvents . ' of ' . $totEvents . ' Shown</span>')?></a>
</div>
</div>
<?php } ?>
<?php } ?>
<div class="ccm-block-calendar-event-list" <?php if ($numEvents > $totalPerPage) {
echo 'style="display:none"';
}
?>>
<?php
if ($total = count($events)) {
foreach ($events as $occurrence) {
$event = $occurrence->getEvent();
$description = $event->getDescription();
// setup some custom event attributes -td
$event_link = $event->getAttribute('event_learn_more_link');
$event_location = $event->getAttribute('event_location');
// event categories returns an array, note the display option -tdd
$event_categories = $event->getAttribute('event_categories', 'display');
$eventStartTime = $service->formatCustom('g:i A', $occurrence->getStart());
$eventEndTime = $service->formatCustom('g:i A', $occurrence->getEnd());
$eventTime = $formatter->getOccurrenceDateString($occurrence);
$eventBits = explode (',', $eventTime);
//echo $eventEndTime;
//echo '<br>' . $eventStartTime;
// figuring out how to flag all day events so we can show time. If "All Day" option is checked, then start time displays as 12:00 AM... which is hacky, but it's the only way I can see to determine if All Day is checked. Ostensibly, no roofing events will begin at midnight... -tdd
if ($eventStartTime == "12:00 AM") {$dayflag = "All Day";}else{$dayflag = "";}
//echo $dayflag;
$safe_name = strtolower($event->getName());
$safe_name = preg_replace('/[^a-z ]/i', '', $safe_name);
$safe_name = str_replace(' ', '+', $safe_name);
?>
<div class="ccm-block-calendar-event-list-event">
<div class="row">
<div class="col-3 col-sm-2 col-md-2 matchheight">
<div class="ccm-block-calendar-event-list-event-date">
<span class="month"><?=$service->formatCustom('M', $occurrence->getStart())?></span>
<span class="day"><?=$service->formatCustom('d', $occurrence->getStart())?></span>
</div>
</div>
<div class="col-9 col-sm-10 col-md-10 matchheight">
<div class="ccm-block-calendar-event-list-event-title">
<?php
$url = $linkFormatter->getEventOccurrenceFrontendViewLink($occurrence);
if ($url) {
?>
<a href="<?= $url ?>"><h3 class="font-weight-bold bottommargin-hair"><?= h($event->getName()) ?></h3></a>
<?php
} else {
?>
<h3 class="font-weight-bold bottommargin-hair"><?= h($event->getName()) ?></h3>
<?php
}
?>
</div>
<div class="ccm-block-calendar-event-list-event-date-full">
<h4 class="font-weight-normal bottommargin-hair"><i class="fa fa-calendar"></i> <?php
echo $formatter->getOccurrenceDateString($occurrence);
?></h4>
<?php
if ($dayflag == "") {
echo '<h4 class="font-weight-normal bottommargin-hair"> <i class="fa fa-clock-o"></i> ' . $eventBits[2] . '</h4>';
} elseif ($dayflag == "All Day") {
echo '<h4 class="font-weight-normal bottommargin-hair"> <i class="fa fa-clock-o"></i> All Day</h4>';
}
?>
<?php if ($event_location) { ?>
<h4 class="font-weight-normal bottommargin-hair"><i class="fa fa-map-marker" style="padding: 0 .2em 0 .2em;"></i> <?php
echo $event_location; ?></h4>
<?php } ?>
<?php if ($event_categories) { ?>
<h4 class="font-weight-normal bottommargin-hair"><i class="fa fa-tags"></i> <?php
echo $event_categories; ?></h4>
<?php } ?>
</div>
<?php if ($description) { ?>
<div class="ccm-block-calendar-event-list-event-description">
<?=$description?>
</div>
<?php } ?>
<?php if ($event_link) { ?>
<a href="<?=$event_link;?>" class="btn btn-default btn-sm">Learn More</a>
<?php }?>
</div> <!--- close col-8 -->
</div> <!-- close row -->
</div>
<?php
}
?>
<?php
} else {
?>
<p class="ccm-block-calendar-event-list-no-events"><?=t('There are no upcoming events.')?></p>
<?php
}
?>
</div>
<div class="btn-group ccm-block-calendar-event-list-controls">
<?php if ($numEvents > $totalPerPage) {
?>
<button type="button" class="btn btn-default" data-cycle="previous"><i class="fa fa-angle-left"></i></button>
<button type="button" class="btn btn-default" data-cycle="next"><i class="fa fa-angle-right"></i></button>
<?php
}
?>
</div>
</div>
<?php if ($numEvents > $totalPerPage) {
?>
<script>
(function() {
function Button(element) {
this.element = element;
}
Button.prototype.disable = function() {
this.element.prop('disabled', true).addClass('disabled');
return this;
};
Button.prototype.enable = function() {
this.element.prop('disabled', false).removeClass('disabled');
return this;
};
var routine = function() {
$('.ccm-block-calendar-event-list-wrapper.unbound').removeClass('unbound').each(function(){
var my = $(this),
previous = new Button($('button[data-cycle=previous]', my)),
next = new Button($('button[data-cycle=next]', my)),
page = my.data('page'),
list = my.children('.ccm-block-calendar-event-list'),
events = list.children(),
start = 0,
container = $('<div />').css({
position: 'relative',
overflow: 'hidden'
}),
set_container = $('<div />'),
slider = $('<div />').css({
position: 'absolute',
top: 0,
left: 0
}),
sliding = false;
list.replaceWith(container);
events.slice(start, page).appendTo(set_container.appendTo(container));
container.height(container.height());
previous.element.click(function(){
if (!sliding && start >= page) {
sliding = true;
start -= page;
var subset = events.slice(start, start + page);
slide(-1, subset, function() {
sliding = false;
});
if (!start) {
previous.disable();
}
next.enable();
}
return false;
});
next.element.click(function(){
if (!sliding || start + 1 >= events.length) {
sliding = true;
start += page;
var subset = events.slice(start, start + page);
slide(1, subset, function() {
sliding = false;
});
if (start + page >= events.length) {
next.disable();
}
previous.enable();
}
return false;
});
if (!start) {
previous.disable();
}
if (start + page > events.length) {
next.disable();
}
function slide(direction, subset, callback, length) {
length = length || 750;
slider.empty().append(subset).height(container.height()).width(container.width()).appendTo(container);
if (direction > 0) {
set_container.css({
position: 'absolute',
top: 0,
left: 0,
width: container.width()
}).animate({
left: -container.width()
}, length);
slider.css('left', container.width()).animate({left: 0}, length, function() {
set_container.empty().css({
position: 'static',
left: 0
}).append(subset);
slider.remove();
callback.apply(this, Array.prototype.slice.call(arguments));
});
} else {
set_container.css({
position: 'absolute',
top: 0,
left: 0,
width: container.width()
}).animate({
left: container.width()
}, length);
slider.css('left', -container.width()).animate({left: 0}, length, function() {
set_container.empty().css({
position: 'static',
left: 0
}).append(subset);
slider.remove();
callback.apply(this, Array.prototype.slice.call(arguments));
});
}
}
});
};
if (typeof jQuery != 'undefined') {
routine();
} else {
window.addEventListener('load', routine);
}
}());
</script>
<?php
}
}
?>
<?php
} ?>
And here is the view.css. Other styles in screen cap come from my theme.
s