I am using clndr.js (http://kylestetz.github.io/CLNDR/) to display dates that a holiday cottage is booked for. These are always shown using the multi-day event system as the minimum booking is 3 days. I now need to style the first and last days of the event differently, to show they are changeover days. Ideally I would do this by adding a class to the td
. This is what I have so far:
JS
$('#calendar').clndr({
template: $('#calendar-template').html(),
weekOffset: 1,
daysOfTheWeek: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
targets: {
nextButton: 'clndr-next',
previousButton: 'clndr-previous'
},
multiDayEvents: {
startDate: 'start',
endDate: 'end'
},
events: events,
clickEvents: {
click: function(target) {
//alert(target);
}
}
});
Example JSON
var events = [
{start:'2016-05-29T00:00:00+00:00',
end:'2016-06-01T00:00:00+00:00',
title:'Mrs A N Human',},
{start:'2016-08-10T00:00:00+00:00',
end:'2016-08-17T00:00:00+00:00',
title:'Mr A Person',}
];
HTML / Underscore
<div id="calendar">
<script type="text/template" id="calendar-template">
<table class="table">
<thead>
<tr>
<th class='clndr-previous'><</th>
<th colspan="5"><%= month %> <%= year %></th>
<th class='clndr-next'>></th>
</tr>
<tr>
<% _.each(daysOfTheWeek, function(day) { %>
<th class="header-day"><%= day %></th>
<% }); %>
</tr>
</thead>
<tbody>
<tr class="days"><% _.each(days, function(day, index) { %>
<td class="<%= day.classes %>" id="<%= day.id %>">
<span class="day-number">
<%= day.day %>
</span>
</td>
<% if ((index + 1) % 7 == 0) {
%> </tr><tr> <%
} %><% }); %>
</tr>
</tbody>
</table>
</script>
</div>
I am struggling to work out how to target those first and last days to apply some different styling. I am using moment.js as well if that can be used. Help greatly appreciated!
So eventually I spent some time looking at using Underscore and Moment to achieve what I was after. Below is my updated code, using a conditional in Underscore to check the date using Moment, and add a class to the <td>
if necessary. This was combined with an adjustment to how my events were represented in the JSON array:
HTML / Underscore
<div id="calendar">
<script type="text/template" id="calendar-template">
<table class="table">
<thead>
<tr>
<th class='clndr-previous'><</th>
<th colspan="5"><%= month %> <%= year %></th>
<th class='clndr-next'>></th>
</tr>
<tr>
<% _.each(daysOfTheWeek, function(day) { %>
<th class="header-day"><%= day %></th>
<% }); %>
</tr>
</thead>
<tbody>
<tr class="days">
<% _.each(days, function(day, index) { %>
<td class="<%= day.classes %> <% _.each(day.events, function(event) { %><% if( moment(event.start).isSame( day.date ) ){ %>start<% } %><% }); %> <% _.each(day.events, function(event) { %><% if( moment(event.end).isSame( day.date ) ){ %>end<% } %><% }); %>">
<span class="day-number"><%= day.day %></span>
</td>
<% if ((index + 1) % 7 == 0) { %> </tr><tr> <% } %>
<% }); %>
</tr>
</tbody>
</table>
</script>
</div>
JSON
var events = [
{start:'2016-05-29',
end:'2016-06-01',
title:'Mrs A N Human',},
{start:'2016-08-10',
end:'2016-08-17',
title:'Mr A Person',}
];
Okay so I hope you can find some of this useful as it took me a long time to get this to work. You will probably need to modify some bits for your template etc. but should give you a good idea. Pay attention to the <% _.each
part as that's what makes the class work from the multi event JSON
Here's my CLNDR template code:
<div id="mini-clndr">
<script id="mini-clndr-template" type="text/template">
<div class="controls">
<div class="clndr-previous-button"><img src="/assets/local/img/calendar-left-arrow.png"></div>
<div class="month">
<%= month %>
<%= year %>
</div>
<div class="clndr-next-button"><img src="/assets/local/img/calendar-right-arrow.png"></div>
</div>
<div class="days-container">
<div class="days">
<div class="headers">
<% _.each(daysOfTheWeek, function(day) { %>
<div class="day-header">
<%= day %>
</div>
<% }); %>
</div>
<% _.each(days, function(day) {
var classes = '';
if( day.events.length ){
for( var i = 0; i < day.events.length; i++ ){
classes += ' ' + day.events[i].class;
}
}
%>
<div class="<%= day.classes %><%= classes %>" id="<%= day.id %>">
<%= day.day %>
</div>
<% }); %>
</div>
<div class="events">
<div class="headers">
<div class="x-button">x</div>
<div class="event-header">EVENTS</div>
</div>
<div class="events-list">
<% _.each(eventsThisMonth, function(event) { %>
<div class="event">
<a target="blank" href="<%= event.url %>">
<%= moment(event.date).format('MMMM Do') %>:
<%= event.title %>
</a>
</div>
<% }); %>
</div>
</div>
</div>
</script>
</div>
Here's my CLNDR.js code:
var clndr = {};
$(function() {
var currentMonth = moment().format('YYYY-MM');
var nextMonth = moment().add(1, 'month').format('YYYY-MM');
var events = [
// Multiday Event Code
{
start: '2016-05-17',
end: '2016-05-19',
title: 'Monday to Friday Event',
class: 'long-event'
},
];
$('#mini-clndr').clndr({
template: $('#mini-clndr-template').html(),
weekOffset: 1,
events: events,
multiDayEvents: {
endDate: 'end',
singleDay: 'date',
startDate: 'start'
},
clickEvents: {
click: function(target) {
if (target.events.length) {
var daysContainer = $('#mini-clndr').find('.days-container');
daysContainer.toggleClass('show-events', true);
$('#mini-clndr').find('.x-button').click(function() {
daysContainer.toggleClass('show-events', false);
});
}
}
},
adjacentDaysChangeMonth: true,
forceSixRows: false,
showAdjacentMonths: false,
});
});
Then my CSS code:
.long-event {
background: orange;
}
:not(.long-event) + .long-event, .long-event:first-child {
background: orange;
border-radius: 50% 0 0 50%;
}
.last {
border-radius: 0 50% 50% 0;
}
And then finally, some jQuery to make those classes work. You'll also need to add a .date
class to every date on the calendar:
$('.long-event + .date:not(.long-event)').prev().addClass('last');
Although this jsFiddle isn't using CLNDR.js, you can see the styling working :)
https://jsfiddle.net/andyjh07/ke0euh5m/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With