From 53226c105069b97369e9a81ef23da2c88e0c9441 Mon Sep 17 00:00:00 2001 From: n1474335 Date: Fri, 8 Feb 2019 00:59:56 +0000 Subject: [PATCH] Added populateMultiOption ingredient type --- .gitignore | 1 + src/core/operations/MultipleBombe.mjs | 94 +++++++----------------- src/web/HTMLIngredient.mjs | 49 +++++++++++- src/web/RecipeWaiter.mjs | 10 +++ tests/operations/tests/MultipleBombe.mjs | 14 ++-- 5 files changed, 92 insertions(+), 76 deletions(-) diff --git a/.gitignore b/.gitignore index edbcf679..b5aad5d0 100755 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ docs/* !docs/*.ico .vscode .*.swp +.DS_Store src/core/config/modules/* src/core/config/OperationConfig.json src/core/operations/index.mjs diff --git a/src/core/operations/MultipleBombe.mjs b/src/core/operations/MultipleBombe.mjs index dac7a334..a453ca34 100644 --- a/src/core/operations/MultipleBombe.mjs +++ b/src/core/operations/MultipleBombe.mjs @@ -60,95 +60,57 @@ class MultipleBombe extends Operation { this.args = [ { "name": "Standard Enigmas", - "type": "populateOption", + "type": "populateMultiOption", "value": [ { name: "German Service Enigma (First - 3 rotor)", - value: rotorsFormat(ROTORS, 0, 5) + value: [ + rotorsFormat(ROTORS, 0, 5), + "", + rotorsFormat(REFLECTORS, 0, 1) + ] }, { name: "German Service Enigma (Second - 3 rotor)", - value: rotorsFormat(ROTORS, 0, 8) + value: [ + rotorsFormat(ROTORS, 0, 8), + "", + rotorsFormat(REFLECTORS, 0, 2) + ] }, { name: "German Service Enigma (Third - 4 rotor)", - value: rotorsFormat(ROTORS, 0, 8) + value: [ + rotorsFormat(ROTORS, 0, 8), + rotorsFormat(ROTORS_FOURTH, 1, 2), + rotorsFormat(REFLECTORS, 2, 3) + ] }, { name: "German Service Enigma (Fourth - 4 rotor)", - value: rotorsFormat(ROTORS, 0, 8) + value: [ + rotorsFormat(ROTORS, 0, 8), + rotorsFormat(ROTORS_FOURTH, 1, 3), + rotorsFormat(REFLECTORS, 2, 4) + ] }, { name: "User defined", - value: "" + value: ["", "", ""] }, ], - "target": 1 + "target": [1, 2, 3] }, { name: "Main rotors", type: "text", value: "" }, - { - "name": "Standard Enigmas", - "type": "populateOption", - "value": [ - { - name: "German Service Enigma (First - 3 rotor)", - value: "" - }, - { - name: "German Service Enigma (Second - 3 rotor)", - value: "" - }, - { - name: "German Service Enigma (Third - 4 rotor)", - value: rotorsFormat(ROTORS_FOURTH, 1, 2) - }, - { - name: "German Service Enigma (Fourth - 4 rotor)", - value: rotorsFormat(ROTORS_FOURTH, 1, 3) - }, - { - name: "User defined", - value: "" - }, - ], - "target": 3 - }, { name: "4th rotor", type: "text", value: "" }, - { - "name": "Standard Enigmas", - "type": "populateOption", - "value": [ - { - name: "German Service Enigma (First - 3 rotor)", - value: rotorsFormat(REFLECTORS, 0, 1) - }, - { - name: "German Service Enigma (Second - 3 rotor)", - value: rotorsFormat(REFLECTORS, 0, 2) - }, - { - name: "German Service Enigma (Third - 4 rotor)", - value: rotorsFormat(REFLECTORS, 2, 3) - }, - { - name: "German Service Enigma (Fourth - 4 rotor)", - value: rotorsFormat(REFLECTORS, 2, 4) - }, - { - name: "User defined", - value: "" - }, - ], - "target": 5 - }, { name: "Reflectors", type: "text", @@ -217,11 +179,11 @@ class MultipleBombe extends Operation { */ run(input, args) { const mainRotorsStr = args[1]; - const fourthRotorsStr = args[3]; - const reflectorsStr = args[5]; - let crib = args[6]; - const offset = args[7]; - const check = args[8]; + const fourthRotorsStr = args[2]; + const reflectorsStr = args[3]; + let crib = args[4]; + const offset = args[5]; + const check = args[6]; const rotors = []; const fourthRotors = []; const reflectors = []; diff --git a/src/web/HTMLIngredient.mjs b/src/web/HTMLIngredient.mjs index bb01d7de..c7c024fb 100755 --- a/src/web/HTMLIngredient.mjs +++ b/src/web/HTMLIngredient.mjs @@ -39,7 +39,7 @@ class HTMLIngredient { */ toHtml() { let html = "", - i, m; + i, m, eventFn; switch (this.type) { case "string": @@ -142,10 +142,11 @@ class HTMLIngredient { `; break; case "populateOption": + case "populateMultiOption": html += `
${this.hint ? "" + this.hint + "" : ""}
`; - this.manager.addDynamicListener("#" + this.id, "change", this.populateOptionChange, this); + eventFn = this.type === "populateMultiOption" ? + this.populateMultiOptionChange : + this.populateOptionChange; + this.manager.addDynamicListener("#" + this.id, "change", eventFn, this); break; case "editableOption": html += `
@@ -248,6 +255,9 @@ class HTMLIngredient { * @param {event} e */ populateOptionChange(e) { + e.preventDefault(); + e.stopPropagation(); + const el = e.target; const op = el.parentNode.parentNode; const target = op.querySelectorAll(".arg")[this.target]; @@ -260,6 +270,37 @@ class HTMLIngredient { } + /** + * Handler for populate multi option changes. + * Populates the relevant arguments with the specified values. + * + * @param {event} e + */ + populateMultiOptionChange(e) { + e.preventDefault(); + e.stopPropagation(); + + const el = e.target; + const op = el.parentNode.parentNode; + const args = op.querySelectorAll(".arg"); + const targets = this.target.map(i => args[i]); + const vals = JSON.parse(el.childNodes[el.selectedIndex].getAttribute("populate-value")); + const evt = new Event("change"); + + for (let i = 0; i < targets.length; i++) { + targets[i].value = vals[i]; + } + + // Fire change event after all targets have been assigned + this.manager.recipe.ingChange(); + + // Send change event for each target once all have been assigned, to update the label placement. + for (const target of targets) { + target.dispatchEvent(evt); + } + } + + /** * Handler for editable option clicks. * Populates the input box with the selected value. diff --git a/src/web/RecipeWaiter.mjs b/src/web/RecipeWaiter.mjs index a8326b27..4c568c8b 100755 --- a/src/web/RecipeWaiter.mjs +++ b/src/web/RecipeWaiter.mjs @@ -205,6 +205,7 @@ class RecipeWaiter { * @fires Manager#statechange */ ingChange(e) { + if (e && e.target && e.target.classList.contains("no-state-change")) return; window.dispatchEvent(this.manager.statechange); } @@ -392,6 +393,15 @@ class RecipeWaiter { this.buildRecipeOperation(item); document.getElementById("rec-list").appendChild(item); + // Trigger populateOption events + const populateOptions = item.querySelectorAll(".populate-option"); + const evt = new Event("change", {bubbles: true}); + if (populateOptions.length) { + for (const el of populateOptions) { + el.dispatchEvent(evt); + } + } + item.dispatchEvent(this.manager.operationadd); return item; } diff --git a/tests/operations/tests/MultipleBombe.mjs b/tests/operations/tests/MultipleBombe.mjs index f809859c..5c06ece4 100644 --- a/tests/operations/tests/MultipleBombe.mjs +++ b/tests/operations/tests/MultipleBombe.mjs @@ -16,9 +16,10 @@ TestRegister.addTests([ "op": "Multiple Bombe", "args": [ // I, II and III - "User defined", "EKMFLGDQVZNTOWYHXUSPAIBRCJ