This commit is contained in:
Axce 2026-01-02 05:09:04 +01:00
parent d8f3fc991d
commit 928b1215f8
2 changed files with 140 additions and 89 deletions

View File

@ -193,24 +193,43 @@
.definition-split { .definition-split {
display: flex; display: flex;
flex-direction: column;
position: absolute; position: absolute;
inset: 0; inset: 0;
} }
.definition-half { .definition-half {
width: 50%; height: 50%;
position: relative; position: relative;
padding: 2px; padding: 2px;
font-size: 5px; font-size: 8px;
line-height: 6px; line-height: 10px;
overflow: hidden; overflow: hidden;
word-wrap: break-word; word-wrap: break-word;
display:flex;
align-items:center;
justify-content:center;
font-variant: small-caps;
text-transform:uppercase;
} }
.definition-half:first-child { .definition-half:first-child {
border-right: 1px solid #6b7280; border-bottom: 1px solid #6b7280;
} }
.definition-text {
font-variant: small-caps;
text-transform:uppercase;
font-size:10px;
display:flex;
align-items:center;
justify-content:center;
}
.definition-item.selected { background-color: #fde68a; }
.def-arrow { position:absolute; pointer-events:none; }
/* Visual hint for hyphens: dotted border between cells */ /* Visual hint for hyphens: dotted border between cells */
.cell.hyphen { .cell.hyphen {
border-right: 2px dotted #000; border-right: 2px dotted #000;
@ -350,7 +369,9 @@
<div class="grid-container"> <div class="grid-container">
<div id="grid" class="grid"></div> <div id="grid" class="grid"></div>
<div class="controls"> <div style="display:flex;gap:8px;margin-top:12px;">
<button class="btn-success" onclick="addRow()">+ Ajouter ligne</button>
<button class="btn-success" onclick="addColumn()">+ Ajouter colonne</button>
<button class="btn-danger" onclick="removeRow()"> Supprimer ligne</button> <button class="btn-danger" onclick="removeRow()"> Supprimer ligne</button>
<button class="btn-danger" onclick="removeColumn()"> Supprimer colonne</button> <button class="btn-danger" onclick="removeColumn()"> Supprimer colonne</button>
</div> </div>
@ -516,12 +537,20 @@
// Gère le double-clic // Gère le double-clic
function handleCellDoubleClick(row, col) { function handleCellDoubleClick(row, col) {
const cell = grid[row][col]; const cell = grid[row][col];
cell.type = cell.type === 'letter' ? 'definition' : 'letter'; if (cell.type === 'letter' && !cell.letter) {
if (cell.type === 'letter') { // empty letter -> become empty definition
cell.type = 'definition';
cell.definitionH = ''; cell.definitionH = '';
cell.definitionV = ''; cell.definitionV = '';
} else { } else {
cell.letter = ''; // otherwise toggle
cell.type = cell.type === 'letter' ? 'definition' : 'letter';
if (cell.type === 'letter') {
cell.definitionH = '';
cell.definitionV = '';
} else {
cell.letter = '';
}
} }
renderGrid(); renderGrid();
} }
@ -558,6 +587,7 @@
const btn = document.createElement('button'); const btn = document.createElement('button');
btn.className = 'definition-item'; btn.className = 'definition-item';
btn.textContent = def; btn.textContent = def;
if (grid[row][col].definitionH === def) btn.classList.add('selected');
btn.onclick = () => { btn.onclick = () => {
grid[row][col].definitionH = def; grid[row][col].definitionH = def;
closeModal(); closeModal();
@ -593,6 +623,7 @@
const btn = document.createElement('button'); const btn = document.createElement('button');
btn.className = 'definition-item'; btn.className = 'definition-item';
btn.textContent = def; btn.textContent = def;
if (grid[row][col].definitionV === def) btn.classList.add('selected');
btn.onclick = () => { btn.onclick = () => {
grid[row][col].definitionV = def; grid[row][col].definitionV = def;
closeModal(); closeModal();
@ -893,83 +924,85 @@
gridEl.appendChild(addRowLine); gridEl.appendChild(addRowLine);
// After grid built, place arrows in the first-letter cells based on adjacent definition cells // After grid built, place arrows in the first-letter cells based on adjacent definition cells
// Clear any previous arrows
if (window._cellEls) { if (window._cellEls) {
for (let r = 0; r < grid.length; r++) { for (let r = 0; r < grid.length; r++) {
for (let c = 0; c < grid[0].length; c++) { for (let c = 0; c < grid[0].length; c++) {
const el = window._cellEls[r] && window._cellEls[r][c]; const el = window._cellEls[r] && window._cellEls[r][c];
if (el) { if (el) {
const prev = el.querySelector('.def-arrow'); const prev = el.querySelectorAll('.def-arrow');
if (prev) prev.remove(); prev.forEach(p => p.remove());
} }
} }
} }
// For each definition cell, compute target first-letter cell and append arrow there
for (let dr = 0; dr < grid.length; dr++) { for (let dr = 0; dr < grid.length; dr++) {
for (let dc = 0; dc < grid[0].length; dc++) { for (let dc = 0; dc < grid[0].length; dc++) {
const defCell = grid[dr][dc]; const defCell = grid[dr][dc];
if (defCell.type !== 'definition') continue; if (defCell.type !== 'definition') continue;
// Horizontal-definition mapping // Horizontal mapping: def at (dr,dc) -> word starts at (dr,dc+1) normally
if (defCell.definitionH) { let trH = dr;
const tr = dr; let tcH = dc + 1;
const tc = dc + 1; // top-row special: horizontal definition maps to vertical word starting at (dr,dc+1)
if (tr >= 0 && tr < grid.length && tc >= 0 && tc < grid[0].length) { let horizontalIsVertical = false;
const targetEl = window._cellEls[tr] && window._cellEls[tr][tc]; if (dr === 0) {
if (targetEl) { horizontalIsVertical = true;
const arrow = document.createElement('div'); trH = dr;
arrow.className = 'def-arrow'; tcH = dc + 1;
// special top-row: curve down }
if (dr === 0) {
arrow.innerHTML = '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="1" class="arrow-down-curved"><path d="M12 0 C12 0 12 6 12 6 L12 16"/><path d="M12 16 L9 13 M12 16 L15 13"/></svg>'; if (defCell.definitionH && tcH < grid[0].length) {
arrow.style.position = 'absolute'; const targetEl = window._cellEls[trH] && window._cellEls[trH][tcH];
arrow.style.top = '2px'; if (targetEl) {
arrow.style.left = '50%'; const arrow = document.createElement('div');
arrow.style.transform = 'translateX(-50%)'; arrow.className = 'def-arrow';
} else { if (horizontalIsVertical) {
// left-pointing arrow near left border // arrow downwards from top border
arrow.innerHTML = '<svg width="12" height="12" viewBox="0 0 8 8" fill="none" stroke="black" stroke-width="1"><path d="M6 1 L2 4 L6 7"/></svg>'; arrow.innerHTML = '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="1"><path d="M12 3 L12 18"/><path d="M12 18 L8 14 M12 18 L16 14"/></svg>';
arrow.style.position = 'absolute'; arrow.style.top = '0px';
arrow.style.left = '4px'; arrow.style.left = '50%';
arrow.style.top = '50%'; arrow.style.transform = 'translateX(-50%)';
arrow.style.transform = 'translateY(-50%)'; } else {
} // arrow pointing leftwards from left border into cell (originates from definition at left)
arrow.style.pointerEvents = 'none'; arrow.innerHTML = '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="1"><path d="M3 12 L18 12"/><path d="M18 12 L14 8 M18 12 L14 16"/></svg>';
arrow.classList.add('def-arrow'); arrow.style.left = '0px';
targetEl.appendChild(arrow); arrow.style.top = '50%';
arrow.style.transform = 'translateY(-50%)';
} }
targetEl.appendChild(arrow);
} }
} }
// Vertical-definition mapping // Vertical mapping: def at (dr,dc) -> word starts at (dr+1,dc) normally
if (defCell.definitionV) { let trV = dr + 1;
const tr = dr + 1; let tcV = dc;
const tc = dc; // left-column special: vertical definition maps to horizontal word starting at (dr+1,dc)
if (tr >= 0 && tr < grid.length && tc >= 0 && tc < grid[0].length) { let verticalIsHorizontal = false;
const targetEl = window._cellEls[tr] && window._cellEls[tr][tc]; if (dc === 0) {
if (targetEl) { verticalIsHorizontal = true;
const arrow = document.createElement('div'); trV = dr + 1;
arrow.className = 'def-arrow'; tcV = dc;
if (dc === 0) { }
// left-edge special: curve right
arrow.innerHTML = '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="1"><path d="M0 12 C0 12 6 12 6 12 L16 12"/><path d="M16 12 L13 9 M16 12 L13 15"/></svg>'; if (defCell.definitionV && trV < grid.length) {
arrow.style.position = 'absolute'; const targetEl = window._cellEls[trV] && window._cellEls[trV][tcV];
arrow.style.left = '2px'; if (targetEl) {
arrow.style.top = '50%'; const arrow = document.createElement('div');
arrow.style.transform = 'translateY(-50%)'; arrow.className = 'def-arrow';
} else { if (verticalIsHorizontal) {
// up-pointing arrow near top border // arrow rightwards from left border
arrow.innerHTML = '<svg width="12" height="12" viewBox="0 0 8 8" fill="none" stroke="black" stroke-width="1"><path d="M1 6 L4 2 L7 6"/></svg>'; arrow.innerHTML = '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="1"><path d="M3 12 L18 12"/><path d="M18 12 L14 8 M18 12 L14 16"/></svg>';
arrow.style.position = 'absolute'; arrow.style.left = '0px';
arrow.style.top = '4px'; arrow.style.top = '50%';
arrow.style.left = '50%'; arrow.style.transform = 'translateY(-50%)';
arrow.style.transform = 'translateX(-50%)'; } else {
} // arrow pointing upwards from top border? we want from definition to word, so arrow downwards from top border
arrow.style.pointerEvents = 'none'; arrow.innerHTML = '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="1"><path d="M12 3 L12 18"/><path d="M12 18 L8 14 M12 18 L16 14"/></svg>';
arrow.classList.add('def-arrow'); arrow.style.top = '0px';
targetEl.appendChild(arrow); arrow.style.left = '50%';
arrow.style.transform = 'translateX(-50%)';
} }
targetEl.appendChild(arrow);
} }
} }
} }
@ -977,19 +1010,24 @@
} }
} }
// Gestion du clavier // Gestion du clavier (saisie, navigation, suppression)
document.addEventListener('keydown', (e) => { document.addEventListener('keydown', (e) => {
if (!activeCell || document.getElementById('gridScreen').style.display === 'none') return; // don't intercept when modifier keys are pressed
if (e.ctrlKey || e.altKey || e.metaKey) return;
const { row, col } = activeCell; if (document.getElementById('gridScreen').style.display === 'none') return;
// Toggle orientation with Tab when an active cell exists
if (e.key === 'Tab') { if (e.key === 'Tab') {
if (!activeCell) return;
e.preventDefault(); e.preventDefault();
orientation = orientation === 'horizontal' ? 'vertical' : 'horizontal'; orientation = orientation === 'horizontal' ? 'vertical' : 'horizontal';
renderGrid(); renderGrid();
return; return;
} }
if (!activeCell) return;
const { row, col } = activeCell;
if (e.key === 'Backspace') { if (e.key === 'Backspace') {
e.preventDefault(); e.preventDefault();
if (grid[row][col].letter) { if (grid[row][col].letter) {
@ -1072,15 +1110,6 @@
renderGrid(); renderGrid();
} }
}); });
// Ensure tab toggles orientation even if focus is elsewhere
document.addEventListener('keydown', (e) => {
if (e.key === 'Tab') {
e.preventDefault();
orientation = orientation === 'horizontal' ? 'vertical' : 'horizontal';
renderGrid();
}
});
</script> </script>
</body> </body>
</html> </html>

View File

@ -1,5 +1,27 @@
chat: doux mais violent chat: doux mais violent
chat: doux mais violent violent violent violent violent
chat: mais violent chat: mais violent
chat: mais violent
chat: mais violenta
chat: mais violentu
chat: mais violenti
chat: mais violente
chat: mais violent,
chat: mais violentc
chat: mais violentt
chat: mais violents
chat: mais violentr
chat: mais violentn
chat: mais violentb
chat: mais violenté
chat: mais violentp
chat: mais violento
chat: mais violentè
chat: mais violent
chat: mais violentôv
chat: mais violentd
chat: mais violentl
chat: mais violentj
plante: assoiffée de calme plante: assoiffée de calme
président: affiné un mandat président: affiné un mandat
président: affiné pour un mandat président: affiné pour un mandat