save at will, not automatically
This commit is contained in:
		
							
								
								
									
										43
									
								
								img/save.svg
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										43
									
								
								img/save.svg
									
									
									
									
									
										Executable 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="Capa_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:#DCF4FF;" d="M512,492H0V20h403.213L512,128.787V492z"/> | ||||||
|  | <polygon style="fill:#CCEFFF;" points="403.213,20 256,20 256,492 512,492 512,128.787 "/> | ||||||
|  | <path style="fill:#0A4EAF;" d="M403.213,20H396v175H116V20H0v472h116V315c0-16.568,13.431-30,30-30h220c16.569,0,30,13.432,30,30 | ||||||
|  | 	v177h116V128.787L403.213,20z"/> | ||||||
|  | <g> | ||||||
|  | 	<rect x="296" y="20" style="fill:#063E8B;" width="40" height="115"/> | ||||||
|  | 	<path style="fill:#063E8B;" d="M403.213,20H396v175H256v90h110c16.569,0,30,13.432,30,30v177h116V128.787L403.213,20z"/> | ||||||
|  | </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> | ||||||
|  | </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 1.0 KiB | 
| @ -236,7 +236,7 @@ input[type="number"]::-webkit-calendar-picker-indicator { | |||||||
|     cursor: not-allowed; |     cursor: not-allowed; | ||||||
| } | } | ||||||
|  |  | ||||||
| .tools button.warning { | .tools button.warning:hover { | ||||||
|     background: #ff5050; |     background: #ff5050; | ||||||
|     border-color: #ff5050; |     border-color: #ff5050; | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										292
									
								
								style.css~
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										292
									
								
								style.css~
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,292 @@ | |||||||
|  | body { | ||||||
|  |     font-family: sans-serif; | ||||||
|  |     width: min-content; | ||||||
|  |     margin: auto; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | h1 { | ||||||
|  |     text-align: center; | ||||||
|  |     margin: 1rem; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | section, div, footer { | ||||||
|  |     align-items: center; | ||||||
|  |     align-items: center; | ||||||
|  |     justify-content: center; | ||||||
|  |     text-align: center; | ||||||
|  |     margin: 0.8rem 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | div { | ||||||
|  |     display: flex; | ||||||
|  |     flex-wrap: wrap; | ||||||
|  |     row-gap: 0.5rem; | ||||||
|  |     column-gap: 0.3rem; | ||||||
|  |     margin: 0.5rem auto; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | .grid { | ||||||
|  |     border-spacing: 0; | ||||||
|  |     border: 1px solid black; | ||||||
|  |     border-radius: 6px; | ||||||
|  |     margin: auto; | ||||||
|  |     cursor: url(img/ink-pen.svg) 2 22, text; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid td, tr { | ||||||
|  |     padding: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid tr:first-child td:first-child { | ||||||
|  |     border-top-left-radius: 5px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid tr:first-child td:first-child input { | ||||||
|  |     border-top-left-radius: 4px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid tr:first-child td:last-child { | ||||||
|  |     border-top-right-radius: 5px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid tr:first-child td:last-child input { | ||||||
|  |     border-top-right-radius: 4px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid tr:last-child td:first-child { | ||||||
|  |     border-bottom-left-radius: 5px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid tr:last-child td:first-child > input { | ||||||
|  |     border-bottom-left-radius: 4px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid tr:last-child td:last-child { | ||||||
|  |     border-bottom-right-radius: 5px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid tr:last-child td:last-child input { | ||||||
|  |     border-bottom-right-radius: 4px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid tr:nth-child(3n+1) td { | ||||||
|  |     border-top: 1px solid black; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid tr:nth-child(3n+2) td { | ||||||
|  |     border-top: 1px solid grey; | ||||||
|  |     border-bottom: 1px solid grey; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid tr:nth-child(3n) td { | ||||||
|  |     border-bottom: 1px solid black; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid td:nth-child(3n+1) { | ||||||
|  |     border-left: 1px solid black; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid td:nth-child(3n+2) { | ||||||
|  |     border-left: 1px solid grey; | ||||||
|  |     border-right: 1px solid grey; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid td:nth-child(3n+3) { | ||||||
|  |     border-right: 1px solid black; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | .grid input { | ||||||
|  |     width: 2.5rem; | ||||||
|  |     height: 2.5rem; | ||||||
|  |     font-size: 1.5rem; | ||||||
|  |     border: 0; | ||||||
|  |     border-radius: 0; | ||||||
|  |     padding: 0; | ||||||
|  |     text-align: center; | ||||||
|  |     transition: background 0.5s; | ||||||
|  |     -moz-appearance: textfield; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | input[type="number"]::-webkit-outer-spin-button, | ||||||
|  | input::-webkit-inner-spin-button { | ||||||
|  |     -webkit-appearance: none; | ||||||
|  |     margin: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | input[type="number"]::-webkit-calendar-picker-indicator { | ||||||
|  |     display: none; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid input:enabled { | ||||||
|  |     background: white; | ||||||
|  |     color: darkblue; | ||||||
|  |     cursor: inherit; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid input.pencil, | ||||||
|  | .grid input::placeholder { | ||||||
|  |     color: #666 !important; | ||||||
|  |     font-size: 0.9rem !important; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid input:disabled { | ||||||
|  |     color: white !important; | ||||||
|  |     background: #6666ff !important; | ||||||
|  |     cursor: not-allowed !important; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid input.forbidden:enabled { | ||||||
|  |     background: #ffffaa !important; | ||||||
|  |     cursor: not-allowed; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid input.same-value:enabled { | ||||||
|  |     background: #ffff33; | ||||||
|  |     cursor: not-allowed !important; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid input.forbidden:disabled { | ||||||
|  |     color: #ffffaa; | ||||||
|  |     background: #6666ff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid input.same-value:disabled, | ||||||
|  | .tools button.same-value:enabled, | ||||||
|  | .tools input:enabled:checked + label { | ||||||
|  |     color: #ffffaa !important; | ||||||
|  |     background: #00b359 !important; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .grid input.one-candidate { | ||||||
|  |     cursor: help !important; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | .tools button, | ||||||
|  | .tools input + label { | ||||||
|  |     color: white; | ||||||
|  |     text-shadow: -1px -1px #5b6c9e; | ||||||
|  |     background: #8ca6f2; | ||||||
|  |     border: 2px outset #8ca6f2; | ||||||
|  |     border-radius: 4px; | ||||||
|  |     font-size: 1.3rem; | ||||||
|  |     min-width:20px; | ||||||
|  |     padding: 4px 5px 5px 5px; | ||||||
|  |     margin:  0px 1px 1px 1px; | ||||||
|  |     cursor: pointer; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .tools img { | ||||||
|  |     display: block; | ||||||
|  |     width: 24px; | ||||||
|  |     height: 24px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .tools input { | ||||||
|  |     position: fixed; | ||||||
|  |     opacity: 0; | ||||||
|  |     width: 0; | ||||||
|  |     pointer-events: none; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .tools button:enabled:hover, | ||||||
|  | .tools button:enabled:focus, | ||||||
|  | .tools input:enabled:hover + label, | ||||||
|  | .tools input:enabled:focus + label { | ||||||
|  |     border-width: 1px; | ||||||
|  |     border-style: outset; | ||||||
|  |     padding: 5px 5px 5px 6px; | ||||||
|  |     margin:  1px 1px 1px 2px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .tools input:enabled:checked:hover + label, | ||||||
|  | .tools input:enabled:checked:focus + label { | ||||||
|  |     border-width: 3px; | ||||||
|  |     border-style: inset; | ||||||
|  |     padding: 4px 2px 2px 5px; | ||||||
|  |     margin:  1px 1px 1px 2px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .tools input:enabled:checked + label { | ||||||
|  |     text-shadow: -1px -1px #005f2f; | ||||||
|  |     border: 2px inset #00b359; | ||||||
|  |     background: #00b359; | ||||||
|  |     padding: 4px 4px 4px 5px; | ||||||
|  |     margin:  1px 1px 0px 2px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .tools button:enabled:active, | ||||||
|  | .tools input:enabled:active + label { | ||||||
|  |     border-width: 4px !important; | ||||||
|  |     border-style: inset !important; | ||||||
|  |     padding: 4px 0px 0px 5px !important; | ||||||
|  |     margin:  0px 1px 0px 2px !important; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .tools button:disabled, | ||||||
|  | .tools input:disabled + label { | ||||||
|  |     text-shadow: -1px -1px #555; | ||||||
|  |     color: #ccc; | ||||||
|  |     background: darkgrey; | ||||||
|  |     border: 1px outset darkgrey; | ||||||
|  |     padding: 5px 6px 6px 6px; | ||||||
|  |     margin:  0px 1px 1px 1px; | ||||||
|  |     cursor: not-allowed; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .tools button.warning { | ||||||
|  |     background: #ff5050; | ||||||
|  |     border-color: #ff5050; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | .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-top-right-radius: 3px; | ||||||
|  |     border-bottom-left-radius: 3px; | ||||||
|  |     border-bottom-right-radius: 3px; | ||||||
|  |     padding: 0; | ||||||
|  |     margin: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .context-menu li { | ||||||
|  |     padding: 6px 10px; | ||||||
|  |     cursor: default; | ||||||
|  |     list-style-type: none; | ||||||
|  |     transition: all .3s ease; | ||||||
|  |     font-size: 1rem; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .context-menu li:hover { | ||||||
|  |     background-color: #DEF; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .context-menu li.error { | ||||||
|  |     color: #888 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .context-menu li.error:hover { | ||||||
|  |     background-color: #EEE; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | a { | ||||||
|  |     text-decoration: none; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | .credits { | ||||||
|  |     font-size: 0.8rem; | ||||||
|  |     margin: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										24
									
								
								sudoku.js
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								sudoku.js
									
									
									
									
									
								
							| @ -10,6 +10,7 @@ let suggestionTimer = null | |||||||
| let valueToInsert = "" | let valueToInsert = "" | ||||||
| let history = [] | let history = [] | ||||||
| let accessKeyModifiers = "AccessKey+" | let accessKeyModifiers = "AccessKey+" | ||||||
|  | let changesToSave = false | ||||||
|  |  | ||||||
| function shuffle(iterable) { | function shuffle(iterable) { | ||||||
|     array = Array.from(iterable) |     array = Array.from(iterable) | ||||||
| @ -142,6 +143,7 @@ function onclick() { | |||||||
| function oninput() { | function oninput() { | ||||||
|     history.push({ box: this, value: this.previousValue, placeholder: this.previousPlaceholder }) |     history.push({ box: this, value: this.previousValue, placeholder: this.previousPlaceholder }) | ||||||
|     undoButton.disabled = false |     undoButton.disabled = false | ||||||
|  |     changesToSave = true | ||||||
|     if (pencilRadio.checked) { |     if (pencilRadio.checked) { | ||||||
|         this.value = Array.from(new Set(this.value)).sort().join("") |         this.value = Array.from(new Set(this.value)).sort().join("") | ||||||
|         this.previousValue = "" |         this.previousValue = "" | ||||||
| @ -157,17 +159,10 @@ function oninput() { | |||||||
| } | } | ||||||
|  |  | ||||||
| function refreshBox(box) { | function refreshBox(box) { | ||||||
|     saveGame() |  | ||||||
|     checkBox(box) |     checkBox(box) | ||||||
|     refreshUI() |     refreshUI() | ||||||
| } | } | ||||||
|  |  | ||||||
| function saveGame() { |  | ||||||
|     let saveGame = boxes.map(box => box.value || UNKNOWN).join("") |  | ||||||
|     localStorage[location.pathname] = saveGame |  | ||||||
|     fixGridLink.href = saveGame |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function checkBox(box) { | function checkBox(box) { | ||||||
|     box.neighbourhood.concat([box]).forEach(neighbour => { |     box.neighbourhood.concat([box]).forEach(neighbour => { | ||||||
|         searchCandidatesOf(neighbour) |         searchCandidatesOf(neighbour) | ||||||
| @ -200,6 +195,7 @@ function checkBox(box) { | |||||||
|     } else { // Errors on grid |     } else { // Errors on grid | ||||||
|         box.form.reportValidity() |         box.form.reportValidity() | ||||||
|     } |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| function refreshUI() { | function refreshUI() { | ||||||
|     enableRadio() |     enableRadio() | ||||||
| @ -316,6 +312,20 @@ function restart() { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | function save() { | ||||||
|  |     let saveGame = boxes.map(box => box.value || UNKNOWN).join("") | ||||||
|  |     localStorage[location.pathname] = saveGame | ||||||
|  |     fixGridLink.href = saveGame | ||||||
|  |     changesToSave = false | ||||||
|  | } | ||||||
|  |  | ||||||
|  | window.onbeforeunload = function(event) { | ||||||
|  |     if (changesToSave) { | ||||||
|  |         event.preventDefault() | ||||||
|  |         event.returnValue = "" | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| function showSuggestion() { | function showSuggestion() { | ||||||
|     const easyBoxes = boxes.filter(box => box.value == "" && box.candidates.size == 1) |     const easyBoxes = boxes.filter(box => box.value == "" && box.candidates.size == 1) | ||||||
|     if (easyBoxes.length) { |     if (easyBoxes.length) { | ||||||
|  | |||||||
| @ -101,6 +101,7 @@ | |||||||
|                 <input type='radio' id='eraserRadio' name='tool' onclick='grid.style.cursor = "url(img/eraser.svg) 2 22, auto"'/><label for='eraserRadio' title='Effacer une case'><img src='img/eraser.svg' alt='Gomme'/></label> |                 <input type='radio' id='eraserRadio' name='tool' onclick='grid.style.cursor = "url(img/eraser.svg) 2 22, auto"'/><label for='eraserRadio' title='Effacer une case'><img src='img/eraser.svg' alt='Gomme'/></label> | ||||||
|                 <button type='button' class='warning' onclick='restart()' title='Recommencer'><img src='img/restart.svg' alt='Recommencer'/></button> |                 <button type='button' class='warning' onclick='restart()' title='Recommencer'><img src='img/restart.svg' alt='Recommencer'/></button> | ||||||
|                 <button id='undoButton' type='button' onclick='undo()' disabled title='Annuler' accesskey='z'><img src='img/undo.svg' alt='Annuler'/></button> |                 <button id='undoButton' type='button' onclick='undo()' disabled title='Annuler' accesskey='z'><img src='img/undo.svg' alt='Annuler'/></button> | ||||||
|  |                 <button id='undoButton' type='button' onclick='save()' title='Sauvegarder' accesskey='s'><img src='img/save.svg' alt='Disquette'/></button> | ||||||
|             </div> |             </div> | ||||||
|         </section> |         </section> | ||||||
|         <section> |         <section> | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user