javascript - 用javascript计算订单上的数量和总数

标签 javascript html

我正在寻找一些代码帮助。我应该创建一个表格,允许用户输入他们想要购买的商品的数量。输入数量后,将显示该特定项目的总价,以及所有采购的总计(在表格底部)。
当用户按下提交按钮时,将弹出一个警报弹出窗口。

我在javascript中的计算部分遇到了麻烦。它不计算任何总量或数量值。
(由于某种原因,代码无法在此处正确缩进,但它们在实际文档中)。



function calc(){

var QtyA = 0; var QtyB = 0; var QtyC = 0;
var TotA = 0; var TotB = 0; var TotC = 0;
var PrcA = 3; var PrcB = 4; var PrcC = 5.50;
 
if (document.getElementById('QtyA').value > "");{
    QtyA = document.getElementById('QtyA').value;}
    TotA = eval(QtyA) * eval(PrcA);
    TotA = TotA.toFixed(2);
    (document.getElementById('TotalA').value = TotA);
	
if (document.getElementById('QtyB').value > "");{
    QtyB = document.getElementById('QtyB')value;}
    TotB = eval(QtyB) * eval(PrcB);
    TotB = TotB.toFixed(2);
    (document.getElementById('TotalB').value = TotB);
	
if (document.getElementById('QtyC').value > "");{
    QtyC = document.getElementById('QtyC')value;}
    TotC = eval(QtyC) * eval(PrcC);
    TotC = TotC.toFixed(2);
	(document.getElementById('TotalC')value = TotC);

    Totamt = eval(TotA) + eval(TotB) + eval(TotC);
    Totamt = Totamt.toFixed(2); //fix to 2 decimal places
    (document.getElementById('Grand Total is: ').value = Totamt);
    alert (Totamt);

<html>
<head>
  <meta charset="UTF-8">
  <title>Order Form</title>
  <style>
    @import "css/OrderForm.css";
  </style>
  <body>
    <form>
      <table border="1">
        <tr>
          <th>Item</th>
          <th>Image</th>
          <th>Quantity</th>
          <th>Price</th>
          <th>Total</th>
        </tr>

        <tr>
          <td width="80">Hat</td>
          <td><img src="images/hat.jpg" alt="Hat"></td>
          <td><input type="text" id="QtyA" size="5" onchange "calc()"></td>
          <td>€3.00</td>
          <td>
            <input type="text" id="TotalA" size="12" onchange "calc()">
          </td>
        </tr>

        <tr>
          <td width="80">T Shirt</td>
          <td><img src="images/t_shirt.jpg" alt="Hat"></td>
          <td><input type="text" id="QtyA" size="5" onchange "calc()"></td>
          <td>€4.00</td>
          <td>
            <input type="text" id="TotalA" size="12" onchange "calc()">
          </td>
        </tr>

        <tr>
          <td width="80">Glasses</td>
          <td><img src="images/glasses.jpg" alt="Hat"></td>
          <td><input type="text" id="QtyA" size="5" onchange "calc()"></td>
          <td>€5.50</td>
          <td>
            <input type="text" id="TotalA" size="12" onchange "calc()">
          </td>
        </tr>

        <tr>
          <td> Total: </td>
          <td><input type="text" id="GrandTotal" size="15" onchange="calc()"></td>
        </tr>
      </table>

      <input type="submit" value="Submit">
      <input type="reset" value="Reset">

    </form>
  </body>
</html>

最佳答案

好吧,作为一名老师,我不能让某人试图教你的所有不良习惯消失。所以,我们开始...

eval()是邪恶的-永远不要使用它!

eval()告诉JavaScript运行时像对待JavaScript一样处理字符串。这是非常危险的,因为如果字符串包含恶意代码,则eval()将运行它。在您的代码中,对在文本框中输入的eval()运行value,并且由于您不知道将输入什么值,因此您也不知道eval()将接收什么字符串。这等于一个巨大的安全漏洞,这是不应使用eval()的原因之一。其次,即使在完美的环境中,eval()也很慢,因此从纯粹的性能角度来看,您不希望使用它。坦白说,我震惊于有人教您使用它,尤其是将字符串转换为数字的过程。仅此一项就可以索回您的钱!

在您的情况下,您需要将字符串输入转换为数字,以便可以对输入进行数学运算。 JavaScript提供了几种方法来做到这一点:


parseInt(stringContainingNumber, radix)
parseFloat(stringContainingNumber)
Number(stringContainingNumber)
+stringThatIsNumber Unary Operator


不要在带有事件属性的HTML中设置事件处理。
首次创建JavaScript(25年前)时,为HTML元素(又名DOM元素)设置事件处理程序的方法是使用HTML属性,例如onclickonchangeonmouseover等。与HTML中的元素内联。不幸的是,由于该技术看起来如此简单,因此它被一遍又一遍地使用,而不是死于它应得的迅速死亡。有several reasons not to use this outdated technique。今天,我们遵循现代标准和最佳做法,因此,事件处理应使用JavaScript与HTML分开,并使用.addEventListener()

另外,您的onchange "calc()"代码还是不正确的,因为该代码应该是:onchange = "calc()"

另外,考虑哪些元素需要为其设置事件。您的原始代码进行了设置,因此,如果总数更改了,将运行calc(),但这没有任何意义。为什么有人可以直接更改总数,而这样做实际上会导致发生什么呢?数量会因为总数发生变化而改变吗?

注意细节
您有3行可以计算3个数量* 3个价格可以得到3个总数,但是即使JavaScript是正确寻找idQtyA

使用CSS而不是HTML进行样式设计
您所有数量输入字段的宽度都必须设置为5。不要为此使用HTML QtyB属性,而应使用QtyC CSS属性。 HTML将更干净,您不必重复相同的指令3次。

@import使用不正确
CSS @import指令旨在用作外部样式表中的第一行,该样式表从另一个样式表中导入指令,从而有效地将多个工作表组合成一个样式表。如果仅使用一个样式表,则不导入它,而是链接到它。

代替:size

使用:width

当您仅显示结果时,请勿将其放置在表单字段中。
当您不希望用户修改结果时,没有理由将总计添加到<style> @import "css/OrderForm.css";</style>字段中。而是将其放置为不可编辑元素的文本-在您的情况下为表格的适当单元格。

最后:使用开发人员的工具!
所有现代浏览器都包含“开发人员工具”,您可以通过按F12激活它。工具中有许多选项卡,但是“控制台”选项卡可能对您来说现在才是最重要的。如果您在语法上有错误(和以前一样),则控制台将显示它们和行号。您必须消除所有语法错误,然后才能期望代码运行。

控制台还是测试代码中值的宝贵工具。您可以插入:

console.log(anything that is supposed to produce a value);


到您的代码中,以验证变量,元素等是否具有您认为的值。



现在,实际上,我将以您尝试的非常不同的方式来解决此问题,但这比您在现阶段准备好要复杂得多,因此,我在某种程度上赞同您的方法。

请仔细阅读HTML和JavaScript注释,以解释正在执行的操作。



<!DOCTYPE html> <!-- The DOCTYPE tells the browser what version of HTML it should be expecting. -->
<html>
<head>
  <meta charset="UTF-8">
  <title>Order Form</title>
  <!-- To reference a single stylesheet, use the link element: -->
  <link href="css/OrderForm.css" rel="stylesheet">
  <style>
    /* Make all the input elements that have an id that starts with Qty
       be 5 characters wide. (Now size=5 isn't needed in the HTML 3 times) */
    input[id^=Qty] { width:5em; }
    /* The first <td> in each row should be 80px wide. Now we don't have to
       clutter up the HTML with this and we don't have to repeat it 3 times. */
    td:first-child { width:80px; }
  </style>
</head> <!-- You didn't close your <head> tag! -->
<body>
  <form>
    <table border="1">
      <tr>
        <th>Item</th>
        <th>Image</th>
        <th>Quantity</th>
        <th>Price</th>
        <th>Total</th>
      </tr>

      <tr>
        <td>Hat</td>
        <td><img src="images/hat.jpg" alt="Hat"></td>
        <td><input type="text" id="QtyA"></td>
        <td>€3.00</td>
        <!-- You shouldn't be putting results of calculations into input fields
             when you don't want the user to modify the data. Just place it into
             an elmeent as its .textContent -->
        <td id="TotalA"></td>
      </tr>

      <tr>
        <td>T Shirt</td>
        <td><img src="images/t_shirt.jpg" alt="T-Shirt"></td>
        <td><input type="text" id="QtyB"></td>
        <td>€4.00</td>
         <!-- You shouldn't be putting results of calculations into input fields
             when you don't want the user to modify the data. Just place it into
             an elmeent as its .textContent -->       
        <td id="TotalB"></td>
      </tr>

      <tr>
        <td>Glasses</td>
        <td><img src="images/glasses.jpg" alt="Glasses"></td>
        <td><input type="text" id="QtyC"></td>
        <td>€5.50</td>
         <!-- You shouldn't be putting results of calculations into input fields
             when you don't want the user to modify the data. Just place it into
             an elmeent as its .textContent --> 
        <td id="TotalC"></td>
      </tr>

      <tr>
        <td> Total: </td>
        <!-- You shouldn't be putting results of calculations into input fields
             when you don't want the user to modify the data. Just place it into
             an elmeent as its .textContent -->
        <!-- You need to have this cell span over the remaining columns of the 
             table, so colspan=4 needs to be added. -->
        <td id="grandTotal" colspan="4"></td>
      </tr>
    </table>

    <!-- Your form doesn't actually submit data anywhere, so you shouldn't
         have a submit button. A regular button will do. -->
    <input type="button" value="Get Grand Total">
    <input type="reset" value="Reset">

  </form>
  <script>
    // Get references to the HTML elements that you'll be working with
    var qtyBoxA = document.getElementById('QtyA');
    var qtyBoxB = document.getElementById('QtyB');
    var qtyBoxC = document.getElementById('QtyC');

    var totBoxA = document.getElementById('TotalA');
    var totBoxB = document.getElementById('TotalB');
    var totBoxC = document.getElementById('TotalC');

    var grandTot = document.getElementById('grandTotal');
    var btnGetTot = document.querySelector("input[type=button]");
    var btnReset = document.querySelector("input[type=reset]");    

    // Set up event handling in JavaScript, not HTML.
    qtyBoxA.addEventListener("change", calc);
    qtyBoxB.addEventListener("change", calc);
    qtyBoxC.addEventListener("change", calc);
    btnGetTot.addEventListener("click", getGrandTotal);
    btnReset.addEventListener("click", reset);
    
    var gt = null; // Will hold the grand total

    function calc() {

      var priceA = 3;
      var priceB = 4;
      var priceC = 5.50;
      gt = 0; 

      // Convert the values in the quantity textboxes to numbers. The 10 that
      // is being passed as the second argument indicates the "radix" or the
      // numeric base system that should be used when the string is being 
      // interpreted. Here (and often), we work in the base 10 numeral system.
      var qtyA = parseInt(qtyBoxA.value, 10);
      var qtyB = parseInt(qtyBoxB.value, 10);
      var qtyC = parseInt(qtyBoxC.value, 10);
      
      // If each of the quantity fields are not empty, calculate the price * quantity
      // for that row, place the answer in that row's total field and add the answer
      // to the grand total
      // NOTE: You had semicolons like this: if(); {}, which is incorrect.
      // NOTE: Notice that there are + signs right in front of the total box references?
      //       this forces a conversion of the string in the text to a number. Since we
      //       just put a number into the cell, we know for sure it can be converted.
      // NOTE: If parseInt() can't parse a number from the string provided, it returns NaN
      //       (Not A Number), we can check to see if we got NaN with the isNaN() function
      //       and here, we want to know if we don't have a NaN, so we prepend a ! to it 
      //       (the logical NOT operator) to test the opposite of the isNaN() function result.
      if (!isNaN(qtyA)) { totBoxA.textContent = qtyA * priceA; gt += +totBoxA.textContent; }
      if (!isNaN(qtyB)) { totBoxB.textContent = qtyB * priceB; gt += +totBoxB.textContent; }
      if (!isNaN(qtyC)) { totBoxC.textContent = qtyC * priceC; gt += +totBoxC.textContent; }

      grandTot.textContent = gt.toFixed(2); // Just place the answer in an element as its text

    }
    
    function getGrandTotal(){
      calc(); // Make sure all values are up to date
      alert(gt);    
    }
    
    function reset(){
      // The built-in functionality of the <input type=reset> will clear out 
      // the quantity input fields automatically, but we need to manually reset
      // non form field element that have been modified:
      totBoxA.textContent = "";
      totBoxB.textContent = "";
      totBoxC.textContent = "";      
      grandTot.textContent = "";
    }
  </script>
</body>
</html>

关于javascript - 用javascript计算订单上的数量和总数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49031366/

相关文章:

javascript - Chrome 控制台显示 "Navigated to http://localhost...."

javascript - 如何在 html5 canvas 上自定义绘制按钮

java - 打破字符串以在 jlabel 中使用 html

javascript - 在 View 中检索响应信息

javascript - 提交按钮上的onclick事件

html - Bootstrap 下拉菜单出现在其他 DIV 的后面

javascript - 按 dom 的顺序优雅地制作重叠的 DIV

javascript - 通过 $sceDelegate 提供程序打开重定向预防

javascript - 使用 Mapzen 以字符串或 JSON 形式返回逐向数据

javascript - Javascript 中的 Qunit 测试