BareGit
/** Create one editable choice row. */
function createChoiceRow()
{
    const row = document.createElement("div");
    row.className = "choice-row";
    row.innerHTML = `
        <input name="choice" type="text" required>
        <button class="clay-action clay-action-secondary move-up"
                type="button">Move up</button>
        <button class="clay-action clay-action-secondary move-down"
                type="button">Move down</button>
        <button class="clay-action clay-action-danger remove-choice"
                type="button">Remove</button>`;
    return row;
}

/** Return the bounded destination for one choice movement. */
function choiceMoveIndex(index, direction, count)
{
    if(count <= 0 || index < 0 || index >= count)
    {
        return index;
    }
    return Math.max(0, Math.min(count - 1, index + direction));
}

/** Update choice-editor visibility and button states. */
function updateChoiceEditor()
{
    const type = document.getElementById("FieldType");
    const is_choice = type.value == "CHOICE" ||
        type.dataset.fieldType == "CHOICE";
    const editor = document.getElementById("ChoiceEditor");
    editor.hidden = !is_choice;
    for(const input of editor.querySelectorAll("input"))
    {
        input.disabled = !is_choice;
    }
    const rows = [...document.querySelectorAll(".choice-row")];
    for(let index = 0; index < rows.length; ++index)
    {
        rows[index].querySelector(".move-up").disabled = index == 0;
        rows[index].querySelector(".move-down").disabled =
            index + 1 == rows.length;
    }
}

/** Handle add, remove, and reorder controls for choice rows. */
function handleChoiceAction(event)
{
    const button = event.target.closest("button");
    if(button == null)
    {
        return;
    }
    const rows = document.getElementById("ChoiceRows");
    if(button.id == "AddChoice")
    {
        const row = createChoiceRow();
        rows.append(row);
        row.querySelector("input").focus();
    }
    else
    {
        const row = button.closest(".choice-row");
        if(button.classList.contains("remove-choice"))
        {
            const focus_target = row.nextElementSibling ??
                row.previousElementSibling;
            row.remove();
            focus_target?.querySelector("input").focus();
        }
        else
        {
            const current_rows = [...rows.querySelectorAll(".choice-row")];
            const index = current_rows.indexOf(row);
            const direction = button.classList.contains("move-up")
                ? -1
                : button.classList.contains("move-down") ? 1 : 0;
            const target = choiceMoveIndex(
                index, direction, current_rows.length);
            if(target < index)
            {
                rows.insertBefore(row, current_rows[target]);
                button.focus();
            }
            else if(target > index)
            {
                rows.insertBefore(row, current_rows[target].nextSibling);
                button.focus();
            }
        }
    }
    updateChoiceEditor();
}

if(typeof document != "undefined")
{
    document.getElementById("GameFieldForm").addEventListener(
        "click", handleChoiceAction);
    document.getElementById("FieldType").addEventListener(
        "change", updateChoiceEditor);
    updateChoiceEditor();
}
if(typeof module != "undefined" && module.exports != null)
{
    module.exports = {choiceMoveIndex};
}