I have implemented VanillaCalendar to display events on specific days.
You can view the complete demo in the code snippet provided below or by visiting it on CodePen
The functionality involves iterating through JSON data and adding a div element to days with events. Here's how it works:
const assignEventsToCalendar = function() {
let eventData = data;
for (const {month, days} of eventData) {
for (const {day, events} of days) {
const key = day.split('-').map(p => p.padStart(2, '0')).join('-');
let dayElement = document.querySelector(`[data-calendar-day="${key}"]`);
if (dayElement) { // only apply flair if day exists (is in current month)
let eventWrapper = document.createElement("div");
eventWrapper.classList.add("event-wrapper");
dayElement.append(eventWrapper);
for (const {title, category} of events) {
let singleEvent = document.createElement("div");
singleEvent.classList.add("event", category);
eventWrapper.append(singleEvent);
}
}
}
}
};
The issue arises when clicking on a day or changing the month using the navigation arrows, causing the event markers on the days to disappear. This makes it difficult to track which events are scheduled on each day.
One approach is to utilize the VanillaCalendar event to trigger the function when navigating between months; however, this method may not cover all user interactions.
actions: {
clickArrow(e, self) {
setTimeout(assignEventsToCalendar, 1000);
}
}
Is there a way to address this challenge using JavaScript?
Code Snippet
let data = [{"month":"2024-2","days":[{"day":"2024-2-15","events":[{"title":"Event One","category":["Category1"]}]},{"day":"2024-2-21","events":[{"title":"Event Two","category":["Category2"]},{"title":"Event Three","category":["Category1"]}]},{"day":"2024-2-20","events":[{"title":"Event Four","category":["Catgory2"]}]}]},{"month":"2024-3","days":[{"day":"2024-3-2","events":[{"title":"Event Five","category":["Category1"]}]},{"day":"2024-3-23","events":[{"title":"Event Six","category":["Category2"]}]}]}];
document.addEventListener("DOMContentLoaded", function() {
var currentDate = new Date().toISOString().slice(0, 10);
var options = {
date: {
min: "1920-01-01",
max: "2038-12-31"
},
settings: {
range: {
min: currentDate
},
visibility: {
disabled: true,
theme: 'light'
}
},
actions: {
clickArrow(e, self) {
setTimeout(assignEventsToCalendar, 1000);
}
}
};
var calendar = new VanillaCalendar("#calendar", options);
calendar.init();
assignEventsToCalendar();
});
const assignEventsToCalendar = function() {
let eventData = data;
for (const {
month,
days
} of eventData) {
for (const {
day,
events
} of days) {
const key = day.split('-').map(p => p.padStart(2, '0')).join('-');
let dayElement = document.querySelector(`[data-calendar-day="${key}"]`);
if (dayElement) { // only apply flair if day exists (is in current month)
let eventWrapper = document.createElement("div");
eventWrapper.classList.add("event-wrapper");
dayElement.append(eventWrapper);
for (const {
title,
category
} of events) {
let singleEvent = document.createElement("div");
singleEvent.classList.add("event", category);
eventWrapper.append(singleEvent);
}
}
}
}
};
#calendar {
max-width: 350px;
}
.vanilla-calendar-day__btn {
.event-wrapper {
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: auto;
}
.event {
display: inline-block;
margin-right: 2px;
width: 5px;
height: 5px;
&.Category1 {
background-color: red;
}
&.Category2 {
background-color: blue;
}
}
}
<div id="calendar"></div>
<script src="https://cdn.jsdelivr.net/npm/@uvarov.frontend/vanilla-calendar/build/vanilla-calendar.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@uvarov.frontend/vanilla-calendar/build/vanilla-calendar.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@uvarov.frontend/vanilla-calendar/build/themes/light.min.css">