草庐IT

javascript - jQuery IF 语句根据两个下拉菜单和一个文本框字段计算费用

coder 2023-08-08 原文

这是一个费用计算器的例子,它将根据用户的选择和答案运行实时费用统计 (jQuery)。我想弄清楚如何创建许多 IF 语句来根据两个下拉菜单和一个文本框字段计算费用。

我想要完成的是一个使用 onChange="calculateTotal()" 计算的 jQuery IF 函数。当用户选择出生月份(计算月份)时,这将计算从现在到下一个生日有多少个月。但是我需要基于车辆下拉(vehiclebody)和输入的重量(ew)的 IF 功能,这三个项目将决定价格。喜欢下面的例子和下面的片段。

例如(三种场景):
[1] 如果选择从现在起 4-12 个月,以及重量低于 2499 的 2dr 车辆,价格将 28.10 添加到运行费计算器中。
[2] 如果选择从现在起 4-12 个月,以及重量在 2500 和 3499 之间的 2dr 车辆,则价格将 36.10 添加到运行费计算器中。
[3] 如果选择从现在起 4-12 个月,以及重量大于 3500 的 2dr 车辆,价格将 46.10 添加到运行费计算器中。

长话短说,我想要一个 IF 函数来计算 onChange="calculateTotal()"var titleFees = getProofOfOwnership() + (New IF Function);取决于(车辆)选择和(ew)输入,然后 IF(monthsToGo)等于 4 到 12 它的价格。如果 (monthsToGo) 是 1、2、3、13、14 或 15,则价格将按比例分配,因此它也会有自己的价格。

如果是 1 个月,他们要求用户支付该月和全年的费用,所以 13 个月,但如果是 2 个月,他们让用户选择 2 个月或 14 个月以及 3 个月或 15 个月(如您所见计算月份下降)但一旦是 4 个月(他们支付全额,无论是 4-12 个月)

可怕的是,我必须弄清楚 50 种不同的组合,所以希望我对 jQuery 的极度缺乏知识很容易理解。

任何帮助将非常,非常,非常,非常感谢!! :)

http://jsfiddle.net/fzy9yev3/15/

见下面的片段:

//Calculate Months
(function() {
    var monthsToGo;
    var Fee = makeStruct("monthSect vehicleBody ewSect price");
    var fees = [
        new Fee(/*monthSect*/2, /*vehicleBody*/0, /*ewSect*/0, /*price*/45.10),
        new Fee(3, 1, 0, 55.10),
        new Fee(4, 2, 0, 65.10),
        new Fee(13, 3, 0, 75.10),
        new Fee(14, 4, 0, 85.10),
        new Fee(15, 5, 0, 95.10)
    ];

    $(document).ready(function() {
        $('#month2, #month3').hide();
    });
    
    $(document).on('change', '#ownership input', function(){
        calculateTotal();
        //statedropDown($(this).val());
    });
    
    $(document).on('change', '#month1', function() {
        // ignore blank options
        if ($(this).val() == '') { return; }
        
        var vehicle = $('#vehiclebody').val();
        var ew = $('#ew').val();
        var ewSect = 0;
        var monthSect = 0;
        var titleFees = 0;
        
        if(vehicle == '' || ew == ''){
            alert('Please enter Vehicle Type and/or Empty Weight');
            $(this).val('');
            return;
        }
        
        var today = new Date();
        var birthdate = new Date();
        birthdate.setMonth($('#month1').val());

        monthsToGo = (today.getMonth() < birthdate.getMonth())
            ? birthdate.getMonth() - today.getMonth()
            : (12 - today.getMonth()) + birthdate.getMonth()
        ;
        
        $('#month2').hide();
        $('#month3').hide();

        if (monthsToGo == 1) {
            this.monthsToGo = 13;
            alert(this.monthsToGo);
        } else if (monthsToGo == 2) {
            $('#month2').show();
        } else if (monthsToGo == 3) {
            $('#month3').show();
        } else {
            this.monthsToGo = monthsToGo;
            alert(this.monthsToGo);
        }
        
        if(monthsToGo >= 4 || monthsToGo <= 12){
            monthSect = 4;
            //Set monthsToGo to 4 if it is in this range for the linked list so
            //categorizing is easier
            //6 possibilities for dates -- 2, 3, 4, 13, 14, 15
        }
        else monthSect = monthsToGo;
        
        switch(vehicle){
            case 0://2dr
            case 2://4dr
            case 4://convertible
            case 5://van
                if(ew < 2500) ewSect = 0;
                else if(ew >= 2500 && ew < 3500) ewSect = 1;
                else if(ew >= 3500) ewSect = 2;
                break;
            case 1://pickup
                if(ew < 2000) ew = 0;
                else if(ew >= 2000 && ew <= 3000) ewSect = 1;
                else if(ew > 3000 && ew <= 5000) ewSect = 2;
                break;
            case 3://trucks
                if(ew > 5000 && ew < 6000) ewSect = 0;
                else if(ew >= 6000 && ew < 8000) ewSect = 1;
                else if(ew >= 8000 && ew < 10000) ewSect = 2;
                else if(ew >= 10000 && ew < 15000) ewSect = 3;
                else if(ew >= 15000 && ew < 20000) ewSect = 4;
                else if(ew >= 20000 && ew <= 26000) ewSect = 5;
                else if(ew > 26000 && ew < 35000) ewSect = 6;
                else if(ew >= 35000 && ew < 44000) ewSect = 7;
                else if(ew >= 44000 && ew < 55000) ewSect = 8;
                else if(ew >= 55000 && ew < 62000) ewSect = 9;
                else if(ew >= 62000 && ew < 72000) ewSect = 10;
                else if(ew >= 72000 && ew <= 8000) ewSect = 11;
                break;
        }
        
        console.log('Month Section (monthSect): ' + monthSect + '; Vehicle: ' + vehicle + '; EW Section (ewSect): ' + ewSect);
        
        for(var i = 0; i < fees.length; i++){
            console.log('infor');
            if(fees[i].monthSect == monthSect && fees[i].vehicleBody == vehicle && fees[i].ewSect == ewSect) {
                titleFees = getProofOfOwnership() + fees[i].price;
                console.log('Title Found! ' + titleFees);
                $('#totalPrice').text('Estimated Transfer Fees $' + titleFees);
                break;
            }
        }
        
    });

    $('#month2, #month3').on('change', function() {
        this.monthToGo = $(this).val();
        alert(this.monthToGo);
    });
    
}($))

//Fee Calculator
//Setting Proof of Ownership Prices
 //Set up an associative array
 var title_prices = new Array();
 title_prices["MCO"]=68.25;
 title_prices["FL Title"]=78.25;
 title_prices["OOS Title"]=88.25;
 
 // Proof of Ownership Radio Buttons
function getProofOfOwnership()
{  
    var proofOfOwnership=0;
    //Get a reference to the form id="form"
    var theForm = document.forms["form"];
    //Get a reference to the title the user Chooses name=ownerShip":
    var ownerShip = theForm.elements["ownership"];
    //Here since there are 4 radio buttons ownerShip.length = 4
    //We loop through each radio buttons
    for(var i = 0; i < ownerShip.length; i++)
    {
        //if the radio button is checked
        if(ownerShip[i].checked)
        {
            proofOfOwnership = title_prices[ownerShip[i].value];
            //If we get a match then we break out of this loop
            //No reason to continue if we get a match
            break;
        }
    }
    //We return the proofOfOwnership
    return proofOfOwnership;
}
function calculateTotal()
{

    var titleFees = getProofOfOwnership();
    


    var divobj = document.getElementById('totalPrice');
    divobj.style.display='block';
    divobj.innerHTML = "Estimated Transfer Fees $"+titleFees;

}

function hideTotal()
{
    var divobj = document.getElementById('totalPrice');
    divobj.style.display='none';
}

function makeStruct(names) {
  var names = names.split(' ');
  var count = names.length;
  function constructor() {
    for (var i = 0; i < count; i++) {
      this[names[i]] = arguments[i];
    }
  }
  return constructor;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<form name="form">
    <div id="ownership">
        <label class='radiolabel'><input type="radio"  name="ownership" required="yes" message="Please select proof of ownership." value="MCO"/>Manufacturer's Statement of Origin&nbsp;&nbsp;</label><br/>
        <label class='radiolabel'><input type="radio"  name="ownership" value="FL Title"/>Florida Certificate of Title&nbsp;&nbsp;</label><br/>
                <label class='radiolabel'><input type="radio"  name="ownership" value="OOS Title"/>Out-of-state Certificate of Title&nbsp;&nbsp;</label>
        </div>

    <br/>
    <br/>

<label for='month1'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Calculate Months:</label>
<select name="month1" id="month1" size="1">
    <option value="">Choose a Month</option>
    <option value="0">January</option>
    <option value="1">February</option>
    <option value="2">March</option>
    <option value="3">April</option>
    <option value="4">May</option>
    <option value="5">June</option>
    <option value="6">July</option>
    <option value="7">August</option>
    <option value="8">September</option>
    <option value="9">October</option>
    <option value="10">November</option>
    <option value="11">December</option>
</select>
<select name="month2" id="month2" size="1">
    <option value="">Choose an Option</option>
    <option value="2">2</option>
    <option value="14">14</option>
</select>
<select name="month3" id="month3" size="1">
    <option value="">Choose an Option</option>
    <option value="3">3</option>
    <option value="15">15</option>
</select>
    <br/>
    

<select name="vehiclebody" id="vehiclebody" required="yes" message="Please select body." size="1">
    <option value="">Choose a Vehicle</option>
    <option value="0">2Dr</option>
    <option value="1">Pickup</option>
    <option value="2">4dr</option>
    <option value="3">Truck</option>
    <option value="4">Convertible</option>
    <option value="5">Van</option>
</select>

<label for="ew">Empty Weight:</label>
    <input type="text" name="ew" id="ew"/>
    <br/>
    <br/>
    <div id="totalPrice"></div>
</form>

最佳答案

我建议采用一种不仅可以清理代码,而且可以使计算、测试、验证和添加新功能更容易的方法。一点点清理可以让你的应用程序更容易扩展和调试,但更重要的是,对于你的情况,一点点清理将帮助你计算你正在寻找的值并解决你的问题直截了当的方式。

建议 #01:组织你的代码

现在,您有一些函数试图一次做太多事情。如果让函数保持简单并让每个函数“专门化”特定的东西,那么函数会更容易测试和调试。例如,在您的 on.("change")您的 $("#month1") 的处理程序下拉菜单中,您正在尝试一次性完成所有操作,这就是您遇到麻烦的地方。相反,您需要分配一个 .on("change")您的处理程序 #month1下拉,这将决定是否 #month2#month3需要显示,然后分配一个单独的.on("change")处理程序从这两个下拉列表中收集值。当您在使用它时,您将希望将任何“专用”功能分解为它自己的功能,以保持您的代码整洁。

您的 #month1 的示例只是试图一次做太多的更改处理程序:

$(document).on('change', '#month1', function() {
    // 1. Stop if Empty Weight or Vehicle Type are Blank
    // 2. Get the user's birth month
    // 3. Calculate the number of months until the user's Birthday
    // 4. Calculate the monthSect value
    // 5. Calculate the ewSect value
    // 6. Lookup the Proof of Ownership Fees
    // 7. Lookup prorated Title Fees
});

与其让这一功能尝试在一个地方执行所有这些任务,不如将任何“专门”功能移动到简单易懂的功能中,每个功能都有明确的目的。您可以创建函数名称,例如:
// Lookup the Prorated Fee
getProratedFeeFromFeeList(monthSect, vehicleBody, ewSect);

// Get the "Payment Plan Details" based on user's birth month
getPaymentPlanDetailsBasedOnBirthMonth(birthMonth);

// Lookup the ewSect (Empty Weight Section)
getWeightSectionFromVehicleClassAndEmptyWeight(vehicleClass, emptyWeight);

注意:我喜欢使用长的、描述性的函数名,这样函数的目的就很明确,提高了代码的可读性。如果您使用具有良好代码完成功能的代码编辑器,像这样的长函数名称不会增加很多额外的输入,但对我来说,我个人喜欢高度可读、自记录代码的好处。

建议 #02:将表单值存储在一个地方。

继续建议 #1,因为您的表单旨在具有“实时统计”,如果您设置了一个系统来始终保留表单值的快照,它将为您省去很多麻烦。您可以使用 Javascript 对象轻松完成此操作。

出于多种原因,这很方便:
  • 它使所有表单值“全局可用”没有
    弄乱全局命名空间
    .
  • 它使您的表单值易于在您的calculateTotal()函数,因为你只需要查询这个
    将值插入方程的一个对象。
  • 您始终拥有整个表单的“实时快照”。这是
    便于测试、调试、验证或将表单结果打印到控制台或浏览器。
  • 它允许您不断向费用计算器应用程序添加功能/值(value)
    无需中断您的工作流程。
  • 通过始终拥有完整的快照,将更容易发现
    功能错误并查看您的个人输入如何
    影响其他输入或整体计算。

  • 所以我会创建一个名为 FC 的全局对象(“费用计算器”的缩写)存储您运行费用计算所需的所有值。像这样创建这个“费用计算器对象”:
    var FC = FC || {};
    

    现在这个 FC对象将可供您访问 FC 的所有函数使用。的范围。为您的 FC 添加值对象可以通过以下两种方式之一完成:
    // First method: In FC's Declaration
    var FC = { monthSect: 0, vehicleBody: null };
    
    // Second Method: Using dot notation
    var FC = {};
    FC.monthSect = 0;
    FC.vehicleBody = null;
    

    注意:请记住,您始终可以使用点表示法为已经声明的对象赋值,因此这两种方法的组合是完全有效的。

    现在您可以从 FC 更新和读取值使用点表示法的对象,例如:
    // Get the monthSect variable
    var monthSect = FC.monthSect;
    
    // Assign or update FC.monthSect
    FC.monthSect = someNewValue; 
    

    我的解决方案

    使用我上面提到的一些建议,这就是我将如何解决您的问题:

    步骤 #01:每个表单输入监听更改、更新 FC并调用 calculateTotal()
    // When the user updates the #month2 or #month3 dropdown
    // Update FC.monthSect 
    $(document).on('change', '#month2, #month3', function() {
        FC.monthSect = $(this).val();
        calculateTotal();
    });
    
    // When someone updates the Empty Weight value
    // update FC.emptyWeight 
    $(document).on('change blur keyup', '#ew', function() {
    
        var emptyWeight = $(this).val();
        FC.emptyWeight = emptyWeight ? emptyWeight : null;
    
        var vehicle = $('#vehiclebody').val();
    
        if (vehicle && emptyWeight) {
            FC.ewSect = FCUtils.getWeightSectionFromVehicleClassAndEmptyWeight(FC.vehicleBody, FC.emptyWeight);
             FCUtils.getProratedFeeFromFeeList(FC.monthSect, FC.vehicleBody, FC.ewSect);
        }
    
        calculateTotal();
    
    });
    
    
    // When the user updates the #month1 drop-down 
    // Update FC.monthSect and assign FC.proratedPrice
    $(document).on('change', '#month1', function() {
    
        // Reset to the defaults
        $("#month2").hide();
        $("#month3").hide();
        FC.monthSect = null;
    
        // ignore blank options
        if ($(this).val() == '') {
            calculateTotal();
            return;
        };
    
        var selecteduserBirthday = $(this).val();
    
        var paymentPlanDetails = FCUtils.getPaymentPlanDetailsBasedOnBirthMonth(selecteduserBirthday);
        var monthsToGo = paymentPlanDetails.monthsUntilBirthday;
    
        if (paymentPlanDetails.paymentPlan == "2or14months") {
            $("#month2").show();
        } else if (paymentPlanDetails.paymentPlan == "3or15months") {
            $("#month3").show();
        }
    
        // Assign FC.monthSect if monthSect = 4-12 | 1 | 13
        if (monthsToGo >= 4 && monthsToGo <= 12) {
            FC.monthSect = 4;
        } else if (monthsToGo == 1 || monthsToGo == 13) {
            FC.monthSect = 13;
        }
    
        FCUtils.getProratedFeeFromFeeList(FC.monthSect, FC.vehicleBody, FC.ewSect);
        calculateTotal();
    
    });
    

    注意:您可能已经注意到,有些函数名称前面带有 FCUtils ,这是我将所有“实用程序”功能附加到的对象。您不一定需要在自己的程序中执行此操作,您可以编写函数并像往常一样调用它们,但是在我的示例应用程序中,我使用了一种名为 The Revealing Module Pattern 的设计模式。 ,这有助于对常见功能进行分组,并且是使代码更具可读性的另一个步骤。

    步骤 #02:查询 FC对象在 calculateTotal()
    现在您的表单输入是独立的,并且它们都知道如何更新 FC 上各自的值。对象,您所有的 calculateTotal()函数需要做的是查询是FC要计算的值的对象:
    function calculateTotal() {
    
        var titleFees =     FC.rvPrice + 
                            FC.titlePrice + 
                            FC.lienPrice + 
                            FC.purchaseDatePrice + 
                            FC.IRFPrice + 
                            FC.proratedPrice + 
                            FC.specialFee;
    
        FC.totalPrice = titleFees;
    
        // Now you can update the browser with this data
        $("#totalPrice").text(titleFees);
    
    }
    

    calculateTotal()函数在表单的每个“更改”事件上都会被调用,这就是给表单“活”的感觉的原因。您还可以在此功能中更新应用程序的其他部分。

    您可以 review a jsfiddle where I put all these ideas into practice here .我添加了一个 HUD(出现在右上 Angular 的“黑匣子”),它将为您提供 FC 中包含的数据的实时快照。任何时候的对象。如果 HUD 挡住了一切,只需在屏幕上“单击以拖动”它即可将其移开。

    希望这可以帮助!祝你好运!

    关于javascript - jQuery IF 语句根据两个下拉菜单和一个文本框字段计算费用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26596109/

    有关javascript - jQuery IF 语句根据两个下拉菜单和一个文本框字段计算费用的更多相关文章

    1. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

      我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

    2. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

      exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

    3. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

      我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

    4. ruby - 这两个 Ruby 类初始化定义有什么区别? - 2

      我正在阅读一本关于Ruby的书,作者在编写类初始化定义时使用的形式与他在本书前几节中使用的形式略有不同。它看起来像这样:classTicketattr_accessor:venue,:datedefinitialize(venue,date)self.venue=venueself.date=dateendend在本书的前几节中,它的定义如下:classTicketattr_accessor:venue,:datedefinitialize(venue,date)@venue=venue@date=dateendend在第一个示例中使用setter方法与在第二个示例中使用实例变量之间是

    5. ruby - 如何在 Ruby 中向现有方法定义添加语句 - 2

      我注意到类定义,如果我打开classMyClass,并在不覆盖的情况下添加一些东西我仍然得到了之前定义的原始方法。添加的新语句扩充了现有语句。但是对于方法定义,我仍然想要与类定义相同的行为,但是当我打开defmy_method时似乎,def中的现有语句和end被覆盖了,我需要重写一遍。那么有什么方法可以使方法定义的行为与定义相同,类似于super,但不一定是子类? 最佳答案 我想您正在寻找alias_method:classAalias_method:old_func,:funcdeffuncold_func#similartoca

    6. ruby - ruby 乘法语句中星号中断语法前的空格 - 2

      在添加一些空格以使代码更具可读性时(与上面的代码对齐),我遇到了这个:classCdefx42endendm=C.new现在这将给出“错误数量的参数”:m.x*m.x这将给出“语法错误,意外的tSTAR,期待$end”:2/m.x*m.x这里的解析器到底发生了什么?我使用Ruby1.9.2和2.1.5进行了测试。 最佳答案 *用于运算符(42*42)和参数解包(myfun*[42,42])。当你这样做时:m.x*m.x2/m.x*m.xRuby将此解释为参数解包,而不是*运算符(即乘法)。如果您不熟悉它,参数解包(有时也称为“spl

    7. ruby - 具有两个参数的 block - 2

      我从用户Hirolau那里找到了这段代码:defsum_to_n?(a,n)a.combination(2).find{|x,y|x+y==n}enda=[1,2,3,4,5]sum_to_n?(a,9)#=>[4,5]sum_to_n?(a,11)#=>nil我如何知道何时可以将两个参数发送到预定义方法(如find)?我不清楚,因为有时它不起作用。这是重新定义的东西吗? 最佳答案 如果您查看Enumerable#find的文档,您会发现它只接受一个block参数。您可以将它发送两次的原因是因为Ruby可以方便地让您根据它的“并行赋

    8. ruby - 如何使用 Selenium Webdriver 根据 div 的内容执行操作? - 2

      我有一个使用SeleniumWebdriver和Nokogiri的Ruby应用程序。我想选择一个类,然后对于那个类对应的每个div,我想根据div的内容执行一个Action。例如,我正在解析以下页面:https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=puppies这是一个搜索结果页面,我正在寻找描述中包含“Adoption”一词的第一个结果。因此机器人应该寻找带有className:"result"的div,对于每个检查它的.descriptiondiv是否包含单词“adoption

    9. ruby - 如何根据长度将路径数组转换为嵌套数组或散列 - 2

      我需要根据字符串路径的长度将字符串路径数组转换为符号、哈希和数组的数组给定以下数组:array=["info","services","about/company","about/history/part1","about/history/part2"]我想生成以下输出,对不同级别进行分组,根据级别的结构混合使用符号和对象。产生以下输出:[:info,:services,about:[:company,history:[:part1,:part2]]]#altsyntax[:info,:services,{:about=>[:company,{:history=>[:part1,:pa

    10. ruby - 有没有办法从 ruby​​ case 语句中访问表达式? - 2

      我想从then子句中访问c​​ase语句表达式,即food="cheese"casefoodwhen"dip"then"carrotsticks"when"cheese"then"#{expr}crackers"else"mayo"end在这种情况下,expr是食物的当前值(value)。在这种情况下,我知道,我可以简单地访问变量food,但是在某些情况下,该值可能无法再访问(array.shift等)。除了将expr移出到局部变量然后访问它之外,是否有直接访问caseexpr值的方法?罗亚附注我知道这个具体示例很简单,只是一个示例场景。 最佳答案

    随机推荐