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

@ -86,49 +86,6 @@
} }
} }
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() { function generate() {
// Init with a shuffle row // Init with a shuffle row
$values = array("1", "2", "3", "4", "5", "6", "7", "8", "9"); $values = array("1", "2", "3", "4", "5", "6", "7", "8", "9");

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" /> <meta charset="utf-8" />
<title>Sudoku</title> <title>Sudoku</title>
<meta name="viewport" content="width=device-width" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" type="text/css" href="css/v4.css" title="Par défaut" /> <link href="css/bootstrap-dark.min.css" rel="stylesheet" type="text/css" title="Automatique" />
<link href="css/v1.css" rel="alternate stylesheet" type="text/css" title="v1"> <link href="css/bootstrap.min.css" rel="alternate stylesheet" type="text/css" title="Clair">
<link href="css/v2.css" rel="alternate stylesheet" type="text/css" title="v2"> <link href="css/bootstrap-night.min.css" rel="alternate stylesheet" type="text/css" title="Sombre">
<link href="css/v3.css" rel="alternate stylesheet" type="text/css" title="v3"> <link rel="stylesheet" type="text/css" href="css/bootstrap-icons.css" />
<link rel="stylesheet" type="text/css" href="fonts/remixicon.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=57" sizes="57x57">
<link rel="apple-touch-icon" href="thumbnail.php?size=114" sizes="114x114"> <link rel="apple-touch-icon" href="thumbnail.php?size=114" sizes="114x114">
<link rel="apple-touch-icon" href="thumbnail.php?size=72" sizes="72x72"> <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." /> 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:locale" content="fr_FR" />
<meta property="og:site_name" content="<?=$_SERVER["HTTP_HOST"]?>" /> <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 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 valueToInsert = "" let valueToInsert = ""
let history = [] let history = []
let accessKeyModifiers = "AccessKey+" let accessKeyModifiers = "AccessKey+"
@ -53,6 +52,9 @@ window.onload = function() {
rowId++ rowId++
} }
if (localStorage["highlighterCheckbox.checked"]) {
highlighterCheckbox.checked = true
}
loadSavedGame() loadSavedGame()
boxes.forEach(box => { boxes.forEach(box => {
@ -169,6 +171,7 @@ function refreshBox(box) {
function checkBox(box) { function checkBox(box) {
box.neighbourhood.concat([box]).forEach(neighbour => { box.neighbourhood.concat([box]).forEach(neighbour => {
neighbour.setCustomValidity("") neighbour.setCustomValidity("")
neighbour.classList.remove("is-invalid")
searchCandidatesOf(neighbour) searchCandidatesOf(neighbour)
if (neighbour.candidates.size == 0) { if (neighbour.candidates.size == 0) {
neighbour.setCustomValidity("Aucun chiffre possible !") neighbour.setCustomValidity("Aucun chiffre possible !")
@ -190,14 +193,18 @@ function checkBox(box) {
if (box != neighbour && box.value == neighbour.value) { if (box != neighbour && box.value == neighbour.value) {
for (neighbour of[box, neighbour]) { for (neighbour of[box, neighbour]) {
neighbour.setCustomValidity(`Il y a un autre ${box.value} dans cette ${area.name}.`) 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 (box.form.checkValidity()) { // Correct grid
if (boxes.filter(box => box.value == "").length == 0) { if (boxes.filter(box => box.value == "").length == 0) {
setTimeout(() => alert(`Bravo ! Vous avez résolu la grille.`), 500)
saveButton.disabled = true saveButton.disabled = true
setTimeout(() => {
if (confirm(`Bravo ! Vous avez résolu la grille. En voulez-vous une autre ?`))
location = "."
}, 400)
} }
} else { // Errors on grid } else { // Errors on grid
box.form.reportValidity() box.form.reportValidity()
@ -228,18 +235,20 @@ function highlight() {
easyBoxes = [] easyBoxes = []
boxes.forEach(box => { boxes.forEach(box => {
if (valueToInsert && box.value == valueToInsert) { if (valueToInsert && box.value == valueToInsert) {
box.classList.add("same-value") box.parentElement.classList.add("table-primary")
box.tabIndex = -1 box.tabIndex = -1
} else { } else {
box.classList.remove("same-value") box.parentElement.classList.remove("table-primary")
if (valueToInsert && highlighterCheckbox.checked && !box.candidates.has(valueToInsert)) {
box.classList.add("forbidden")
box.tabIndex = -1
} else {
box.classList.remove("forbidden")
box.tabIndex = 0 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) { if (!box.value && box.candidates.size == 1) {
hintButton.disabled = false hintButton.disabled = false
easyBoxes.push(box) easyBoxes.push(box)
@ -307,6 +316,7 @@ function save() {
} }
window.onbeforeunload = function(event) { window.onbeforeunload = function(event) {
localStorage["highlighterCheckbox.checked"] = highlighterCheckbox.checked
if (!saveButton.disabled) { if (!saveButton.disabled) {
event.preventDefault() event.preventDefault()
event.returnValue = "La partie n'est pas sauvegardée. Quitter quand même ?" event.returnValue = "La partie n'est pas sauvegardée. Quitter quand même ?"
@ -319,10 +329,6 @@ function showHint() {
let box = easyBoxes.pop() let box = easyBoxes.pop()
box.placeholder = "💡" box.placeholder = "💡"
box.focus() box.focus()
/*value = Array.from(box.candidates)[0]
radio = document.getElementById("insertRadio" + value)
radio.checked = true
insert(radio)*/
return box return box
} }
hintButton.disabled = true hintButton.disabled = true
@ -336,13 +342,18 @@ function oncontextmenu(event) {
Array.from(box.candidates).sort().forEach(candidate => { Array.from(box.candidates).sort().forEach(candidate => {
li = document.createElement("li") li = document.createElement("li")
li.innerText = candidate li.innerText = candidate
li.onclick = function(event) { li.classList = "list-group-item list-group-item-action"
li.onclick = function(e) {
contextMenu.style.display = "none" contextMenu.style.display = "none"
valueToInsert = event.target.innerText valueToInsert = e.target.innerText
grid.style.cursor = "copy" grid.style.cursor = "copy"
document.getElementById("insertRadio" + valueToInsert).checked = true document.getElementById("insertRadio" + valueToInsert).checked = true
box.onclick() box.onclick()
} }
li.oncontextmenu = function(e) {
e.preventDefault()
li.onclick(e)
}
contextMenu.appendChild(li) contextMenu.appendChild(li)
}) })
} else { } else {

View File

@ -5,49 +5,60 @@
<?php require_once("head.php") ?> <?php require_once("head.php") ?>
</head> </head>
<body> <body class="text-center">
<header> <header>
<h1>Sudoku</h1> <h1 class="display-4 mb-3">Sudoku</h1>
</header> </header>
<div class='toolBar'> <div class='d-flex justify-content-between mb-2'>
<div class='radioGroup'> <div class='radioGroup btn-group'>
<input type='radio' id='inkPenRadio' name='tool' checked /><label for='inkPenRadio' <input type='radio' id='inkPenRadio' class='btn-check' name='tool' checked />
title='Écrire un chiffre'><i class="ri-ball-pen-fill"></i></label> <label for='inkPenRadio' class='btn btn-primary' title='Écrire un chiffre'>
<input type='radio' id='pencilRadio' name='tool' /><label for='pencilRadio' title='Prendre des notes'><i <i class="bi bi-pen-fill"></i>
class="ri-pencil-fill"></i></label> </label>
<input type='radio' id='eraserRadio' name='tool' '/><label for='eraserRadio' <input type='radio' id='pencilRadio' class='btn-check' name='tool' />
title='Effacer une case'><i class="ri-eraser-fill"></i></label> <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> </div>
<input id='highlighterCheckbox' type="checkbox" onclick='highlight()' /><label for='highlighterCheckbox' <input id='highlighterCheckbox' type="checkbox" class='btn-check' onclick='highlight()' />
title='Surligner les lignes, colonnes et régions contenant déjà le chiffre sélectionné'><i <label for='highlighterCheckbox' class='btn btn-primary' title='Surligner les lignes, colonnes et régions contenant déjà le chiffre sélectionné'>
class="ri-mark-pen-fill"></i></label> <i class="bi bi-magic"></i>
<button id="hintButton" type="button" onclick="showHint()" title="Afficher un indice" accesskey="H" </label>
disabled=""><i class="ri-lightbulb-flash-fill"></i></button> <button id="hintButton" type="button" class='btn btn-primary' onclick="showHint()" title="Montrer une case avec une seule possibilité" accesskey="H" disabled="">
<button id='restartButton' type='button' class='warning' onclick='restart()' disabled title='Recommencer'><i <i class="bi bi-lightbulb-fill"></i>
class="ri-restart-fill"></i></button> </button>
<button id='undoButton' type='button' onclick='undo()' disabled title='Annuler' accesskey='Z'><i <button id='restartButton' type='button' class='btn btn-primary' onclick='restart()' disabled title='Recommencer'>
class="ri-arrow-go-back-fill"></i></button> <i class="bi bi-x-circle-fill"></i></i>
<button id='saveButton' type='button' onclick='save()' disabled title='Sauvegarder' accesskey='S'><i </button>
class="ri-save-3-fill"></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> </div>
<form id='sudokuForm'> <form id='sudokuForm' class='needs-validation' novalidate>
<table id='grid' class='grid'> <table id='grid' class='table mb-2'>
<tbody> <tbody>
<?php <?php
for ($row = 0; $row < 81; $row += 9) { for ($row = 0; $row < 81; $row += 9) {
?> ?>
<tr> <tr class="input-group d-inline-block">
<?php <?php
for ($column = 0; $column < 9; $column++) { for ($column = 0; $column < 9; $column++) {
$value = $currentGrid[$row+$column]; $value = $currentGrid[$row+$column];
if ($value == UNKNOWN) { 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> title='Valeurs possibles [Clic-droit]' /></td>
<?php <?php
} else { } 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 <?php
} }
} }
@ -59,16 +70,16 @@
</tbody> </tbody>
</table> </table>
</form> </form>
<div class='toolBar'> <div class='d-flex mb-2'>
<div id='insertRadioGroup' class='radioGroup'> <div id='insertRadioGroup' class='radioGroup btn-group flex-fill'>
<?php <?php
for($value=1; $value<=9; $value++) { 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>
<div> <div class='mb-3'>
<?php <?php
if (isset($warning)) if (isset($warning))
echo(" <strong>⚠️ $warning ⚠️</strong><br/>\n"); 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") 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> </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> <footer>
<div id='links'> <div id='links' class='list-group mb-2'>
<a href='.'>Nouvelle grille</a> <a href='.' class='list-group-item list-group-item-action'>Nouvelle grille</a>
<a href=''>Lien vers cette grille</a> <a href='' class='list-group-item list-group-item-action'>Lien vers cette grille</a>
<a href='?.................................................................................'>Grille <a href='?.................................................................................' class='list-group-item list-group-item-action'>Grille
vierge</a> 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> </div>
</footer> </footer>
</body> </body>