Как я могу скрыть кнопку до тех пор, пока не будут установлены по крайней мере три флажка ввода (по одному из каждого отдельного набора из шести)?

#javascript #html #function #dom-events #addeventlistener

Вопрос:

У меня есть три списка (элементы набора полей HTML) с шестью продуктами (элементы ввода 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 amp; 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 amp; 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 amp; 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> 

Комментарии:

1. Спасибо — функция генератора еды довольно длинная (~350 строк), но она просто отключается и извлекает случайные записи из массива каждого макронаправления и помещает их на дисплей плана питания — я могу добавить ее, если это стоит сделать, хотя, если можно вставить все 350 строк? еще раз спасибо

2. Привет @ишервуд — извиняюсь, это очень плохо, но я не уверен, что это значит — я только что добавил пару строк в javascript, чтобы определить функцию mealgenerator в качестве консоли. журнал «Фиктивной функции» — надеюсь, это правильные строки?

Ответ №1:

Вам нужно будет перебрать ВСЕ флажки, независимо от того, установлен ли хотя бы один из каждого раздела. И вам нужно будет сделать это также, когда флажок снят, потому что, вероятно, вы снова захотите скрыть кнопку, когда условие больше не будет выполнено …

Прямой подход будет заключаться в следующем

 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 amp;amp; f amp;amp; 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.contains , используете ли вы classList.add или classList.remove . Эти функции позаботятся об этом. Т. е. он не добавит один и тот же класс дважды, если он уже содержится, и при попытке удалить класс, который не содержится в classList )

Конечно, вы можете оптимизировать этот код. Например, просто установите флажок, который только что был изменен, и сохраните счетчик для каждого из разделов. И когда все счетчики будут > 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 amp;amp; c amp;amp; 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"> 

Комментарии:

1. Супер спасибо @derpircher — я нажал на символ зеленой галочки, чтобы принять ответ, так как он отлично работал. Я также нажал, чтобы проголосовать, однако это просто говорит мне, что мне нужно не менее 15 репутации, прежде чем я смогу проголосовать — если есть какой-либо способ, которым я все еще могу проголосовать, я сделаю это? Еще раз спасибо за вашу помощь 🙂