-1

The point is i have radio button that send value to an array with push method, when it is clicked.

The problem is the radio button became like an increment and decrement to the value. How do i fix this ? Sorry for my bad english

I have tried use 'pop' method to take back the value.

var total = document.getElementById("total");
        var subTotal = [];
        var toppings = {
            'Avocado': [true, false, false],
            'Tuna': [true, false, true],
            'Duck': [false, false, true],
            'Sausage': [false, false, true],
            'Lobster': [false, true, false],
            'Oyster': [false, true, false],
            'Salmon': [false, true, false],
            'Bacon': [false, true, true]
        };

        function pizzaChoice(menuId) {
            var menu = document.querySelectorAll('input[name="pizza"]');
            if (menu[menuId].checked) {
                subTotal.push(parseInt(menu[menuId].value));
            } else {
                subTotal.pop();
            };
            for (const name of Object.keys(toppings)) {
                var chkbox = document.getElementById(name);
                if (toppings[name][menuId]) { // available topping on this menu
                    chkbox.disabled = false;
                }
                else {
                    chkbox.disabled = menu[menuId].checked;
                    if (menu[menuId].checked) {
                        chkbox.checked = false;
                    }
                }
            }
        }

        function pickSize() {
            var foo = document.getElementsByName("size");
            for (let i = 0; i < foo.length; i++) {
                if (foo[i].checked) {
                    subTotal.push(parseInt(foo[i].value));
                } else {
                    subTotal.pop();
                }
            }
        }

        function pickTopping(toppingName) {
            var x = document.getElementById(toppingName);
            if (x.checked) {
                subTotal.push(parseInt(x.value));
            } else {
                subTotal.pop();
            }
        }

        function calc() {
            if (!subTotal.length == 0) {
                var grandTotal = subTotal.reduce(function (a, b) {
                    return a + b;
                }, 0);
                total.innerHTML = grandTotal;
            };
        };
  • Please create a minimum reproducible example – brk Sep 19 '20 at 08:20
  • pop() just removes the last element in the array - it is not an "undo" function. If you need to find a value in the array, you have to use something like find() or indexOf() and then splice() to remove it. Alternatively, you could use a Map object and its has(), get(), set() and delete() functions to maintain a list of selections. – ATD Sep 19 '20 at 08:36
  • I have posted a suggested answer but I may be making it more general than you need. Could you clarify whether you are allowed to pick multiple toppings or just one - I suspect it may be just one as you talk of radio button, but I wanted a choice where I could have avocado with my duck - possibly not allowed(?) – A Haworth Sep 19 '20 at 14:35

2 Answers2

0

I think you can check if such array element is already there before adding it using push. For example use indexOf to check if it is already there.

  • And inversely, use indexOf followed by splice to remove an existing item. See [this question](https://stackoverflow.com/questions/5767325/how-can-i-remove-a-specific-item-from-an-array). – Patrick Sep 19 '20 at 08:31
  • I don't understand why this would work. The things being pushed onto subtotal are numeric values. I assume that a customer can chose more than one topping, they may have the same values and you wouldn't want to remove say the cost of Avocado if he also wanted Duck on his pizza. Of course if only one topping is allowed then the method in this answer would work, but it's not a general answer for checkboxes where several values can be chosen at the same time. (and it's not normal for pizzas!) – A Haworth Sep 19 '20 at 11:34
0

The question asks how repeated clicks on, for example, a topping don't add multiple costs of that topping to subtotal.

Assuming it's possible to have more than one topping and as items may have the same prices as each other it isn't enough just to remove a value from subtotal just because something has already added that value to the subtotal. You need to remember which items have already been added to subtotal. You can do this by remembering the topping's input element, not just its value. Then if the item is unclicked we can remove it from the array.

This is a suggested pickTopping function, obviously the other pick functions would have to be changed similarly:

    function pickTopping(x){
           picked = picked.filter(removex);
        if (x.checked) {
            picked.push(x); 
        }
        function removex(val) {
            return !(val==x);
        }
  }

And here is the altered calc function

   function calc()  {
        var total=0;
        for (var i=0;i<picked.length;i++) {
            total +=Number(picked[i].value);
        }
        document.getElementById('total').innerHTML=total.toFixed(2);               
    }

A simple example for just toppings can be tried in the snippet.

A few notes - in the original code the value is forced into an integer, and if the currency is always an integer then this will be OK, but I've assumed a currency which has two decimal places in order to make things more general.

I have assumed that several toppings can be picked, but this may not be the case as the question talks of radio buttons so the code would need to be altered accordingly but the basic principle of storing the element rather than just its value still works (though it is not essential it does seem more 'right').

When the inputs are clicked they pass themselves to the pickTopping function - this saves having to do another getElementById but of course this can be changed back if it's not suitable. Without seeing the input elements it's not possible to judge.

<input id="Avocado" type="checkbox" onclick="pickTopping(this);" value="3">Avocado
<input id="Tuna" type="checkbox" onclick="pickTopping(this);" value="3">Tuna
<input id="Duck" type="checkbox" onclick="pickTopping(this);" value="5.50">Duck
<input id="Sausage" type="checkbox" onclick="pickTopping(this);" value="2.30">Sausage
<input id="Lobster" type="checkbox" onclick="pickTopping(this);" value="8.00">Lobster
<input id="Oyster" type="checkbox" onclick="pickTopping(this);" value="10.00">Oyster
<input id="Salmon" type="checkbox" onclick="pickTopping(this);" value="3">Salmon
<input id="Bacon" type="checkbox" onclick="pickTopping(this);" value="2.50">Bacon

<p>The current total is <span id="total">0.00</span></p>
<script>
    var picked=[];    
        
        function pickTopping(x){
               picked = picked.filter(removex);
            if (x.checked) {
                picked.push(x); 
            }
            calc();//just put in to show the current total in this example
            function removex(val) {
                return !(val==x);
            }
      }

        function calc()  {
            var total=0;
            for (var i=0;i<picked.length;i++) {
                total +=Number(picked[i].value);
            }
            document.getElementById('total').innerHTML=total.toFixed(2);
        }
</script>
A Haworth
  • 7,433
  • 2
  • 4
  • 10