starting with as you mentioned eventDidMount() and inset-inline-start, gave me an head-start or an idea as to where to start off, so using inspect found that each element of was positioned absolute and with css inline inset values automatically by the fullCalendar library, played around a little with classes and the inset values,
after doing all these i was sure that i need to change the inset values, which was already told by ADyson, but for having an clear picture i still checked it out once,
now it was straight-forward like just overwrite the css inset left to 25% and right to 0 and rest to default set by the lib, the problem was all the elements were aligned in a single column overlapping each other, maybe even this is what you have tried and mentioned, which i realised it later, anyways
inset: unset 25% unset 0 !important;
so to tackle the issue, the option left was using js, used the setProperty() to overwrite the left and right values, according to a condition, basically if the pre-set value by the lib was
it worked like a charm , but later when tried it on different real-world cases, i found out that it only worked for at least 3 events, which were in the same row, this failed miserably with 2 events, even after cracking around about it for a while, i felt thinking of another solution would be better as, literally everything was same, there was no way to distinguish between row with 3 and row with 2 events, so even this solution was scarped
similar to the solution 2 we use javascript, and instead of using simple if-else based upon the pre-set left value, i used different data structures like array and dictionary, the idea was to add the start and end time values to the data structure, but before adding , i checked whether there is a an overlapping of the current event with the previously added events, if present then increase the left with 25%, it was the perfect solution for two events, but when the third event was introduced, it wasnt being positioned as expected,
tried different method on how the overlapping was checked, but still no progress, so had to again discard this method
using the dictionary data-structure, simply put i divide the whole width of the table into 4 parts with 25% for each part, as it was mentioned that the maximum events is 4 and the width is maximum of 25%,
so after dividing the page into 4 parts, kept adding events to each part based upon the overlapping status for that single part instead of all the events ( method used in solution 3 ),if not overlapping then add that event to that part, as simple as that
var dicte= new Map(); // dictionary to store the events of each part
eventDidMount: function(info) {
// this function is called when everytime a new evented is added to the table
var e = info.el.parentNode; // accessing the container class for current event, basically where the inset was added
var sT = info.event.start; // to access the start time of the current event
var eT = info.event.end; // to access the end time of the current event
var startTime = new Date(sT).toTimeString().split(' ')[0]; // extract the start time in hh:mm:ss format
var endTime = new Date(eT).toTimeString().split(' ')[0]; // extract the end time in hh:mm:ss format
startTime = parseInt(startTime.split(":")[0].trim())*3600 + parseInt(startTime.split(":")[1].trim())*60 + parseInt(startTime.split(":")[2].trim()) // converting the start time to total seconds
endTime = parseInt(endTime.split(":")[0].trim())*3600 + parseInt(endTime.split(":")[1].trim())*60 + parseInt(endTime.split(":")[2].trim()) // converting the end time to total seconds
var base=0; // variable used to mention which part of the table, will the event be added to
var skip=0; // used as an variable to determine, whther to go to the next part or not
for (const [key, value] of dicte) { // iterating over the dict
for (const data of value){ // iterating over the array of current part's event time positions
var currentstart=data[0] // extracting the start-time
var currentend=data[1] // extracting the end-time
if( // if cases to check all the possible overlapping conditions
(startTime<=currentstart && (endTime>=currentstart && endTime<currentend)) || // checks for events starting earlier than the previous event but ending after the start of previous event
((startTime>=currentstart && startTime<currentend) && endTime>=currentend) || // checks for events starting in between of previous event but ending after the completion
((startTime>=currentstart && startTime<currentend) && (endTime>=currentstart && endTime<currentend)) || // checks for events starting and ending inbetween of previous events
(startTime<=currentstart && endTime>=currentend) // checks for events starting before and ending later than the previous events
){
skip=1; // if any of the condition satisfies, then break from the loop and skip to the next part of the body
break;
}
}
if(skip==1){
base+=25; // skipping to next part by adding 25%
}else break;// if skip == 0 meaning no collision or overlapping found in this part
skip=0;// to reset the value for new part
}
var arr=(dicte.get(base)||[]);// get or create a new array for storing current part's events time
arr.push([startTime,endTime]);// adding the current event time
dicte.set(base,arr);// updating the dict
e.style.setProperty("left",(base+"%"),"important"); // positioning the event based upon the base value
e.style.setProperty('right','0%','important'); // setting it to zero always, providies clarity of logic
}
added an image which was used to develop the overlapping check condition, not sure if you understand it due to incomplete drawing, but still for reference
so the working in simple words is that the time is converted to seconds,for example
used 24-hr format, to make this solution work use 24hr format only to get the time and conversion to seconds, hope the above example was enough to understand why 23-hr format is used
okay so after converting the time to seconds it becomes way easier to compare with other event times, specially when dealing with a fixed size column ( 25% width ), instead of a matrix or table with uneven row sizes
so the control flow is like when an event is added the event time is converted to seconds , then every part of the table from beginning is checked in a column wise manner, where the event can be replaced without overlapping, after checking. the part is returned and required changes are made to the left and right style property of the event
according to me , while developing the code i have taken care of all the possible use cases, if i have left out any, please feel free to reach out
also if there is any part of the code that you feel, i havent explained, you can still contact