write values on click, choose highlighting, svg icons

This commit is contained in:
Adrien MALINGREY 2020-11-09 01:24:09 +01:00
parent d5655b7a9a
commit ef758fac04
14 changed files with 299 additions and 27 deletions

69
app.js
View File

@ -1,4 +1,5 @@
const VALUES = "123456789" const VALUES = "123456789"
const UNKNOWN = '.'
const SUGESTION_DELAY = 60000 //ms const SUGESTION_DELAY = 60000 //ms
let boxes = [] let boxes = []
@ -6,10 +7,11 @@ let rows = Array.from(Array(9), x => [])
let columns = Array.from(Array(9), x => []) let columns = Array.from(Array(9), x => [])
let regions = Array.from(Array(9), x => []) let regions = Array.from(Array(9), x => [])
let suggestionTimer= null let suggestionTimer= null
let highlightedValue = "" let selectedValue = ""
let history = [] let history = []
let accessKeyModifiers = "AccessKey+" let accessKeyModifiers = "AccessKey+"
let penStyle = "ink-pen" let penStyle = "ink-pen"
let highlighting = false
window.onload = function() { window.onload = function() {
let rowId = 0 let rowId = 0
@ -21,6 +23,8 @@ window.onload = function() {
box.onfocus = onfocus box.onfocus = onfocus
box.oninput = oninput box.oninput = oninput
box.onblur = onblur box.onblur = onblur
box.onclick = onclick
box.previousPlaceholder = ""
} }
box.oncontextmenu = oncontextmenu box.oncontextmenu = oncontextmenu
box.rowId = rowId box.rowId = rowId
@ -38,7 +42,10 @@ window.onload = function() {
let savedGame = localStorage[location.href] let savedGame = localStorage[location.href]
if (savedGame) { if (savedGame) {
boxes.forEach((box, i) => { boxes.forEach((box, i) => {
if (!box.disabled && savedGame[i] != '.') box.value = savedGame[i] if (!box.disabled && savedGame[i] != UNKNOWN) {
box.value = savedGame[i]
box.previousValue = savedGame[i]
}
}) })
} }
@ -49,19 +56,19 @@ window.onload = function() {
searchCandidatesOf(box) searchCandidatesOf(box)
}) })
enableButtons()
highlightAndTab()
if (/Win/.test(navigator.platform) || /Linux/.test(navigator.platform)) accessKeyModifiers = "Alt+Maj+" if (/Win/.test(navigator.platform) || /Linux/.test(navigator.platform)) accessKeyModifiers = "Alt+Maj+"
else if (/Mac/.test(navigator.platform)) accessKeyModifiers = "⌃⌥" else if (/Mac/.test(navigator.platform)) accessKeyModifiers = "⌃⌥"
for(node of document.querySelectorAll("*[accesskey]")) { for(node of document.querySelectorAll("*[accesskey]")) {
node.title += " [" + (node.accessKeyLabel || accessKeyModifiers + node.accessKey) + "]" node.title += " [" + (node.accessKeyLabel || accessKeyModifiers + node.accessKey) + "]"
} }
enableButtons()
highlightAndTab()
document.onclick = function (event) { document.onclick = function (event) {
contextMenu.style.display = "none" contextMenu.style.display = "none"
} }
suggestionTimer = setTimeout(showSuggestion, 30000) suggestionTimer = setTimeout(showSuggestion, SUGESTION_DELAY)
if ("serviceWorker" in navigator) { if ("serviceWorker" in navigator) {
navigator.serviceWorker.register("service-worker.js") navigator.serviceWorker.register("service-worker.js")
@ -85,6 +92,18 @@ function searchCandidatesOf(box) {
} }
} }
function onclick() {
if (selectedValue) {
if (penStyle == "ink-pen") {
this.value = selectedValue
} else {
if (!this.value.includes(selectedValue))
this.value += selectedValue
}
oninput.apply(this)
}
}
function onfocus() { function onfocus() {
if (penStyle == "pencil" && this.value == "") { if (penStyle == "pencil" && this.value == "") {
this.value = this.placeholder this.value = this.placeholder
@ -96,7 +115,9 @@ function onfocus() {
} }
function oninput() { function oninput() {
history.push({box: this, value: this.previousValue || "", placeholder: this.previousPlaceholder || ""}) history.push({box: this, value: this.previousValue, placeholder: this.previousPlaceholder})
this.previousValue = this.value
this.previousPlaceholder = this.placeholder
undoButton.disabled = false undoButton.disabled = false
if (penStyle != "pencil") { if (penStyle != "pencil") {
refresh(this) refresh(this)
@ -165,29 +186,33 @@ function onblur() {
this.value = "" this.value = ""
this.classList.remove("pencil") this.classList.remove("pencil")
} }
this.previousValue = this.value
this.previousPlaceholder = this.placeholder
} }
function enableButtons() { function enableButtons() {
for (button of buttons.getElementsByTagName("button")) { for (button of buttons.getElementsByTagName("button")) {
if (boxes.filter(box => box.value == "").some(box => box.candidates.has(button.textContent))) { if (boxes.filter(box => box.value == "").some(box => box.candidates.has(button.textContent))) {
button.disabled = false button.disabled = false
if (button.previousTitle) {
button.title = button.previousTitle
button.previousTitle = null
}
} else { } else {
button.disabled = true button.disabled = true
if (highlightedValue == button.textContent) highlightedValue = "" button.previousTitle = button.title
button.title = "Tous les " + button.textContent + " sont posés"
if (selectedValue == button.textContent) selectedValue = ""
} }
} }
} }
function highlight(value) { function highlight(value) {
if (value == highlightedValue) { if (value == selectedValue) {
highlightedValue = "" selectedValue = ""
} else { } else {
highlightedValue = value selectedValue = value
} }
for (button of buttons.getElementsByTagName("button")) { for (button of buttons.getElementsByTagName("button")) {
if (button.textContent == highlightedValue) button.classList.add("pressed") if (button.textContent == selectedValue) button.classList.add("pressed")
else button.classList.remove("pressed") else button.classList.remove("pressed")
} }
highlightAndTab() highlightAndTab()
@ -195,15 +220,15 @@ function highlight(value) {
} }
function highlightAndTab() { function highlightAndTab() {
if (highlightedValue) { if (highlighting && selectedValue) {
boxes.forEach(box => { boxes.forEach(box => {
if (box.value == highlightedValue) { if (box.value == selectedValue) {
box.classList.add("same-value") box.classList.add("same-value")
box.tabIndex = -1 box.tabIndex = -1
} }
else { else {
box.classList.remove("same-value") box.classList.remove("same-value")
if (box.candidates.has(highlightedValue)) { if (box.candidates.has(selectedValue)) {
box.classList.remove("forbidden-value") box.classList.remove("forbidden-value")
box.tabIndex = 0 box.tabIndex = 0
} else { } else {
@ -319,3 +344,13 @@ function eraseAll() {
highlightAndTab() highlightAndTab()
} }
} }
function toggleHighlighting() {
highlighting = !highlighting
if (highlighting) {
highlighterButton.classList.add("pressed")
} else {
highlighterButton.classList.remove("pressed")
}
highlightAndTab()
}

44
img/highlighter.svg Normal file
View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<polygon style="fill:#FFCC75;" points="47.202,417.53 94.404,464.732 47.202,511.945 0,464.743 "/>
<polygon style="fill:#082947;" points="236.149,414.811 212.545,438.4 111.564,368.892 166.634,313.823 "/>
<polygon style="fill:#274B6D;" points="182.37,329.559 127.301,384.628 73.529,299.384 97.126,275.788 "/>
<polygon style="fill:#FF9D49;" points="512,118.078 452.926,59.003 294.044,186.413 166.634,345.296 251.886,430.548 "/>
<path style="fill:#274B6D;" d="M143.037,368.892l69.508,69.508c0,0-61.136,0.802-102.397,42.063l-39.35-39.333l20.383-51.855
L143.037,368.892z"/>
<polygon style="fill:#FFCC75;" points="393.977,0.055 81.39,260.051 166.634,345.296 452.926,59.003 "/>
<path style="fill:#185F8D;" d="M73.529,299.384l69.508,69.508l-72.239,72.239L31.458,401.79
C72.719,360.529,73.529,299.384,73.529,299.384z"/>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

43
img/ink-eraser.svg Normal file
View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<path style="fill:#E06B34;" d="M497.559,163.289L368.481,34.211c-19.253-19.253-50.47-19.253-69.723,0L14.44,318.529
c-19.253,19.253-19.253,50.47,0,69.723l103.975,103.975h119.928l259.216-259.216C516.813,213.759,516.813,182.542,497.559,163.289z"
/>
<path style="fill:#D1393C;;" d="M497.56,163.289L433.021,98.75L78.979,452.792l39.436,39.436h119.928l259.216-259.216
C516.813,213.759,516.813,182.542,497.56,163.289z"/>
<path style="fill:#A8EAEF;" d="M14.44,318.529c-19.253,19.253-19.253,50.47,0,69.723l103.975,103.975h119.928L355.4,375.171
L156.599,176.37L14.44,318.529z"/>
<polygon style="fill:#80CDD8" points="78.979,452.792 118.415,492.229 238.343,492.229 355.4,375.171 255.999,275.771 "/>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

48
img/ink-pen.svg Normal file
View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 511.989 511.989" style="enable-background:new 0 0 511.989 511.989;" xml:space="preserve">
<rect x="408.399" y="26.854" transform="matrix(-0.7071 0.7071 -0.7071 -0.7071 819.7593 -231.0359)" style="fill:#9EC8E8;" width="98.659" height="54.811"/>
<polygon style="fill:#082947;" points="430.604,174.402 186.029,418.976 124.017,372.468 376.343,120.141 "/>
<polygon style="fill:#274B6D;" points="384.094,127.892 131.769,380.219 93.012,325.958 337.586,81.384 "/>
<polygon style="fill:#4284B2;" points="477.112,127.892 430.604,174.402 376.343,120.141 430.604,81.384 "/>
<rect x="20.377" y="439.543" transform="matrix(-0.7071 -0.7071 0.7071 -0.7071 -273.1405 837.2019)" style="fill:#082947;" width="32.886" height="71.254"/>
<polygon style="fill:#4284B2;" points="186.029,418.976 69.757,488.74 46.502,465.484 77.509,403.473 139.52,372.468 "/>
<g>
<polygon style="fill:#6DA8D6;" points="139.52,372.468 46.502,465.484 23.248,442.23 93.012,325.958 "/>
<rect x="351.209" y="48.511" transform="matrix(-0.7071 0.7071 -0.7071 -0.7071 713.2485 -132.6418)" style="fill:#6DA8D6;" width="65.773" height="65.773"/>
</g>
<polygon style="fill:#9EC8E8;" points="178.681,193.781 155.426,170.527 302.704,23.249 442.229,162.774 418.975,186.028
302.704,69.757 "/>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

43
img/pencil-eraser.svg Normal file
View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<path style="fill:#A8EAEF;" d="M497.559,163.289L368.481,34.211c-19.253-19.253-50.47-19.253-69.723,0L14.44,318.529
c-19.253,19.253-19.253,50.47,0,69.723l103.975,103.975h119.928l259.216-259.216C516.813,213.759,516.813,182.542,497.559,163.289z"
/>
<path style="fill:#80CDD8;" d="M497.56,163.289L433.021,98.75L78.979,452.792l39.436,39.436h119.928l259.216-259.216
C516.813,213.759,516.813,182.542,497.56,163.289z"/>
<path style="fill:#E06B34;" d="M14.44,318.529c-19.253,19.253-19.253,50.47,0,69.723l103.975,103.975h119.928L355.4,375.171
L156.599,176.37L14.44,318.529z"/>
<polygon style="fill:#D1393C;" points="78.979,452.792 118.415,492.229 238.343,492.229 355.4,375.171 255.999,275.771 "/>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

45
img/pencil.svg Normal file
View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<polygon style="fill:#FF9D49;" points="393.29,213.665 142.441,464.524 87.044,424.954 345.817,150.364 "/>
<polygon style="fill:#FFCC75;" points="353.73,158.277 87.044,424.954 47.473,369.557 298.333,118.708 "/>
<polygon style="fill:#BD1515;" points="512,94.965 440.78,166.185 377.475,118.708 464.522,47.486 "/>
<polygon style="fill:#F2484B;" points="464.516,47.482 385.382,126.615 345.817,71.224 417.038,0.002 "/>
<g>
<rect x="335.974" y="75.292" transform="matrix(-0.7071 0.7071 -0.7071 -0.7071 731.5841 -18.1559)" style="fill:#082947;" width="67.157" height="134.292"/>
<polygon style="fill:#082947;" points="71.22,488.261 0,511.998 23.736,440.776 63.305,448.692 "/>
</g>
<polygon style="fill:#F2EBD9;" points="47.473,369.557 23.736,440.776 71.22,488.261 142.441,464.524 "/>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

1
img/undo.svg Normal file
View File

@ -0,0 +1 @@
<svg height="511pt" viewBox="1 -55 511.99899 511" width="511pt" xmlns="http://www.w3.org/2000/svg"><path d="m349.703125 77.675781h-225.726563v-77.175781l-123.976562 123.980469 123.976562 123.976562v-79.765625h225.726563c39.304687 0 71.28125 31.976563 71.28125 71.277344 0 39.304688-31.976563 71.28125-71.28125 71.28125h-257.425781v91.015625h257.425781c89.492187 0 162.296875-72.804687 162.296875-162.296875 0-89.488281-72.804688-162.292969-162.296875-162.292969zm0 0" fill="#fb4c2e"/><path d="m349.703125 77.675781h-84.410156v91.015625h84.410156c39.304687 0 71.28125 31.976563 71.28125 71.277344 0 39.304688-31.976563 71.28125-71.28125 71.28125h-84.410156v91.015625h84.410156c89.492187 0 162.296875-72.804687 162.296875-162.296875 0-89.488281-72.804688-162.292969-162.296875-162.292969zm0 0" fill="#de1617"/></svg>

After

Width:  |  Height:  |  Size: 814 B

View File

@ -121,7 +121,7 @@ input::-webkit-calendar-picker-indicator {
height: 2.5rem !important; height: 2.5rem !important;
} }
.highlight-buttons { .select-buttons {
column-gap: 2px; column-gap: 2px;
} }
button, input[type="color"] { button, input[type="color"] {
@ -131,6 +131,10 @@ button, input[type="color"] {
padding: 4px 9px 5px 9px; padding: 4px 9px 5px 9px;
margin: 0px 1px 1px 1px; margin: 0px 1px 1px 1px;
} }
button img {
width: 16px;
height: 16px;
}
button:enabled:hover { button:enabled:hover {
border-width: 1px; border-width: 1px;
border-style: outset; border-style: outset;
@ -211,3 +215,8 @@ a {
.context-menu li.error:hover { .context-menu li.error:hover {
background-color: #EEE; background-color: #EEE;
} }
.credits {
font-size: 0.8rem;
margin: 0;
}

View File

@ -68,28 +68,31 @@
</tbody> </tbody>
</table> </table>
</div> </div>
<div id='buttons' class='highlight-buttons'> <div id='buttons' class='select-buttons'>
<?php <?php
for($value=1; $value<=9; $value++) { for($value=1; $value<=9; $value++) {
echo " <button type='button' onclick='highlight(\"$value\")' title='Surligner les $value' accesskey='$value'>$value</button>\n"; echo " <button type='button' onclick='highlight(\"$value\")' title='Écrire un $value' accesskey='$value'>$value</button>\n";
} }
?> ?>
</div> </div>
<div> <div>
<button id='inkPenButton' type='button' onclick='useInkPen()' title='Stylo' class='pressed'> <button id='highlighterButton' type='button' onclick='toggleHighlighting()' title='Surligner les chiffres sélectionnés'>
<img src="img/ink-pen.png" alt='Stylo' width=16 height=16/> <img src="img/highlighter.svg" alt='Surligneur'/>
</button> </button>
<button id='pencilButton' type='button' onclick='usePencil()' title='Crayon'> <button id='inkPenButton' type='button' onclick='useInkPen()' title='Écrire au stylo' class='pressed'>
<img src="img/pencil.png" alt='Crayon' width=16 height=16/> <img src="img/ink-pen.svg" alt='Stylo'/>
</button>
<button id='pencilButton' type='button' onclick='usePencil()' title='Écrire au crayon'>
<img src="img/pencil.svg" alt='Crayon'/>
</button> </button>
<button type='button' onclick='erasePencil()' title='Effacer le crayon'> <button type='button' onclick='erasePencil()' title='Effacer le crayon'>
<img src="img/pencil-eraser.png" alt="Gomme blanche" width=16 height=16/> <img src="img/pencil-eraser.svg" alt="Gomme blanche"/>
</button> </button>
<button class="warning" type='button' onclick='eraseAll()' title='Effacer tout'> <button class="warning" type='button' onclick='eraseAll()' title='Effacer tout'>
<img src="img/ink-eraser.png" alt="Gomme bleue" width=16 height=16/> <img src="img/ink-eraser.svg" alt="Gomme bleue"/>
</button> </button>
<button id='undoButton' type='button' onclick='undo()' disabled title='Annuler' accesskey='z'> <button id='undoButton' type='button' onclick='undo()' disabled title='Annuler' accesskey='z'>
<img src="img/undo.png" alt="Annuler" width=16 height=16/> <img src="img/undo.svg" alt="Annuler"/>
</button> </button>
</div> </div>
</form> </form>
@ -98,6 +101,7 @@
<footer> <footer>
<a href=''>Lien vers cette grille</a><br/> <a href=''>Lien vers cette grille</a><br/>
<a href='.'>Nouvelle grille</a> <a href='.'>Nouvelle grille</a>
<div class="credits">Icons made by <a href="https://www.flaticon.com/authors/freepik" title="Freepik">Freepik</a> from <a href="https://www.flaticon.com/" title="Flaticon">www.flaticon.com</a></div>
</footer> </footer>
</body> </body>
</html> </html>