0

How can I make checkbox and radio inputs disabled per fieldset and then sequentially enabled after certain inputs are selected?

For example: Initially, all fieldsets but the first one are disabled. After user selects input in the first fieldset, second one is enabled. And so on and so forth.

Related to that, how can I display the calculated value only after radio input in the second fieldset is checked?

const calculator = document.querySelector("form");

const occasionPricing = {
 party: 20,
 birthday: 25,
 anniversary: 50,
 wedding: 100
}

const sizeIndexes = {
 six: 1,
 eight: 1.5,
 ten: 2,
 twelve: 2.5
}

const extrasPricing = {
 candles: 5,
 inscription: 10,
 decoration: 25,
 special: 50
}

function cakes() { 
 var cakes = Array.from(calculator.elements["cake"]).slice(0, 3);
 var raphael = calculator.elements["raphael"];

 function isChecked(checkbox) {
  return checkbox.checked;
 }

 var count = cakes.filter(isChecked).length;
 if (count) {
  count = count * 0.5 + 0.5;
  if (raphael.checked) {
   count += 1;
  }
  return count;
 }
 return 0;
}

function occasion() {
 var occasionCost = 0;
 var occasion = calculator.elements["occasion"];

 for (var i = 0; i < occasion.length; i++) {
  if (occasion[i].checked) {
   occasionCost = occasionPricing[occasion[i].value];
   break;
  }
 }
 return occasionCost;
}

function size() {
 var sizeIndex = 1;
 var size = calculator.elements["size"];

 for (var i = 0; i < size.length; i++) {
  if (size[i].checked) {
   sizeIndex = sizeIndexes[size[i].value];
   break;
  }
 }
 return sizeIndex;
}

function extras() {
 var extrasCost = 0;
 const extras = calculator.elements["extras"];

 for (var i = 0; i < extras.length; i++) {
  if (extras[i].checked) {
   extrasCost = extrasCost + extrasPricing[extras[i].value];
  }
 }
 return extrasCost;
}

function calculateTotal() {
 var totalCost = cakes() * occasion() * size() + extras();
 calculator.total.value = "$" + totalCost;
}
<form>

<fieldset>
 <legend>Select Cakes</legend>
 <label><input type="checkbox" name="cake" id="leonardo" onclick="calculateTotal()">Leonardo</label>
 <label><input type="checkbox" name="cake" id="donatello" onclick="calculateTotal()">Donatello</label>
 <label><input type="checkbox" name="cake" id="michelangelo" onclick="calculateTotal()">Michelangelo</label>
 <label><input type="checkbox" name="cake" id="raphael" onclick="calculateTotal()">Raphael</label>
 <p>If you select more than one cake, the other cakes are discounted 50%.</p>
 <p><small>Does not apply to Raphael.</small></p>
</fieldset>

<fieldset>
 <legend>Choose Occasion</legend>
 <label><input type="radio" name="occasion" value="party" onclick="calculateTotal()" required>Party</label><br>
 <label><input type="radio" name="occasion" value="birthday" onclick="calculateTotal()">Birthday</label><br>
 <label><input type="radio" name="occasion" value="anniversary" onclick="calculateTotal()">Anniversary</label><br>
 <label><input type="radio" name="occasion" value="wedding" onclick="calculateTotal()">Wedding</label><br>
</fieldset>

<fieldset>
 <legend>Choose Size</legend>
 <label><input type="radio" name="size" value="six" onclick="calculateTotal()" required>6-inch</label><br>
 <label><input type="radio" name="size" value="eight" onclick="calculateTotal()">8-inch</label><br>
 <label><input type="radio" name="size" value="ten" onclick="calculateTotal()">10-inch</label><br>
 <label><input type="radio" name="size" value="twelve" onclick="calculateTotal()">12-inch</label><br>
</fieldset>

<fieldset>
 <legend>Select Extras</legend>
 <label><input type="checkbox" name="extras" value="candles" onclick="calculateTotal()">Candles</label>
 <label><input type="checkbox" name="extras" value="inscription" onclick="calculateTotal()">Inscription</label>
 <label><input type="checkbox" name="extras" value="decoration" onclick="calculateTotal()">Decoration</label>
 <label><input type="checkbox" name="extras" value="special" onclick="calculateTotal()">Special Frosting & Icing</label>
</fieldset>

<input type="text" name="total">
<input type="submit" value="Submit" onclick="calculateTotal()">
Tzar
  • 5,132
  • 4
  • 23
  • 57

1 Answers1

2

Create an onchange event listener on fieldset and trigger a function that would enable the next fieldset. Check out the working snippet

const calculator = document.querySelector("form");

const occasionPricing = {
  party: 20,
  birthday: 25,
  anniversary: 50,
  wedding: 100
}

const sizeIndexes = {
  six: 1,
  eight: 1.5,
  ten: 2,
  twelve: 2.5
}

const extrasPricing = {
  candles: 5,
  inscription: 10,
  decoration: 25,
  special: 50
}

function cakes() {
  var cakes = Array.from(calculator.elements["cake"]).slice(0, 3);
  var raphael = calculator.elements["raphael"];

  function isChecked(checkbox) {
    return checkbox.checked;
  }

  var count = cakes.filter(isChecked).length;
  if (count) {
    count = count * 0.5 + 0.5;
    if (raphael.checked) {
      count += 1;
    }
    return count;
  }
  return 0;
}

function occasion() {
  var occasionCost = 0;
  var occasion = calculator.elements["occasion"];

  for (var i = 0; i < occasion.length; i++) {
    if (occasion[i].checked) {
      occasionCost = occasionPricing[occasion[i].value];
      break;
    }
  }
  return occasionCost;
}

function size() {
  var sizeIndex = 1;
  var size = calculator.elements["size"];

  for (var i = 0; i < size.length; i++) {
    if (size[i].checked) {
      sizeIndex = sizeIndexes[size[i].value];
      break;
    }
  }
  return sizeIndex;
}

function extras() {
  var extrasCost = 0;
  const extras = calculator.elements["extras"];

  for (var i = 0; i < extras.length; i++) {
    if (extras[i].checked) {
      extrasCost = extrasCost + extrasPricing[extras[i].value];
    }
  }
  return extrasCost;
}

function calculateTotal() {
  var totalCost = cakes() * occasion() * size() + extras();
  calculator.total.value = "$" + totalCost;
}

function enableFieldset(element, event) {
  
  if (event.currentTarget.id == 'cakes') {
    var checked = false;
    var checkboxes = document.getElementsByName("cake");
    for (var i = 0; i < checkboxes.length; i++) {
      if (checkboxes[i].checked) {
        checked = true;
        break;
      }
    }
    if (checked) {
      document.getElementById(element).disabled = false;
    } else {
      document.getElementById(element).disabled = true;
    }
  } else {
    document.getElementById(element).disabled = false;
  }


}
<form>

  <fieldset id="cakes" onchange="enableFieldset('occasion',event)">
    <legend>Select Cakes</legend>
    <label><input type="checkbox" name="cake" id="leonardo">Leonardo</label>
    <label><input type="checkbox" name="cake" id="donatello">Donatello</label>
    <label><input type="checkbox" name="cake" id="michelangelo">Michelangelo</label>
    <label><input type="checkbox" name="cake" id="raphael">Raphael</label>
    <p>If you select more than one cake, the other cakes are discounted 50%.</p>
    <p><small>Does not apply to Raphael.</small></p>
  </fieldset>

  <fieldset id="occasion" onchange="enableFieldset('size', event)" disabled>
    <legend>Choose Occasion</legend>
    <label><input type="radio" name="occasion" value="party" onclick="calculateTotal()" required>Party</label><br>
    <label><input type="radio" name="occasion" value="birthday" onclick="calculateTotal()">Birthday</label><br>
    <label><input type="radio" name="occasion" value="anniversary" onclick="calculateTotal()">Anniversary</label><br>
    <label><input type="radio" name="occasion" value="wedding" onclick="calculateTotal()">Wedding</label><br>
  </fieldset>

  <fieldset id="size" onchange="enableFieldset('extras', event)" disabled>
    <legend>Choose Size</legend>
    <label><input type="radio" name="size" value="six" onclick="calculateTotal()" required>6-inch</label><br>
    <label><input type="radio" name="size" value="eight" onclick="calculateTotal()">8-inch</label><br>
    <label><input type="radio" name="size" value="ten" onclick="calculateTotal()">10-inch</label><br>
    <label><input type="radio" name="size" value="twelve" onclick="calculateTotal()">12-inch</label><br>
  </fieldset>

  <fieldset id="extras" disabled>
    <legend>Select Extras</legend>
    <label><input type="checkbox" name="extras" value="candles" onclick="calculateTotal()">Candles</label>
    <label><input type="checkbox" name="extras" value="inscription" onclick="calculateTotal()">Inscription</label>
    <label><input type="checkbox" name="extras" value="decoration" onclick="calculateTotal()">Decoration</label>
    <label><input type="checkbox" name="extras" value="special" onclick="calculateTotal()">Special Frosting & Icing</label>
  </fieldset>

  <input type="text" name="total">
  <input type="submit" value="Submit" onclick="calculateTotal()">
cdoshi
  • 2,772
  • 1
  • 13
  • 20
  • This is exactly what I was looking for. And how would you display the calculated value only after input in the second fieldset is checked? – Tzar Aug 17 '18 at 03:31
  • Have modified the snippet. Check it out! Or now if I think of it, just remove calculate cost on cakes. – cdoshi Aug 17 '18 at 03:35
  • Cake multiplier in the first fieldset then isn’t used for calculation. – Tzar Aug 17 '18 at 03:41
  • 1
    Great answer @cdoshi but one minor issue.... If you check and then uncheck something from **Cakes** you can still continue enabling the rest of the form. I believe the OP is wanting to use this to ensure the required options are selected (Client-side validation). I am sure you can make a minor change to your existing answer to fix this "If this is what the expectations are" – NewToJS Aug 17 '18 at 03:42
  • Yes you are right @NewToJS. Ideally the first fieldset should have been a radio button like other fieldsets instead of checkbox. This will ensure that at least one option is selected. – cdoshi Aug 17 '18 at 03:43
  • I agree, @NewToJS. – Tzar Aug 17 '18 at 03:44
  • I did plan on submitting a solution but since this is a great start I didn't see much point so I thought I would share my input to try help you improve your post. – NewToJS Aug 17 '18 at 03:45
  • @NewToJS I have edited my post and switched from checkbox to radio. This will ensure that one option is always selected. – cdoshi Aug 17 '18 at 03:47
  • @cdoshi Well maybe you can make some use from one of my previous answers.... [**How can I make the radio boxes...**](https://stackoverflow.com/questions/42989096/how-can-i-make-the-radio-boxes-in-html-look-like-checkboxes-and-make-them-have-x/42989382#42989382) – NewToJS Aug 17 '18 at 03:48
  • But checkboxes in the first fieldset are required so customers can order multiple cakes and get a discount :) – Tzar Aug 17 '18 at 03:50
  • 1
    Ohh I see. My bad!! – cdoshi Aug 17 '18 at 03:50
  • 2
    @Boletrone added extra logic to handle in case all cakes are unselected again. I think you can take it up from here :) – cdoshi Aug 17 '18 at 04:13