diff --git a/static/js/calendar.js b/static/js/calendar.js index 15dd4d9..4a6802b 100644 --- a/static/js/calendar.js +++ b/static/js/calendar.js @@ -85,19 +85,9 @@ if(selStart && rangeEnd){ if(selStart<=isoStr && isoStr<=rangeEnd) dayDiv.classList.add('in-range'); } else if(selStart && selStart===isoStr) dayDiv.classList.add('selected'); dayDiv.dataset.iso = isoStr; - dayDiv.onclick = function(){ - const clicked = this.dataset.iso; - if(!selStart){ selStart = clicked; selEnd = null; } - else if(selStart && !selEnd){ if(clicked < selStart){ selEnd = selStart; selStart = clicked } else selEnd = clicked } - else { selStart = clicked; selEnd = null } - previewEnd = null; - render(); - // Auto-confirm on range completion: open request URL with params - if(selStart && selEnd){ - const url = requestUrl + '?worker_id=' + encodeURIComponent(workerId) + '&start_date=' + selStart + '&end_date=' + selEnd; - try{ htmx.ajax('GET', url, {target:'#modal', swap:'innerHTML'}); }catch(e){ window.location = url; } - } - }; + // Pointer handling is done via a delegated listener attached to the + // container (see below) so clicks that hit the numeric text node are + // still caught. Keep the day hover handlers here for previews. dayDiv.onmouseover = function(){ if(selStart && !selEnd){ previewEnd = this.dataset.iso; render(); } }; dayDiv.onmouseout = function(){ if(selStart && !selEnd){ previewEnd = null; render(); } }; } @@ -129,6 +119,32 @@ window._calendars[containerId] = { clearSelection, setLeaves, refreshLeaves }; + // Delegated pointer handler: attach once to the container so clicks on + // numeric text nodes (or any child) are still detected via event + // delegation. This is more reliable than per-day handlers when the + // DOM changes or when the target is a text node. + if(!container._pointerHandlerAttached){ + container.addEventListener('pointerdown', function(evt){ + try{ + const dayEl = evt.target.closest && evt.target.closest('.day'); + if(!dayEl || dayEl.classList.contains('other-month')) return; + const clicked = dayEl.dataset.iso; + if(!selStart){ selStart = clicked; selEnd = null; } + else if(selStart && !selEnd){ if(clicked < selStart){ selEnd = selStart; selStart = clicked } else selEnd = clicked } + else { selStart = clicked; selEnd = null } + previewEnd = null; + render(); + if(selStart && selEnd){ + const url = requestUrl + '?worker_id=' + encodeURIComponent(workerId) + '&start_date=' + selStart + '&end_date=' + selEnd; + setTimeout(function(){ + try{ if(window.htmx && typeof window.htmx.ajax === 'function'){ window.htmx.ajax('GET', url, {target:'#modal', swap:'innerHTML'}); } else { htmx.ajax('GET', url, {target:'#modal', swap:'innerHTML'}); } }catch(e){ window.location = url; } + }, 80); + } + }catch(e){ console.error('calendar pointer handler', e); } + }); + container._pointerHandlerAttached = true; + } + render(); // If a server leavesUrl is provided, refresh from server to ensure authoritative data if(leavesUrl){