使用下拉框值时JQuery药物计算器无法完成计算
药物计算器下拉框填充后计算NaN/Infinity问题修复
问题描述
我是JQuery新手,开发了一款药物计算器。支持用户自定义数值的功能运行正常,但用SQL查询驱动的下拉框填充字段时出现问题:下拉框能正常填充表单字段,填充后调用calcTotals()计算,但结果始终为NaN或Infinity;手动编辑表单字段后计算器恢复正常,但这失去了下拉框填充的意义。
下拉框代码
<select name="stock_item_used" id="stock_item_used" required> <option value="" disabled selected>Medication</option> <?php //Find medications $stmt = $conn->prepare("SELECT * from rescue_medication_trans LEFT JOIN rescue_medications ON rescue_medication_trans.med_profile_id = rescue_medications.medication_id LEFT JOIN rescue_stock_medication ON rescue_stock_medication.medication = rescue_medication_trans.med_profile_id WHERE rescue_medication_trans.centre_id = :centre_id ORDER BY common_name ASC"); $stmt->bindParam(':centre_id', $centre_id, PDO::PARAM_INT); // initialise an array for the results $instock = array(); $stmt->execute(); while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { $med_profile_id = $row["med_profile_id"]; $batch_number = $row["batch_number"]; $expiry = $row["expiry"]; $med_common_name = $row["common_name"]; $mcd = $row["concentration_dose"]; $mcv = $row["concentration_volume"]; $dose_type = $row["concentration_dose_type"]; $volume_type = $row["concentration_volume_type"]; //format the exp date $exp = new DateTime($expiry); $exp = $exp->format('d-m-Y'); print '<option value="' . $med_profile_id . '" data-dose="' . $mcd . '" data-volume="' . $mcv . '">' . $med_common_name . ' - ' . $mcd . '<i>' . $dose_type . '</i> in ' . $mcv . '<i>' . $volume_type. '</i> (' . $batch_number . ' exp: ' . $exp . ') </option>'; } ?> </select>
注:已移除重复的name="stock_item_used"属性,修复HTML无效问题
JQuery脚本
<script> var req_dose = 0; var med_dose = 0; var med_vol = 0; var weight = 0; $("#required_dose").change( function(){ req_dose = $("#required_dose").val(); calcTotals(); }); $("#medication_dose").change( function() { med_dose = $("#medication_dose").val(); calcTotals(); }); $("#medication_volume").change( function() { med_vol = $("#medication_volume").val(); calcTotals(); }); $("#animal_weight").change( function() { weight = $("#animal_weight").val(); calcByweight(); }); var selectdose = document.getElementById("stock_item_used"); selectdose.addEventListener("change", function() { var optiondose = selectdose.options[selectdose.selectedIndex].getAttribute("data-dose"); document.getElementById('medication_dose').value = optiondose; calcTotals(); calcByweight(); }); var selectvol = document.getElementById("stock_item_used"); selectvol.addEventListener("change", function() { var optionvol = selectvol.options[selectvol.selectedIndex].getAttribute("data-volume"); document.getElementById('medication_volume').value = optionvol; calcTotals(); calcByweight(); }); function calcTotals(){ $("#volume").text(req_dose * (med_vol / med_dose)); } function calcByweight(){ $("#perweight").text((req_dose * (med_vol / med_dose)) * weight); } </script>
问题根源
- 全局变量未更新:
med_dose、med_vol只有在输入框的change事件触发时才会赋值,但通过下拉框给输入框赋值时,并未触发输入框的change事件,导致这两个变量始终是初始值0,计算时出现0/0(NaN)或除数为0(Infinity)的情况。 - 字符串类型运算:从
getAttribute获取的data-*值是字符串类型,直接参与运算可能引发类型错误。 - 重复事件监听:同一个下拉框绑定了两个
change事件,冗余且容易引发逻辑混乱。
修复方案
方案1:合并下拉框事件,直接更新全局变量
替换原有的两个下拉框事件监听,改成以下代码:
$("#stock_item_used").change(function() { // 获取选中选项的data值,并转为数字(默认0避免空值/非数字) var selectedOption = $(this).find("option:selected"); var optiondose = parseFloat(selectedOption.data("dose")) || 0; var optionvol = parseFloat(selectedOption.data("volume")) || 0; // 更新输入框值 $("#medication_dose").val(optiondose); $("#medication_volume").val(optionvol); // 直接更新全局变量 med_dose = optiondose; med_vol = optionvol; // 执行计算 calcTotals(); calcByweight(); });
方案2:触发输入框change事件复用原有逻辑
如果想保留原有的输入框change事件逻辑,可以通过trigger("change")触发事件,让原有代码更新全局变量:
$("#stock_item_used").change(function() { var selectedOption = $(this).find("option:selected"); var optiondose = selectedOption.data("dose"); var optionvol = selectedOption.data("volume"); // 赋值并触发change事件 $("#medication_dose").val(optiondose).trigger("change"); $("#medication_volume").val(optionvol).trigger("change"); // 执行重量计算 calcByweight(); });
优化计算函数(可选)
为了避免除数为0或非数字输入的问题,在计算函数里增加类型校验和容错处理:
function calcTotals(){ // 转为数字,默认0避免无效值 var reqDoseNum = parseFloat(req_dose) || 0; var medVolNum = parseFloat(med_vol) || 0; var medDoseNum = parseFloat(med_dose) || 0; // 避免除数为0 var result = medDoseNum !== 0 ? reqDoseNum * (medVolNum / medDoseNum) : 0; $("#volume").text(result); } function calcByweight(){ var reqDoseNum = parseFloat(req_dose) || 0; var medVolNum = parseFloat(med_vol) || 0; var medDoseNum = parseFloat(med_dose) || 0; var weightNum = parseFloat(weight) || 0; var baseResult = medDoseNum !== 0 ? reqDoseNum * (medVolNum / medDoseNum) : 0; $("#perweight").text(baseResult * weightNum); }
内容的提问来源于stack exchange,提问作者Dan Lindley
相关产品推荐
相关产品推荐

