From d8f3fc991debf62ef1998d7010d0114422e3ca2c Mon Sep 17 00:00:00 2001 From: Axce Date: Fri, 2 Jan 2026 04:52:37 +0100 Subject: [PATCH] init2 --- index.html | 328 ++++++++++++++++++++++++++++++++++++++--------------- mots.txt | 8 ++ 2 files changed, 243 insertions(+), 93 deletions(-) create mode 100644 mots.txt diff --git a/index.html b/index.html index 8956e91..b7684f0 100644 --- a/index.html +++ b/index.html @@ -340,11 +340,11 @@

Charger un dictionnaire

+
-
@@ -473,37 +473,36 @@ if (cell.type === 'definition') { // Determine associated words in both directions (starting at the neighboring letter cell) - const wordInfoH = getWordAt(row, col + 1, 'horizontal'); - const wordInfoV = getWordAt(row + 1, col, 'vertical'); + // Special rules for top row and left column mappings + let wordInfoH; + let wordInfoV; - let targetWord = null; - let targetDir = null; - - if (half === 'h') { - targetWord = wordInfoH; - targetDir = 'horizontal'; - } else if (half === 'v') { - targetWord = wordInfoV; - targetDir = 'vertical'; + // Horizontal definition normally maps to word starting at (row, col+1) horizontally, + // but if this definition is on the top row, its horizontal definition maps to the vertical word starting at (row, col+1). + if (row === 0) { + wordInfoH = getWordAt(row, col + 1, 'vertical'); } else { - // if no half specified, pick the direction that actually has a word - if (wordInfoH && wordInfoH.word) { - targetWord = wordInfoH; - targetDir = 'horizontal'; - } else if (wordInfoV && wordInfoV.word) { - targetWord = wordInfoV; - targetDir = 'vertical'; - } + wordInfoH = getWordAt(row, col + 1, 'horizontal'); } - if (targetWord && targetWord.word) { - const normalized = normalizeWord(targetWord.word); - const defs = dictionaries[normalized] || []; - const uniqueDefs = [...new Set(defs)]; - - currentModal = { row, col, half, direction: targetDir }; - showDefinitions(targetWord.word, uniqueDefs); + // Vertical definition normally maps to word starting at (row+1, col) vertically, + // but if this definition is on the first column, its vertical definition maps to the horizontal word starting at (row+1, col). + if (col === 0) { + wordInfoV = getWordAt(row + 1, col, 'horizontal'); + } else { + wordInfoV = getWordAt(row + 1, col, 'vertical'); } + + // Build words and definitions for both sides (may be empty) + const wordH = (wordInfoH && wordInfoH.word) ? wordInfoH.word : null; + const wordV = (wordInfoV && wordInfoV.word) ? wordInfoV.word : null; + + const defsH = wordH ? ([...new Set(dictionaries[normalizeWord(wordH)] || [])]) : []; + const defsV = wordV ? ([...new Set(dictionaries[normalizeWord(wordV)] || [])]) : []; + + // If half specified, still show modal but prioritize that half for selection via UI + currentModal = { row, col, half }; + showDefinitionModal(row, col, wordH, defsH, wordV, defsV); } else { if (activeCell && activeCell.row === row && activeCell.col === col) { orientation = orientation === 'horizontal' ? 'vertical' : 'horizontal'; @@ -527,44 +526,110 @@ renderGrid(); } - // Affiche les définitions - function showDefinitions(word, definitions) { - document.getElementById('modalTitle').textContent = `Définitions pour "${word}"`; + // Affiche le modal de sélection des définitions, en deux parties (horizontal / vertical) + function showDefinitionModal(row, col, wordH, defsH, wordV, defsV) { + currentModal = { row, col }; + document.getElementById('modalTitle').textContent = `Définitions`; const list = document.getElementById('definitionList'); list.innerHTML = ''; - - if (definitions.length === 0) { - list.innerHTML = '

Aucune définition disponible pour ce mot.

'; + + const sectionH = document.createElement('div'); + const titleH = document.createElement('h4'); + titleH.textContent = 'Mot horizontal'; + sectionH.appendChild(titleH); + if (!wordH) { + const p = document.createElement('p'); + p.style.color = '#6b7280'; + p.textContent = 'Aucun mot associé'; + sectionH.appendChild(p); } else { - definitions.forEach(def => { - const btn = document.createElement('button'); - btn.className = 'definition-item'; - btn.textContent = def; - btn.onclick = () => selectDefinition(def); - list.appendChild(btn); - }); + const wordP = document.createElement('p'); + wordP.style.fontWeight = '600'; + wordP.textContent = wordH; + sectionH.appendChild(wordP); + + if (defsH.length === 0) { + const p = document.createElement('p'); + p.style.color = '#6b7280'; + p.textContent = 'Aucune définition disponible pour ce mot.'; + sectionH.appendChild(p); + } else { + defsH.forEach(def => { + const btn = document.createElement('button'); + btn.className = 'definition-item'; + btn.textContent = def; + btn.onclick = () => { + grid[row][col].definitionH = def; + closeModal(); + renderGrid(); + }; + sectionH.appendChild(btn); + }); + } } - + + const sectionV = document.createElement('div'); + const titleV = document.createElement('h4'); + titleV.textContent = 'Mot vertical'; + sectionV.appendChild(titleV); + if (!wordV) { + const p = document.createElement('p'); + p.style.color = '#6b7280'; + p.textContent = 'Aucun mot associé'; + sectionV.appendChild(p); + } else { + const wordP = document.createElement('p'); + wordP.style.fontWeight = '600'; + wordP.textContent = wordV; + sectionV.appendChild(wordP); + + if (defsV.length === 0) { + const p = document.createElement('p'); + p.style.color = '#6b7280'; + p.textContent = 'Aucune définition disponible pour ce mot.'; + sectionV.appendChild(p); + } else { + defsV.forEach(def => { + const btn = document.createElement('button'); + btn.className = 'definition-item'; + btn.textContent = def; + btn.onclick = () => { + grid[row][col].definitionV = def; + closeModal(); + renderGrid(); + }; + sectionV.appendChild(btn); + }); + } + } + + // Delete button: transforms case into letter empty + const deleteBtn = document.createElement('button'); + deleteBtn.className = 'btn-danger'; + deleteBtn.style.marginTop = '12px'; + deleteBtn.textContent = 'Supprimer (transformer en case lettre)'; + deleteBtn.onclick = () => { + const cell = grid[row][col]; + const hasDefs = !!(cell.definitionH || cell.definitionV); + if (hasDefs) { + if (!confirm('La case contient des définitions. Confirmer la transformation en case lettre vide ?')) return; + } + cell.type = 'letter'; + cell.letter = ''; + cell.definitionH = ''; + cell.definitionV = ''; + closeModal(); + renderGrid(); + }; + + // Append sections to list + list.appendChild(sectionH); + list.appendChild(sectionV); + list.appendChild(deleteBtn); + document.getElementById('definitionModal').classList.add('show'); } - // Sélectionne une définition - function selectDefinition(definition) { - if (!currentModal) return; - - const { row, col, direction } = currentModal; - - if (direction === 'horizontal') { - grid[row][col].definitionH = definition; - } else { - grid[row][col].definitionV = definition; - } - - closeModal(); - renderGrid(); - } - - // Ferme le modal function closeModal() { document.getElementById('definitionModal').classList.remove('show'); currentModal = null; @@ -763,47 +828,36 @@ } else { hasBoth = cell.definitionH && cell.definitionV; - if (hasBoth) { - const split = document.createElement('div'); - split.className = 'definition-split'; + if (hasBoth) { + const split = document.createElement('div'); + split.className = 'definition-split'; - const halfH = document.createElement('div'); - halfH.className = 'definition-half'; - halfH.textContent = cell.definitionH; - halfH.innerHTML += ''; + const halfH = document.createElement('div'); + halfH.className = 'definition-half'; + halfH.textContent = cell.definitionH; - const halfV = document.createElement('div'); - halfV.className = 'definition-half'; - halfV.textContent = cell.definitionV; - halfV.innerHTML += ''; + const halfV = document.createElement('div'); + halfV.className = 'definition-half'; + halfV.textContent = cell.definitionV; - split.appendChild(halfH); - split.appendChild(halfV); - cellEl.appendChild(split); + split.appendChild(halfH); + split.appendChild(halfV); + cellEl.appendChild(split); - halfH.onclick = (e) => { - e.stopPropagation(); - handleCellClick(rowIndex, colIndex, 'h'); - }; - halfV.onclick = (e) => { - e.stopPropagation(); - handleCellClick(rowIndex, colIndex, 'v'); - }; - } else { - const text = document.createElement('div'); - text.className = 'definition-text'; - text.textContent = cell.definitionH || cell.definitionV; - - if (cell.definitionH || cell.definitionV) { - if (cell.definitionV) { - text.innerHTML += ''; + halfH.onclick = (e) => { + e.stopPropagation(); + handleCellClick(rowIndex, colIndex, 'h'); + }; + halfV.onclick = (e) => { + e.stopPropagation(); + handleCellClick(rowIndex, colIndex, 'v'); + }; } else { - text.innerHTML += ''; + const text = document.createElement('div'); + text.className = 'definition-text'; + text.textContent = cell.definitionH || cell.definitionV; + cellEl.appendChild(text); } - } - - cellEl.appendChild(text); - } } if (!hasBoth) { @@ -812,6 +866,10 @@ cellEl.ondblclick = () => handleCellDoubleClick(rowIndex, colIndex); rowEl.appendChild(cellEl); + // store reference for later arrow placement + if (!window._cellEls) window._cellEls = []; + if (!window._cellEls[rowIndex]) window._cellEls[rowIndex] = []; + window._cellEls[rowIndex][colIndex] = cellEl; }); // Bouton d'ajout de colonne @@ -833,6 +891,90 @@ addRowLine.appendChild(addBtn); } gridEl.appendChild(addRowLine); + + // After grid built, place arrows in the first-letter cells based on adjacent definition cells + // Clear any previous arrows + if (window._cellEls) { + for (let r = 0; r < grid.length; r++) { + for (let c = 0; c < grid[0].length; c++) { + const el = window._cellEls[r] && window._cellEls[r][c]; + if (el) { + const prev = el.querySelector('.def-arrow'); + if (prev) prev.remove(); + } + } + } + + // For each definition cell, compute target first-letter cell and append arrow there + for (let dr = 0; dr < grid.length; dr++) { + for (let dc = 0; dc < grid[0].length; dc++) { + const defCell = grid[dr][dc]; + if (defCell.type !== 'definition') continue; + + // Horizontal-definition mapping + if (defCell.definitionH) { + const tr = dr; + const tc = dc + 1; + if (tr >= 0 && tr < grid.length && tc >= 0 && tc < grid[0].length) { + const targetEl = window._cellEls[tr] && window._cellEls[tr][tc]; + if (targetEl) { + const arrow = document.createElement('div'); + arrow.className = 'def-arrow'; + // special top-row: curve down + if (dr === 0) { + arrow.innerHTML = ''; + arrow.style.position = 'absolute'; + arrow.style.top = '2px'; + arrow.style.left = '50%'; + arrow.style.transform = 'translateX(-50%)'; + } else { + // left-pointing arrow near left border + arrow.innerHTML = ''; + arrow.style.position = 'absolute'; + arrow.style.left = '4px'; + arrow.style.top = '50%'; + arrow.style.transform = 'translateY(-50%)'; + } + arrow.style.pointerEvents = 'none'; + arrow.classList.add('def-arrow'); + targetEl.appendChild(arrow); + } + } + } + + // Vertical-definition mapping + if (defCell.definitionV) { + const tr = dr + 1; + const tc = dc; + if (tr >= 0 && tr < grid.length && tc >= 0 && tc < grid[0].length) { + const targetEl = window._cellEls[tr] && window._cellEls[tr][tc]; + if (targetEl) { + const arrow = document.createElement('div'); + arrow.className = 'def-arrow'; + if (dc === 0) { + // left-edge special: curve right + arrow.innerHTML = ''; + arrow.style.position = 'absolute'; + arrow.style.left = '2px'; + arrow.style.top = '50%'; + arrow.style.transform = 'translateY(-50%)'; + } else { + // up-pointing arrow near top border + arrow.innerHTML = ''; + arrow.style.position = 'absolute'; + arrow.style.top = '4px'; + arrow.style.left = '50%'; + arrow.style.transform = 'translateX(-50%)'; + } + arrow.style.pointerEvents = 'none'; + arrow.classList.add('def-arrow'); + targetEl.appendChild(arrow); + } + } + } + } + } + } } // Gestion du clavier diff --git a/mots.txt b/mots.txt new file mode 100644 index 0000000..4d5fb89 --- /dev/null +++ b/mots.txt @@ -0,0 +1,8 @@ +chat: doux mais violent +chat: mais violent +plante: assoiffée de calme +président: affiné un mandat +président: affiné pour un mandat +arc-en-ciel: couleur de la pluie +chômeur: cauchemar de libéral +ut: en rut sans en avoir l’air