<link media="all" rel="stylesheet" href="/assets/themes/default/css/events-calendar.css?cb=">
<div class="calendar-events collapsed" data-module="calendarEvents" data-endpoint="/components/preview/events-calendar-api-results" data-event-days-endpoint="/data/eventdays.json">
<button class="calendar-events__toggle">+</button>
<h3 class="calendar-events__title"></h3>
<div class="calendar-events__calendar">
<div class="calendar-events__calendar-row" style="display: none">
<div class="calendar-events__calendar-item">Sun</div>
<div class="calendar-events__calendar-item">Mon</div>
<div class="calendar-events__calendar-item">Tue</div>
<div class="calendar-events__calendar-item">Wed</div>
<div class="calendar-events__calendar-item">Thu</div>
<div class="calendar-events__calendar-item">Fri</div>
<div class="calendar-events__calendar-item">Sat</div>
</div>
<div class="calendar-body">
</div>
</div>
<div class="calendar-events__calendar-nav">
<button class="calendar-events__btn-prev"></button>
<button class="calendar-events__btn-next"></button>
</div>
<div class="event-cards__holder" data-url="">
</div>
</div>
{{#if firstInstance}}
<link media="all" rel="stylesheet" href="/assets/themes/{{theme}}/css/events-calendar.css?cb={{cacheBuster}}">
{{/if}}
<div class="calendar-events collapsed" data-module="calendarEvents" data-endpoint="{{endpoint}}" data-event-days-endpoint="{{eventDaysEndpoint}}">
<button class="calendar-events__toggle">+</button>
<h3 class="calendar-events__title"></h3>
<div class="calendar-events__calendar">
<div class="calendar-events__calendar-row" style="display: none">
<div class="calendar-events__calendar-item">Sun</div>
<div class="calendar-events__calendar-item">Mon</div>
<div class="calendar-events__calendar-item">Tue</div>
<div class="calendar-events__calendar-item">Wed</div>
<div class="calendar-events__calendar-item">Thu</div>
<div class="calendar-events__calendar-item">Fri</div>
<div class="calendar-events__calendar-item">Sat</div>
</div>
<div class="calendar-body">
</div>
</div>
<div class="calendar-events__calendar-nav">
<button class="calendar-events__btn-prev"></button>
<button class="calendar-events__btn-next"></button>
</div>
<div class="event-cards__holder" data-url="{{dataUrl}}">
</div>
</div>
{
"theme": "default",
"firstInstance": true,
"endpoint": "/components/preview/events-calendar-api-results",
"eventDaysEndpoint": "/data/eventdays.json"
}
export class EventsCalendar {
constructor(container) {
this.today = new Date();
this.currentDay = this.today.getDate();
this.currentMonth = this.today.getMonth();
this.currentYear = this.today.getFullYear();
this.selectedDay = null;
this.selectedMonth = null;
this.selectedYear = null;
this.container = container;
this.monthAndYear = container.querySelector('.calendar-events__title');
this.eventsListingHolder = container.querySelector('.event-cards__holder');
const toggleBtn = container.querySelector('.calendar-events__toggle');
this.next = container.querySelector('.calendar-events__btn-next');
this.previous = container.querySelector('.calendar-events__btn-prev');
this.showCalendar();
this.next.addEventListener('click', () => {
this.currentYear = (this.currentMonth === 11) ? this.currentYear + 1 : this.currentYear;
this.currentMonth = (this.currentMonth + 1) % 12;
this.eventsListingHolder.innerHTML = '';
this.showCalendar();
});
this.previous.addEventListener('click', () => {
this.currentYear = (this.currentMonth === 0) ? this.currentYear - 1 : this.currentYear;
this.currentMonth = (this.currentMonth === 0) ? 11 : this.currentMonth - 1;
this.eventsListingHolder.innerHTML = '';
this.showCalendar();
});
toggleBtn.addEventListener('click', () => {
container.classList.toggle('collapsed');
if (container.classList.contains('collapsed')) {
toggleBtn.innerHTML = '+';
this.showCalendar();
} else {
toggleBtn.innerHTML = '-';
}
});
}
showCalendar() {
const month = this.currentMonth;
const year = this.currentYear;
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
const firstDay = (new Date(year, month)).getDay();
const daysInMonth = 32 - new Date(year, month, 32).getDate();
const tbl = document.querySelector('.calendar-body'); // body of the calendar
// clearing all previous cells
tbl.innerHTML = '';
// filing data about month and in the page via DOM.
this.monthAndYear.innerHTML = `${months[month]} ${year}`;
if (month === 11) {
this.next.innerHTML = `See ${months[0]} ${year + 1}`;
this.previous.innerHTML = `See ${months[month - 1]} ${year}`;
} else if (month === 0) {
this.next.innerHTML = `See ${months[month + 1]} ${year}`;
this.previous.innerHTML = `See ${months[11]} ${year - 1}`;
} else {
this.next.innerHTML = `See ${months[month + 1]} ${year}`;
this.previous.innerHTML = `See ${months[month - 1]} ${year}`;
}
if (this.currentMonth === this.today.getMonth() && this.currentYear === this.today.getFullYear()) {
this.previous.setAttribute('style', 'display:none;');
} else if (this.currentMonth > this.today.getMonth() && this.currentYear >= this.today.getFullYear()) {
this.previous.setAttribute('style', 'display:inline-none;');
}
// creating all cells
let date = 1;
for (let i = 0; i < 6; i++) {
// creates a table row
const row = document.createElement('div');
row.classList.add('calendar-events__calendar-row');
const daysOfTheWeek = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
// creating individual cells, filing them up with data.
for (let j = 0; j < 7; j++) {
if (i === 0 && j < firstDay) {
const cellHolder = document.createElement('div');
cellHolder.classList.add('calendar-item-holder');
const cell = document.createElement('div');
cell.classList.add('calendar-events__calendar-item');
cell.classList.add('calendar-events__calendar-item--empty');
const dayOfWeek = document.createElement('div');
dayOfWeek.classList.add('calendar-weekday');
dayOfWeek.innerHTML = daysOfTheWeek[j];
cell.appendChild(dayOfWeek);
const cellText = document.createTextNode('');
cell.appendChild(cellText);
cellHolder.appendChild(cell);
row.appendChild(cellHolder);
} else if (date > daysInMonth) {
break;
} else {
const cellHolder = document.createElement('div');
cellHolder.classList.add('calendar-item-holder');
const cell = document.createElement('div');
cell.classList.add('calendar-events__calendar-item');
const cellText = document.createTextNode(date);
if (date === this.today.getDate() && year === this.today.getFullYear() && month === this.today.getMonth()) {
// highlight today's date
cell.classList.add('calendar-events__calendar-item--today');
}
if (date === this.currentDay && year === this.currentYear && month === this.currentMonth) {
row.classList.add('current-row');
}
if (date === this.selectedDay && year === this.selectedYear && month === this.selectedMonth) {
cell.classList.add('calendar-events__calendar-item--active');
}
const dayOfWeek = document.createElement('div');
dayOfWeek.classList.add('calendar-weekday');
dayOfWeek.innerHTML = daysOfTheWeek[j];
cell.appendChild(dayOfWeek);
cell.appendChild(cellText);
cellHolder.appendChild(cell);
row.appendChild(cellHolder);
const selectedMonth = this.currentMonth + 1;
const selectedYear = this.currentYear;
const dataAttr = `${selectedYear}-${selectedMonth}-${date}`;
cell.dataset.date = dataAttr;
date++;
}
}
tbl.appendChild(row); // appending each row into calendar body.
}
this.loadEventDays();
const cellItem = document.querySelectorAll('.calendar-events__calendar-item');
cellItem.forEach((e) => {
e.addEventListener('click', () => {
document.querySelectorAll('.calendar-events__calendar-item').forEach((crnt) => {
crnt.classList.remove('calendar-events__calendar-item--active');
});
e.classList.add('calendar-events__calendar-item--active');
this.eventsListingHolder.innerHTML = '';
const clickedEventDate = e.dataset.date;
const selectedDate = new Date(clickedEventDate);
this.selectedMonth = selectedDate.getMonth();
this.selectedYear = selectedDate.getFullYear();
this.selectedDay = selectedDate.getDate();
this.loadEvents(clickedEventDate);
});
});
}
loadEventDays() {
const queryStringPrefix = this.container.dataset.eventDaysEndpoint.includes('?') ? '&' : '?';
const fetchDataUrl = `${this.container.dataset.eventDaysEndpoint}${queryStringPrefix}month=${this.currentMonth + 1}&year=${this.currentYear}`;
fetch(fetchDataUrl, { credentials: 'same-origin' })
.then((resolve) => {
if (resolve.ok) {
return resolve.text();
}
throw new Error(resolve.status);
})
.then((res) => {
const dates = JSON.parse(res);
dates.forEach((date) => {
const calendarItem = this.container.querySelector(`.calendar-events__calendar-item[data-date='${date}']`);
if (calendarItem) {
calendarItem.classList.add('calendar-events__calendar-item--has-event');
}
});
})
.catch((reject) => {
console.error('error', reject);
});
}
loadEvents(eventDate) {
let fetchDataUrl = this.container.dataset.endpoint;
fetchDataUrl += fetchDataUrl.includes('?') ? '&' : '?';
fetchDataUrl += `eventDate=${eventDate}`;
fetch(fetchDataUrl, { credentials: 'same-origin' })
.then((resolve) => {
if (resolve.ok) {
return resolve.text();
}
throw new Error(resolve.status);
})
.then((res) => {
const newGrid = new DOMParser().parseFromString(res, 'text/html');
const gridList = newGrid.querySelectorAll('.api-events');
gridList.forEach((grid) => {
this.eventsListingHolder.innerHTML = grid.innerHTML;
});
const alsoHappeningLinks = this.container.querySelectorAll('.event-card__repeated-date');
alsoHappeningLinks.forEach((alsoHappeningLink) => {
alsoHappeningLink.addEventListener('click', (e) => {
e.preventDefault();
const date = alsoHappeningLink.dataset.eventDate;
const alsoHappeningDate = new Date(date);
this.selectedMonth = alsoHappeningDate.getMonth();
this.selectedYear = alsoHappeningDate.getFullYear();
this.selectedDay = alsoHappeningDate.getDate();
this.showCalendar();
this.loadEvents(date);
});
});
})
.catch((reject) => {
console.error('error', reject);
});
}
}
export default (module) => new EventsCalendar(module);
@import 'source/scss/01-settings/_import';
@import 'source/scss/02-tools/_import';
.calendar-events {
$this: &;
display: block;
position: relative;
width: 100%;
&__title {
@extend %heading02;
margin: rem(20);
}
&__toggle {
background: transparent;
border: 0;
font-size: 30px;
line-height: 1rem;
margin: 0;
outline: none;
padding: 0;
position: absolute;
right: rem(20);
top: rem(80);
@include breakpoint(medium) {
top: rem(90);
}
@include breakpoint(large) {
font-size: 60px;
right: rem(20);
top: rem(95);
}
}
&__calendar {
display: block;
margin: rem(20) auto;
width: 100%;
@include breakpoint(medium) {
width: 100%;
}
@include breakpoint(large) {
width: 100%;
}
}
&__calendar-row {
clear: both;
display: block;
margin: rem(20) 0;
width: 90%;
&.current-row {
display: block;
}
}
&.collapsed {
#{$this}__calendar-nav {
display: none;
}
#{$this}__calendar-row {
display: none;
&.current-row {
display: block;
}
}
}
&__calendar-item {
background-color: $color-calendar-bg;
border: 1px solid $color-calendar-border;
border-radius: 100%;
color: $color-calendar-text;
display: inline-block;
font-size: rem(15);
font-weight: bold;
height: rem(46);
line-height: rem(16);
position: relative;
text-align: center;
transition: background-color .3s;
vertical-align: top;
width: rem(46);
@include breakpoint(medium) {
font-size: rem(25);
font-weight: normal;
height: rem(70);
width: rem(70);
}
&--has-event {
background-color: $color-calendar-bg-has-event;
color: $color-calendar-has-event;
cursor: pointer;
&:hover {
background-color: $color-calendar-bg-hover;
color: $color-calendar-hover;
}
}
&--active {
background-color: $color-calendar-bg-active;
color: $color-calendar-active;
}
&--today {
background-color: $color-calendar-bg-today;
color: $color-calendar-today;
}
&--empty {
opacity: 0;
}
}
&__calendar-nav {
display: block;
width: 100%;
&::after {
clear: both;
content: '';
display: block;
}
}
&__btn-prev {
float: left;
}
&__btn-next {
float: right;
}
}
.calendar-item-holder {
display: inline-block;
margin: 0 1%;
text-align: center;
width: 12%;
}
.current-month__title {
@extend %heading02;
display: block;
margin-bottom: rem(20px);
}
.calendar-weekday {
font-size: rem(10);
line-height: 1rem;
margin-top: rem(5);
padding-bottom: 0;
text-align: center;
@include breakpoint(medium) {
font-size: rem(13);
line-height: 1rem;
margin-top: rem(11);
padding-bottom: rem(6);
}
@include breakpoint(large) {
font-size: 13px;
line-height: 1rem;
margin-top: rem(11);
padding-bottom: rem(6);
}
}
.calendar-body {
display: block;
width: 100%;
}
.event-cards__holder {
border-top: 1px solid;
display: block;
padding: rem(20) 0;
width: 100%;
}
.event-card {
&__holder {
background-color: $color-events-card-bg;
margin: rem(20);
}
&__timings {
@extend %p--strong;
padding: rem(20);
}
&__title {
@extend %heading02;
padding: 0 rem(20);
}
&__description {
@extend %p--body;
line-height: 1.7rem;
padding: rem(20);
}
&__location {
@extend %p--strong;
padding: rem(20) rem(20) 0;
}
&__price {
@extend %p--strong;
padding: rem(20);
}
&__cta {
padding: rem(20);
}
&__repeated {
@extend %p--small;
padding: rem(20);
}
&__repeated-date {
display: block;
padding: 0 rem(20) rem(20);
}
}
.api-holder__no-results {
@extend %p--lead;
}
No notes defined.