Restrict Event Dropping for Specific Time Ranges
Hello,
I am trying to restrict event dropping in EventCalendar for specific time ranges on a particular date. While I can successfully prevent events from being dropped for an entire day, I am unable to enforce restrictions for only a specific time window.
For example, if an employee takes a half-day leave in the morning (from 12 AM to 12 PM), I want to prevent events from being dropped within that time range while still allowing events to be dropped after 12 PM until the end of the day. In FullCalendar, the eventAllow method worked for this purpose. Could you please suggest an alternative approach to achieve this functionality in EventCalendar?
and this is my code ,
window.drop = function(event) { event.preventDefault(); console.log("drop event log " + event);
// Retrieve the dragged event data
const data = JSON.parse(event.dataTransfer.getData("application/json"));
console.log("Dropped Event Data:", data);
const x = event.clientX;
const y = event.clientY;
// console.warn("⚠️ Using `document.elementFromPoint()` to determine drop target.");
// Find the nearest calendar slot where the event was dropped
let targetElement = document.elementFromPoint(x, y);
console.log("tarr ", targetElement);
if (!targetElement) {
return;
}
if (targetElement && targetElement.textContent.trim() === 'Holiday') {
alert("cannot assign work on holidays")
return false;
}
else if (targetElement && targetElement.textContent.trim() === 'Leave') {
alert("cannot assign work on Leaves");
return false;
}
console.log("✅ Target Drop Element:", targetElement);
// Find the closest `.ec-day`
let dayElement = targetElement.closest(".ec-day");
if (!dayElement) {
// console.error("❌ Error: Could not determine the drop date. No `.ec-day` found.");
return;
}
// console.log("✅ Found day element:", dayElement);
// Move up to `.ec-container` or `.ec-main` to find `.ec-day-head`
let container = dayElement.closest(".ec-container, .ec-main, .ec-days");
if (!container) {
console.error(
"❌ Error: Could not find `.ec-container` or `.ec-main` to locate `.ec-day-head`.");
return;
}
// console.log("✅ Found calendar container:", container);
// Find the `.ec-day-head` elements
let allDayHeads = [...document.querySelectorAll(".ec-day-head time[datetime]")];
// console.log("allDaysHeads ", allDayHeads);
// console.log("✅ Checking available elements in the document...");
// console.log([...document.querySelectorAll(".ec-day-head")]);
if (allDayHeads.length === 0) {
// console.error("❌ Error: `.ec-day-head time[datetime]` not found anywhere.");
return;
}
// Find the matching `.ec-day-head` based on `.ec-day` index
let allDays = [...container.querySelectorAll(".ec-day")]; // Get all day columns
let dayIndex = allDays.indexOf(dayElement); // Get index of dropped day
if (dayIndex === -1 || dayIndex >= allDayHeads.length) {
// console.error("❌ Error: Could not determine the correct `.ec-day-head`.");
return;
}
let dateElement = allDayHeads[dayIndex]; // Match index with day head
let dateStr = dateElement.getAttribute("datetime");
// console.log("✅ Extracted Date:", dateStr);
// Find the closest `.ec-time` to get the correct time slot
let timeElement = targetElement.closest(".ec-time");
let dateStart;
if (!timeElement) {
// console.warn("⚠️ No exact time slot found. Defaulting to 9:00 AM.");
dateStart = new Date(`${dateStr}T09:00:00`);
} else {
// Extract the exact time from the `.ec-time time[datetime]`
let timeSlot = timeElement.querySelector("time[datetime]");
if (!timeSlot) {
// console.warn("⚠️ No time datetime attribute found. Defaulting to 9:00 AM.");
dateStart = new Date(`${dateStr}T09:00:00`);
} else {
dateStart = new Date(timeSlot.getAttribute("datetime"));
}
}
// Define event duration (default 2 hours)
const dateEnd = new Date(dateStart);
dateEnd.setHours(dateEnd.getHours() + 2);
// Assign a default resourceId (Modify this based on your setup)
let allResources = [...document.querySelectorAll(
".ec-resource-label")]; // Get all resource elements
console.log("📌 All Resource Elements:", allResources);
let resourceElement = null;
// **Loop through each `.ec-resource-label` to check which is closest**
for (let resource of allResources) {
let rect = resource.getBoundingClientRect();
if (y >= rect.top && y <= rect.bottom) {
resourceElement = resource;
break; // Stop once the closest resource is found
}
}
console.log(resourceElement);
console.log("🔍 Found Resource Element:", resourceElement);
let newResourceId = resourceElement ? resourceElement.getAttribute("data-resource-id") : null;
console.log("✅ Extracted Resource ID:", newResourceId);
// Fallback if no resource ID is found
if (!newResourceId) {
console.warn("⚠️ No resource ID found. Defaulting to first employee.");
newResourceId = resources.length > 0 ? resources[0].id : "default_resource";
}
console.log("🎯 Final Resource ID:", newResourceId);
const isHoliday = dayElement.classList.contains("holiday");
const newEvent = {
id: data.id,
title: data.title,
start: dateStart,
end: dateEnd,
resourceIds: [newResourceId],
extendedProps: {
client_id: data.client_id,
isHoliday: isHoliday
}
};
// console.log("✅ Replacing event with new data:", newEvent);
// Add the new event by resetting the events list
// existingEvents.push(updatedEvent);
// if (calendar.setEvents) {
// calendar.updateEvent(existingEvents);
// console.log("✅ Events updated successfully via `setEvents()`.");
// } else if (calendar.update) {
// calendar.update({
// events: existingEvents
// });
// console.log("✅ Events updated successfully via `update()`.");
// } else {
// console.warn("⚠️ No direct update method found. Consider reloading the calendar.");
// }
if (window.eventCalendar && typeof window.eventCalendar.addEvent === "function") {
window.eventCalendar.addEvent(newEvent);
// console.log("✅ Event added successfully.", newEvent);
} else {
// console.error("❌ Error: `eventCalendar.addEvent` is not available.");
// console.log("🔍 Available methods:", Object.keys(window.eventCalendar || {}));
}
const jobData = {
id: data.id,
title: data.title,
client_id: data.client_id,
start: convertToISO(dateStart),
end: convertToISO(dateEnd),
resource_id: newResourceId // Optional, modify based on your system
};
// console.log("📤 Sending job data to backend:", jobData);
createJobSheet(jobData);
}
Thank you.
Currently, only the prevent() function is available in the eventDrop callback. This function allows you to cancel the drag if necessary.
eventAllow may be implemented in future versions of the Event Calendar.
Thanks for your response.
I can prevent events from being scheduled on specific dates, but I am unable to restrict event drops for certain time slots. Currently, I am trying to retrieve the exact datetime from the.ec-times element. While I can access the datetime, I am unable to determine the precise time slot where the event is dropped.
I am unable to determine the precise time slot where the event is dropped
The eventDrop callback contains this information. You are given event that already contains the new start and end, and the oldEvent where these are the values before the drag.
thank you once again. I will try and update here
Hi,
I am currently facing an issue with the allowDrop method. How can I retrieve the start and end datetime of an external event when attempting to drop it onto the calendar? Which method in the documentation provides access to the dates of an external event?
and this the method i used
window.allowDrop = function(event) { event.preventDefault(); // Allow dropping
// Find the closest `.ec-day` where the event was dropped
let targetDay = event.target.closest(".ec-day");
if (!targetDay) {
console.log("❌ No `.ec-day` found.");
return;
}
let x = event.clientX;
let y = event.clientY
console.log("✅ Found Target `.ec-day`:", targetDay);
// Get the index of `.ec-day`
let allDays = [...document.querySelectorAll(".ec-day")];
let dayIndex = allDays.indexOf(targetDay);
if (dayIndex === -1) {
console.log("❌ Could not find `.ec-day` index.");
return;
}
// Find `.ec-header`
let headerContainer = document.querySelector(".ec-header");
if (!headerContainer) {
console.log("❌ No `.ec-header` found.");
return;
}
console.log("✅ Found `.ec-header`: ", headerContainer);
// Get all time slots from `.ec-times`
let allTimeHeaders = [...headerContainer.querySelectorAll(".ec-times time[datetime]")];
console.log("📌 Found Time Elements:", allTimeHeaders.length, allTimeHeaders);
if (allTimeHeaders.length === 0) {
console.log("❌ No `.ec-times time[datetime]` elements found in `.ec-header`.");
return;
}
// Get mouse Y position relative to `.ec-day`
let dayRect = targetDay.getBoundingClientRect();
let mouseY = event.clientY - dayRect.top; // Mouse Y relative to `.ec-day`
// Get all `.ec-time` elements (they define the hourly slots)
let allTimeRows = [...document.querySelectorAll(".ec-time")];
let matchedTime = null;
// Loop through `.ec-time` rows to find the closest match
for (let timeRow of allTimeRows) {
let rowRect = timeRow.getBoundingClientRect();
console.log(rowRect);
if (y >= rowRect.top && y <= rowRect.bottom) {
matchedTime = timeRow.querySelector("time[datetime]");
console.log(`✅ Matched Time Row - X: ${rowRect.left}, Y: ${rowRect.top}`);
break;
}
}
if (!matchedTime || !matchedTime.hasAttribute("datetime")) {
console.log("❌ No `datetime` found in `.ec-time`.");
return;
}
// Extract the `datetime` attribute
let dropStartDate = new Date(matchedTime.getAttribute("datetime"));
console.log("📅 Dropped on Date & Time (Start):", dropStartDate.toISOString());
// Store the drop start date globally for use in `window.drop`
window.droppedStartDate = dropStartDate.toISOString();
};
external event when attempting to drop it onto the calendar
Event Calendar does not support dragging and dropping external events into the calendar.
hi mate !
hope you well
Any updates on external events allowing in the event calendar?
Please see the new dragConstraint option.
For external drop.you can use dateFromPoint method, see #145 .
Hi, when we drag an external event into the calendar and try to place it in a specific time slot, is it possible to capture that time?
Hi, when we drag an external event into the calendar and try to place it in a specific time slot, is it possible to capture that time?
You can try to use dateFromPoint method which gives you information about the time slot for any cursor position.