dimanche 23 janvier 2022

Dynamic Javascript String Generator w/ Checkboxes

My web page allows users to generate strings/phrases by selecting a combination of two radio buttons from two different groups: mode and category. Mode determines the order that the generator runs through the array, while category determines which array the function is pulling the strings from. After selecting their choice of buttons, they click the 'Push' button and a string pops up. See the snippet below:

class modes {
    constructor(items) {
        this.items = items;
        this.randomUnused = [...items];
        this.forwardIndex = 0;
        this.reverseIndex = items.length - 1;
    }
    forwardItem() {
        return this.items[this.forwardIndex++ % (this.items.length)];
    }
    randomItem() {
        if (!this.randomUnused.length) {
          this.randomUnused.push(...this.items);
        }
        const index = Math.floor(Math.random() * this.randomUnused.length);
        return this.randomUnused.splice(index, 1);
    }
    reverseItem() {
        if (this.reverseIndex < 0) {
          this.reverseIndex = this.items.length - 1;
        }
        return this.items[this.reverseIndex--];
    }
}
const categ = {
    A: new modes([
        "A example 1",
        "A example 2",
        "A example 3",
        "A example 4",
    ]),
    B: new modes([
        "B example 1",
        "B example 2",
        "B example 3",
        "B example 4",
    ]),
    C: new modes([
        "C example 1",
        "C example 2",
        "C example 3",
        "C example 4",
    ]),
    D: new modes([
        "D example 1",
        "D example 2",
        "D example 3",
        "D example 4",
    ])
};
function main() {
    const output = document.querySelector("output");
    if(!(document.forms.thingSelection2.type.value in categ)) {
        return false;
    }
    const list = categ[document.forms.thingSelection2.type.value];
    const method = document.forms.thingSelection1.mode.value + "Item";
    const item = list[method]();
    output.innerHTML = item;
}
const abutton = document.getElementById("abutton");
if(abutton) {
    abutton.addEventListener("click", main);
}
<output></output>

<button id="abutton">Push</button>

<form name="thingSelection1">
    Forwards<input type="radio" name="mode" value="forward">
    Random<input type="radio" name="mode" value="random">
    Backwards<input type="radio" name="mode" value="reverse">
</form>

<form name="thingSelection2">
    <li><input type="radio" name="type" value="A">Choice A</li>
    <li><input type="radio" name="type" value="B">Choice B</li>
    <li><input type="radio" name="type" value="C">Choice C</li>
    <li><input type="radio" name="type" value="D">Choice D</li>
</form>

Each category is currently represented by a radio button and has its own separate array, so only one may be selected at a time. My goal is to allow the user to select multiple categories and combine them into a new array, then cycle through them.

Problem 1: Changing the category radio buttons into checkboxes causes the function to break. The snippet below illustrates this. I figure this is due to the fact that checkboxes have 3 possible states (checked, unchecked, indeterminate) while radio buttons can only be true or false. I am unsure what changes to make to the function to allow the checkboxes to work. I could use some assistance. I'm fairly new to javascript, so please be patient.

class modes {
    constructor(items) {
        this.items = items;
        this.randomUnused = [...items];
        this.forwardIndex = 0;
        this.reverseIndex = items.length - 1;
    }
    forwardItem() {
        return this.items[this.forwardIndex++ % (this.items.length)];
    }
    randomItem() {
        if (!this.randomUnused.length) {
          this.randomUnused.push(...this.items);
        }
        const index = Math.floor(Math.random() * this.randomUnused.length);
        return this.randomUnused.splice(index, 1);
    }
    reverseItem() {
        if (this.reverseIndex < 0) {
          this.reverseIndex = this.items.length - 1;
        }
        return this.items[this.reverseIndex--];
    }
}
const categ = {
    A: new modes([
        "A example 1",
        "A example 2",
        "A example 3",
        "A example 4",
    ]),
    B: new modes([
        "B example 1",
        "B example 2",
        "B example 3",
        "B example 4",
    ]),
    C: new modes([
        "C example 1",
        "C example 2",
        "C example 3",
        "C example 4",
    ]),
    D: new modes([
        "D example 1",
        "D example 2",
        "D example 3",
        "D example 4",
    ])
};
function main() {
    const output = document.querySelector("output");
    if(!(document.forms.thingSelection2.type.value in categ)) {
        return false;
    }
    const list = categ[document.forms.thingSelection2.type.value];
    const method = document.forms.thingSelection1.mode.value + "Item";
    const item = list[method]();
    output.innerHTML = item;
}
const abutton = document.getElementById("abutton");
if(abutton) {
    abutton.addEventListener("click", main);
}
<output></output>

<button id="abutton">Push</button>

<form name="thingSelection1">
    Forwards<input type="radio" name="mode" value="forward">
    Random<input type="radio" name="mode" value="random">
    Backwards<input type="radio" name="mode" value="reverse">
</form>

<form name="thingSelection2">
    <li><input type="checkbox" name="type" value="A">Choice A</li>
    <li><input type="checkbox" name="type" value="B">Choice B</li>
    <li><input type="checkbox" name="type" value="C">Choice C</li>
    <li><input type="checkbox" name="type" value="D">Choice D</li>
</form>

Problem 2: Constructing the custom array in a specific order. While internet searches provide many ways to combine multiple arrays into one, like concat, none of them explain how to organize the strings in a custom order.

Example of what im looking for: ["A example 1", "B example 1", "C example 1", "D example 1", "A example 2", "B example 2"...]

Rather than simply stacking the array contents on top of each other, like concat and every other method of combining arrays: ["A example 1", "A example 2", "A example 3", "A example 4", "B example 1", "B example 2"...]

I'm unaware of any method to achieve this. No external libraries please.




Aucun commentaire:

Enregistrer un commentaire