Planification: Suppr/Backspace pour vider les cases sélectionnées (ou la case active)

onKey: garde anti-champ (n'intercepte pas dans input/textarea/select/contenteditable) + empêche
le 'retour arrière' du navigateur (preventDefault). Suppr/⌫ vide la sélection (ou la case cliquée),
avec pushHistory (annulable). Hint de légende mis à jour.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
louispaulb 2026-06-04 19:46:04 -04:00
parent 89a366d197
commit ece0ccb6ff

View File

@ -98,7 +98,7 @@
<span class="leg-garde"></span><span class="text-grey-7 q-mr-sm">garde</span> <span class="leg-garde"></span><span class="text-grey-7 q-mr-sm">garde</span>
<span class="free q-mr-xs">·</span><span class="text-grey-7 q-mr-sm">libre</span> <span class="free q-mr-xs">·</span><span class="text-grey-7 q-mr-sm">libre</span>
<span class="cell-dirty-demo q-mr-xs">J</span><span class="text-grey-7 q-mr-sm">modifié (non publié)</span> <span class="cell-dirty-demo q-mr-xs">J</span><span class="text-grey-7 q-mr-sm">modifié (non publié)</span>
<span class="text-teal-8">· <b>glisser</b> = sélection · shift+clic = bloc · clic en-tête = colonne · clic nom = rangée · ctrl+clic = +1 · <b>ctrl+C/V</b> = copier/coller une case</span> <span class="text-teal-8">· <b>glisser</b> = sélection · shift+clic = bloc · clic en-tête = colonne · clic nom = rangée · ctrl+clic = +1 · <b>ctrl+C/V</b> = copier/coller · <b>Suppr/</b> = vider</span>
</div> </div>
<div class="grid-wrap"> <div class="grid-wrap">
@ -645,10 +645,19 @@ async function togglePause (t) { try { const paused = !isPaused(t); await roster
function err (e) { $q.notify({ type: 'negative', message: '' + (e.message || e) }) } function err (e) { $q.notify({ type: 'negative', message: '' + (e.message || e) }) }
function onKey (e) { function onKey (e) {
const tag = (e.target && e.target.tagName) || ''
if (/INPUT|TEXTAREA|SELECT/.test(tag) || (e.target && e.target.isContentEditable)) return // ne pas intercepter quand on tape dans un champ
const k = e.key.toLowerCase() const k = e.key.toLowerCase()
if ((e.ctrlKey || e.metaKey) && k === 'z') { e.preventDefault(); if (e.shiftKey) redo(); else undo(); return } if ((e.ctrlKey || e.metaKey) && k === 'z') { e.preventDefault(); if (e.shiftKey) redo(); else undo(); return }
if ((e.ctrlKey || e.metaKey) && k === 'c' && (selection.value.length || activeCell.value)) { e.preventDefault(); menu.show = false; copyCell(); return } if ((e.ctrlKey || e.metaKey) && k === 'c' && (selection.value.length || activeCell.value)) { e.preventDefault(); menu.show = false; copyCell(); return }
if ((e.ctrlKey || e.metaKey) && k === 'v' && (selection.value.length || activeCell.value)) { e.preventDefault(); menu.show = false; pasteCells() } if ((e.ctrlKey || e.metaKey) && k === 'v' && (selection.value.length || activeCell.value)) { e.preventDefault(); menu.show = false; pasteCells(); return }
if ((k === 'delete' || k === 'backspace') && (selection.value.length || activeCell.value)) {
e.preventDefault(); menu.show = false
const targets = selection.value.length ? selection.value.slice() : [activeCell.value.id + '|' + activeCell.value.iso]
pushHistory()
for (const key of targets) { const [tid, iso] = key.split('|'); clearLocal(tid, iso) }
if (selection.value.length) selection.value = []
}
} }
function onUnload (e) { if (dirty.value) { e.preventDefault(); e.returnValue = '' } } function onUnload (e) { if (dirty.value) { e.preventDefault(); e.returnValue = '' } }
onMounted(async () => { loadLS(); document.addEventListener('keydown', onKey); document.addEventListener('mouseup', onUp); window.addEventListener('beforeunload', onUnload); try { await loadBase() } catch (e) { err(e) } await loadWeek() }) onMounted(async () => { loadLS(); document.addEventListener('keydown', onKey); document.addEventListener('mouseup', onUp); window.addEventListener('beforeunload', onUnload); try { await loadBase() } catch (e) { err(e) } await loadWeek() })