[英]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 中使用外部变量( inputID
、 p
、 s
)引起的。这 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.