简体   繁体   中英

Placing code in my Javascript array

I have the following problem,

I have made a form with alot of input fields. Where if the user types a 1 it will show the price immediately next to it. My code for this is this:

var priceMargherita = 7;
    var numPizzaMargheritaInput = document.getElementById('countMargherita');
    var priceMargheritaLabel    = document.getElementById('totalMargherita');

    function onNumPizzaMargheritaInputChange(e){

        var totalMargherita = priceMargherita * parseInt(e.target.value);
        var formattedPrice = '\u20ac '+totalMargherita.toFixed(2);

        priceMargheritaLabel.innerHTML = '';
        priceMargheritaLabel.appendChild(document.createTextNode(formattedPrice));
    }
    numPizzaMargheritaInput.addEventListener('change', onNumPizzaMargheritaInputChange, false);

and it places the price like this:

<td>Pizza Margherita</td>
<td><input type="number" id="countMargherita" class="formnumbers" name="PizzaMargherita" onChange="validateForm(this)" min="1" max="99"/></td>
<td><span id="totalMargherita"></span></td>

Now my problem is that i have 11 products like this Pizza Margherita. And at the moment i have 11 pieces of code like the top one. I think this can be done in an array since the only things that change are some names.

Correct me if i'm wrong since im nowhere experienced in JS nor Arrays.

Any help is greatly appreciated!

For me, the simplest way to do it is to NOT use arrays or ids.

If you can change the html, you should add the price as a data-attribute, and then you can have a generic code :

<td>Pizza Margherita</td>
<td><input type="number" class="formnumbers" name="PizzaMargherita"
           onChange="changeTotalFromCount(this)" min="1"
           max="99" data-unitPrice="7" /></td>
<td></td>

JS :

function changeTotalFromCount(input) {
    var unitPrice = parseFloat(input.getAttribute("data-unitPrice"));
    var count = input.value;

    var price = unitPrice * count;
    var formattedPrice = '\u20ac ' + price.toFixed(2);

    var label = input.parentNode.nextElementSibling;
    label.innerHTML = '';
    label.appendChild(document.createTextNode(formattedPrice));
}

Rather than arrays, I think the word you're looking for is loops. Here is a way to factor your program using an object and a loop:

var prices = {
  Margherita: 7,
  Hawaiian: 7,
  NewYork: 8
};

for (var pizzaType in prices) {
  var inputElement = document.getElementbyId('count' + pizzaType);
  var labelElement = document.getElementbyId('total' + pizzaType);

  inputElement.addEventListener('change', function(event) {
    var total = prices[pizzaType] * parseInt(event.target.value);
    var formattedPrice = '\u20ac ' + total.toFixed(2);

    labelElement.innerHTML = '';
    labelElement.appendChild(document.createTextNode(formattedPrice));
  }, false);
}

I chose to use an anonymous function instead of a named one, as this is the most common practice with event listeners.

An array isn't the most efficient way to solve the problem. You'd be better off with a more generalised function that has the necessary information (the event, the price, and the ID of the element to display the price) as parameters. Then use an array of objects to initialise everything. Something like this:

var pizzas = [
    {
        pizza: 'margherita',
        price: 7,
        input: 'countMargherita',
        label: 'totalMargherita'
    },
    {
        pizza: 'pepperoni',
        price: 10,
        input: 'countPepperoni',
        label: 'totalPepperoni'
    }
]

function calculatePrice(e, price, label) {
    var total = price * parseInt(e.target.value);
    var formattedPrice = '\u20ac '+total.toFixed(2);

    var outputElement = document.getElementById(label);
    outputElement .innerHTML = '';
    outputElement .appendChild(document.createTextNode(formattedPrice));
}

Then iterate over that pizzas array to bind everything up:

for(var i = 0, l = pizzas.length; i < l; i++) {
    (function(pizza) {
        document.getElementById(pizza.input).addEventListener('change', function(e) {
            calculatePrice(e, pizza.price, pizza.label);
        }, false);
    })(pizzas[i]);
}

The above uses a closure to avoid issues due to JavaScript's variable scoping; i is scoped to the function scope since there isn't block-level scoping. Since the event handler is essentially a deferred action, the value of i when that executes will also be the last value of i if you don't use one.

Make a more generic function for calculating your price, like onNumPizzChange which takes the base element name, eg 'Margherita'. In this function, extract your element like

var inputElm = document.getElementById('count'+elmBase);

then set up your events by wrapping this function with another like so:

document.getElementById('numPizzaMargheritaCount').addEventListener('change', function(){ onNumPizzaChange('Margherita')}, false);

Does that make sense?

Good luck!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM