Improve date handling for the calendar widget

This commit is contained in:
2026-04-06 08:49:14 +02:00
parent 5c74c2e667
commit c1ffbc3f3a
2 changed files with 71 additions and 21 deletions

View File

@@ -51,19 +51,33 @@
function getCalendarStateKey(calendar) { function getCalendarStateKey(calendar) {
var baseNs = calendar.getAttribute('data-base-ns') || 'chronological'; var baseNs = calendar.getAttribute('data-base-ns') || 'chronological';
return 'luxtools.calendar.month.' + baseNs; return 'luxtools_calendar_month_' + baseNs.replace(/[^a-zA-Z0-9]/g, '_');
} }
function shouldPersistCalendarMonth(calendar) { function shouldPersistCalendarMonth(calendar) {
return (calendar.getAttribute('data-luxtools-size') || 'large') === 'small'; return (calendar.getAttribute('data-luxtools-size') || 'large') === 'small';
} }
function getCookieValue(name) {
var match = document.cookie.match('(^|;)\\s*' + name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '\\s*=\\s*([^;]+)');
return match ? decodeURIComponent(match[2]) : null;
}
function setCookie(name, value) {
var date = new Date();
date.setFullYear(date.getFullYear() + 1);
document.cookie = name + '=' + encodeURIComponent(value) + '; expires=' + date.toUTCString() + '; path=/; SameSite=Lax';
}
function deleteCookie(name) {
document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; SameSite=Lax';
}
function readSavedCalendarMonth(calendar) { function readSavedCalendarMonth(calendar) {
if (!shouldPersistCalendarMonth(calendar)) return null; if (!shouldPersistCalendarMonth(calendar)) return null;
if (!window.localStorage) return null;
try { try {
var raw = window.localStorage.getItem(getCalendarStateKey(calendar)); var raw = getCookieValue(getCalendarStateKey(calendar));
if (!raw) return null; if (!raw) return null;
var parsed = JSON.parse(raw); var parsed = JSON.parse(raw);
@@ -79,31 +93,17 @@
function saveCalendarMonth(calendar) { function saveCalendarMonth(calendar) {
if (!shouldPersistCalendarMonth(calendar)) return; if (!shouldPersistCalendarMonth(calendar)) return;
if (!window.localStorage) return;
var year = parseInt(calendar.getAttribute('data-current-year') || '', 10); var year = parseInt(calendar.getAttribute('data-current-year') || '', 10);
var month = parseInt(calendar.getAttribute('data-current-month') || '', 10); var month = parseInt(calendar.getAttribute('data-current-month') || '', 10);
if (!year || month < 1 || month > 12) return; if (!year || month < 1 || month > 12) return;
try { setCookie(getCalendarStateKey(calendar), JSON.stringify({ year: year, month: month }));
window.localStorage.setItem(getCalendarStateKey(calendar), JSON.stringify({
year: year,
month: month
}));
} catch (e) {
// ignore storage failures
}
} }
function clearSavedCalendarMonth(calendar) { function clearSavedCalendarMonth(calendar) {
if (!shouldPersistCalendarMonth(calendar)) return; if (!shouldPersistCalendarMonth(calendar)) return;
if (!window.localStorage) return; deleteCookie(getCalendarStateKey(calendar));
try {
window.localStorage.removeItem(getCalendarStateKey(calendar));
} catch (e) {
// ignore storage failures
}
} }
function fetchCalendarMonth(calendar, year, month) { function fetchCalendarMonth(calendar, year, month) {
@@ -227,11 +227,22 @@
function restoreCalendarMonth(calendar) { function restoreCalendarMonth(calendar) {
if (!shouldPersistCalendarMonth(calendar)) return; if (!shouldPersistCalendarMonth(calendar)) return;
var saved = readSavedCalendarMonth(calendar);
if (!saved) return;
var year = parseInt(calendar.getAttribute('data-current-year') || '', 10); var year = parseInt(calendar.getAttribute('data-current-year') || '', 10);
var month = parseInt(calendar.getAttribute('data-current-month') || '', 10); var month = parseInt(calendar.getAttribute('data-current-month') || '', 10);
if (!year || !month) return;
var saved = readSavedCalendarMonth(calendar);
if (!saved) {
var now = new Date();
var todayYear = now.getFullYear();
var todayMonth = now.getMonth() + 1;
if (year !== todayYear || month !== todayMonth) {
loadCalendarMonth(calendar, todayYear, todayMonth, false);
}
return;
}
if (saved.year === year && saved.month === month) return; if (saved.year === year && saved.month === month) return;
loadCalendarMonth(calendar, saved.year, saved.month, true); loadCalendarMonth(calendar, saved.year, saved.month, true);
@@ -258,7 +269,17 @@
navigateCalendarMonth(calendar, direction, true); navigateCalendarMonth(calendar, direction, true);
} }
function updateClientDateCookie() {
var now = new Date();
setCookie('luxtools_client_month', JSON.stringify({
year: now.getFullYear(),
month: now.getMonth() + 1
}));
}
function initCalendarWidgets() { function initCalendarWidgets() {
updateClientDateCookie();
var calendars = document.querySelectorAll('div.luxtools-calendar[data-luxtools-calendar="1"]'); var calendars = document.querySelectorAll('div.luxtools-calendar[data-luxtools-calendar="1"]');
for (var i = 0; i < calendars.length; i++) { for (var i = 0; i < calendars.length; i++) {
syncCalendarToday(calendars[i]); syncCalendarToday(calendars[i]);

View File

@@ -91,6 +91,16 @@ class syntax_plugin_luxtools_calendar extends SyntaxPlugin
$size = ChronologicalCalendarWidget::normalizeSize((string)($data['size'] ?? 'large')); $size = ChronologicalCalendarWidget::normalizeSize((string)($data['size'] ?? 'large'));
$showTimes = (bool)($data['show_times'] ?? true); $showTimes = (bool)($data['show_times'] ?? true);
if ($size === 'small') {
$resolved = $this->resolveMonthFromCookie(
'luxtools_calendar_month_' . preg_replace('/[^a-zA-Z0-9]/', '_', $baseNs)
) ?? $this->resolveMonthFromCookie('luxtools_client_month');
if ($resolved !== null) {
$year = $resolved['year'];
$month = $resolved['month'];
}
}
$slots = CalendarSlot::loadEnabled($this); $slots = CalendarSlot::loadEnabled($this);
$widgetSlots = CalendarSlot::filterWidgetVisible($slots); $widgetSlots = CalendarSlot::filterWidgetVisible($slots);
$indicators = []; $indicators = [];
@@ -122,6 +132,25 @@ class syntax_plugin_luxtools_calendar extends SyntaxPlugin
return true; return true;
} }
/**
* @param string $cookieName
* @return array{year:int,month:int}|null
*/
protected function resolveMonthFromCookie(string $cookieName): ?array
{
$raw = $_COOKIE[$cookieName] ?? null;
if ($raw === null) return null;
$decoded = json_decode($raw, true);
if (!is_array($decoded)) return null;
$year = (int)($decoded['year'] ?? 0);
$month = (int)($decoded['month'] ?? 0);
if ($year < 1 || $month < 1 || $month > 12) return null;
return ['year' => $year, 'month' => $month];
}
/** /**
* @param string $flags * @param string $flags
* @return array<string,string> * @return array<string,string>