mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Completed frontend controls
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
export class Control {
|
||||
#container: HTMLElement | null;
|
||||
expectedValue: any = null;
|
||||
|
||||
constructor(ID: string) {
|
||||
this.#container = document.getElementById(ID);
|
||||
@@ -18,4 +19,16 @@ export class Control {
|
||||
getContainer() {
|
||||
return this.#container;
|
||||
}
|
||||
|
||||
setExpectedValue(expectedValue: any) {
|
||||
this.expectedValue = expectedValue;
|
||||
}
|
||||
|
||||
resetExpectedValue() {
|
||||
this.expectedValue = null;
|
||||
}
|
||||
|
||||
checkExpectedValue(value: any) {
|
||||
return this.expectedValue === null || value === this.expectedValue;
|
||||
}
|
||||
}
|
||||
@@ -19,14 +19,12 @@ export class Dropdown {
|
||||
}
|
||||
|
||||
this.#value.addEventListener("click", (ev) => {
|
||||
this.#element.classList.toggle("is-open");
|
||||
this.#options.classList.toggle("scrollbar-visible", this.#options.scrollHeight > this.#options.clientHeight);
|
||||
this.#clip();
|
||||
this.#toggle();
|
||||
});
|
||||
|
||||
document.addEventListener("click", (ev) => {
|
||||
if (!(this.#value.contains(ev.target as Node) || this.#options.contains(ev.target as Node) || this.#element.contains(ev.target as Node))) {
|
||||
this.#element.classList.remove("is-open");
|
||||
this.#close();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -46,12 +44,7 @@ export class Dropdown {
|
||||
|
||||
button.addEventListener("click", (e: MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
this.#value = document.createElement("div");
|
||||
this.#value.classList.add("ol-ellipsed");
|
||||
this.#value.innerText = option;
|
||||
this.#close();
|
||||
this.#callback(option, e);
|
||||
this.#index = idx;
|
||||
this.selectValue(idx);
|
||||
});
|
||||
return div;
|
||||
}));
|
||||
@@ -113,6 +106,8 @@ export class Dropdown {
|
||||
|
||||
#open() {
|
||||
this.#element.classList.add("is-open");
|
||||
this.#options.classList.toggle("scrollbar-visible", this.#options.scrollHeight > this.#options.clientHeight);
|
||||
this.#clip();
|
||||
}
|
||||
|
||||
#toggle() {
|
||||
|
||||
@@ -5,6 +5,8 @@ import { aircraftDatabase } from "../units/aircraftdatabase";
|
||||
import { groundUnitsDatabase } from "../units/groundunitsdatabase";
|
||||
import { ContextMenu } from "./contextmenu";
|
||||
import { Dropdown } from "./dropdown";
|
||||
import { Switch } from "./switch";
|
||||
import { Slider } from "./slider";
|
||||
|
||||
export interface SpawnOptions {
|
||||
role: string;
|
||||
@@ -13,24 +15,29 @@ export interface SpawnOptions {
|
||||
coalition: string;
|
||||
loadout: string | null;
|
||||
airbaseName: string | null;
|
||||
altitude: number | null;
|
||||
}
|
||||
|
||||
export class MapContextMenu extends ContextMenu {
|
||||
#coalitionSwitch: Switch;
|
||||
#aircraftRoleDropdown: Dropdown;
|
||||
#aircraftTypeDropdown: Dropdown;
|
||||
#aircraftLoadoutDropdown: Dropdown;
|
||||
#aircrafSpawnAltitudeSlider: Slider;
|
||||
#groundUnitRoleDropdown: Dropdown;
|
||||
#groundUnitTypeDropdown: Dropdown;
|
||||
#spawnOptions: SpawnOptions = { role: "", type: "", latlng: new LatLng(0, 0), loadout: null, coalition: "blue", airbaseName: null };
|
||||
|
||||
#spawnOptions: SpawnOptions = { role: "", type: "", latlng: new LatLng(0, 0), loadout: null, coalition: "blue", airbaseName: null, altitude: 20000 };
|
||||
|
||||
constructor(id: string) {
|
||||
super(id);
|
||||
this.getContainer()?.querySelector("#context-menu-switch")?.addEventListener('click', (e) => this.#onToggleLeftClick(e));
|
||||
this.getContainer()?.querySelector("#context-menu-switch")?.addEventListener('contextmenu', (e) => this.#onToggleRightClick(e));
|
||||
|
||||
this.#coalitionSwitch = new Switch("coalition-switch", this.#onSwitchClick);
|
||||
this.#coalitionSwitch.setValue(false);
|
||||
this.#coalitionSwitch.getContainer()?.addEventListener("contextmenu", (e) => this.#onSwitchRightClick(e));
|
||||
this.#aircraftRoleDropdown = new Dropdown("aircraft-role-options", (role: string) => this.#setAircraftRole(role));
|
||||
this.#aircraftTypeDropdown = new Dropdown("aircraft-type-options", (type: string) => this.#setAircraftType(type));
|
||||
this.#aircraftLoadoutDropdown = new Dropdown("loadout-options", (loadout: string) => this.#setAircraftLoadout(loadout));
|
||||
this.#aircrafSpawnAltitudeSlider = new Slider("aircraft-spawn-altitude-slider", 0, 50000, "ft", (value: number) => {this.#spawnOptions.altitude = value;});
|
||||
this.#groundUnitRoleDropdown = new Dropdown("ground-unit-role-options", (role: string) => this.#setGroundUnitRole(role));
|
||||
this.#groundUnitTypeDropdown = new Dropdown("ground-unit-type-options", (type: string) => this.#setGroundUnitType(type));
|
||||
|
||||
@@ -61,6 +68,10 @@ export class MapContextMenu extends ContextMenu {
|
||||
spawnSmoke(e.detail.color, this.getLatLng());
|
||||
});
|
||||
|
||||
this.#aircrafSpawnAltitudeSlider.setIncrement(500);
|
||||
this.#aircrafSpawnAltitudeSlider.setValue(20000);
|
||||
this.#aircrafSpawnAltitudeSlider.setActive(true);
|
||||
|
||||
this.hide();
|
||||
}
|
||||
|
||||
@@ -102,26 +113,13 @@ export class MapContextMenu extends ContextMenu {
|
||||
this.#spawnOptions.latlng = latlng;
|
||||
}
|
||||
|
||||
#onToggleLeftClick(e: any) {
|
||||
if (this.getContainer() != null) {
|
||||
if (e.srcElement.dataset.activeCoalition == "blue")
|
||||
setActiveCoalition("neutral");
|
||||
else if (e.srcElement.dataset.activeCoalition == "neutral")
|
||||
setActiveCoalition("red");
|
||||
else
|
||||
setActiveCoalition("blue");
|
||||
}
|
||||
#onSwitchClick(value: boolean) {
|
||||
value? setActiveCoalition("red"): setActiveCoalition("blue");
|
||||
}
|
||||
|
||||
#onToggleRightClick(e: any) {
|
||||
if (this.getContainer() != null) {
|
||||
if (e.srcElement.dataset.activeCoalition == "red")
|
||||
setActiveCoalition("neutral");
|
||||
else if (e.srcElement.dataset.activeCoalition == "neutral")
|
||||
setActiveCoalition("blue");
|
||||
else
|
||||
setActiveCoalition("red");
|
||||
}
|
||||
#onSwitchRightClick(e: any) {
|
||||
this.#coalitionSwitch.setValue(undefined);
|
||||
setActiveCoalition("neutral");
|
||||
}
|
||||
|
||||
/********* Aircraft spawn menu *********/
|
||||
|
||||
@@ -2,38 +2,38 @@ import { zeroPad } from "../other/utils";
|
||||
import { Control } from "./control";
|
||||
|
||||
export class Slider extends Control {
|
||||
#callback: CallableFunction;
|
||||
#callback: CallableFunction | null = null;
|
||||
#slider: HTMLInputElement | null = null;
|
||||
#valueText: HTMLElement | null = null;
|
||||
#minValue: number;
|
||||
#maxValue: number;
|
||||
#increment: number;
|
||||
#minValue: number = 0;
|
||||
#maxValue: number = 0;
|
||||
#increment: number = 0;
|
||||
#minMaxValueDiv: HTMLElement | null = null;
|
||||
#unit: string;
|
||||
#unitOfMeasure: string;
|
||||
#dragged: boolean = false;
|
||||
#value: number = 0;
|
||||
|
||||
constructor(ID: string, minValue: number, maxValue: number, unit: string, callback: CallableFunction) {
|
||||
constructor(ID: string, minValue: number, maxValue: number, unitOfMeasure: string, callback: CallableFunction) {
|
||||
super(ID);
|
||||
this.#callback = callback;
|
||||
this.#minValue = minValue;
|
||||
this.#maxValue = maxValue;
|
||||
this.#increment = 1;
|
||||
this.#unit = unit;
|
||||
this.#callback = callback;
|
||||
this.#unitOfMeasure = unitOfMeasure;
|
||||
this.#slider = this.getContainer()?.querySelector("input") as HTMLInputElement;
|
||||
|
||||
if (this.#slider != null) {
|
||||
this.#slider.addEventListener("input", (e: any) => this.#onInput());
|
||||
this.#slider.addEventListener("input", (e: any) => this.#update());
|
||||
this.#slider.addEventListener("mousedown", (e: any) => this.#onStart());
|
||||
this.#slider.addEventListener("mouseup", (e: any) => this.#onFinalize());
|
||||
}
|
||||
|
||||
this.#valueText = this.getContainer()?.querySelector(".ol-slider-value") as HTMLElement;
|
||||
this.#minMaxValueDiv = this.getContainer()?.querySelector(".ol-slider-min-max") as HTMLElement;
|
||||
|
||||
this.setIncrement(1);
|
||||
this.setMinMax(minValue, maxValue);
|
||||
}
|
||||
|
||||
setActive(newActive: boolean) {
|
||||
if (!this.#dragged) {
|
||||
if (!this.getDragged()) {
|
||||
this.getContainer()?.classList.toggle("active", newActive);
|
||||
if (!newActive && this.#valueText != null)
|
||||
this.#valueText.innerText = "Mixed values";
|
||||
@@ -41,27 +41,31 @@ export class Slider extends Control {
|
||||
}
|
||||
|
||||
setMinMax(newMinValue: number, newMaxValue: number) {
|
||||
this.#minValue = newMinValue;
|
||||
this.#maxValue = newMaxValue;
|
||||
this.#updateMax();
|
||||
if (this.#minMaxValueDiv != null) {
|
||||
this.#minMaxValueDiv.setAttribute('data-min-value', `${this.#minValue}${this.#unit}`);
|
||||
this.#minMaxValueDiv.setAttribute('data-max-value', `${this.#maxValue}${this.#unit}`);
|
||||
if (this.#minValue != newMinValue || this.#maxValue != newMaxValue) {
|
||||
this.#minValue = newMinValue;
|
||||
this.#maxValue = newMaxValue;
|
||||
this.#updateMaxValue();
|
||||
|
||||
if (this.#minMaxValueDiv != null) {
|
||||
this.#minMaxValueDiv.setAttribute('data-min-value', `${this.#minValue}${this.#unitOfMeasure}`);
|
||||
this.#minMaxValueDiv.setAttribute('data-max-value', `${this.#maxValue}${this.#unitOfMeasure}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setIncrement(newIncrement: number) {
|
||||
this.#increment = newIncrement;
|
||||
this.#updateMax();
|
||||
if (this.#increment != newIncrement) {
|
||||
this.#increment = newIncrement;
|
||||
this.#updateMaxValue();
|
||||
}
|
||||
}
|
||||
|
||||
setValue(newValue: number) {
|
||||
// Disable value setting if the user is dragging the element
|
||||
if (!this.#dragged) {
|
||||
setValue(newValue: number, ignoreExpectedValue: boolean = true) {
|
||||
if (!this.getDragged() && (ignoreExpectedValue || this.checkExpectedValue(newValue))) {
|
||||
this.#value = newValue;
|
||||
if (this.#slider != null)
|
||||
this.#slider.value = String((newValue - this.#minValue) / (this.#maxValue - this.#minValue) * parseFloat(this.#slider.max));
|
||||
this.#onValue()
|
||||
this.#update();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,45 +73,51 @@ export class Slider extends Control {
|
||||
return this.#value;
|
||||
}
|
||||
|
||||
setDragged(newDragged: boolean) {
|
||||
this.#dragged = newDragged;
|
||||
}
|
||||
|
||||
getDragged() {
|
||||
return this.#dragged;
|
||||
}
|
||||
|
||||
#updateMax() {
|
||||
#updateMaxValue() {
|
||||
var oldValue = this.getValue();
|
||||
if (this.#slider != null)
|
||||
this.#slider.max = String((this.#maxValue - this.#minValue) / this.#increment);
|
||||
this.setValue(oldValue);
|
||||
}
|
||||
|
||||
#onValue() {
|
||||
#update() {
|
||||
if (this.#valueText != null && this.#slider != null)
|
||||
{
|
||||
/* Update the text value */
|
||||
var value = this.#minValue + Math.round(parseFloat(this.#slider.value) / parseFloat(this.#slider.max) * (this.#maxValue - this.#minValue));
|
||||
var strValue = String(value);
|
||||
if (value > 1000)
|
||||
strValue = String(Math.floor(value / 1000)) + "," + zeroPad(value - Math.floor(value / 1000) * 1000, 3);
|
||||
this.#valueText.innerText = strValue + " " + this.#unit.toUpperCase();
|
||||
this.#valueText.innerText = `${strValue} ${this.#unitOfMeasure.toUpperCase()}`;
|
||||
|
||||
/* Update the position of the slider */
|
||||
var percentValue = parseFloat(this.#slider.value) / parseFloat(this.#slider.max) * 90 + 5;
|
||||
this.#slider.style.background = 'linear-gradient(to right, var(--accent-light-blue) 5%, var(--accent-light-blue) ' + percentValue + '%, var(--background-grey) ' + percentValue + '%, var(--background-grey) 100%)'
|
||||
this.#slider.style.background = `linear-gradient(to right, var(--accent-light-blue) 5%, var(--accent-light-blue) ${percentValue}%, var(--background-grey) ${percentValue}%, var(--background-grey) 100%)`
|
||||
}
|
||||
this.setActive(true);
|
||||
}
|
||||
|
||||
#onInput() {
|
||||
this.#onValue();
|
||||
}
|
||||
|
||||
#onStart() {
|
||||
this.#dragged = true;
|
||||
this.setDragged(true);
|
||||
}
|
||||
|
||||
#onFinalize() {
|
||||
this.#dragged = false;
|
||||
this.setDragged(false);
|
||||
if (this.#slider != null) {
|
||||
this.#value = this.#minValue + parseFloat(this.#slider.value) / parseFloat(this.#slider.max) * (this.#maxValue - this.#minValue);
|
||||
this.#callback(this.getValue());
|
||||
this.resetExpectedValue();
|
||||
this.setValue(this.#minValue + parseFloat(this.#slider.value) / parseFloat(this.#slider.max) * (this.#maxValue - this.#minValue));
|
||||
if (this.#callback) {
|
||||
this.#callback(this.getValue());
|
||||
this.setExpectedValue(this.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,16 @@
|
||||
import { Control } from "./control";
|
||||
|
||||
export class Switch extends Control {
|
||||
#value: boolean = false;
|
||||
constructor(ID: string, initialValue?: boolean) {
|
||||
#value: boolean | undefined = false;
|
||||
#callback: CallableFunction | null = null;
|
||||
|
||||
constructor(ID: string, callback: CallableFunction, initialValue?: boolean) {
|
||||
super(ID);
|
||||
this.getContainer()?.addEventListener('click', (e) => this.#onToggle());
|
||||
this.setValue(initialValue !== undefined? initialValue: true);
|
||||
|
||||
this.#callback = callback;
|
||||
|
||||
/* Add the toggle itself to the document */
|
||||
const container = this.getContainer();
|
||||
if (container != undefined){
|
||||
@@ -14,14 +18,17 @@ export class Switch extends Control {
|
||||
const height = getComputedStyle(container).height;
|
||||
var el = document.createElement("div");
|
||||
el.classList.add("ol-switch-fill");
|
||||
el.style.setProperty("--width", width? width: "0px");
|
||||
el.style.setProperty("--height", height? height: "0px");
|
||||
el.style.setProperty("--width", width? width: "0");
|
||||
el.style.setProperty("--height", height? height: "0");
|
||||
this.getContainer()?.appendChild(el);
|
||||
}
|
||||
}
|
||||
setValue(value: boolean) {
|
||||
this.#value = value;
|
||||
this.getContainer()?.setAttribute("data-value", String(value));
|
||||
|
||||
setValue(newValue: boolean | undefined, ignoreExpectedValue: boolean = true) {
|
||||
if (ignoreExpectedValue || this.checkExpectedValue(newValue)) {
|
||||
this.#value = newValue;
|
||||
this.getContainer()?.setAttribute("data-value", String(newValue));
|
||||
}
|
||||
}
|
||||
|
||||
getValue() {
|
||||
@@ -29,6 +36,11 @@ export class Switch extends Control {
|
||||
}
|
||||
|
||||
#onToggle() {
|
||||
this.resetExpectedValue();
|
||||
this.setValue(!this.getValue());
|
||||
if (this.#callback) {
|
||||
this.#callback(this.getValue());
|
||||
this.setExpectedValue(this.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user