简体   繁体   English

多个事件侦听器仅更新设置的最后一个字段

[英]Multiple event listeners only update the last field that was setup

I am trying to setup an order form where the user can enter a quantity into an input field and the total for that particular product will update.我正在尝试设置一个订单表格,用户可以在其中输入数量到输入字段,并且该特定产品的总数将更新。 There will be dozens of products in the end.最终会有几十种产品。

At the moment, I have the product data stored into a javascript object that is turned into an array to work with.目前,我将产品数据存储到一个 javascript object 中,它被转换成一个数组来使用。 Using this array, I have the products and all fields set up.使用这个数组,我设置了产品和所有字段。 The price is setup based on a products size.价格是根据产品尺寸设置的。 Certain products will have multiple sizes and some only one size.某些产品会有多种尺寸,有些只有一种尺寸。

The problem I am having is that when I loop over the products to setup their event listeners, it only seems to work on the last element of the array.我遇到的问题是,当我遍历产品以设置它们的事件侦听器时,它似乎只适用于数组的最后一个元素。 Here is just the sections I think are the culprits:以下是我认为是罪魁祸首的部分:

//Set the listener for each products input box
function SetListeners(_prodList) {
    for(var p in _prodList)
    {
        //We need a listener for each size
        for(var s in _prodList[p].sizes)
        {
            //Get the html of the element in question and add a listener with the product details
            var inputID = 'input-' + _prodList[p].sizes[s].sku;
            document.getElementById(inputID).addEventListener('input', function() {
                UpdatePrice(inputID, _prodList[p].sizes[s].price, 'total-' + _prodList[p].id);
                UpdateTotal();
            });
        }
    }
}

//Updates our total for each product
function UpdatePrice(_id, _price, _total)
{
    var prodQty = document.getElementById(_id).value;
    var prodTotal = (prodQty * _price).toFixed(2);
    document.getElementById(_total).innerHTML = '$' + prodTotal;
}

How can I get it so that every input box registers to a specific total innerHTML based on the products sku?我怎样才能得到它,以便每个输入框都根据产品 sku 注册到特定的总 innerHTML?

Here is a fiddle with the whole code running and with formatting: https://jsfiddle.net/BlueVolcano/cx70veh3/1/这是整个代码运行和格式化的小提琴: https://jsfiddle.net/BlueVolcano/cx70veh3/1/

Here is the full javascript only:以下是完整的 javascript:

//The total for the order
var orderTotal = 0;

//The data object containing all the products
const products = {
    "shirts": 
        [
        {
            "name": "Product 1",
            "id": "Prod-1",
            "img": "https://i.imgur.com/Ycfi8RS.png",
            "details": "These are the details for the product.",
            "sizes": [
                {"size": "Large", "sku": "Prod-1-1", "price": 10.99}
            ]
        },
        {
            "name": "Product 2",
            "id": "Prod-2",
            "img": "https://i.imgur.com/Ycfi8RS.png",
            "details": "These are the details for the product.",
            "sizes": [
                {"size": "Large", "sku": "Prod-2-1", "price": 20.99}
            ]
        },
        {
            "name": "Product 3",
            "id": "Prod-3",
            "img": "https://i.imgur.com/Ycfi8RS.png",
            "details": "These are the details for the product.",
            "sizes": [
                {"size": "Large", "sku": "Prod-3-1", "price": 30.99},
                {"size": "Medium", "sku": "Prod-3-2", "price": 26.99},
                {"size": "Small", "sku": "Prod-3-3", "price": 22.99}
            ]
        }
    ]
};

//Sort all products from data object into array and flatten it
var thisProductList = [];
for(var v in products)
    thisProductList.push(products[v]);
thisProductList = thisProductList.flat();

//Category specific lists from the all products
SetProducts(thisProductList, 'shirts');
    
//Creates our products and adds them as new html elements
function SetProducts(_products, _category)
{
    //Create the section header
    var sectionDiv = document.createElement('section');
    sectionDiv.setAttribute("class", _category);
    sectionDiv.innerHTML = '<h2 class="section-header">' + _category.toUpperCase() + '</h2>';
    document.getElementById('container').append(sectionDiv);

    //Loop through the list and create the products
    for(var p in _products)
    {
        var rowDiv = document.createElement('div');
        rowDiv.setAttribute("class","row");
        
        var productDiv = document.createElement('div');
        productDiv.setAttribute("class","product");

        var productImage = document.createElement('div');
        productImage.setAttribute("class","product-image padding");
        productImage.innerHTML = '<img src="'+ _products[p].img + '" />';
        productDiv.append(productImage);
        
        var productName = document.createElement('div');
        productName.setAttribute("class","product-name padding");
        productName.innerHTML = '<h2 class="product-header">' + _products[p].name + '</h2>';
        productDiv.append(productName);
        
        var productDetails = document.createElement('div');
        productDetails.setAttribute("class","product-details");
        productDetails.innerHTML = _products[p].details;
        productName.append(productDetails);
        
        var productSizes = document.createElement('div');
        productSizes.setAttribute("class","product-sizes padding");
        for(var s in _products[p].sizes)
        {
            var temp = document.createElement('div');
            var size = _products[p].sizes[s];
            temp.setAttribute("id","size-"+size.sku); 
            _products[p].sizes.length > 1 ? temp.setAttribute("class","flex underline") : temp.setAttribute("class","flex"); 
            var price= document.createElement('div');
            price.innerHTML = (size.size == '' ? '' : size.size + ': ') + '<strong>$' + size.price.toFixed(2) + '</strong><br/><span class="sku"><i>' + size.sku + '</i></span>';
            price.setAttribute("class","half"); 
            temp.append(price);
            var input = document.createElement("input");
            input.type = "number";
            input.setAttribute("id", "input-" + size.sku);
            input.setAttribute("class", "quantity-input half");
            temp.append(input);
            productSizes.append(temp);
        }
        productDiv.append(productSizes);
        
        var productTotal = document.createElement('div');
        productTotal.setAttribute("id","total-" + _products[p].id);
        productTotal.setAttribute("class","product-total padding");
        productTotal.innerHTML = '$0.00';
        productDiv.append(productTotal);
        
        sectionDiv.append(rowDiv);
        rowDiv.append(productDiv);
    }
    
    SetListeners(_products);
}

//Set the listener for each products input box
function SetListeners(_prodList) {
    for(var p in _prodList)
    {
        //We need a listener for each size
        for(var s in _prodList[p].sizes)
        {
            //Get the html of the element in question and add a listener with the product details
            var inputID = 'input-' + _prodList[p].sizes[s].sku;
            document.getElementById(inputID).addEventListener('input', function() {
                UpdatePrice(inputID, _prodList[p].sizes[s].price, 'total-' + _prodList[p].id);
                UpdateTotal();
            });
        }
    }
}

//Updates our total for each product
function UpdatePrice(_id, _price, _total)
{
    var prodQty = document.getElementById(_id).value;
    var prodTotal = (prodQty * _price).toFixed(2);
    document.getElementById(_total).innerHTML = '$' + prodTotal;
}

//Updates the order total field
function UpdateTotal()
{
    orderTotal = 0;
    var totals = document.getElementsByClassName('product-total');
    for(var i = 0; i < totals.length; i++)
    {
        var temp = totals[i].innerHTML;
        temp = temp.replace('$','');
        var t = parseFloat(temp);
        orderTotal += t;
    }
    document.getElementById('top-order-total-val').innerHTML = '$' + orderTotal.toFixed(2);
}

Your issue is caused by using outside variables ( inputID , p , s ) inside your input handler function. The values of these 3 variables are the values of last product in your loop.您的问题是由在输入处理程序 function 中使用外部变量( inputIDps )引起的。这 3 个变量的值是循环中最后一个产品的值。

To solve this issue, when generation HTML elements for the products, you could add some more attributes, for storing pricing and its corresponding total's id.为了解决这个问题,当为产品生成 HTML 元素时,您可以添加更多属性,用于存储定价及其对应的总计的 id。

var input = document.createElement("input");
input.type = "number";
input.setAttribute("id", "input-" + size.sku);
input.setAttribute("class", "quantity-input half");
// set additional attribute for calculation
input.setAttribute("price", size.price);
input.setAttribute("total", "total-" + _products[p].id);
input.setAttribute("last-value", "0");

Then in your input handler function, reference these additional attributes for pricing and corresponding total element.然后在您的输入处理程序 function 中,为定价和相应的总计元素引用这些附加属性。

//Get the html of the element in question and add a listener with the product details
var inputID = 'input-' + _prodList[p].sizes[s].sku;
document.getElementById(inputID).addEventListener('input', function() {
    var input = event.target;
    UpdatePrice(input.id, input.getAttribute("price"), input.getAttribute("total"));
    UpdateTotal();
});

In your UpdatePrice function, update formula for total calculation在您的UpdatePrice function 中,更新总计算公式

 {New Total} = {Last Total} - {Last Value Of Current Size} + {New Value Of Current Size}

Updated UpdatePrice function:更新更新价格UpdatePrice

function UpdatePrice(_id, _price, _total) {
  var inputElement = document.getElementById(_id);
  var totalElement = document.getElementById(_total);
  var prodQty = inputElement.value;
  var lastTotal = parseInt(totalElement.getAttribute("last-total"));
  var lastValue = parseInt(inputElement.getAttribute("last-value"));
  var newValue = prodQty * _price;
  var prodTotal = lastTotal - lastValue + newValue;
  inputElement.setAttribute("last-value", newValue);
  totalElement.setAttribute("last-total", prodTotal);
  totalElement.innerHTML = '$' + prodTotal.toFixed(2);
}

You could reference it here: https://jsfiddle.net/bt9dz63a/你可以在这里参考它: https://jsfiddle.net/bt9dz63a/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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