我正在尝试为以下情况创建一个函数:
我有许多接受 0 到 100 之间的数字值的用户输入
如果我在 input1 中输入 100,则 input2 到 input-n 将不接受任何数字,因为 100% 已赋予 input1
如果我在input1中输入80,那么input2将是20,并且不会接受高于20的值如果我在input2中输入15,那么剩下的5将进入input3
就我而言,我有 4 个输入,但将来这些输入可能会增加。
这是我迄今为止所做的功能:
function updatePayments() {
var payment1 = parseInt(document.getElementById('in-line1').value) || 0;
var payment2 = parseInt(document.getElementById('in-line2').value) || 0;
var payment3 = parseInt(document.getElementById('in-line3').value) || 0;
var payment4 = parseInt(document.getElementById('in-line4').value) || 0;
if (payment1 >= 100) {
payment2 = 0;
payment3 = 0;
payment4 = 0;
}
else {
var remainingPercent = 100 - payment1;
payment2 = remainingPercent;
if (payment3 > 0) {
payment2 = remainingPercent - payment3;
}
if (payment4 > 0) {
payment3 = remainingPercent - payment2 - payment4;
}
}
document.getElementById('in-line2').value = payment2;
document.getElementById('in-line3').value = payment3;
document.getElementById('in-line4').value = payment4;
var poNetTotalValue = GetPoNetTotalValue();
$('#out-line1').text(formatNumber(payment1 / 100 * poNetTotalValue));
$('#out-line2').text(formatNumber(payment2 / 100 * poNetTotalValue));
$('#out-line3').text(formatNumber(payment3 / 100 * poNetTotalValue));
$('#out-line4').text(formatNumber(payment4 / 100 * poNetTotalValue));
var totalPayments =
payment1 / 100 * poNetTotalValue +
payment2 / 100 * poNetTotalValue +
payment3 / 100 * poNetTotalValue +
payment4 / 100 * poNetTotalValue;
var submitButton = document.getElementById('btn-submit');
if (totalPayments != poNetTotalValue) {
$('#payment-check-validation').removeClass('visually-hidden');
submitButton.disabled = true;
}
else {
$('#payment-check-validation').addClass('visually-hidden');
submitButton.disabled = false;
}
$('#out-lines-total').text(formatNumber(totalPayments));
}
这是 HTML(它是 cshtml 的一部分)
<tbody>
<!-- line1: down payment -->
<tr>
<td width="50%">
Down Payment
<input type="hidden" asp-for="PoPayments[0].Notes" value="Down Payment"/>
</td>
<td width="20%">
<input id="in-line1"
asp-for="PoPayments[0].Percentage"
type="number" min="0" max="100"
class="w-100"
placeholder="%"
oninput="enforceMinMax(this); updatePayments()" />
</td>
<td>
<span id="out-line1" data-down-payment-value="0">
0
</span>
</td>
</tr>
<!-- line2: upon delivery -->
<tr>
<td width="50%">
Upon Delivery
<input type="hidden" asp-for="PoPayments[1].Notes" value="Upon Delivery" />
</td>
<td width="20%">
<input id="in-line2"
asp-for="PoPayments[1].Percentage"
type="number" min="0" max="100"
class="w-100"
placeholder="%"
oninput="enforceMinMax(this); updatePayments()">
</td>
<td>
<span id="out-line2" data-upon-delivery-value="0">
0
</span>
</td>
</tr>
<!-- line3: criteria1 -->
<tr>
<td width="50%">
<input type="text" asp-for="PoPayments[2].Notes"
placeholder="Enter Payment Criteria">
</td>
<td width="20%">
<input id="in-line3"
asp-for="PoPayments[2].Percentage"
type="number" min="0" max="100"
class="w-100"
placeholder="%"
oninput="enforceMinMax(this); updatePayments()">
</td>
<td>
<span id="out-line3" data-criteria1-value="0">
0
</span>
</td>
</tr>
<!-- line4: criteria2 -->
<tr>
<td width="50%">
<input type="text" asp-for="PoPayments[3].Notes"
placeholder="Enter Payment Criteria">
</td>
<td width="20%">
<input id="in-line4"
asp-for="PoPayments[3].Percentage"
type="number" min="0" max="100"
class="w-100"
placeholder="%"
oninput="enforceMinMax(this); updatePayments()">
</td>
<td>
<span id="out-line4" data-criteria2-value="0">
0
</span>
</td>
</tr>
</tbody>
function GetPoNetTotalValue() { return document.getElementById('poNetTotal').dataset.poNetTotalValue; }
这只是一个函数,这样我就不必一次又一次地重复相同的变量,而且如果元素 id 发生变化,我也不必在很多地方更改它,因为 JS 中的另一部分正在使用这个值
至于formatNumber和enforeMinMax
function formatNumber(num) {
return num.toLocaleString('en-US', { maximumFractionDigits: 2 });
}
function enforceMinMax(el) {
if (el.value != "") {
if (parseInt(el.value) < parseInt(el.min)) {
el.value = el.min;
el.dispatchEvent(new Event("input"));
}
if (parseInt(el.value) > parseInt(el.max)) {
el.value = el.max;
el.dispatchEvent(new Event("input"));
}
}
}
由于您显然使用了 jQuery,所以我会充分使用它,而不是将标准 DOM 方法与它混合。
对于 4 个输入,我建议循环它们并跟踪剩余输入仍然可用的值:
function updatePayments() {
const poNetTotalValue = GetPoNetTotalValue();
let totalPayments = 0;
let available = 100;
const $outs = $('#out-line1,#out-line2,#out-line3,#out-line4');
$('#in-line1,#in-line2,#in-line3,#in-line4').each(function (i) {
const value = +$(this).val();
const payment = Math.max(0, Math.min(available, value));
available -= payment;
if (value != payment) $(this).val(payment);
const out = payment / 100 * poNetTotalValue;
$outs.eq(i).text(formatNumber(out));
totalPayments += out;
});
var submitButton = document.getElementById('btn-submit');
if (totalPayments != poNetTotalValue) {
$('#payment-check-validation').removeClass('visually-hidden');
submitButton.disabled = true;
}
else {
$('#payment-check-validation').addClass('visually-hidden');
submitButton.disabled = false;
}
$('#out-lines-total').text(formatNumber(totalPayments));
}
function enforceMinMax(el) {
if (el.value != "") {
if (+el.value < +el.min) {
el.value = el.min;
el.dispatchEvent(new Event("input"));
} else if (+el.value > +el.max) {
el.value = el.max;
el.dispatchEvent(new Event("input"));
}
}
}
function GetPoNetTotalValue() {
return $('#poNetTotal').data("poNetTotalValue") ?? 1;
}
function formatNumber(num) {
return num.toLocaleString('en-US', { maximumFractionDigits: 2 });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<table>
<tbody>
<!-- line1: down payment -->
<tr>
<td width="50%">
Down Payment
<input type="hidden" asp-for="PoPayments[0].Notes" value="Down Payment"/>
</td>
<td width="20%">
<input id="in-line1"
asp-for="PoPayments[0].Percentage"
type="number" min="0" max="100"
class="w-100"
placeholder="%"
oninput="enforceMinMax(this); updatePayments()" />
</td>
<td>
<span id="out-line1" data-down-payment-value="0">
0
</span>
</td>
</tr>
<!-- line2: upon delivery -->
<tr>
<td width="50%">
Upon Delivery
<input type="hidden" asp-for="PoPayments[1].Notes" value="Upon Delivery" />
</td>
<td width="20%">
<input id="in-line2"
asp-for="PoPayments[1].Percentage"
type="number" min="0" max="100"
class="w-100"
placeholder="%"
oninput="enforceMinMax(this); updatePayments()">
</td>
<td>
<span id="out-line2" data-upon-delivery-value="0">
0
</span>
</td>
</tr>
<!-- line3: criteria1 -->
<tr>
<td width="50%">
<input type="text" asp-for="PoPayments[2].Notes"
placeholder="Enter Payment Criteria">
</td>
<td width="20%">
<input id="in-line3"
asp-for="PoPayments[2].Percentage"
type="number" min="0" max="100"
class="w-100"
placeholder="%"
oninput="enforceMinMax(this); updatePayments()">
</td>
<td>
<span id="out-line3" data-criteria1-value="0">
0
</span>
</td>
</tr>
<!-- line4: criteria2 -->
<tr>
<td width="50%">
<input type="text" asp-for="PoPayments[3].Notes"
placeholder="Enter Payment Criteria">
</td>
<td width="20%">
<input id="in-line4"
asp-for="PoPayments[3].Percentage"
type="number" min="0" max="100"
class="w-100"
placeholder="%"
oninput="enforceMinMax(this); updatePayments()">
</td>
<td>
<span id="out-line4" data-criteria2-value="0">
0
</span>
</td>
</tr>
</tbody>
</table>
<button id="btn-submit">Submit</button>