- ID de l'analyse :
- 3fcdf64b-7a89-4838-bb31-cd1c10fd7949Terminée
- URL soumise :
- https://story-safe-wiki.com/
- Fin du rapport :
Liens : 0 trouvé(s)
Liens sortants identifiés à partir de la page
Variables JavaScript : 16 trouvée(s)
Les variables JavaScript globales chargées dans l'objet fenêtre d'une page sont des variables déclarées en dehors des fonctions et accessibles depuis n'importe quel endroit du code au sein du champ d'application actuel
Nom | Type |
---|---|
onbeforetoggle | object |
documentPictureInPicture | object |
onscrollend | object |
updateTable | function |
generateUserId | function |
getUserId | function |
updateMemoriesTable | function |
updateStatus | function |
showError | function |
initializePage | function |
Messages de journal de console : 2 trouvé(s)
Messages consignés dans la console web
Type | Catégorie | Enregistrement |
---|---|---|
error | network |
|
error | javascript |
|
HTML
Le corps HTML de la page en données brutes
<!DOCTYPE html><html lang="en"><head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hush House Catalogue</title>
<style>
/*!
* chota.css v0.9.2 | MIT License | https://github.com/jenil/chota
*/
:root {
--bg-color: #fff;
--bg-secondary-color: #f3f3f6;
--color-primary: #14854f;
--color-lightGrey: #d2d6dd;
--color-grey: #747681;
--color-darkGrey: #3f4144;
--color-error: #d43939;
--color-success: #28bd14;
--grid-maxWidth: 120rem;
--grid-gutter: 2rem;
--font-size: 1.6rem;
--font-color: #333;
--font-family-sans: -apple-system, "BlinkMacSystemFont", "Avenir",
"Avenir Next", "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell",
"Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
--font-family-mono: monaco, "Consolas", "Lucida Console", monospace;
}
html {
-webkit-text-size-adjust: 100%;
-moz-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
text-size-adjust: 100%;
-webkit-box-sizing: border-box;
box-sizing: border-box;
font-size: 62.5%;
line-height: 1.15;
}
*,
:after,
:before {
-webkit-box-sizing: inherit;
box-sizing: inherit;
}
body {
background-color: var(--bg-color);
color: var(--font-color);
font-family: Segoe UI, Helvetica Neue, sans-serif;
font-family: var(--font-family-sans);
font-size: var(--font-size);
line-height: 1.6;
margin: 0;
padding: 0;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: 500;
margin: 0.35em 0 0.7em;
}
h1 {
font-size: 2em;
}
h2 {
font-size: 1.75em;
}
h3 {
font-size: 1.5em;
}
h4 {
font-size: 1.25em;
}
h5 {
font-size: 1em;
}
h6 {
font-size: 0.85em;
}
a {
color: var(--color-primary);
text-decoration: none;
}
a:hover:not(.button) {
opacity: 0.75;
}
button {
font-family: inherit;
}
p {
margin-top: 0;
}
blockquote {
background-color: var(--bg-secondary-color);
border-left: 3px solid var(--color-lightGrey);
padding: 1.5rem 2rem;
}
dl dt {
font-weight: 700;
}
hr {
background-color: var(--color-lightGrey);
height: 1px;
margin: 1rem 0;
}
hr,
table {
border: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
text-align: left;
width: 100%;
}
table.striped tr:nth-of-type(2n) {
background-color: var(--bg-secondary-color);
}
td,
th {
padding: 1.2rem 0.4rem;
vertical-align: middle;
}
thead {
border-bottom: 2px solid var(--color-lightGrey);
}
tfoot {
border-top: 2px solid var(--color-lightGrey);
}
code,
kbd,
pre,
samp,
tt {
font-family: var(--font-family-mono);
}
code,
kbd {
border-radius: 4px;
color: var(--color-error);
font-size: 90%;
padding: 0.2em 0.4em;
white-space: pre-wrap;
}
code,
kbd,
pre {
background-color: var(--bg-secondary-color);
}
pre {
font-size: 1em;
overflow-x: auto;
padding: 1rem;
}
pre code {
background: none;
padding: 0;
}
abbr[title] {
border-bottom: none;
text-decoration: underline;
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
}
img {
max-width: 100%;
}
fieldset {
border: 1px solid var(--color-lightGrey);
}
iframe {
border: 0;
}
.container {
margin: 0 auto;
max-width: var(--grid-maxWidth);
padding: 0 calc(var(--grid-gutter) / 2);
width: 96%;
}
.row {
-webkit-box-direction: normal;
-webkit-box-pack: start;
-ms-flex-pack: start;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-ms-flex-flow: row wrap;
flex-flow: row wrap;
justify-content: flex-start;
margin-left: calc(var(--grid-gutter) / -2);
margin-right: calc(var(--grid-gutter) / -2);
}
.row,
.row.reverse {
-webkit-box-orient: horizontal;
}
.row.reverse {
-webkit-box-direction: reverse;
-ms-flex-direction: row-reverse;
flex-direction: row-reverse;
}
.col {
-webkit-box-flex: 1;
-ms-flex: 1;
flex: 1;
}
.col,
[class*=" col-"],
[class^="col-"] {
margin: 0 calc(var(--grid-gutter) / 2) calc(var(--grid-gutter) / 2);
}
.col-1 {
-ms-flex: 0 0 calc(8.33333% - var(--grid-gutter));
flex: 0 0 calc(8.33333% - var(--grid-gutter));
max-width: calc(8.33333% - var(--grid-gutter));
}
.col-1,
.col-2 {
-webkit-box-flex: 0;
}
.col-2 {
-ms-flex: 0 0 calc(16.66667% - var(--grid-gutter));
flex: 0 0 calc(16.66667% - var(--grid-gutter));
max-width: calc(16.66667% - var(--grid-gutter));
}
.col-3 {
-ms-flex: 0 0 calc(25% - var(--grid-gutter));
flex: 0 0 calc(25% - var(--grid-gutter));
max-width: calc(25% - var(--grid-gutter));
}
.col-3,
.col-4 {
-webkit-box-flex: 0;
}
.col-4 {
-ms-flex: 0 0 calc(33.33333% - var(--grid-gutter));
flex: 0 0 calc(33.33333% - var(--grid-gutter));
max-width: calc(33.33333% - var(--grid-gutter));
}
.col-5 {
-ms-flex: 0 0 calc(41.66667% - var(--grid-gutter));
flex: 0 0 calc(41.66667% - var(--grid-gutter));
max-width: calc(41.66667% - var(--grid-gutter));
}
.col-5,
.col-6 {
-webkit-box-flex: 0;
}
.col-6 {
-ms-flex: 0 0 calc(50% - var(--grid-gutter));
flex: 0 0 calc(50% - var(--grid-gutter));
max-width: calc(50% - var(--grid-gutter));
}
.col-7 {
-ms-flex: 0 0 calc(58.33333% - var(--grid-gutter));
flex: 0 0 calc(58.33333% - var(--grid-gutter));
max-width: calc(58.33333% - var(--grid-gutter));
}
.col-7,
.col-8 {
-webkit-box-flex: 0;
}
.col-8 {
-ms-flex: 0 0 calc(66.66667% - var(--grid-gutter));
flex: 0 0 calc(66.66667% - var(--grid-gutter));
max-width: calc(66.66667% - var(--grid-gutter));
}
.col-9 {
-ms-flex: 0 0 calc(75% - var(--grid-gutter));
flex: 0 0 calc(75% - var(--grid-gutter));
max-width: calc(75% - var(--grid-gutter));
}
.col-10,
.col-9 {
-webkit-box-flex: 0;
}
.col-10 {
-ms-flex: 0 0 calc(83.33333% - var(--grid-gutter));
flex: 0 0 calc(83.33333% - var(--grid-gutter));
max-width: calc(83.33333% - var(--grid-gutter));
}
.col-11 {
-ms-flex: 0 0 calc(91.66667% - var(--grid-gutter));
flex: 0 0 calc(91.66667% - var(--grid-gutter));
max-width: calc(91.66667% - var(--grid-gutter));
}
.col-11,
.col-12 {
-webkit-box-flex: 0;
}
.col-12 {
-ms-flex: 0 0 calc(100% - var(--grid-gutter));
flex: 0 0 calc(100% - var(--grid-gutter));
max-width: calc(100% - var(--grid-gutter));
}
@media screen and (max-width: 599px) {
.container {
width: 100%;
}
.col,
[class*="col-"],
[class^="col-"] {
-webkit-box-flex: 0;
-ms-flex: 0 1 100%;
flex: 0 1 100%;
max-width: 100%;
}
}
@media screen and (min-width: 900px) {
.col-1-md {
-webkit-box-flex: 0;
-ms-flex: 0 0 calc(8.33333% - var(--grid-gutter));
flex: 0 0 calc(8.33333% - var(--grid-gutter));
max-width: calc(8.33333% - var(--grid-gutter));
}
.col-2-md {
-webkit-box-flex: 0;
-ms-flex: 0 0 calc(16.66667% - var(--grid-gutter));
flex: 0 0 calc(16.66667% - var(--grid-gutter));
max-width: calc(16.66667% - var(--grid-gutter));
}
.col-3-md {
-webkit-box-flex: 0;
-ms-flex: 0 0 calc(25% - var(--grid-gutter));
flex: 0 0 calc(25% - var(--grid-gutter));
max-width: calc(25% - var(--grid-gutter));
}
.col-4-md {
-webkit-box-flex: 0;
-ms-flex: 0 0 calc(33.33333% - var(--grid-gutter));
flex: 0 0 calc(33.33333% - var(--grid-gutter));
max-width: calc(33.33333% - var(--grid-gutter));
}
.col-5-md {
-webkit-box-flex: 0;
-ms-flex: 0 0 calc(41.66667% - var(--grid-gutter));
flex: 0 0 calc(41.66667% - var(--grid-gutter));
max-width: calc(41.66667% - var(--grid-gutter));
}
.col-6-md {
-webkit-box-flex: 0;
-ms-flex: 0 0 calc(50% - var(--grid-gutter));
flex: 0 0 calc(50% - var(--grid-gutter));
max-width: calc(50% - var(--grid-gutter));
}
.col-7-md {
-webkit-box-flex: 0;
-ms-flex: 0 0 calc(58.33333% - var(--grid-gutter));
flex: 0 0 calc(58.33333% - var(--grid-gutter));
max-width: calc(58.33333% - var(--grid-gutter));
}
.col-8-md {
-webkit-box-flex: 0;
-ms-flex: 0 0 calc(66.66667% - var(--grid-gutter));
flex: 0 0 calc(66.66667% - var(--grid-gutter));
max-width: calc(66.66667% - var(--grid-gutter));
}
.col-9-md {
-webkit-box-flex: 0;
-ms-flex: 0 0 calc(75% - var(--grid-gutter));
flex: 0 0 calc(75% - var(--grid-gutter));
max-width: calc(75% - var(--grid-gutter));
}
.col-10-md {
-webkit-box-flex: 0;
-ms-flex: 0 0 calc(83.33333% - var(--grid-gutter));
flex: 0 0 calc(83.33333% - var(--grid-gutter));
max-width: calc(83.33333% - var(--grid-gutter));
}
.col-11-md {
-webkit-box-flex: 0;
-ms-flex: 0 0 calc(91.66667% - var(--grid-gutter));
flex: 0 0 calc(91.66667% - var(--grid-gutter));
max-width: calc(91.66667% - var(--grid-gutter));
}
.col-12-md {
-webkit-box-flex: 0;
-ms-flex: 0 0 calc(100% - var(--grid-gutter));
flex: 0 0 calc(100% - var(--grid-gutter));
max-width: calc(100% - var(--grid-gutter));
}
}
@media screen and (min-width: 1200px) {
.col-1-lg {
-webkit-box-flex: 0;
-ms-flex: 0 0 calc(8.33333% - var(--grid-gutter));
flex: 0 0 calc(8.33333% - var(--grid-gutter));
max-width: calc(8.33333% - var(--grid-gutter));
}
.col-2-lg {
-webkit-box-flex: 0;
-ms-flex: 0 0 calc(16.66667% - var(--grid-gutter));
flex: 0 0 calc(16.66667% - var(--grid-gutter));
max-width: calc(16.66667% - var(--grid-gutter));
}
.col-3-lg {
-webkit-box-flex: 0;
-ms-flex: 0 0 calc(25% - var(--grid-gutter));
flex: 0 0 calc(25% - var(--grid-gutter));
max-width: calc(25% - var(--grid-gutter));
}
.col-4-lg {
-webkit-box-flex: 0;
-ms-flex: 0 0 calc(33.33333% - var(--grid-gutter));
flex: 0 0 calc(33.33333% - var(--grid-gutter));
max-width: calc(33.33333% - var(--grid-gutter));
}
.col-5-lg {
-webkit-box-flex: 0;
-ms-flex: 0 0 calc(41.66667% - var(--grid-gutter));
flex: 0 0 calc(41.66667% - var(--grid-gutter));
max-width: calc(41.66667% - var(--grid-gutter));
}
.col-6-lg {
-webkit-box-flex: 0;
-ms-flex: 0 0 calc(50% - var(--grid-gutter));
flex: 0 0 calc(50% - var(--grid-gutter));
max-width: calc(50% - var(--grid-gutter));
}
.col-7-lg {
-webkit-box-flex: 0;
-ms-flex: 0 0 calc(58.33333% - var(--grid-gutter));
flex: 0 0 calc(58.33333% - var(--grid-gutter));
max-width: calc(58.33333% - var(--grid-gutter));
}
.col-8-lg {
-webkit-box-flex: 0;
-ms-flex: 0 0 calc(66.66667% - var(--grid-gutter));
flex: 0 0 calc(66.66667% - var(--grid-gutter));
max-width: calc(66.66667% - var(--grid-gutter));
}
.col-9-lg {
-webkit-box-flex: 0;
-ms-flex: 0 0 calc(75% - var(--grid-gutter));
flex: 0 0 calc(75% - var(--grid-gutter));
max-width: calc(75% - var(--grid-gutter));
}
.col-10-lg {
-webkit-box-flex: 0;
-ms-flex: 0 0 calc(83.33333% - var(--grid-gutter));
flex: 0 0 calc(83.33333% - var(--grid-gutter));
max-width: calc(83.33333% - var(--grid-gutter));
}
.col-11-lg {
-webkit-box-flex: 0;
-ms-flex: 0 0 calc(91.66667% - var(--grid-gutter));
flex: 0 0 calc(91.66667% - var(--grid-gutter));
max-width: calc(91.66667% - var(--grid-gutter));
}
.col-12-lg {
-webkit-box-flex: 0;
-ms-flex: 0 0 calc(100% - var(--grid-gutter));
flex: 0 0 calc(100% - var(--grid-gutter));
max-width: calc(100% - var(--grid-gutter));
}
}
fieldset {
padding: 0.5rem 2rem;
}
legend {
font-size: 0.8em;
letter-spacing: 0.1rem;
text-transform: uppercase;
}
input:not(
[type="checkbox"],
[type="radio"],
[type="submit"],
[type="color"],
[type="button"],
[type="reset"]
),
select,
textarea,
textarea[type="text"] {
border: 1px solid var(--color-lightGrey);
border-radius: 4px;
display: block;
font-family: inherit;
font-size: 1em;
padding: 0.8rem 1rem;
-webkit-transition: all 0.2s ease;
transition: all 0.2s ease;
width: 100%;
}
select {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background: #f3f3f6 no-repeat 100%;
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='60' height='40' fill='%23555'><polygon points='0,0 60,0 30,40'/></svg>");
background-origin: content-box;
background-size: 1ex;
}
.button,
[type="button"],
[type="reset"],
[type="submit"],
button {
background: var(--color-lightGrey);
border: 1px solid transparent;
border-radius: 4px;
color: var(--color-darkGrey);
cursor: pointer;
display: inline-block;
font-size: var(--font-size);
line-height: 1;
padding: 1rem 2.5rem;
text-align: center;
text-decoration: none;
-webkit-transform: scale(1);
transform: scale(1);
-webkit-transition: opacity 0.2s ease;
transition: opacity 0.2s ease;
}
.button.dark,
.button.error,
.button.primary,
.button.secondary,
.button.success,
[type="submit"] {
background-color: #000;
background-color: var(--color-primary);
color: #fff;
z-index: 1;
}
.button:hover,
[type="button"]:hover,
[type="reset"]:hover,
[type="submit"]:hover,
button:hover {
opacity: 0.8;
}
button:disabled,
button:disabled:hover,
input:disabled,
input:disabled:hover {
cursor: not-allowed;
opacity: 0.4;
}
.grouped {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
}
.grouped > :not(:last-child) {
margin-right: 16px;
}
.grouped.gapless > * {
border-radius: 0 !important;
margin: 0 0 0 -1px !important;
}
.grouped.gapless > :first-child {
border-radius: 4px 0 0 4px !important;
margin: 0 !important;
}
.grouped.gapless > :last-child {
border-radius: 0 4px 4px 0 !important;
}
input:not(
[type="checkbox"],
[type="radio"],
[type="submit"],
[type="color"],
[type="button"],
[type="reset"],
:disabled
):hover,
select:hover,
textarea:hover,
textarea[type="text"]:hover {
border-color: var(--color-grey);
}
input:not(
[type="checkbox"],
[type="radio"],
[type="submit"],
[type="color"],
[type="button"],
[type="reset"]
):focus,
select:focus,
textarea:focus,
textarea[type="text"]:focus {
border-color: var(--color-primary);
-webkit-box-shadow: 0 0 1px var(--color-primary);
box-shadow: 0 0 1px var(--color-primary);
outline: none;
}
input.error:not(
[type="checkbox"],
[type="radio"],
[type="submit"],
[type="color"],
[type="button"],
[type="reset"]
),
textarea.error {
border-color: var(--color-error);
}
input.success:not(
[type="checkbox"],
[type="radio"],
[type="submit"],
[type="color"],
[type="button"],
[type="reset"]
),
textarea.success {
border-color: var(--color-success);
}
[type="checkbox"],
[type="radio"] {
height: 3.2rem;
width: 4rem;
}
.button + .button {
margin-left: 1rem;
}
.button.secondary {
background-color: var(--color-grey);
}
.button.dark {
background-color: var(--color-darkGrey);
}
.button.error {
background-color: var(--color-error);
}
.button.success {
background-color: var(--color-success);
}
.button.outline {
background-color: transparent;
border-color: var(--color-lightGrey);
}
.button.outline.primary {
border-color: var(--color-primary);
color: var(--color-primary);
}
.button.outline.secondary {
border-color: var(--color-grey);
color: var(--color-grey);
}
.button.outline.dark {
border-color: var(--color-darkGrey);
color: var(--color-darkGrey);
}
.button.clear {
background-color: transparent;
border-color: transparent;
color: var(--color-primary);
}
.button.icon {
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
display: -webkit-inline-box;
display: -ms-inline-flexbox;
display: inline-flex;
}
.button.icon > img {
margin-left: 2px;
}
.button.icon-only {
padding: 1rem;
}
.button:active:not(:disabled),
[type="button"]:active:not(:disabled),
[type="reset"]:active:not(:disabled),
[type="submit"]:active:not(:disabled),
button:active:not(:disabled) {
-webkit-transform: scale(0.98);
transform: scale(0.98);
}
::-webkit-input-placeholder {
color: #bdbfc4;
}
::-moz-placeholder {
color: #bdbfc4;
}
:-ms-input-placeholder {
color: #bdbfc4;
}
::-ms-input-placeholder {
color: #bdbfc4;
}
::placeholder {
color: #bdbfc4;
}
.nav {
-webkit-box-align: stretch;
-ms-flex-align: stretch;
align-items: stretch;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
min-height: 5rem;
}
.nav img {
max-height: 3rem;
}
.nav-center,
.nav-left,
.nav-right,
.nav > .container {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
}
.nav-center,
.nav-left,
.nav-right {
-webkit-box-flex: 1;
-ms-flex: 1;
flex: 1;
}
.nav-left {
-webkit-box-pack: start;
-ms-flex-pack: start;
justify-content: flex-start;
}
.nav-right {
-webkit-box-pack: end;
-ms-flex-pack: end;
justify-content: flex-end;
}
.nav-center {
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
}
@media screen and (max-width: 480px) {
.nav,
.nav > .container {
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
}
.nav-center,
.nav-left,
.nav-right {
-webkit-box-pack: center;
-ms-flex-pack: center;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
justify-content: center;
}
}
.nav .brand,
.nav a {
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
color: var(--color-darkGrey);
display: -webkit-box;
display: -ms-flexbox;
display: flex;
padding: 1rem 2rem;
text-decoration: none;
}
.nav .active:not(.button),
.nav [aria-current="page"]:not(.button) {
color: #000;
color: var(--color-primary);
}
.nav .brand {
font-size: 1.75em;
padding-bottom: 0;
padding-top: 0;
}
.nav .brand img {
padding-right: 1rem;
}
.nav .button {
margin: auto 1rem;
}
.card {
background: var(--bg-color);
border-radius: 4px;
-webkit-box-shadow: 0 1px 3px var(--color-grey);
box-shadow: 0 1px 3px var(--color-grey);
padding: 1rem 2rem;
}
.card p:last-child {
margin: 0;
}
.card header > * {
margin-bottom: 1rem;
margin-top: 0;
}
.tabs {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
}
.tabs a {
text-decoration: none;
}
.tabs > .dropdown > summary,
.tabs > a {
-webkit-box-flex: 0;
border-bottom: 2px solid var(--color-lightGrey);
color: var(--color-darkGrey);
-ms-flex: 0 1 auto;
flex: 0 1 auto;
padding: 1rem 2rem;
text-align: center;
}
.tabs > a:hover {
border-bottom: 2px solid var(--color-darkGrey);
opacity: 1;
}
.tabs > a[aria-selected="true"] {
color: var(--color-primary);
border-bottom: 2px solid var(--color-primary);
opacity: 1;
}
.tabs.is-full a {
-webkit-box-flex: 1;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
}
.tag {
border: 1px solid var(--color-lightGrey);
color: var(--font-color);
display: inline-block;
letter-spacing: 0.5px;
line-height: 1;
padding: 0.5rem;
text-transform: uppercase;
}
.tag.is-small {
font-size: 0.75em;
padding: 0.4rem;
}
.tag.is-large {
font-size: 1.125em;
padding: 0.7rem;
}
.tag + .tag {
margin-left: 1rem;
}
details.dropdown {
display: inline-block;
position: relative;
}
details.dropdown > :last-child {
left: 0;
position: absolute;
white-space: nowrap;
}
.bg-primary {
background-color: var(--color-primary) !important;
}
.bg-light {
background-color: var(--color-lightGrey) !important;
}
.bg-dark {
background-color: var(--color-darkGrey) !important;
}
.bg-grey {
background-color: var(--color-grey) !important;
}
.bg-error {
background-color: var(--color-error) !important;
}
.bg-success {
background-color: var(--color-success) !important;
}
.bd-primary {
border: 1px solid var(--color-primary) !important;
}
.bd-light {
border: 1px solid var(--color-lightGrey) !important;
}
.bd-dark {
border: 1px solid var(--color-darkGrey) !important;
}
.bd-grey {
border: 1px solid var(--color-grey) !important;
}
.bd-error {
border: 1px solid var(--color-error) !important;
}
.bd-success {
border: 1px solid var(--color-success) !important;
}
.text-primary {
color: var(--color-primary) !important;
}
.text-light {
color: var(--color-lightGrey) !important;
}
.text-dark {
color: var(--color-darkGrey) !important;
}
.text-grey {
color: var(--color-grey) !important;
}
.text-error {
color: var(--color-error) !important;
}
.text-success {
color: var(--color-success) !important;
}
.text-white {
color: #fff !important;
}
.pull-right {
float: right !important;
}
.pull-left {
float: left !important;
}
.text-center {
text-align: center;
}
.text-left {
text-align: left;
}
.text-right {
text-align: right;
}
.text-justify {
text-align: justify;
}
.text-uppercase {
text-transform: uppercase;
}
.text-lowercase {
text-transform: lowercase;
}
.text-capitalize {
text-transform: capitalize;
}
.is-full-screen {
min-height: 100vh;
width: 100%;
}
.is-full-width {
width: 100% !important;
}
.is-vertical-align {
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
}
.is-center,
.is-horizontal-align {
-webkit-box-pack: center;
-ms-flex-pack: center;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
justify-content: center;
}
.is-center {
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
.is-right {
-webkit-box-pack: end;
-ms-flex-pack: end;
justify-content: flex-end;
}
.is-left,
.is-right {
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
}
.is-left {
-webkit-box-pack: start;
-ms-flex-pack: start;
justify-content: flex-start;
}
.is-fixed {
position: fixed;
width: 100%;
}
.is-paddingless {
padding: 0 !important;
}
.is-marginless {
margin: 0 !important;
}
.is-pointer {
cursor: pointer !important;
}
.is-rounded {
border-radius: 100%;
}
.clearfix {
clear: both;
content: "";
display: table;
}
.is-hidden {
display: none !important;
}
@media screen and (max-width: 599px) {
.hide-xs {
display: none !important;
}
}
@media screen and (min-width: 600px) and (max-width: 899px) {
.hide-sm {
display: none !important;
}
}
@media screen and (min-width: 900px) and (max-width: 1199px) {
.hide-md {
display: none !important;
}
}
@media screen and (min-width: 1200px) {
.hide-lg {
display: none !important;
}
}
@media print {
.hide-pr {
display: none !important;
}
}
.checkbox-cell {
text-align: center;
}
.aspect-tag {
width: 32px;
height: 32px;
font-size: large;
}
.aspects-cell {
min-width: 120px;
text-align: center;
}
.aspect-container {
display: flex;
flex-direction: column;
align-items: center;
}
.aspects-row {
display: flex;
gap: 8px;
justify-content: center;
flex-wrap: wrap;
}
.tables-grid {
display: grid;
grid-template-columns: 2fr 1fr;
gap: 2rem;
margin-top: 2rem;
}
.table-title {
margin-bottom: 1rem;
padding-bottom: 0.5rem;
border-bottom: 2px solid var(--color-primary);
}
.memory-cell {
cursor: pointer;
transition: color 0.2s ease;
}
.memory-cell:hover {
color: var(--color-primary);
}
</style>
</head>
<body>
<div class="container">
<header class="text-center">
<h1>Hush House Catalogue</h1>
</header>
<div class="grouped">
<input type="search" name="input__text6" id="searchInput" placeholder="Search">
<button class="button icon-only" onclick="performSearch()">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search">
<circle cx="11" cy="11" r="8"></circle>
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
</svg>
</button>
</div>
<div class="tables-grid">
<div class="">
<nav class="nav table-title">
<div class="nav-left">
<h2 class="text-center">Books</h2>
</div>
<div class="nav-right">
<div class="tabs">
<a href="#allbooks" id="allbooks-tab" aria-selected="true">All books</a>
<a href="#owned" id="owned-tab" aria-selected="false">Owned</a>
<a href="#mastered" id="mastered-tab" aria-selected="false">Mastered</a>
</div>
</div>
</nav>
<div class="container">
<table class="striped">
<thead>
<tr class="text-center">
<th>Title</th>
<th>Aspect</th>
<th>Owned</th>
<th>Mastered</th>
<th>Memory</th>
<th>Memory Aspects</th>
</tr>
</thead>
<tbody id="catalogueTableBody"><tr><td colspan="6" class="text-center text-error">Error loading initial data</td></tr></tbody>
</table>
</div>
</div>
<div class="">
<h2 class="table-title text-center">Accessible Memories</h2>
<div class="container">
<table class="striped">
<thead>
<tr>
<th>Memory</th>
<th>Aspects</th>
</tr>
</thead>
<tbody id="memoriesTableBody"><tr><td colspan="2" class="text-center text-error">Error loading initial data</td></tr></tbody>
</table>
</div>
</div>
</div>
</div>
<script>
const API_BASE_URL = "http://localhost:8080";
let allBooksData = []; // Store all books data
document.querySelector(".tabs").addEventListener("click", (e) => {
if (e.target.tagName === "A") {
// Remove selected state from all tabs
document.querySelectorAll(".tabs a").forEach((tab) => {
tab.setAttribute("aria-selected", "false");
});
// Set selected state on clicked tab
e.target.setAttribute("aria-selected", "true");
}
});
// Function to update the books table with data
function updateTable(data) {
const tableBody = document.getElementById("catalogueTableBody");
tableBody.innerHTML = "";
if (data.length === 0) {
tableBody.innerHTML =
'<tr><td colspan="6" class="text-center">No results found</td></tr>';
return;
}
data.forEach((item) => {
const row = document.createElement("tr");
row.innerHTML = `
<td>${escapeHtml(item.title)}</td>
<td class="text-center">
<div class="aspect-container">
<img class="aspect-tag" src="/images/${escapeHtml(
item.aspect.label
)}.webp" alt="${escapeHtml(item.aspect.label)}">
<span class="tag aspect-tag">${escapeHtml(
item.aspect.level
)}</span>
</div>
</td>
<td class="checkbox-cell">
<input type="checkbox" ${
item.owned ? "checked" : ""
} class="owned-checkbox" data-title="${escapeHtml(
item.title
)}">
</td>
<td class="checkbox-cell">
<input type="checkbox" ${
item.mastered ? "checked" : ""
} class="mastered-checkbox" data-title="${escapeHtml(
item.title
)}">
</td>
<td>${escapeHtml(item.memory)}</td>
<td class="aspects-cell">
<div class="aspects-row">
${item.memoryAspects
.map(
(aspect) => `
<div class="aspect-container">
<img class="aspect-tag" src="/images/${escapeHtml(
aspect.label
)}.webp" alt="${escapeHtml(aspect.label)}">
<span class="tag aspect-tag">${escapeHtml(
aspect.level
)}</span>
</div>
`
)
.join("")}
</div>
</td>
`;
const ownedCheckbox = row.querySelector(".owned-checkbox");
const masteredCheckbox = row.querySelector(".mastered-checkbox");
ownedCheckbox.addEventListener("change", function () {
updateStatus(this.dataset.title, "owned", this.checked);
});
masteredCheckbox.addEventListener("change", function () {
updateStatus(this.dataset.title, "mastered", this.checked);
});
tableBody.appendChild(row);
});
updateMemoriesTable(data);
}
function generateUserId() {
// Start from a reasonable base number to avoid confusion with test/admin IDs
const baseNumber = 10000;
// Generate a random integer between baseNumber and baseNumber + 89999
// This gives us 90,000 possible unique IDs from 10000 to 99999
return Math.floor(Math.random() * 90000) + baseNumber;
}
// In your main JS file
function getUserId() {
let userId = localStorage.getItem('userId');
if (!userId) {
// Generate a random ID if none exists
userId = generateUserId();
localStorage.setItem('userId', userId);
}
return userId;
}
function updateMemoriesTable(data) {
const memoriesTableBody = document.getElementById("memoriesTableBody");
memoriesTableBody.innerHTML = "";
const masteredMemories = data
.filter((item) => item.mastered)
.reduce((acc, item) => {
if (item.memory && !acc.some((m) => m.memory === item.memory)) {
acc.push({
memory: item.memory,
aspects: item.memoryAspects,
});
}
return acc;
}, []);
if (masteredMemories.length === 0) {
memoriesTableBody.innerHTML =
'<tr><td colspan="2" class="text-center">No accessible memories</td></tr>';
return;
}
masteredMemories.forEach((item) => {
const row = document.createElement("tr");
row.innerHTML = `
<td class="memory-cell" onclick="showMemoryBooks('${escapeHtml(
item.memory
)}')">${escapeHtml(item.memory)}</td>
<td class="aspects-cell">
<div class="aspects-row">
${item.aspects
.map(
(aspect) => `
<div class="aspect-container">
<img class="aspect-tag" src="/images/${escapeHtml(
aspect.label
)}.webp" alt="${escapeHtml(aspect.label)}">
<span class="tag aspect-tag">${escapeHtml(
aspect.level
)}</span>
</div>
`
)
.join("")}
</div>
</td>
`;
memoriesTableBody.appendChild(row);
});
}
// Modify your update status function
async function updateStatus(title, field, value) {
try {
const userId = getUserId();
const response = await fetch(`${API_BASE_URL}/update`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
user_id: userId,
title: title,
field: field,
value: value
})
});
if (!response.ok) {
throw new Error('Failed to update status');
}
// Update the local allBooksData array
const bookIndex = allBooksData.findIndex(book => book.title === title);
if (bookIndex !== -1) {
// Update the specific field (owned or mastered)
allBooksData[bookIndex][field] = value;
// If checking mastered, ensure owned is also checked
if (field === 'mastered' && value) {
allBooksData[bookIndex].owned = true;
// Also update the checkbox in the UI
const ownedCheckbox = document.querySelector(`.owned-checkbox[data-title="${title}"]`);
if (ownedCheckbox) {
ownedCheckbox.checked = true;
}
}
}
else {
console.log(allBooksData);
console.error('Book not found:', title);
}
// Re-render the tables to reflect the changes
updateTable(allBooksData);
} catch (error) {
console.error('Error updating status:', error);
alert('Failed to update status. Please try again.');
await initializePage();
}
}
function showError(message) {
const tableBody = document.getElementById("catalogueTableBody");
const memoriesTableBody = document.getElementById("memoriesTableBody");
tableBody.innerHTML = `<tr><td colspan="6" class="text-center text-error">${escapeHtml(
message
)}</td></tr>`;
memoriesTableBody.innerHTML = `<tr><td colspan="2" class="text-center text-error">${escapeHtml(
message
)}</td></tr>`;
}
// Modify your initialization function
async function initializePage() {
try {
const userId = getUserId();
const response = await fetch(`${API_BASE_URL}/all?userId=${userId}`);
if (!response.ok) {
throw new Error('Failed to fetch initial data');
}
const data = await response.json();
allBooksData = data;
updateTable(data);
} catch (error) {
console.error('Initialization error:', error);
showError('Error loading initial data');
}
}
function performSearch() {
const searchTerm = document
.getElementById("searchInput")
.value.toLowerCase()
.trim();
if (!searchTerm) {
updateTable(allBooksData);
return;
}
const filteredData = allBooksData.filter((book) =>
book.title.toLowerCase().includes(searchTerm)
);
updateTable(filteredData);
}
function escapeHtml(unsafe) {
if (unsafe === null || unsafe === undefined) return "";
return unsafe
.toString()
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
// Event listeners
document
.getElementById("searchInput")
.addEventListener("keyup", function (event) {
performSearch();
});
document.addEventListener("DOMContentLoaded", () => {
document
.querySelector(".nav-right")
.addEventListener("click", async (e) => {
if (e.target.tagName === "A" && e.target.closest(".tabs")) {
// Remove selected state from all tabs
document.querySelectorAll(".tabs a").forEach((tab) => {
tab.setAttribute("aria-selected", "false");
});
// Set selected state on clicked tab
e.target.setAttribute("aria-selected", "true");
// Handle different tab selections with fresh data
switch (e.target.id) {
case "allbooks-tab":
showAllBooks();
break;
case "owned-tab":
showOwnedBooks();
break;
case "mastered-tab":
showMasteredBooks();
break;
default:
showAllBooks();
}
}
});
initializePage();
});
function showAllBooks() {
console.log("Showing all books");
updateTable(allBooksData);
}
function showOwnedBooks() {
console.log("Showing owned books");
const ownedBooks = allBooksData.filter((book) => book.owned);
updateTable(ownedBooks);
}
function showMasteredBooks() {
console.log("Showing mastered books");
const masteredBooks = allBooksData.filter((book) => book.mastered);
updateTable(masteredBooks);
}
function showMemoryBooks(memory) {
console.log("Showing memory books");
const memoryBooks = allBooksData
.filter((book) => book.mastered)
.filter((book) => book.memory === memory);
document.querySelectorAll(".tabs a").forEach((tab) => {
tab.setAttribute("aria-selected", "false");
});
document
.getElementById("allbooks-tab")
.setAttribute("aria-selected", "true");
updateTable(memoryBooks);
}
</script>
</body></html>