在 JavaScript 中的 n 个输入中分配剩余输入百分比

问题描述 投票:0回答:1

我正在尝试为以下情况创建一个函数:

我有许多接受 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"));
        }
    }
    }
javascript html algorithm input razor
1个回答
0
投票

由于您显然使用了 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>

© www.soinside.com 2019 - 2024. All rights reserved.