Автор: Khilinski 2024-12-05

AJAX-Календарь для WordPress

Код начинает выполнение после полной загрузки DOM.
2. Основные элементы:

const calendarContainer = document.getElementById("calendar-container");
const calendarMonth = document.getElementById("calendar-month");
const tooltip = document.createElement("div");
tooltip.className = "calendar-tooltip";
document.body.appendChild(tooltip);
    

calendarContainer: Контейнер для отображения дней месяца. calendarMonth: Элемент, в котором отображается название текущего месяца и года. tooltip: Подсказка, отображающая список записей для конкретной даты. Она создается динамически и добавляется в body. 3. Проверка наличия элементов:

if (!calendarContainer || !calendarMonth) {
console.error("Не найдены элементы календаря: #calendar-container или #calendar-month");
return;
}
    

Если необходимые элементы отсутствуют, выводится сообщение об ошибке, и выполнение прекращается. 4. Рендеринг календаря:

function renderCalendar(date) {
calendarContainer.innerHTML = "";
    

Очищается содержимое контейнера календаря перед рендерингом нового месяца. 5. Подготовка данных о текущем месяце:

const year = date.getFullYear();
const month = date.getMonth();
const firstDay = new Date(year, month, 1);
const lastDay = new Date(year, month + 1, 0);
    

Вычисляются год, месяц, первый день и последний день текущего месяца. 6. Установка названия месяца:


calendarMonth.textContent = date.toLocaleDateString("ru-RU", {
month: "long",
year: "numeric",
});
    

Название месяца отображается в формате "Месяц Год" на русском языке. 7. Запрос записей для месяца:

fetch(calendarAjax.ajaxUrl, {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: `action=get_posts_for_month&year=${year}&month=${month + 1}`,
})
    

Отправляется AJAX-запрос на сервер для получения записей, привязанных к датам текущего месяца. calendarAjax.ajaxUrl: URL, задаваемый сервером (например, через wp_localize_script в WordPress). action: Указывает обработчик для серверной логики (здесь get_posts_for_month). Передаются год и месяц. 8. Обработка ответа:


if (data.success && data.data) {
const postsByDate = data.data; // Объект с датами и записями
    

Если запрос успешен, данные (записи, сгруппированные по датам) сохраняются в объект postsByDate. 9. Рендеринг дней месяца:


  
for (let day = 1; day <= lastDay.getDate(); day++) {
const dayCell = document.createElement("div");
dayCell.className = "calendar-day";
dayCell.textContent = day;

const fullDate = `${year}-${String(month + 1).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
dayCell.dataset.date = fullDate;
    

Для каждого дня создается элемент div с классом calendar-day и текстом дня. fullDate: Формат даты (например, 2024-12-01), сохраняется в атрибут data-date. 10. Проверка наличия записей:

   
    if (postsByDate[fullDate]) {
    dayCell.classList.add("has-posts");
    dayCell.addEventListener("mouseover", () => showTooltip(dayCell, fullDate));
    dayCell.addEventListener("mouseleave", hideTooltip);
    dayCell.addEventListener("click", () => {
    window.location.href = `/date/${fullDate}`;
    });
    } else {
    dayCell.classList.add("no-posts");
    }
    calendarContainer.appendChild(dayCell);
    Если для даты есть записи:
    Элементу добавляется класс has-posts.
    Устанавливаются обработчики событий:
    mouseover: Показывает подсказку.
    mouseleave: Скрывает подсказку.
    click: Переходит на страницу /date/дата.
    Если записей нет, добавляется класс no-posts.
    11. Подсказка (tooltip):
    
    function showTooltip(dayCell, date) {
    fetch(calendarAjax.ajaxUrl, {
    method: "POST",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    body: `action=get_posts_for_date&date=${date}`,
    })
    .then((response) => response.json())
    .then((data) => {
    if (data.success && data.data.length > 0) {
    tooltip.innerHTML = data.data
    .map((post) => `< a href="${post.link}">${post.title}< /a>`)
    .join("< br >");
    tooltip.style.display = "block";
    tooltip.style.top = dayCell.getBoundingClientRect().bottom + window.scrollY + "px";
    tooltip.style.left = dayCell.getBoundingClientRect().left + "px";
    } else {
    tooltip.style.display = "none";
    }
    });
    }
    

Отправляется запрос для получения записей конкретной даты. Если записи есть, формируется содержимое подсказки в виде ссылок на статьи. Устанавливаются позиции подсказки относительно выбранного дня. 12. Перелистывание месяцев:

  
    document.getElementById("prev-month").addEventListener("click", () => {
    currentDate.setMonth(currentDate.getMonth() - 1);
    renderCalendar(currentDate);
    });

    document.getElementById("next-month").addEventListener("click", () => {
    currentDate.setMonth(currentDate.getMonth() + 1);
    renderCalendar(currentDate);
    });

Кнопки prev-month и next-month переключают месяцы, обновляя календарь. 13. Инициализация:

   
    renderCalendar(currentDate);
    

Календарь рендерится для текущей даты при загрузке страницы. Подробнее смотри на моем youtube канале Ссылка на YouTube