在选中至少三个输入复选框(每组六个中的一个)之前,如何隐藏按钮?

How can I hide a button until at least three input checkboxes (one from each separate set of six) are checked?

我有三个列表(HTML Fieldset 元素),每个列表中有六种食物(HTML 输入元素 - 从未选中开始)。我想在这三个列表下方隐藏一个按钮元素,直到检查了三个列表中的每一个列表中的至少一种食物。当至少检查了每个列表中的一种食物时,我希望取消隐藏按钮。

这将在单击第一个字段集中的输入之一时取消隐藏按钮...但我需要扩展功能,以便按钮仅在每个 3x 字段集中的至少一个(蛋白质、碳水化合物和脂肪)被选中。

// Add variable for the DOM element button with id "generate-meals" 
let generateMealButton = document.getElementById("generate-meals");

generateMealButton.classList.add("hide");

// Add an eventlistener to generate meal button to listen for a "click" event and run the 
// function "runMealGenerator when the event occurs"
generateMealButton.addEventListener("click", runMealGenerator);

// find all input fields
const proteinInputs = document.querySelectorAll("input[class='protein-input']");
console.log(proteinInputs[0].checked)
const carbInputs = document.querySelectorAll("input[class='carb-input']");
console.log(carbInputs)
const fatInputs = document.querySelectorAll("input[class='fat-input']");
console.log(fatInputs)
// add click event-listener for all input buttons
proteinInputs.forEach((input) => {
  input.addEventListener("click", checkProteinInput);
});

// check if any input buttons are 'checked'
function checkProteinInput() {
  // if the macroChoice button is 'not' hidden, then unhide it
  console.log(proteinInputs[0].checked)
  if (generateMealButton.classList.contains("hide")) {
    generateMealButton.classList.remove("hide");
  }
}

function runMealGenerator() {
console.log("Dummy Function Added")
}
<!-- This section contains the 3x menus of sample foods the user can select for inclusion in their meal plan ideas  -->
<section id="foodListContainer">
  <!-- Small section for direction to the user - instructions on how to proceed -->
  <section class="food-groups" id="generator_instructions">
    <h3 id="food-heading">Instructions</h3>
    <p>Please select at least one food from each group for inclusion in meal plans:</p>
  </section>
  <!-- Fieldset to contain checkboxes for each Protein food option for selection by user -->
  <fieldset class="food-groups" id="proteinFieldset">
    <legend>Protein:</legend>
    <!-- Each Protein input is housed in a div to enable dematcation & styling -->
    <div>
      <label for="chicken">Chicken</label>
      <input class="protein-input" type="checkbox" id="chicken" name="chicken">
    </div>
    <div>
      <label for="turkey">Turkey</label>
      <input class="protein-input" type="checkbox" id="turkey" name="turkey">
    </div>
    <div>
      <label for="fish">Fish</label>
      <input class="protein-input" type="checkbox" id="fish" name="fish">
    </div>
    <div>
      <label for="beef">beef</label>
      <input class="protein-input" type="checkbox" id="beef" name="beef">
    </div>
    <div>
      <label for="eggs">eggs</label>
      <input class="protein-input" type="checkbox" id="eggs" name="eggs">
    </div>
    <div>
      <label for="pork">pork</label>
      <input class="protein-input" type="checkbox" id="pork" name="pork">
    </div>
  </fieldset>
  <!-- Fieldset to contain checkboxes for each Carbohydrate food option -->
  <fieldset class="food-groups">
    <legend>Carbohydrate:</legend>
    <!-- Each Carbohydrate input is housed in a div to enable dematcation & styling -->
    <div>
      <label for="bread">Bread</label>
      <input class="carb-input" type="checkbox" id="bread" name="bread">
    </div>
    <div>
      <label for="pasta">Pasta</label>
      <input class="carb-input" type="checkbox" id="pasta" name="pasta">
    </div>
    <div>
      <label for="rice">Rice</label>
      <input class="carb-input" type="checkbox" id="rice" name="rice">
    </div>
    <div>
      <label for="oats">Oats</label>
      <input class="carb-input" type="checkbox" id="oats" name="oats">
    </div>
    <div>
      <label for="cereal">Cereal</label>
      <input class="carb-input" type="checkbox" id="cereal" name="cereal">
    </div>
    <div>
      <label for="quinoa">Quinoa</label>
      <input class="carb-input" type="checkbox" id="quinoa" name="quinoa">
    </div>
  </fieldset>
  <!-- Fieldset to contain checkboxes for each Fat food option -->
  <fieldset class="food-groups">
    <legend>Fat:</legend>
    <!-- Each Fat input is housed in a div to enable dematcation & styling -->
    <div>
      <label for="butter">Butter</label>
      <input class="fat-input" type="checkbox" id="butter" name="butter">
    </div>
    <div>
      <label for="cheese">Cheese</label>
      <input class="fat-input" type="checkbox" id="cheese" name="cheese">
    </div>
    <div>
      <label for="cream">Cream</label>
      <input class="fat-input" type="checkbox" id="cream" name="cream">
    </div>
    <div>
      <label for="nuts">Nuts</label>
      <input class="fat-input" type="checkbox" id="nuts" name="nuts">
    </div>
    <div>
      <label for="bacon">Bacon</label>
      <input class="fat-input" type="checkbox" id="bacon" name="bacon">
    </div>
    <div>
      <label for="olive-oil">Olive Oil</label>
      <input class="fat-input" type="checkbox" id="olive-oil" name="olive-oil">
    </div>
  </fieldset>
  <!-- End of foodListContainer section -->
  <!-- Button to allow the user proceed to generate meal plan ideas when they have selected
            All foods they wish to include/exclude -->
  <section id="generate-container">
    <button id="generate-meals">Generate A Meal Plan</button>
  </section>
</section>

您将需要遍历所有复选框,以确定每个部分是否至少有一个被选中。你也需要这样做,当一个复选框被取消选中时,因为你可能想再次隐藏按钮,当条件不再满足时...

直接的方法如下

function checkInputs() {
  let p = false, f = false, c = false; //protein, carbon, fat
  for (let i = 0; i < proteinInputs.length; i++) {
    if (proteinInputs[i].checked) { p = true; break;} //we found at least one
  }
  for (let i = 0; i < fatInputs.length; i++) {
    if (fatInputs[i].checked) { f = true; break;} //we found at least one
  }
  for (let i = 0; i < carbonInputs.length; i++) {
    if (carbonInputs[i].checked) { c = true; break;} //we found at least one
  }

  if (p && f && c) {  //found at least one in each section
    //show the button
    generateMealButton.classList.remove("hide");
  } else {  //at least one is missing
    //hide the button
    generateMealButton.classList.add("hide");
  }
}

并将此 checkInputs 添加到所有复选框(即不仅用于蛋白质,还用于脂肪和碳)

顺便说一句。如果您使用 classList.addclassList.remove,则无需明确检查 classList.contains。这些功能将解决这个问题。也就是说,如果 class 已经包含,它不会添加两次,并且如果您尝试删除不包含在 classList 中的 class,也不会出现错误)

当然你可以优化这段代码。例如,只需评估刚刚更改的复选框并为每个部分保留一个计数器。当所有计数器都 > 0 取消隐藏按钮,并在一个变为零时隐藏按钮 ...

let cb = document.querySelectorAll("input[type='checkbox']")
for (let i = 0; i < cb.length; i++) cb[i].addEventListener("change", check);

let c = 0, f= 0, p= 0
function check(event) {

  let addval = event.currentTarget.checked ? 1 : -1
  switch(event.currentTarget.getAttribute("data-tag")) {
    case "f": f += addval; break;
    case "c": c += addval; break;
    case "p": p += addval; break;
  }
  
  console.log(f,c,p);
  if (f && c && p)
    document.getElementById("thebutton").classList.remove("hide")
  else
    document.getElementById("thebutton").classList.add("hide")
}
.hide {
  display: none;
}
<input type="checkbox" data-tag="f"/>fat
<input type="checkbox" data-tag="c"/>carbon
<input type="checkbox" data-tag="p"/>protein

<input type="checkbox" data-tag="f"/>fat2
<input type="checkbox" data-tag="c"/>carbon2
<input type="checkbox" data-tag="p"/>protein2


<input id="thebutton" type="button" value="create meal" class="hide">