I'm trying to implement a function that will return a result (blue text) based on the combination of choices according to this tree diagram:
I currently have three functions:
optionA
click - handles the left option click using switchoptionB
click - handles the right option click using switchreset
click - resets everything to initial stateThis approach works fine but I was wondering if there is a more effective way of achieving the same result. My current code is not really scalable. It's repetitive and I think it could potentially be shortened but I'm not really sure how to approach it.
let optA = document.querySelector(".optionA");
let optB = document.querySelector(".optionB");
let result = document.querySelector(".result");
let reset = document.querySelector(".reset")
function handleOptAClick() {
if (result.innerHTML === '') {
switch (optA.innerHTML) {
case 'Hot':
optA.innerHTML = "Leaf";
optB.innerHTML = "Flower";
break;
case 'Leaf':
optA.innerHTML = "Pure";
optB.innerHTML = "Blend";
break;
case 'Alcohol':
optA.innerHTML = "Plum";
optB.innerHTML = "Rice";
break;
case 'Pure':
optA.innerHTML = "Sunlight";
optB.innerHTML = "Shade";
break;
case 'Plum':
result.innerHTML = "Umeshu";
break;
case 'Bacteria':
optA.innerHTML = "Yeast";
optB.innerHTML = "Milk";
break;
case 'Sunlight':
result.innerHTML = "Sencha";
break;
case 'Yeast':
result.innerHTML = "Kombucha"
break;
default:
console.log("Something went wrong");
}
}
}
function handleOptBClick() {
if (result.innerHTML === '') {
switch (optB.innerHTML) {
case 'Cold':
optA.innerHTML = "Alcohol";
optB.innerHTML = "Soft";
break;
case 'Flower':
result.innerHTML = "Sakura"
break;
case 'Soft':
optA.innerHTML = "Bacteria";
optB.innerHTML = "Soy";
break;
case 'Blend':
result.innerHTML = "Genmaicha"
break;
case 'Rice':
result.innerHTML = "Sake"
break;
case 'Soy':
result.innerHTML = "Soymilk"
break;
case 'Plum':
result.innerHTML = "Umeshu";
break;
case 'Shade':
result.innerHTML = "Matcha";
break;
case 'Milk':
result.innerHTML = "Yakuruto";
break;
default:
console.log("Something went wrong");
}
}
}
function handleResetClick() {
optA.innerHTML = "Hot";
optB.innerHTML = "Cold";
result.innerHTML = '';
}
<div>
<button class="optionA" onClick=handleOptAClick()>Hot</button>
<button class="optionB" onClick=handleOptBClick()>Cold</button>
<button class="reset" onClick=handleResetClick()>Reset</button>
<p class="result"></p>
</div>
I'm thankful for any suggestions.
There is quite some repetition in your code. You could improve it by making a data structure to represent the tree, instead of hard-coding every parent-child relation in the code.
For instance, a tree node could be an array with three elements: the choice (to be displayed), the (nested) tree node for the left choice, and the (nested) tree node for the right choice. A leaf in the tree would be an array with only two entries: the choice (to be displayed) and the corresponding result to be displayed.
The code could then focus on maintaining a reference to what is the current node in the tree, i.e. the node that corresponds with the choices that were made up to this point.
I would also suggest to not define the click handlers with HTML attributes, but with code (using addEventListener
).
Here is how that would look:
const tree =
["Root",
["Hot",
["Leaf",
["Pure",
["Sunlight", "Sencha"],
["Shade", "Matcha"]
],
["Blend", "Genmaicha"]
],
["Flower", "Sakura"]
],
["Cold",
["Alcohol",
["Plum", "Umeshu"],
["Rice", "Sake"]
],
["Soft",
["Bacteria",
["Yeast", "Kombucha"],
["Milk", "Yakuruto"]
],
["Soy", "Soymilk"]
]
]
];
let current = tree;
const [left, right] = document.querySelectorAll(".option");
const result = document.querySelector(".result");
const reset = document.querySelector(".reset")
left.addEventListener("click", () => choose(current[1]));
right.addEventListener("click", () => choose(current[2]));
reset.addEventListener("click", () => choose(tree));
function choose(choice) {
if (choice.length == 2) { // We're at a leaf
result.textContent = choice[1];
} else {
current = choice;
left.textContent = current[1][0];
right.textContent = current[2][0];
result.textContent = "";
}
}
<div>
<button class="option">Hot</button>
<button class="option">Cold</button>
<button class="reset">Reset</button>
<p class="result"></p>
</div>