From 5589e891f4aa2d3be20617041cf3ecb0cd1a9e76 Mon Sep 17 00:00:00 2001 From: davegilligan Date: Sun, 24 May 2026 08:19:28 +0200 Subject: [PATCH] Fix file picker reopening after selection on legal-analysis + summarize The "browse" label's native for=input trigger AND the upload-zone click handler both called uploadInput.click(), so the picker opened twice when the user clicked the browse text. Stop propagation on the label and the input itself, plus tighten the zone handler to recognise any label-for descendant. Co-Authored-By: Claude Sonnet 4.6 --- assets/js/legal-analysis.js | 14 +++++++++++++- assets/js/summarize.js | 13 ++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/assets/js/legal-analysis.js b/assets/js/legal-analysis.js index f1b0425..ab8712e 100644 --- a/assets/js/legal-analysis.js +++ b/assets/js/legal-analysis.js @@ -56,9 +56,21 @@ handleFiles(e.dataTransfer.files); } }); + // Stop label-for and the input itself from bubbling into the zone click + // handler — otherwise the picker opens twice (native + programmatic). + var browseLabel = uploadZone.querySelector('label[for="' + (uploadInput && uploadInput.id) + '"]'); + if (browseLabel) { + browseLabel.addEventListener('click', function (e) { e.stopPropagation(); }); + } + if (uploadInput) { + uploadInput.addEventListener('click', function (e) { e.stopPropagation(); }); + } uploadZone.addEventListener('click', function (e) { if (e.target === uploadClear || (uploadClear && uploadClear.contains(e.target))) return; - if (e.target.tagName === 'LABEL') return; + if (e.target === uploadInput) return; + // Any label or descendant of a label-for=uploadInput already triggered the input + var lbl = e.target.closest && e.target.closest('label'); + if (lbl && lbl.getAttribute('for') === uploadInput.id) return; if (uploadInput) uploadInput.click(); }); } diff --git a/assets/js/summarize.js b/assets/js/summarize.js index c80df93..2bb2d81 100644 --- a/assets/js/summarize.js +++ b/assets/js/summarize.js @@ -73,9 +73,20 @@ handleFiles(e.dataTransfer.files); } }); + // Stop label-for and the input itself from bubbling into the zone click + // handler — otherwise the picker opens twice (native + programmatic). + var browseLabel = uploadZone.querySelector('label[for="' + (uploadInput && uploadInput.id) + '"]'); + if (browseLabel) { + browseLabel.addEventListener('click', function (e) { e.stopPropagation(); }); + } + if (uploadInput) { + uploadInput.addEventListener('click', function (e) { e.stopPropagation(); }); + } uploadZone.addEventListener('click', function (e) { if (e.target === uploadClear || (uploadClear && uploadClear.contains(e.target))) return; - if (e.target.tagName === 'LABEL') return; + if (e.target === uploadInput) return; + var lbl = e.target.closest && e.target.closest('label'); + if (lbl && lbl.getAttribute('for') === uploadInput.id) return; if (uploadInput) uploadInput.click(); }); }