context menu

This commit is contained in:
Adrien MALINGREY 2020-10-16 23:56:12 +02:00
parent a67a38c92f
commit 3f2e7b8fd7
3 changed files with 92 additions and 39 deletions

View File

@ -19,6 +19,7 @@ window.onload = function() {
if (!box.disabled) {
box.onfocus = onfocus
box.oninput = oninput
box.oncontextmenu = oncontextmenu
}
box.rowId = rowId
box.columnId = columnId
@ -37,16 +38,18 @@ window.onload = function() {
box.neighbourhood = Array.from(box.neighbourhood)
})
boxes.forEach(searchCandidatesOf)
boxes.forEach(showCandidatesOn)
enableButtons()
highlightAndTab()
if (/Win/.test(navigator.platform) || /Linux/.test(navigator.platform)) accessKeyModifiers = "Alt+Maj+"
else if (/Mac/.test(navigator.platform)) accessKeyModifiers = "⌃⌥ "
for(node of document.querySelectorAll("*[accesskey]")) {
node.title += " [" + (node.accessKeyLabel || accessKeyModifiers + "+" + node.accessKey) + "]"
node.title += " [" + (node.accessKeyLabel || accessKeyModifiers + node.accessKey) + "]"
}
document.body.onclick = function (event) {
contextMenu.style.display = "none"
}
suggestionTimer = setTimeout(showSuggestion, 30000)
}
@ -55,20 +58,6 @@ function searchCandidatesOf(box) {
box.neighbourhood.forEach(neighbour => box.candidates.delete(neighbour.value))
}
function showCandidatesOn(box) {
if (!box.disabled) {
while (box.list.firstChild) box.list.firstChild.remove()
if (!box.value && box.candidates.size) {
const candidatesArray = Array.from(box.candidates).sort()
candidatesArray.forEach(candidate => {
option = document.createElement('option')
option.value = candidate
box.list.appendChild(option)
})
}
}
}
function onfocus() {
this.previousValue = this.value
this.select()
@ -94,31 +83,30 @@ function refresh(box) {
box.neighbourhood.concat([box]).forEach(neighbour => {
searchCandidatesOf(neighbour)
showCandidatesOn(neighbour)
neighbour.setCustomValidity("")
neighbour.required = false
})
enableButtons()
highlightAndTab()
for (neighbour1 of box.neighbourhood) {
neighbour1.setCustomValidity("")
if (neighbour1.value.length) {
if (neighbour1.value) {
for (area of [
{name: "région", neighbours: regions[neighbour1.regionId]},
{name: "ligne", neighbours: rows[neighbour1.rowId]},
{name: "colonne", neighbours: columns[neighbour1.columnId]},
])
for (neighbour2 of area.neighbours)
if (neighbour2 != neighbour1 && neighbour2.value == neighbour1.value) {
for (neighbour of [neighbour1, neighbour2]) {
neighbour.setCustomValidity(`Il y a un autre ${neighbour.value} dans cette ${area.name}.`)
}
for (area of [
{name: "région", neighbours: regions[neighbour1.regionId]},
{name: "ligne", neighbours: rows[neighbour1.rowId]},
{name: "colonne", neighbours: columns[neighbour1.columnId]},
])
for (neighbour2 of area.neighbours)
if (neighbour2 != neighbour1 && neighbour2.value == neighbour1.value) {
for (neighbour of [neighbour1, neighbour2]) {
neighbour.setCustomValidity(`Il y a un autre ${neighbour.value} dans cette ${area.name}.`)
}
} else {
if (neighbour1.candidates.size == 0)
neighbour1.setCustomValidity("Aucun value possible !")
}
} else {
if (neighbour1.candidates.size == 0) {
neighbour1.setCustomValidity("Aucun chiffre possible !")
neighbour1.required = true
}
}
}
@ -131,7 +119,7 @@ function refresh(box) {
suggestionTimer = setTimeout(showSuggestion, SUGESTION_DELAY)
}
} else { // Errors on grid
box.reportValidity()
box.form.reportValidity()
box.select()
}
}
@ -216,7 +204,35 @@ function clearAll() {
box.placeholder = ""
})
boxes.forEach(searchCandidatesOf)
boxes.forEach(showCandidatesOn)
enableButtons()
highlightAndTab()
}
function oncontextmenu(event) {
event.preventDefault()
while (contextMenu.firstChild) contextMenu.firstChild.remove()
const box = event.target
if (box.value == "") {
if (box.candidates.size) {
candidatesArray = Array.from(box.candidates).sort().forEach(candidate => {
li = document.createElement("li")
li.innerText = candidate
li.onclick = function (event) {
contextMenu.style.display = "none"
box.value = event.target.innerText
refresh(box)
}
contextMenu.appendChild(li)
})
} else {
li = document.createElement("li")
li.innerText = "Aucun chiffre possible"
li.className = "error"
contextMenu.appendChild(li)
}
contextMenu.style.left = `${event.pageX}px`
contextMenu.style.top = `${event.pageY}px`
contextMenu.style.display = "block"
}
return false
}

View File

@ -12,7 +12,7 @@
<meta name='viewport' content='width=device-width' />
<title>Sudoku</title>
<link rel='stylesheet' type='text/css' href='style.css' />
<script src='sudoku.js'></script>
<script src='app.js'></script>
<link rel="icon" type="image/png" href="favicon.png">
</head>
<body>
@ -38,8 +38,8 @@
}
?>
<td>
<input type='number' min='1' max='9' step='1' value='<?=$value?>' list='<?=$row.$column?>' <?=$disabled?>/>
<datalist id='<?=$row.$column?>'></datalist>
<input type='number' min='1' max='9' step='1' value='<?=$value?>' list='list<?=$row.$column?>' title='[Clic-droit]' <?=$disabled?>/>
<datalist id='list<?=$row.$column?>'></datalist>
</td>
<?php
}
@ -67,6 +67,8 @@
<section>
Remplissez la grille de sorte que chaque ligne, colonne et région (carré de 3×3 cases) contienne tous les chiffres de 1 à 9.
</section>
<ul id="contextMenu" class="context-menu">
</ul>
<footer>
<a href=''>Lien vers cette grille</a><br/>
<a href='.'>Nouvelle grille</a>
@ -77,9 +79,9 @@
} else {
$grid = new Grid();
$grid->generate();
header("HTTP/1.0 400 Bad Request", true, 400);
$urlDir = $_SERVER["REQUEST_SCHEME"] . "://" . $_SERVER["HTTP_HOST"] . dirname($_SERVER["DOCUMENT_URI"]);
$urlExample = $urlDir . "/" . $grid->toString();
?>

View File

@ -143,3 +143,38 @@ input[type="color"] {
a {
text-decoration: none;
}
.context-menu {
display: none;
z-index: 1000;
position: absolute;
overflow: hidden;
border: 1px solid #CCC;
white-space: nowrap;
font-family: sans-serif;
background: #EEE;
color: #333;
border-radius: 3px;
padding: 0;
}
.context-menu li {
padding: 6px 10px;
cursor: default;
list-style-type: none;
transition: all .3s ease;
user-select: none;
font-size: 0.8em;
}
.context-menu li:hover {
background-color: #DEF;
}
.context-menu li.error {
color: #888
}
.context-menu li.error:hover {
background-color: #EEE;
}