Fix floating point number imprecision when configuring keybinds
Refactor keybind input code to improve performance and fix inconsistenciespull/20/head
							parent
							
								
									05f59c31bd
								
							
						
					
					
						commit
						14c94507f3
					
				|  | @ -1,4 +1,7 @@ | |||
| const truncate = n => parseFloat(n.toFixed(12)); | ||||
| 
 | ||||
| export function KeybindsInput(/** @type {HTMLElement} */ containerElement) { | ||||
| 
 | ||||
|     const header = document.createElement("p"); | ||||
|     header.innerText = "Attack Percentage Keybinds"; | ||||
|     const keybindContainer = document.createElement("div"); | ||||
|  | @ -6,61 +9,70 @@ export function KeybindsInput(/** @type {HTMLElement} */ containerElement) { | |||
|     const keybindAddButton = document.createElement("button"); | ||||
|     keybindAddButton.innerText = "Add"; | ||||
|     containerElement.append(header, keybindContainer, keybindAddButton); | ||||
| 
 | ||||
|     containerElement.className = "keybinds-input"; | ||||
|     this.container = keybindContainer; | ||||
|     this.keys = [ "key", "type", "value" ]; | ||||
|     this.objectKeys = ["key", "type", "value"]; | ||||
|     this.objectArray = []; | ||||
|     this.addObject = function () { | ||||
|         this.objectArray.push({ key: "", type: "absolute", value: 0.8 }); | ||||
|         this.displayObjects(); | ||||
|         this.container.appendChild(createInputRow(this.objectArray.length - 1)); | ||||
|         keybindAddButton.scrollIntoView(false); | ||||
|     }; | ||||
|     keybindAddButton.addEventListener("click", this.addObject.bind(this)); | ||||
|     this.update = function (settings) { | ||||
|         this.objectArray = settings.attackPercentageKeybinds; | ||||
|         this.displayObjects(); | ||||
|     } | ||||
|     keybindAddButton.addEventListener("click", this.addObject.bind(this)); | ||||
|     this.displayObjects = function () { | ||||
|         // Clear the content of the container
 | ||||
|         this.container.innerHTML = ""; | ||||
|         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
 | ||||
|         for (var i = 0; i < this.objectArray.length; i++) { | ||||
|             var objectDiv = document.createElement("div"); | ||||
|             // 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); | ||||
|             this.container.appendChild(createInputRow(i)); | ||||
|         } | ||||
|     }; | ||||
|     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) { | ||||
|         event.target.value = "Press any key"; | ||||
|         const handler = this.updateObject.bind(this, index, property); | ||||
|  | @ -68,25 +80,28 @@ export function KeybindsInput(/** @type {HTMLElement} */ containerElement) { | |||
|         event.target.addEventListener("blur", () => { | ||||
|             event.target.removeEventListener('keydown', handler); | ||||
|             event.target.value = this.objectArray[index][property]; | ||||
|             //this.displayObjects();
 | ||||
|         }, { once: true }); | ||||
|     }; | ||||
|     this.convertIntoNumberInput = function (index, property, event) { | ||||
|         event.target.value = event.target.value.slice(0, -1); | ||||
|         event.target.type = "number"; | ||||
|         event.target.addEventListener("blur", () => { | ||||
|             //event.target.value = this.objectArray[index][property];
 | ||||
|             this.displayObjects(); | ||||
|             this.recreateInputField(index, property); | ||||
|         }, { once: true }); | ||||
|     }; | ||||
|     this.updateObject = function (index, property, event) { | ||||
|         if (index >= this.objectArray.length) return; | ||||
|         // Update the corresponding property of the object in the array
 | ||||
|         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; | ||||
|         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) { | ||||
|         // Remove the object from the array
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue