基于JavaScript实现配料重量联动更新及水重量计算方案咨询
Hey there! Let's work through your problem step by step. I see you're trying to build a real-time calculation feature for ingredient nutrition values, plus auto-calculate water weight based on total ingredient weight. Let's fix and enhance your existing code to make this work correctly.
First, Let's Fix the Core Issue in Your Current Code
Right now, your updatevalues function uses the already calculated value in the fat/sweet input boxes to multiply by the new weight. That means if a user adjusts the weight multiple times, the numbers will get progressively wrong (since you're multiplying a multiplied value again). Instead, we need to store the original per-gram values of each ingredient so we always calculate from the source data.
Step 1: Update Your HTML to Store Original Data
We'll add data-* attributes to your readonly input fields to hold the original per-gram values. This keeps the source data accessible without relying on the displayed (and potentially modified) values:
<td> <input type="text" name="name" placeholder="Weight" class='smalltextbo onlynumbers' id="w<?=$thedetails_array['sno']?>" onkeyup="updatevalues(this);" onkeypress="return isNumber(event);" value='1'/> </td> <td> <input type="text" name='fat' value="<?=$thedetails_array['fat']?>" id="fat<?=$thedetails_array['sno']?>" readonly data-original="<?=$thedetails_array['fat']?>"/> </td> <td> <input type="text" name='sweet' value="<?=$thedetails_array['sweet']?>" id="sweet<?=$thedetails_array['sno']?>" readonly data-original="<?=$thedetails_array['sweet']?>"/> </td> <td> <input type="text" name='solid1' value="<?=$thedetails_array['solid1']?>" id="solid<?=$thedetails_array['sno']?>" readonly data-original="<?=$thedetails_array['solid1']?>"/> </td> <!-- Add this row for water weight (adjust IDs/structure to match your table) --> <tr> <td>Water</td> <td><input type="text" id="water-weight" readonly placeholder="Auto-calculated"/></td> <td></td> <td></td> </tr>
Step 2: Rewrite the JavaScript for Accurate Calculations
This updated function will:
- Use the original per-gram values to calculate nutrition totals
- Handle invalid weight inputs (like empty/non-numeric values)
- Auto-calculate water weight as total ingredient weight minus 1000
- Keep numbers clean with fixed decimal places
function updatevalues(input) { // Get the unique suffix for this ingredient's IDs const idSuffix = input.id.substr(1); // Get the input weight, default to 1 if input is invalid/empty const weight = parseFloat(input.value) || 1; // Fetch the original per-gram values from data attributes const originalFat = parseFloat($(`#fat${idSuffix}`).data('original')); const originalSweet = parseFloat($(`#sweet${idSuffix}`).data('original')); const originalSolid = parseFloat($(`#solid${idSuffix}`).data('original')); // Calculate and update nutrition values (keep 2 decimal places for readability) $(`#fat${idSuffix}`).val((originalFat * weight).toFixed(2)); $(`#sweet${idSuffix}`).val((originalSweet * weight).toFixed(2)); $(`#solid${idSuffix}`).val((originalSolid * weight).toFixed(2)); // Calculate total weight of all ingredients let totalIngredientWeight = 0; $('.onlynumbers').each(function() { const val = parseFloat($(this).val()) || 0; totalIngredientWeight += val; }); // Calculate water weight: total - 1000. Use Math.max to avoid negative values const waterWeight = Math.max(totalIngredientWeight - 1000, 0); $('#water-weight').val(waterWeight.toFixed(2)); } // Keep your existing number validation function function isNumber(event) { const charCode = event.which || event.keyCode; return !(charCode > 31 && (charCode < 48 || charCode > 57)); }
Key Improvements Explained
- Original Data Storage: The
data-originalattributes ensure we always calculate from the true per-gram values, never from previously computed totals. - Input Safety: We use
parseFloat(...) || 1to handle empty or non-numeric weight inputs, preventingNaNerrors. - Water Weight Logic: We sum all ingredient weights (using the
onlynumbersclass to target all weight inputs) and subtract 1000.Math.maxensures water weight never goes negative (you can adjust this if you want to handle under-1000 totals differently, like showing a warning). - Clean Display:
toFixed(2)ensures consistent, readable decimal formatting (adjust the number if you need more/less precision).
Quick Notes for Your Implementation
- Make sure every ingredient's weight input has the
onlynumbersclass so the total weight calculation works correctly. - If your water weight input has a different ID than
#water-weight, update that in the JS to match your actual HTML. - You can add an
onblur="updatevalues(this)"to the weight inputs to ensure calculations trigger when the user clicks away from the field.
内容的提问来源于stack exchange,提问作者Amani

