Динамическое позиционирование событий календаря JSCSS

Разбираемся в CSS
Ответить
Гость
 Динамическое позиционирование событий календаря JS

Сообщение Гость »


I have a created a calendar with js, css and html. I have managed to add one day events and longer lasting events - all seems fine when events are not overlapping, but when events are overlapping, the overlapping part is fine, but if there are two events one from 10-18 and another from 16-22, then days 16-18 are fine and the two events are not on top of each other but days 18-22 are not affected the same way days 16-18 are.

const holidayInputs = document.querySelectorAll('.holidayInputs'); const holidays = []; holidayInputs.forEach(input => { const value = input.value; const [date, name] = value.split('.'); holidays.push({ hdate: date, holiday: name }); }); const events = [ { title: "As puhkab", startDate: "03-12-2024", endDate: "03-20-2024", }, { title: "Ak puhkab", startDate: "03-04-2024", endDate: "03-14-2024", }, { title: "AC puhkab", startDate: "03-26-2024", endDate: "03-31-2024", } // Add more events as needed ]; const calendar = document.querySelector("#calendar"); const monthBanner = document.querySelector("#month"); let navigation = 0; const weekdays = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]; function loadCalendar() { const dt = new Date(); if (navigation != 0) { dt.setMonth(new Date().getMonth() + navigation); } const day = dt.getDate(); const month = dt.getMonth(); const year = dt.getFullYear(); monthBanner.innerText = `${dt.toLocaleDateString("en-us", { month: "long", })} ${year}`; calendar.innerHTML = ""; const daysInMonth = new Date(year, month + 1, 0).getDate(); const firstDayofMonth = new Date(year, month, 1); const dateText = firstDayofMonth.toLocaleDateString("en-us", { weekday: "long", year: "numeric", month: "numeric", day: "numeric", }); const dayString = dateText.split(", ")[0]; const emptyDays = weekdays.indexOf(dayString); const shownEventsDates = new Set(); for (let i = 1; i 0 && currentIndex e.hdate == dateText); if (i - emptyDays === day && navigation == 0) { dayBox.id = "currentDay"; } // Push holidays into the calendar - can be recreated with birthdays if (holidayOfTheDay) { const eventDiv = document.createElement("div"); eventDiv.classList.add("event"); eventDiv.classList.add("holiday"); eventDiv.innerText = holidayOfTheDay.holiday; dayBox.appendChild(eventDiv); dayBox.addEventListener("click", () => { showModal(dateText); }); } // Check if there are events for this day and it hasn't been shown already const eventsForDay = events.filter(event => { const eventStartDate = new Date(event.startDate); const eventEndDate = new Date(event.endDate); const isWithinMonth = eventStartDate.getMonth() == month || eventEndDate.getMonth() == month; const isWithinEventRange = currentDate >= eventStartDate && currentDate 0) { // Create a container for day events const dayEventContainer = document.createElement("div"); dayEventContainer.classList.add("day-events"); dayBox.appendChild(dayEventContainer); // Sort events by start time eventsForDay.sort((a, b) => new Date(a.startDate) - new Date(b.startDate)); // Keep track of processed events within each week const processedEventsByWeek = new Map(); eventsForDay.forEach((event, index) => { // Get event Start and end dates const eventStart = new Date(event.startDate); const eventEnd = new Date(event.endDate); let marginTop = 0; let overlappingEvents = []; const weekNumber = Math.floor((currentDate.getDate() - 1 + emptyDays) / 7); if (!processedEventsByWeek.has(weekNumber)) { processedEventsByWeek.set(weekNumber, new Set()); } for (let week = 0; week processedEventStart) { overlappingEvents.push(processedEvent); } } } } // Calculate maximum marginTop for the entire duration of the event if (overlappingEvents.length > 0) { marginTop = overlappingEvents.length * 20; } /*// Ensure there's an entry for this week if (!processedEventsByWeek.has(weekNumber)) { processedEventsByWeek.set(weekNumber, new Set()); } // Check if the event overlaps with any previously processed event in this week let marginTop = 0; for (const processedEvent of processedEventsByWeek.get(weekNumber)) { const processedEventEnd = new Date(processedEvent.endDate); // If there's an overlap, adjust marginTop and break if ( eventStart 0) { eventDiv.style.marginTop = `${marginTop}px`; } // Set the right offset for event start let eventStartOffset = Math.max(0, eventStart.getDay() * dayWidth); const dayEventDiv = document.createElement("div"); dayEventDiv.classList.add("day-event"); dayEventDiv.style.left = eventStartOffset + "px" if (eventEnd.getDate() == currentDate.getDate() || dayOfWeek == 6) { dayEventDiv.style.width = 95 + "px"; } else { dayEventDiv.style.width = dayWidth + "px"; } eventDiv.appendChild(dayEventDiv); dayEventContainer.appendChild(eventDiv); shownEventsDates.add(dateText); // Record that this event has been shown }); dayBox.addEventListener("click", () => { showModal(dateText); }); } } else { dayBox.classList.add("plain"); } calendar.append(dayBox); } } function buttons() { const btnBack = document.querySelector("#btnBack"); const btnNext = document.querySelector("#btnNext"); btnBack.addEventListener("click", () => { navigation--; loadCalendar(); }); btnNext.addEventListener("click", () => { navigation++; loadCalendar(); }); } const modal = document.querySelector("#modal"); const modalClose = document.querySelector(".modal-close"); function showModal(dateText) { clicked = dateText; modal.style.display = "flex"; // modaali sisu loogika :D modalClose.addEventListener("click", () => { modal.style.display = "none"; }); } buttons(); loadCalendar(); .container { width: 770px; background-color: #fff; display: inline-table; } .header { padding: 10px; display: flex; justify-content: space-between; } .header #month { color: #1562CE; font-size: 25px; font-weight: 500; } button { cursor: pointer; border: none; outline: none; padding: 5px; border-radius: 3px; color: white; } .header button { background-color: #1562CE; } .weekdays { width: 100%; display: flex; background-color: #E8F2FE;; font-size: 17px; color: #0A253C; font-weight: 500; } .weekdays div { width: 110px; padding: 10px; text-align: center; text-transform: uppercase; } #calendar { width: 100%; margin: auto; display: flex; flex-wrap: wrap; position: relative; } .day:hover { background-color: #C2D8F6; color: #03a9f4; } .day.plain:hover { background-color: white; } #currentDay { background-color: #a3c5f5; color: #fff; } .day-row { display: flex; flex-direction: row; } .day { width: 100px; height: 100px; padding: 8px; cursor: pointer; margin: 5px; box-sizing: border-box; box-shadow: 0px 0px 3px #cbd4c2; color: #7f8fa6; font-weight: 500; display: flex; flex-direction: column; justify-content: space-between; align-items: flex-start; border-radius: 4px; } .day-events { position: relative; display: flex; justify-content: space-between; flex-direction: column; height: 39px; } .day-event { margin: 0 !important; padding: 0 !important; } .event { background-color: #007bff; color: #fff; border-radius: 5px; padding: 2px 3px; overflow: hidden; font-size: 11px; max-height: 18px; white-space: nowrap; position: absolute; text-align: left; } .event.event-span { display: inline-block; margin-left: -9px; min-height: 18px; } .event.event-span-one { display: inline-block; margin-top: 2px; } .event.holiday { background-color: #E0593E; color: white; position: initial; max-width: 87px; text-overflow: ellipsis; } .plain { cursor: default; box-shadow: none; } #modal { display: none; position: absolute; top: 340px; left: 795px; width: 420px; height: 51vh; z-index: 10; background-color: rgba(0, 0, 0, 0.8); justify-content: flex-end; } #modal .modal-close { background-color: #E0593E; height: min-content; } Mon Tue Wed Thu Fri Sat Sun

I have tried changing the logic how the margin top is given, but i cannot think of a good way for this to be implemented on the whole event duration.


Источник: https://stackoverflow.com/questions/781 ... ositioning
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «CSS»