diff --git a/ZATACKA.html b/ZATACKA.html index 029d788..8367950 100644 --- a/ZATACKA.html +++ b/ZATACKA.html @@ -63,7 +63,7 @@

Achtung, die Kurve!

-
+
  • @@ -90,6 +90,7 @@

    Achtung, die Kurve!

+
+
@@ -135,6 +140,7 @@

Achtung, die Kurve!

+ diff --git a/Zatacka.css b/Zatacka.css index 55642fe..da1760b 100644 --- a/Zatacka.css +++ b/Zatacka.css @@ -34,43 +34,61 @@ a:hover, a:focus, a:active { text-decoration: none; } -input[type="checkbox"] { +input[type="checkbox"], +input[type="radio"] { display: none; } /* Checkbox and label: */ -input[type="checkbox"] + label { - cursor: pointer; - opacity: 0.75; +input[type="checkbox"] + label, +input[type="radio"] + label { padding-left: 18px; position: relative; } -/* Checkbox and label on hover: */ -input[type="checkbox"] + label:hover, -input[type="checkbox"] + label:focus, -input[type="checkbox"] + label:active { - opacity: 1; -} - /* Actual checkbox: */ -input[type="checkbox"] + label::before { - border: 1px white solid; +input[type="checkbox"] + label::before, +input[type="radio"] + label::before { + background-position: center center; + background-repeat: no-repeat; box-sizing: border-box; content: ""; display: inline-block; height: 12px; left: 0; position: absolute; - top: 1px; + top: 2px; width: 12px; } +input[type="checkbox"] + label::before { + border: 1px white solid; +} + +input[type="radio"] + label::before { + background-image: url("resources/kurve-radio-button.png"); +} + /* Actual checkbox when checked: */ input[type="checkbox"]:checked + label::before { background-image: url("resources/kurve-checkbox-tickmark.png"); - background-position: center center; - background-repeat: no-repeat; +} + +input[type="radio"]:checked + label::before { + background-image: url("resources/kurve-radio-button-checked.png"); +} + +input[type="checkbox"] + label, +input[type="radio"] + label { + padding-top: 1px; + padding-bottom: 1px; +} + +/* Checkbox and label on hover: */ +input[type="checkbox"] + label, +input[type="radio"] + label, +select { + cursor: pointer; } .button { @@ -131,6 +149,24 @@ input[type="checkbox"]:checked + label::before { cursor: none; } +.icon-button { + background-image: url("resources/kurve-icons.png"); + cursor: pointer; + height: 16px; + opacity: 0.75; + width: 16px; +} + +.icon-button:hover, .icon-button:focus, .icon-button:active { + opacity: 1; +} + +.corner { + position: absolute; + right: 16px; + top: 16px; +} + #debug { background-color: black; border: 1px white solid; @@ -185,6 +221,10 @@ input[type="checkbox"]:checked + label::before { border-color: #515151; } +.flex { + display: flex; +} + .overlay { display: block; height: 100%; @@ -195,6 +235,10 @@ input[type="checkbox"]:checked + label::before { box-sizing: border-box; } +.hidden { + display: none; +} + .unobtrusive { pointer-events: none; } @@ -204,14 +248,15 @@ input[type="checkbox"]:checked + label::before { overflow: hidden; } -#lobby.hidden, #KONEC_HRY.hidden { - display: none; +#lobby { + padding-left: 81px; + padding-top: 50px; + padding-bottom: 130px; /* 130 = 480 - 7 * 50, where 50 is the total height of each player's controls and 7 is 6 players plus 1 for margin */ } #lobby #controls { + display: inline-block; list-style-type: none; - margin-left: 80px; - margin-top: 50px; } #lobby #controls li { @@ -229,13 +274,13 @@ input[type="checkbox"]:checked + label::before { } #lobby #controls .ready { + visibility: hidden; background-image: url("resources/kurve-lobby-controls-ready.png"); - display: none; width: 80px; } #lobby #controls .ready.active { - display: block; + visibility: visible; } #lobby #controls .red.controls { background-position: 0px 0px; } @@ -251,8 +296,77 @@ input[type="checkbox"]:checked + label::before { #lobby #controls .blue.controls { background-position: 0px -250px; } #lobby #controls .blue.ready { background-position: -160px -250px; } -#lobby footer { +#button-show-settings { + background-position: 0 -16px; +} + +#button-hide-settings { + background-position: 0 0; +} + +#settings { + background-color: rgba(0, 0, 0, 0.95); + padding: 50px 80px 50px 80px; +} + +#settings-form > div { + box-sizing: border-box; + margin: 12px 0; + opacity: 0.6; +} + +#settings-form > div:hover { + opacity: 1; +} + +#settings-form > div:hover .description { + visibility: visible; +} + +#settings-form fieldset { + border: 1px solid white; + padding: 2px 8px 6px 8px; +} + +#settings-form fieldset legend { + padding: 0 4px; +} + +#settings-form input[type="checkbox"] + label { + margin-left: 13px; /* to align with fieldset content */ +} + +#settings-form fieldset input[type="radio"] + label { + margin-left: 4px; /* to align with legend */ +} + +#settings-form label { + display: inline-block; +} + +#settings-form .description { + box-sizing: border-box; + bottom: 0; + font-size: 0.75em; + height: 50px; + left: 0; + opacity: 0.8; padding: 0 80px; + position: absolute; + visibility: hidden; + width: 100%; +} + +#settings-form select { + background: black; + border: 1px solid white; + color: white; + margin-top: 2px; + width: 219px; +} + +#settings-form input[type="radio"] + label { + display: block; } #messages { @@ -274,6 +388,15 @@ input[type="checkbox"]:checked + label::before { color: #C3C300; } +#messages.hints-none .message, +#messages.hints-warnings-only .message { + display: none; +} + +#messages.hints-warnings-only .message.warning { + display: block; +} + .canvasHeight { height: 480px; } diff --git a/index.html b/index.html index 089a101..b4f78c4 100644 --- a/index.html +++ b/index.html @@ -64,6 +64,7 @@

Achtung, die Kurve!

+ diff --git a/js/GUIController.js b/js/GUIController.js index 6a904fb..40c8cc9 100644 --- a/js/GUIController.js +++ b/js/GUIController.js @@ -2,10 +2,6 @@ function GUIController(cfg) { - const CURSOR_VISIBLE = "visible"; - const CURSOR_HIDDEN_ON_CANVAS = "hidden_on_canvas"; - const CURSOR_HIDDEN = "hidden"; - const config = cfg; const lobby = byID("lobby"); const controls = byID("controls"); @@ -16,6 +12,8 @@ function GUIController(cfg) { const results = byID("results"); const KONEC_HRY = byID("KONEC_HRY"); const messagesContainer = byID("messages"); + const settingsContainer = byID("settings"); + const settingsForm = byID("settings-form"); const ORIGINAL_LEFT_WIDTH = left.offsetWidth; @@ -52,14 +50,10 @@ function GUIController(cfg) { function setCursorBehavior(behavior) { switch (behavior) { - case CURSOR_VISIBLE: + case STRINGS.cursor_visible: document.body.classList.remove(STRINGS.class_nocursor); break; - case CURSOR_HIDDEN_ON_CANVAS: - canvas_main.classList.add(STRINGS.class_nocursor); - canvas_overlay.classList.add(STRINGS.class_nocursor); - break; - case CURSOR_HIDDEN: + case STRINGS.cursor_hidden: document.body.classList.add(STRINGS.class_nocursor); break; default: @@ -67,8 +61,66 @@ function GUIController(cfg) { } } - function resetCursorBehavior() { - setCursorBehavior(CURSOR_VISIBLE); + function settingsEntryHTMLElement(preference, preferenceValue) { + if (!preference instanceof Preference) { + throw new TypeError(`${preference} is not a preference.`); + } + + // Common + const div = document.createElement("div"); + const label = document.createElement("label"); + label.textContent = preference.label; + label.setAttribute("for", `${STRINGS.html_name_preference_prefix}${preference.key}`); + const description = document.createElement("aside"); + description.textContent = preference.description; + description.classList.add(STRINGS.class_description); + + // Boolean + if (preference instanceof BooleanPreference) { + const input = document.createElement("input"); + input.type = "checkbox"; + input.dataset.key = preference.key; + input.id = STRINGS.html_name_preference_prefix + preference.key; + input.checked = preferenceValue === true; + div.appendChild(input); + div.appendChild(label); + } + + // Multichoice + else if (preference instanceof MultichoicePreference) { + const fieldset = document.createElement("fieldset"); + const legend = document.createElement("legend"); + legend.textContent = preference.label; + fieldset.appendChild(legend); + preference.values.forEach((value, index) => { + const id = STRINGS.html_name_preference_prefix + preference.key + "-" + preference.values[index]; + const radioButton = document.createElement("input"); + radioButton.type = "radio"; + radioButton.id = id; + radioButton.name = STRINGS.html_name_preference_prefix + preference.key; + radioButton.value = value; + radioButton.dataset.key = preference.key; + radioButton.checked = preferenceValue === value; + const radioButtonLabel = document.createElement("label"); + radioButtonLabel.textContent = preference.labels[index]; + radioButtonLabel.setAttribute("for", id); + fieldset.appendChild(radioButton); + fieldset.appendChild(radioButtonLabel); + }); + div.appendChild(fieldset); + } + + // Range + else if (preference instanceof RangePreference) { + div.appendChild(label); + const input = document.createElement("input"); + input.type = "number"; + input.name = STRINGS.html_name_preference_prefix + preference.key; + div.appendChild(input); + } + + div.appendChild(description); + return div; } @@ -115,7 +167,7 @@ function GUIController(cfg) { resetScoreboard(); resetResults(); allPlayersUnready(); - resetCursorBehavior(); + setCursorBehavior(STRINGS.cursor_visible); } function konecHry() { @@ -138,6 +190,47 @@ function GUIController(cfg) { updateMessages(currentMessages); } + function showSettings() { + settings.classList.remove(STRINGS.class_hidden); + } + + function hideSettings() { + settings.classList.add(STRINGS.class_hidden); + } + + function updateSettingsForm(preferencesWithData) { + flush(settingsForm); + preferencesWithData.forEach((preferenceWithData) => { + settingsForm.appendChild(settingsEntryHTMLElement(preferenceWithData.preference, preferenceWithData.value)); + }); + } + + function parseSettingsForm() { + const newSettings = []; + // elements: + const inputs = settingsForm.querySelectorAll("input"); + Array.from(inputs).forEach((input) => { + if (input.type === "checkbox") { + // checkbox + newSettings.push({ key: input.dataset.key, value: input.checked }); + } else if (input.type === "radio") { + // radio + if (input.checked === true) { + newSettings.push({ key: input.dataset.key, value: input.value }); + } + } else { + // text, number etc + newSettings.push({ key: input.dataset.key, value: input.value.toString() }); + } + }); + //