Fix floating point number imprecision when configuring keybinds
Refactor keybind input code to improve performance and fix inconsistenciesmain
parent
05f59c31bd
commit
14c94507f3
|
@ -1,4 +1,7 @@
|
||||||
|
const truncate = n => parseFloat(n.toFixed(12));
|
||||||
|
|
||||||
export function KeybindsInput(/** @type {HTMLElement} */ containerElement) {
|
export function KeybindsInput(/** @type {HTMLElement} */ containerElement) {
|
||||||
|
|
||||||
const header = document.createElement("p");
|
const header = document.createElement("p");
|
||||||
header.innerText = "Attack Percentage Keybinds";
|
header.innerText = "Attack Percentage Keybinds";
|
||||||
const keybindContainer = document.createElement("div");
|
const keybindContainer = document.createElement("div");
|
||||||
|
@ -6,61 +9,70 @@ export function KeybindsInput(/** @type {HTMLElement} */ containerElement) {
|
||||||
const keybindAddButton = document.createElement("button");
|
const keybindAddButton = document.createElement("button");
|
||||||
keybindAddButton.innerText = "Add";
|
keybindAddButton.innerText = "Add";
|
||||||
containerElement.append(header, keybindContainer, keybindAddButton);
|
containerElement.append(header, keybindContainer, keybindAddButton);
|
||||||
|
|
||||||
containerElement.className = "keybinds-input";
|
containerElement.className = "keybinds-input";
|
||||||
this.container = keybindContainer;
|
this.container = keybindContainer;
|
||||||
this.keys = [ "key", "type", "value" ];
|
this.objectKeys = ["key", "type", "value"];
|
||||||
this.objectArray = [];
|
this.objectArray = [];
|
||||||
this.addObject = function () {
|
this.addObject = function () {
|
||||||
this.objectArray.push({ key: "", type: "absolute", value: 0.8 });
|
this.objectArray.push({ key: "", type: "absolute", value: 0.8 });
|
||||||
this.displayObjects();
|
this.container.appendChild(createInputRow(this.objectArray.length - 1));
|
||||||
keybindAddButton.scrollIntoView(false);
|
keybindAddButton.scrollIntoView(false);
|
||||||
};
|
};
|
||||||
|
keybindAddButton.addEventListener("click", this.addObject.bind(this));
|
||||||
this.update = function (settings) {
|
this.update = function (settings) {
|
||||||
this.objectArray = settings.attackPercentageKeybinds;
|
this.objectArray = settings.attackPercentageKeybinds;
|
||||||
this.displayObjects();
|
this.displayObjects();
|
||||||
}
|
}
|
||||||
keybindAddButton.addEventListener("click", this.addObject.bind(this));
|
|
||||||
this.displayObjects = function () {
|
this.displayObjects = function () {
|
||||||
// Clear the content of the container
|
// Clear the content of the container
|
||||||
this.container.innerHTML = "";
|
this.container.innerHTML = "";
|
||||||
if (this.objectArray.length === 0) return this.container.innerText = "No custom attack percentage keybinds added";
|
if (this.objectArray.length === 0) return this.container.innerText = "No custom attack percentage keybinds added";
|
||||||
// Loop through the array and display input fields for each object
|
// Loop through the array and display input fields for each object
|
||||||
for (var i = 0; i < this.objectArray.length; i++) {
|
for (var i = 0; i < this.objectArray.length; i++) {
|
||||||
var objectDiv = document.createElement("div");
|
this.container.appendChild(createInputRow(i));
|
||||||
// Create input fields for each key
|
|
||||||
this.keys.forEach(function (key) {
|
|
||||||
let inputField = document.createElement(key === "type" ? "select" : "input");
|
|
||||||
if (key === "type") {
|
|
||||||
inputField.innerHTML = '<option value="absolute">Absolute</option><option value="relative">Relative</option>';
|
|
||||||
inputField.addEventListener("change", this.updateObject.bind(this, i, key));
|
|
||||||
} else if (key === "key") {
|
|
||||||
inputField.type = "text";
|
|
||||||
inputField.setAttribute("readonly", "");
|
|
||||||
inputField.setAttribute("placeholder", "No key set");
|
|
||||||
inputField.addEventListener("click", this.startKeyInput.bind(this, i, key));
|
|
||||||
} else { // key === "value"
|
|
||||||
const isAbsolute = this.objectArray[i].type === "absolute";
|
|
||||||
inputField.type = isAbsolute ? "text" : "number";
|
|
||||||
if (isAbsolute) inputField.addEventListener("click", this.convertIntoNumberInput.bind(this, i, key), { once: true });
|
|
||||||
else inputField.setAttribute("step", "0.1");
|
|
||||||
inputField.addEventListener("input", this.updateObject.bind(this, i, key));
|
|
||||||
}
|
|
||||||
if (key === "value" && this.objectArray[i].type === "absolute")
|
|
||||||
inputField.value = this.objectArray[i][key] * 100 + "%";
|
|
||||||
else inputField.value = this.objectArray[i][key];
|
|
||||||
// Append input field to the object div
|
|
||||||
objectDiv.appendChild(inputField);
|
|
||||||
}, this);
|
|
||||||
// Button to delete the object
|
|
||||||
var deleteButton = document.createElement("button");
|
|
||||||
deleteButton.textContent = "Delete";
|
|
||||||
deleteButton.addEventListener("click", this.deleteObject.bind(this, i));
|
|
||||||
// Append delete button to the object div
|
|
||||||
objectDiv.appendChild(deleteButton);
|
|
||||||
// Append the object div to the container
|
|
||||||
this.container.appendChild(objectDiv);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const createInputRow = (i) => {
|
||||||
|
var objectDiv = document.createElement("div");
|
||||||
|
// Create input fields for each modifiable parameter
|
||||||
|
this.objectKeys.forEach(key => {
|
||||||
|
objectDiv.appendChild(this.createInputField(i, key))
|
||||||
|
});
|
||||||
|
// Button to delete the object
|
||||||
|
var deleteButton = document.createElement("button");
|
||||||
|
deleteButton.textContent = "Delete";
|
||||||
|
deleteButton.addEventListener("click", this.deleteObject.bind(this, i));
|
||||||
|
objectDiv.appendChild(deleteButton);
|
||||||
|
|
||||||
|
return objectDiv;
|
||||||
|
}
|
||||||
|
this.createInputField = function (i, property) {
|
||||||
|
let inputField = document.createElement(property === "type" ? "select" : "input");
|
||||||
|
if (property === "type") {
|
||||||
|
inputField.innerHTML = '<option value="absolute">Absolute</option><option value="relative">Relative</option>';
|
||||||
|
inputField.addEventListener("change", this.updateObject.bind(this, i, property));
|
||||||
|
} else if (property === "key") {
|
||||||
|
inputField.type = "text";
|
||||||
|
inputField.setAttribute("readonly", "");
|
||||||
|
inputField.setAttribute("placeholder", "No key set");
|
||||||
|
inputField.addEventListener("click", this.startKeyInput.bind(this, i, property));
|
||||||
|
} else { // property === "value"
|
||||||
|
const isAbsolute = this.objectArray[i].type === "absolute";
|
||||||
|
inputField.type = isAbsolute ? "text" : "number";
|
||||||
|
if (isAbsolute) inputField.addEventListener("click", this.convertIntoNumberInput.bind(this, i, property), { once: true });
|
||||||
|
else inputField.setAttribute("step", "0.1");
|
||||||
|
inputField.addEventListener("input", this.updateObject.bind(this, i, property));
|
||||||
|
}
|
||||||
|
if (property === "value" && this.objectArray[i].type === "absolute")
|
||||||
|
inputField.value = truncate(this.objectArray[i][property] * 100) + "%";
|
||||||
|
else inputField.value = this.objectArray[i][property];
|
||||||
|
|
||||||
|
return inputField;
|
||||||
|
};
|
||||||
|
this.recreateInputField = function (index, property) {
|
||||||
|
this.container.children[index].children[this.objectKeys.indexOf(property)].replaceWith(this.createInputField(index, property))
|
||||||
|
};
|
||||||
this.startKeyInput = function (index, property, event) {
|
this.startKeyInput = function (index, property, event) {
|
||||||
event.target.value = "Press any key";
|
event.target.value = "Press any key";
|
||||||
const handler = this.updateObject.bind(this, index, property);
|
const handler = this.updateObject.bind(this, index, property);
|
||||||
|
@ -68,25 +80,28 @@ export function KeybindsInput(/** @type {HTMLElement} */ containerElement) {
|
||||||
event.target.addEventListener("blur", () => {
|
event.target.addEventListener("blur", () => {
|
||||||
event.target.removeEventListener('keydown', handler);
|
event.target.removeEventListener('keydown', handler);
|
||||||
event.target.value = this.objectArray[index][property];
|
event.target.value = this.objectArray[index][property];
|
||||||
//this.displayObjects();
|
|
||||||
}, { once: true });
|
}, { once: true });
|
||||||
};
|
};
|
||||||
this.convertIntoNumberInput = function (index, property, event) {
|
this.convertIntoNumberInput = function (index, property, event) {
|
||||||
event.target.value = event.target.value.slice(0, -1);
|
event.target.value = event.target.value.slice(0, -1);
|
||||||
event.target.type = "number";
|
event.target.type = "number";
|
||||||
event.target.addEventListener("blur", () => {
|
event.target.addEventListener("blur", () => {
|
||||||
//event.target.value = this.objectArray[index][property];
|
this.recreateInputField(index, property);
|
||||||
this.displayObjects();
|
|
||||||
}, { once: true });
|
}, { once: true });
|
||||||
};
|
};
|
||||||
this.updateObject = function (index, property, event) {
|
this.updateObject = function (index, property, event) {
|
||||||
if (index >= this.objectArray.length) return;
|
if (index >= this.objectArray.length) return;
|
||||||
// Update the corresponding property of the object in the array
|
// Update the corresponding property of the object in the array
|
||||||
const value = property === "value" ? (
|
const value = property === "value" ? (
|
||||||
this.objectArray[index].type === "absolute" ? parseFloat(event.target.value) / 100 : parseFloat(event.target.value)
|
this.objectArray[index].type === "absolute"
|
||||||
|
? truncate(parseFloat(event.target.value) / 100)
|
||||||
|
: parseFloat(event.target.value)
|
||||||
) : property === "key" ? event.key : event.target.value;
|
) : property === "key" ? event.key : event.target.value;
|
||||||
this.objectArray[index][property] = value;
|
this.objectArray[index][property] = value;
|
||||||
if (property === "key") this.displayObjects();
|
|
||||||
|
if (property === "key") this.recreateInputField(index, property);
|
||||||
|
// when the keybind's type (absolute or relative) is changed
|
||||||
|
else if (property === "type") this.recreateInputField(index, "value");
|
||||||
};
|
};
|
||||||
this.deleteObject = function (index) {
|
this.deleteObject = function (index) {
|
||||||
// Remove the object from the array
|
// Remove the object from the array
|
||||||
|
|
Loading…
Reference in New Issue