bootstrap css

This commit is contained in:
Adrien MALINGREY 2023-03-29 23:28:48 +02:00
parent 573608b63c
commit fa970170d4
28 changed files with 2270 additions and 24039 deletions

View File

@ -85,49 +85,6 @@
array_unset_value($box->value, $neighbour->candidates);
}
}
function generate_() {
// Init with a shuffle row
$values = array("1", "2", "3", "4", "5", "6", "7", "8", "9");
shuffle($values);
forEach($this->rows[0] as $columnId => $box) {
$box->value = $values[$columnId];
forEach($box->neighbourhood as $neighbour)
array_unset_value($box->value, $neighbour->candidates);
}
// Fill grid
$this->solutionsGenerator(true)->current();
// Remove clues while there is still a unique solution
shuffle($this->boxes);
$nbClues = count($this->boxes);
foreach($this->boxes as $testBox) {
$testBoxes = array($testBox);
if ($nbClues >= 30)
$testBoxes[] = $this->rows[8-$testBox->rowId][8-$testBox->columnId];
if ($nbClues >= 61) {
$testBoxes[] = $this->rows[8-$testBox->rowId][$testBox->columnId];
$testBoxes[] = $this->rows[$testBox->rowId][8-$testBox->columnId];
}
$testBoxes = array_filter($testBoxes, "isKnown");
$erasedValues = array();
forEach($testBoxes as $testBox) {
$erasedValues[] = $testBox->value;
$testBox->value = UNKNOWN;
forEach($testBox->neighbourhood as $neighbour)
$neighbour->searchCandidates();
}
if ($this->isValid()) {
$nbClues -= count($testBoxes);
} else {
forEach($testBoxes as $i => $testBox) {
$testBox->value = $erasedValues[$i];
forEach($testBox->neighbourhood as $neighbour) array_unset_value($testBox->value, $neighbour->candidates);
}
}
}
$validGrids[] = $this->toString();
}
function generate() {
// Init with a shuffle row

11
css/bootstrap-dark.min.css vendored Normal file

File diff suppressed because one or more lines are too long

2018
css/bootstrap-icons.css vendored Normal file

File diff suppressed because it is too large Load Diff

10
css/bootstrap-night.min.css vendored Normal file

File diff suppressed because one or more lines are too long

6
css/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

135
css/style.css Normal file
View File

@ -0,0 +1,135 @@
body {
width: min-content;
margin: auto;
}
input[type="number"]::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none !important;
margin: 0 !important;
}
input[type="number"]::-webkit-calendar-picker-indicator {
display: none !important;
}
table {
border-collapse: separate;
border-spacing: 0;
}
table input {
width: 2.5rem !important;
height: 2.5rem !important;
font-size: 1.3rem !important;
padding: 0 !important;
margin: 0 !important;
text-align: center;
-moz-appearance: textfield !important;
border-radius: 0 !important;
}
table td.table-primary input,
table td.table-active input,
table input:not([disabled]) {
background: transparent !important;
}
tr:nth-child(3n+1) td input {
border-top-width: 3px !important;
}
tr:last-child td input {
border-bottom-width: 3px !important;
}
td:nth-child(3n+1) input {
border-left-width: 3px !important;
}
td:last-child input {
border-right-width: 3px !important;
}
tr:first-child td:first-child {
border-top-left-radius: .7rem !important;
}
tr:first-child td:first-child input {
border-top-left-radius: .5rem !important;
}
tr:first-child td:last-child {
border-top-right-radius: .7rem !important;
}
tr:first-child td:last-child input {
border-top-right-radius: .5rem !important;
}
tr:last-child td:first-child {
border-bottom-left-radius: .7rem !important;
}
tr:last-child td:first-child input {
border-bottom-left-radius: .5rem !important;
}
tr:last-child td:last-child {
border-bottom-right-radius: .7rem !important;
}
tr:last-child td:last-child input {
border-bottom-right-radius: .5rem !important;
}
td {
padding: 0 !important;
margin: 0 !important;
transition: background-color .4s, box-shadow .4s !important;
border: 0 !important;
}
.context-menu li {
cursor: default;
}
.table-active {
cursor: not-allowed !important;
}
table {
cursor: text;
}
button,
label {
cursor: pointer;
}
button:disabled,
:disabled+label {
cursor: not-allowed !important;
}
table input:enabled {
cursor: inherit;
}
.modal-content {
z-index: 1000;
}
.bi::before {
vertical-align: 0;
}
.pencil {
color: var(--bs-secondary-color) !important;
}
@media (prefers-color-scheme:dark) {
.pencil {
color: #5a5a5a !important;
}
}

View File

@ -1,103 +0,0 @@
body {
/* Background pattern from Toptal Subtle Patterns */
background: url("handmadepaper.png");
text-align: center;
}
h1 {
text-align: center;
text-shadow: 1px 1px grey;
text-decoration: underline;
}
table {
border-spacing: 0;
border-collapse: collapse;
margin: auto;
}
div {
display: flex;
column-gap: 0.5em;
row-gap: 0.5em;
margin: 1em auto;
justify-content: center;
}
input[type="radio"] {
margin-top: -1px;
vertical-align: middle;
}
label.disabled {
color: #aaa;
}
.grid td {
border: 2px solid black;
padding: 0;
}
.region td {
border: 1px solid grey;
}
.grid input {
width: 1.6em;
height: 1.6em;
font-size: 1.5em;
border: 0;
padding: 0;
text-align: center;
}
.grid input:enabled {
font-family: cursive;
color: darkblue;
}
.grid input:disabled {
color: black;
font-weight: bold;
}
.grid input::placeholder {
color: #888;
}
.unhighlighted:enabled {
background: transparent;
}
.highlighted {
background: yellow;
}
#shareDiv {
display: block;
line-height: 80%;
}
#shareA {
text-decoration: none;
font-size: 0.8em;
letter-spacing: 0.5em;
}
#highlightRadiosDiv {
column-gap: 0;
}
input[type="number"] {
-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;
}

View File

@ -1,304 +0,0 @@
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: default;
}
.grid input.forbidden:enabled {
background: #f9f99f;
cursor: not-allowed;
}
.grid input.same-value:enabled {
background: #ffff33;
cursor: not-allowed !important;
}
.grid input.forbidden:disabled {
color: #f9f99f;
background: #6666ff;
cursor: not-allowed;
}
.grid input.same-value:disabled,
.tools button.same-value:enabled,
.tools input:enabled:checked+label {
color: #f9f99f !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:disabled * {
filter: grayscale(100%);
opacity: 0.7;
}
.tools button.warning:hover {
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;
}
@media (prefers-color-scheme: dark) {
body {
color: #eee;
background: #121212;
}
body a {
color: #809fff;
}
}

View File

@ -1,314 +0,0 @@
:root {
--body-bc: #e8ffff;
--body-fc: black;
--shadow: lightgray;
--border-color: #555b6e;
--box-bc: #F7FFF7;
--box-fc: black;
--forbidden-box-bc: #FFEE99;
--same-value-box-bc: #ffbc25;
--placeholder-fc: var(--grid-color);
--clue-bc: #60D2CB;
--forbidden-clue-bc: var(--clue-bc);
--same-value-clue-bc: #24737F;
--clue-fc: var(--box-bc);
--forbidden-clue-fc: var(--forbidden-box-bc);
--same-value-clue-fc: var(--forbidden-box-bc);
--tool-fc: var(--clue-fc);
--tool-bc: var(--clue-bc);
--selected-tool-bc: var(--same-value-clue-bc);
--selected-tool-fc: var(--same-value-clue-fc);
--tool-hover-bc: #80DBD5;
--selected-tool-hover-bc: #319EAF;
}
@media (prefers-color-scheme: dark) {
:root {
--body-bc: #1c1c1e;
--body-fc: #fefefe;
--shadow: darkgray;
--border-color: #292929;
--box-bc: #0C151D;
--box-fc: #bfcbce;
--forbidden-box-bc: #004E52;
--same-value-box-bc: #09BC8A;
--placeholder-fc: var(--grid-color);
--clue-bc: #508991;
--forbidden-clue-bc: var(--clue-bc);
--same-value-clue-bc: #75DDDD;
--clue-fc: var(--box-bc);
--forbidden-clue-fc: var(--forbidden-box-bc);
--same-value-clue-fc: var(--forbidden-box-bc);
--tool-fc: var(--clue-fc);
--tool-bc: var(--clue-bc);
--selected-tool-bc: var(--same-value-clue-bc);
--selected-tool-fc: var(--same-value-clue-fc);
--tool-hover-bc: #61A0A8;
--selected-tool-hover-bc: #9DE7E7;
}
}
body {
font-family: sans-serif;
width: min-content;
margin: auto;
background: var(--body-bc);
color: var(--body-fc)
}
h1 {
text-align: center;
font-weight: 50;
margin: 2rem;
text-transform: uppercase;
letter-spacing: 1rem;
text-indent: 1rem;
text-shadow: .1rem .1rem var(--shadow);
}
section,
div,
footer {
align-items: center;
align-items: center;
justify-content: center;
text-align: center;
margin: 1rem 0;
}
div {
display: flex;
flex-wrap: wrap;
row-gap: 0.5rem;
column-gap: 0.3rem;
margin: 0.5rem auto;
}
.grid {
border-spacing: 0;
margin: auto;
cursor: url(img/ink-pen.svg) 2 22, text;
border-collapse: collapse;
}
.grid td,
tr {
padding: 0;
}
.grid tr:nth-child(3n+1) td {
border-top: 2px solid var(--border-color);
}
.grid tr:nth-child(3n+2) td {
border-top: 1px solid var(--border-color);
border-bottom: 1px solid var(--border-color);
}
.grid tr:nth-child(3n) td {
border-bottom: 2px solid var(--border-color);
}
.grid td:nth-child(3n+1) {
border-left: 2px solid var(--border-color);
}
.grid td:nth-child(3n+2) {
border-left: 1px solid var(--border-color);
border-right: 1px solid var(--border-color);
}
.grid td:nth-child(3n+3) {
border-right: 2px solid var(--border-color);
}
.grid input {
width: 2.5rem;
height: 2.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 {
font-size: 1.4rem;
color: var(--box-fc);
background: var(--box-bc);
cursor: inherit;
}
.grid input.pencil,
.grid input::placeholder {
color: #666 !important;
font-size: 0.9rem !important;
}
.grid input:disabled {
font-size: 1.3rem;
font-weight: bold;
color: var(--clue-fc);
background: var(--clue-bc);
cursor: default;
}
.grid input.forbidden:enabled {
background: var(--forbidden-box-bc);
cursor: not-allowed;
}
.grid input.same-value:enabled {
background: var(--same-value-box-bc);
cursor: not-allowed !important;
}
.grid input.forbidden:disabled {
color: var(--forbidden-clue-fc);
background: var(--forbidden-clue-bc) !important;
cursor: not-allowed;
}
.grid input.same-value:disabled {
color: var(--same-value-clue-fc) !important;
background: var(--same-value-clue-bc) !important;
}
.grid input.one-candidate {
cursor: help !important;
}
.tools div {
justify-content: space-between;
}
.tools button,
.tools input+label {
color: var(--tool-fc);
background: var(--clue-bc);
border: 1px outset var(--clue-bc);
font-size: 1.3rem;
font-weight: bold;
min-width: 20px;
padding: 6px;
margin: .1rem;
cursor: pointer;
}
.tools img {
display: block;
width: 24px;
height: 24px;
}
.tools input {
position: fixed;
opacity: 0;
width: 0;
pointer-events: none;
}
.tools button:enabled:checked,
.tools input:enabled:checked+label {
border-style: inset;
}
.tools button.same-value:enabled,
.tools input:enabled:checked+label {
background: var(--selected-tool-bc);
color: var(--selected-tool-fc);
border-color: var(--selected-tool-bc);
}
.tools button:enabled:hover,
.tools input:enabled:hover+label {
background: var(--tool-hover-bc);
border-color: var(--tool-hover-bc);
}
.tools button:enabled:checked:hover,
.tools input:enabled:checked:hover+label {
background: var(--selected-tool-hover-bc);
border-color: var(--selected-tool-hover-bc);
}
.tools button:disabled,
.tools input:disabled+label {
color: #ccc;
background: darkgrey;
border-style: outset;
border-color: darkgrey;
cursor: not-allowed;
}
.tools button:disabled * {
filter: grayscale(100%);
opacity: 0.7;
}
.tools button.warning:hover {
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;
color: var(--forbidden-clue-bc);
}
a:visited {
color: var(--same-value-clue-bc);
}
.credits {
font-size: 0.8rem;
margin: 0;
}

View File

@ -1,387 +0,0 @@
* {
font-family: "Roboto", "Calibri", "Arial", sans-serif;
}
body {
width: min-content;
margin: auto;
font-weight: 300;
}
h1 {
text-align: center;
margin: 1rem;
font-weight: 300;
font-size: 2rem;
}
div {
display: flex;
flex-wrap: wrap;
row-gap: 0.5rem;
column-gap: 0.2rem;
align-items: center;
justify-content: center;
text-align: center;
margin: 0.5rem 0;
}
button,
label {
font-weight: 400;
transition: all 200ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
border: 1px solid;
border-radius: 3px;
padding: 3px 0px;
margin: 0;
background-clip: border-box;
font-size: 1.1rem;
cursor: pointer;
min-width: 2.5rem;
}
button:disabled,
:disabled+label {
cursor: not-allowed !important;
}
i {
height: 18px;
width: 18px;
font-size: 1.1rem;
}
input[type="checkbox"],
input[type="radio"] {
position: fixed;
opacity: 0;
width: 0;
pointer-events: none;
}
.radioGroup {
column-gap: 0px;
}
input[type="radio"]+label {
margin: 0;
border-radius: 0;
}
input[type="radio"]:first-child+label {
border-top-left-radius: 3px;
border-bottom-left-radius: 3px;
}
.radioGroup label:last-child {
border-right-width: 1px;
border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
}
form {
border: 3px solid;
border-radius: 6px;
box-shadow: 0 2px 5px 0 rgb(0 0 0 / 16%), 0 2px 10px 0 rgb(0 0 0 / 12%);
}
table {
border-spacing: 0;
margin: auto;
cursor: text;
border-collapse: collapse;
}
td {
padding: 0;
border: 1px solid;
}
table input {
width: 2.4rem;
height: 2.4rem;
font-size: 1.4rem;
border: 1px solid transparent;
padding: 0;
transition: background 0.5s;
text-align: center;
-moz-appearance: textfield;
}
tr:nth-child(3n+1) td {
border-top-width: 3px;
}
tr:nth-child(3n) td {
border-bottom-width: 3px;
}
td:nth-child(3n+1) {
border-left-width: 3px;
}
td:nth-child(3n) {
border-right-width: 3px;
}
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;
}
table input:enabled {
cursor: inherit;
}
.forbidden {
cursor: not-allowed !important;
}
.pencil,
::placeholder {
font-size: 0.9rem !important;
}
#links {
flex-direction: column;
row-gap: .2rem;
}
a {
text-decoration: none;
}
.context-menu {
display: none;
z-index: 1000;
position: absolute;
overflow: hidden;
border: 1px solid;
white-space: nowrap;
font-family: sans-serif;
box-shadow: 0 2px 5px 0 rgb(0 0 0 / 16%), 0 2px 10px 0 rgb(0 0 0 / 12%);
padding: 0;
margin: 0;
border-radius: 3px;
}
.context-menu li {
padding: 6px 10px;
cursor: default;
list-style-type: none;
transition: all .3s ease;
font-size: 1rem;
}
/* Colors */
body {
color: #273134;
background-color: #f7f7f7;
}
form,
td {
border-color: #d3e1e8;
}
table input {
color: #303d41;
background-color: #ffffff;
}
table input:enabled:hover {
color: #273134;
}
:focus {
border-color: rgba(46, 179, 152, 0.5);
}
:checked+label,
.context-menu li:hover {
color: #ffffff;
background-color: #2eb398;
}
:checked+label img {
filter: invert();
opacity: 100%;
}
:disabled,
:disabled+label,
.context-menu li.error {
color: rgba(39, 49, 52, 0.55);
}
:disabled img,
:disabled+label img {
opacity: 25%;
}
button,
input+label,
.context-menu {
color: #273134;
border-color: rgba(0, 0, 0, 0.15);
background-color: #fcfcfc;
}
img {
opacity: 70%;
}
:focus,
:focus+label {
border-color: rgba(46, 179, 152, 0.5);
}
button:enabled:hover,
input:enabled:hover+label {
color: #060808;
background-color: white;
}
input:enabled:checked:hover+label {
background-color: #59d4bc;
}
button:enabled:hover img,
input:enabled:hover+label img {
opacity: 85%;
}
a {
color: #248a76;
}
a:visited {
color: #252f32;
}
a:hover {
color: #2eb398;
}
a:active {
color: #248a76;
}
.forbidden {
background-color: #ebebeb;
}
.same-value {
background-color: #ebebeb;
color: #2eb398;
}
h1 {
color: #2eb398;
}
@media (prefers-color-scheme: dark) {
body {
color: #abb9b6;
background-color: #1b2224;
}
form,
td {
border-color: #3f5055;
}
img {
filter: invert();
}
table input {
color: #abb9b6;
background-color: #222b2e;
}
table input:enabled:hover {
color: #ccd7d4;
}
:focus {
border-color: rgba(46, 179, 152, 0.7);
}
:checked+label,
.context-menu li:hover {
color: #ffffff;
background-color: #2eb398;
}
:checked+label img {
filter: invert();
}
:disabled,
:disabled+label,
.context-menu li.error {
color: rgba(204, 215, 212, 0.45);
}
button,
input+label,
.context-menu {
color: #ccd7d4;
border-color: rgba(0, 0, 0, 0.25);
background-color: #263034;
}
img {
opacity: 70%;
}
:focus,
:focus+label {
border-color: rgba(46, 179, 152, 0.7);
;
}
button:enabled:hover,
input:enabled:hover+label {
color: #a1b5b0;
border-color: rgba(0, 0, 0, 0.25);
background-color: #38464b;
}
:enabled:hover+label img {
opacity: 85%;
}
a {
color: #6ddac4;
}
a:visited {
color: #c7d0ce;
}
a:hover {
color: #96e4d4;
}
a:active {
color: #6ddac4;
}
.forbidden {
background-color: #2d383b;
}
.same-value {
color: #2eb398;
background-color: #2d383b;
}
}

View File

View File

BIN
fonts/bootstrap-icons.woff Normal file

Binary file not shown.

BIN
fonts/bootstrap-icons.woff2 Normal file

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 1.1 MiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 877 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,11 +1,11 @@
<meta charset="utf-8" />
<title>Sudoku</title>
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" type="text/css" href="css/v4.css" title="Par défaut" />
<link href="css/v1.css" rel="alternate stylesheet" type="text/css" title="v1">
<link href="css/v2.css" rel="alternate stylesheet" type="text/css" title="v2">
<link href="css/v3.css" rel="alternate stylesheet" type="text/css" title="v3">
<link rel="stylesheet" type="text/css" href="fonts/remixicon.css">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link href="css/bootstrap-dark.min.css" rel="stylesheet" type="text/css" title="Automatique" />
<link href="css/bootstrap.min.css" rel="alternate stylesheet" type="text/css" title="Clair">
<link href="css/bootstrap-night.min.css" rel="alternate stylesheet" type="text/css" title="Sombre">
<link rel="stylesheet" type="text/css" href="css/bootstrap-icons.css" />
<link rel="stylesheet" type="text/css" href="css/style.css" />
<link rel="apple-touch-icon" href="thumbnail.php?size=57" sizes="57x57">
<link rel="apple-touch-icon" href="thumbnail.php?size=114" sizes="114x114">
<link rel="apple-touch-icon" href="thumbnail.php?size=72" sizes="72x72">
@ -32,4 +32,5 @@
content="Remplissez la grille de sorte que chaque ligne, colonne et région (carré de 3×3 cases) contienne tous les chiffres de 1 à 9." />
<meta property="og:locale" content="fr_FR" />
<meta property="og:site_name" content="<?=$_SERVER["HTTP_HOST"]?>" />
<script src='sudoku.js'></script>
<script src='js/sudoku.js'></script>
<script src="js/bootstrap.bundle.min.js" integrity="sha384-qKXV1j0HvMUeCBQ+QVp7JcfGl760yU08IQ+GpUo5hlbpg51QRiuqHAJz8+BrxE/N" crossorigin="anonymous"></script>

7
js/bootstrap.bundle.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -6,7 +6,6 @@ let boxes = []
let rows = Array.from(Array(9), x => [])
let columns = Array.from(Array(9), x => [])
let regions = Array.from(Array(9), x => [])
let suggestionTimer = null
let valueToInsert = ""
let history = []
let accessKeyModifiers = "AccessKey+"
@ -53,6 +52,9 @@ window.onload = function() {
rowId++
}
if (localStorage["highlighterCheckbox.checked"]) {
highlighterCheckbox.checked = true
}
loadSavedGame()
boxes.forEach(box => {
@ -169,6 +171,7 @@ function refreshBox(box) {
function checkBox(box) {
box.neighbourhood.concat([box]).forEach(neighbour => {
neighbour.setCustomValidity("")
neighbour.classList.remove("is-invalid")
searchCandidatesOf(neighbour)
if (neighbour.candidates.size == 0) {
neighbour.setCustomValidity("Aucun chiffre possible !")
@ -190,14 +193,18 @@ function checkBox(box) {
if (box != neighbour && box.value == neighbour.value) {
for (neighbour of[box, neighbour]) {
neighbour.setCustomValidity(`Il y a un autre ${box.value} dans cette ${area.name}.`)
neighbour.classList.add("is-invalid")
}
}
}
if (box.form.checkValidity()) { // Correct grid
if (boxes.filter(box => box.value == "").length == 0) {
setTimeout(() => alert(`Bravo ! Vous avez résolu la grille.`), 500)
saveButton.disabled = true
setTimeout(() => {
if (confirm(`Bravo ! Vous avez résolu la grille. En voulez-vous une autre ?`))
location = "."
}, 400)
}
} else { // Errors on grid
box.form.reportValidity()
@ -228,18 +235,20 @@ function highlight() {
easyBoxes = []
boxes.forEach(box => {
if (valueToInsert && box.value == valueToInsert) {
box.classList.add("same-value")
box.parentElement.classList.add("table-primary")
box.tabIndex = -1
} else {
box.classList.remove("same-value")
if (valueToInsert && highlighterCheckbox.checked && !box.candidates.has(valueToInsert)) {
box.classList.add("forbidden")
box.tabIndex = -1
} else {
box.classList.remove("forbidden")
box.tabIndex = 0
}
box.parentElement.classList.remove("table-primary")
box.tabIndex = 0
}
if (valueToInsert && highlighterCheckbox.checked && !box.candidates.has(valueToInsert)) {
box.parentElement.classList.add("table-active")
box.tabIndex = -1
} else {
box.parentElement.classList.remove("table-active")
box.tabIndex = 0
}
if (!box.value && box.candidates.size == 1) {
hintButton.disabled = false
easyBoxes.push(box)
@ -307,6 +316,7 @@ function save() {
}
window.onbeforeunload = function(event) {
localStorage["highlighterCheckbox.checked"] = highlighterCheckbox.checked
if (!saveButton.disabled) {
event.preventDefault()
event.returnValue = "La partie n'est pas sauvegardée. Quitter quand même ?"
@ -319,10 +329,6 @@ function showHint() {
let box = easyBoxes.pop()
box.placeholder = "💡"
box.focus()
/*value = Array.from(box.candidates)[0]
radio = document.getElementById("insertRadio" + value)
radio.checked = true
insert(radio)*/
return box
}
hintButton.disabled = true
@ -336,13 +342,18 @@ function oncontextmenu(event) {
Array.from(box.candidates).sort().forEach(candidate => {
li = document.createElement("li")
li.innerText = candidate
li.onclick = function(event) {
li.classList = "list-group-item list-group-item-action"
li.onclick = function(e) {
contextMenu.style.display = "none"
valueToInsert = event.target.innerText
valueToInsert = e.target.innerText
grid.style.cursor = "copy"
document.getElementById("insertRadio" + valueToInsert).checked = true
box.onclick()
}
li.oncontextmenu = function(e) {
e.preventDefault()
li.onclick(e)
}
contextMenu.appendChild(li)
})
} else {

View File

@ -5,49 +5,60 @@
<?php require_once("head.php") ?>
</head>
<body>
<body class="text-center">
<header>
<h1>Sudoku</h1>
<h1 class="display-4 mb-3">Sudoku</h1>
</header>
<div class='toolBar'>
<div class='radioGroup'>
<input type='radio' id='inkPenRadio' name='tool' checked /><label for='inkPenRadio'
title='Écrire un chiffre'><i class="ri-ball-pen-fill"></i></label>
<input type='radio' id='pencilRadio' name='tool' /><label for='pencilRadio' title='Prendre des notes'><i
class="ri-pencil-fill"></i></label>
<input type='radio' id='eraserRadio' name='tool' '/><label for='eraserRadio'
title='Effacer une case'><i class="ri-eraser-fill"></i></label>
<div class='d-flex justify-content-between mb-2'>
<div class='radioGroup btn-group'>
<input type='radio' id='inkPenRadio' class='btn-check' name='tool' checked />
<label for='inkPenRadio' class='btn btn-primary' title='Écrire un chiffre'>
<i class="bi bi-pen-fill"></i>
</label>
<input type='radio' id='pencilRadio' class='btn-check' name='tool' />
<label for='pencilRadio' class='btn btn-primary' title='Prendre des notes'>
<i class="bi bi-pencil-fill"></i>
</label>
<input type='radio' id='eraserRadio' class='btn-check' name='tool' '/>
<label for='eraserRadio' class='btn btn-primary' title='Effacer une case'>
<i class="bi bi-eraser-fill"></i>
</label>
</div>
<input id='highlighterCheckbox' type="checkbox" onclick='highlight()' /><label for='highlighterCheckbox'
title='Surligner les lignes, colonnes et régions contenant déjà le chiffre sélectionné'><i
class="ri-mark-pen-fill"></i></label>
<button id="hintButton" type="button" onclick="showHint()" title="Afficher un indice" accesskey="H"
disabled=""><i class="ri-lightbulb-flash-fill"></i></button>
<button id='restartButton' type='button' class='warning' onclick='restart()' disabled title='Recommencer'><i
class="ri-restart-fill"></i></button>
<button id='undoButton' type='button' onclick='undo()' disabled title='Annuler' accesskey='Z'><i
class="ri-arrow-go-back-fill"></i></button>
<button id='saveButton' type='button' onclick='save()' disabled title='Sauvegarder' accesskey='S'><i
class="ri-save-3-fill"></i></button>
<input id='highlighterCheckbox' type="checkbox" class='btn-check' onclick='highlight()' />
<label for='highlighterCheckbox' class='btn btn-primary' title='Surligner les lignes, colonnes et régions contenant déjà le chiffre sélectionné'>
<i class="bi bi-magic"></i>
</label>
<button id="hintButton" type="button" class='btn btn-primary' onclick="showHint()" title="Montrer une case avec une seule possibilité" accesskey="H" disabled="">
<i class="bi bi-lightbulb-fill"></i>
</button>
<button id='restartButton' type='button' class='btn btn-primary' onclick='restart()' disabled title='Recommencer'>
<i class="bi bi-x-circle-fill"></i></i>
</button>
<button id='undoButton' type='button' class='btn btn-primary' onclick='undo()' disabled title='Annuler' accesskey='Z'>
<i class="bi bi-arrow-counterclockwise"></i>
</button>
<button id='saveButton' type='button' class='btn btn-primary' onclick='save()' disabled title='Sauvegarder' accesskey='S'>
<i class="bi bi-save-fill"></i>
</button>
</div>
<form id='sudokuForm'>
<table id='grid' class='grid'>
<form id='sudokuForm' class='needs-validation' novalidate>
<table id='grid' class='table mb-2'>
<tbody>
<?php
for ($row = 0; $row < 81; $row += 9) {
?>
<tr>
<tr class="input-group d-inline-block">
<?php
for ($column = 0; $column < 9; $column++) {
$value = $currentGrid[$row+$column];
if ($value == UNKNOWN) {
?>
<td><input type='number' min='1' max='9' step='1' value=''
<td><input type='number' min='1' max='9' step='1' value='' class='form-control'
title='Valeurs possibles [Clic-droit]' /></td>
<?php
} else {
?>
<td><input type='number' min='1' max='9' step='1' value='<?=$value?>' disabled /></td>
<td><input type='number' min='1' max='9' step='1' value='<?=$value?>' class='form-control' disabled /></td>
<?php
}
}
@ -59,16 +70,16 @@
</tbody>
</table>
</form>
<div class='toolBar'>
<div id='insertRadioGroup' class='radioGroup'>
<div class='d-flex mb-2'>
<div id='insertRadioGroup' class='radioGroup btn-group flex-fill'>
<?php
for($value=1; $value<=9; $value++) {
echo " <input type='radio' id='insertRadio$value' value='$value' name='insertRadioGroup' onclick='insert(this)' accesskey='$value'/><label for='insertRadio$value' title='Insérer un $value'>$value</label>\n";
echo " <input type='radio'class='btn-check' id='insertRadio$value' value='$value' name='insertRadioGroup' onclick='insert(this)' accesskey='$value'/><label for='insertRadio$value' class='btn btn-primary' title='Insérer un $value'>$value</label>\n";
}
?>
</div>
</div>
<div>
<div class='mb-3'>
<?php
if (isset($warning))
echo(" <strong>⚠️ $warning ⚠️</strong><br/>\n");
@ -76,14 +87,14 @@
echo(" Remplissez la grille de sorte que chaque ligne, colonne et région (carré de 3×3 cases) contienne tous les chiffres de 1 à 9.\n")
?>
</div>
<ul id='contextMenu' class='context-menu'></ul>
<ul id='contextMenu' class='context-menu modal-content shadow list-group w-auto position-absolute'></ul>
<footer>
<div id='links'>
<a href='.'>Nouvelle grille</a>
<a href=''>Lien vers cette grille</a>
<a href='?.................................................................................'>Grille
<div id='links' class='list-group mb-2'>
<a href='.' class='list-group-item list-group-item-action'>Nouvelle grille</a>
<a href='' class='list-group-item list-group-item-action'>Lien vers cette grille</a>
<a href='?.................................................................................' class='list-group-item list-group-item-action'>Grille
vierge</a>
<a href='' id='fixGridLink'>Figer la grille enregistrée</a>
<a href='' id='fixGridLink' class='list-group-item list-group-item-action'>Figer la grille enregistrée</a>
</div>
</footer>
</body>