简体   繁体   中英

Javascript strange error when I am doing adding the values of row?

I have a strange error in my JavaScript code. My markup is something like this

<table id="invoice-details">
  <tbody id="tableToModify">
  <?php
    $i=1;
    while($i<2){
  ?>
    <tr>
      <td>
        <input type="hidden" name="prdid[]" id="prd_id<?php echo $i; ?>" />
          <input type="text" tabindex="<?php echo 2+($i*5);?>"  name="prdname[]" id="prd_name<?php echo $i; ?>" />
      </td>
      <td>
        <input type="text" name="prddesc[]" id="prd_desc<?php echo $i; ?>" disabled="disabled" />
       </td>
       <td>
        <input type="text" name="prdcost[]" id="prd_cost<?php echo $i; ?>" value="0" disabled="disabled" style="color:#333;" />
       </td>
       <td>
        <input type="text" name="prdquentity[]" id="prd_quentity<?php echo $i; ?>" tabindex="<?php echo 3+($i*5);?>" onKeyUp="calprice1(this.value,'<?php echo $i; ?>');" value="1" />
       </td>
       <td>
        <input type="text" name="prddamount[]" tabindex="<?php echo 5+($i*5);?>" readonly="true" id="prd_damount<?php echo $i; ?>" onKeyUp="calprice2(this.value,'<?php echo $i; ?>');"  />
       </td>
       <td id="readonly">
        <input readonly="readonly" name="prdprice[]" id="prd_price<?php echo $i; ?>" value="0" />
       </td>
      </tr>
      <?php
      $i++;
      }
      ?>
    </tbody>
  </table><!--#invoice-details-->

Now under that I have a button called add a new line. The markup is like this

 <input type="button" style="float:left;" onClick="createRow();" class="add-line" value="Add a new line">

For that I have made my java script like this

function createRow()
    {
      //var newlineno=document.forms[0].elements["prdprice[]"].length;
      var newlineno = document.querySelectorAll("[name='prdprice[]']").length
      newlineno++;
      //console.log(newlineno);
      var row = document.createElement('tr'); 
      var col1 = document.createElement('td');
      var col2 = document.createElement('td');
      var col3 = document.createElement('td'); 
      var col4 = document.createElement('td');
      var col5 = document.createElement('td'); 
      var col6 = document.createElement('td'); 
      var col7 = document.createElement('td'); 

      row.appendChild(col1); 
      row.appendChild(col2);
      row.appendChild(col3); 
      row.appendChild(col4);
      row.appendChild(col5); 
      row.appendChild(col6);
      row.appendChild(col7); 

      col1.innerHTML = "<input type=\"hidden\" name=\"prdid[]\" id=\"prd_id"+newlineno+"\" /><input type=\"text\" name=\"prdname[]\" id=\"prd_name"+newlineno+"\" autocomplete=\"off\" onKeyUp=\"producthint(this.value,'"+newlineno+"');\" /><div id=\"prd"+newlineno+"\" style=\"position:absolute;\"></div>";
      col2.innerHTML = "<input type=\"text\" disabled=\"disabled\" name=\"prddesc[]\" id=\"prd_desc"+newlineno+"\" />";
      col3.innerHTML = "<input type=\"text\" disabled=\"disabled\" name=\"prdcost[]\" id=\"prd_cost"+newlineno+"\" value=\"0\" />";
      col4.innerHTML = "<input type=\"text\" name=\"prdquentity[]\" id=\"prd_quentity"+newlineno+"\" onKeyUp=\"calprice1(this.value,'"+newlineno+"');\" value=\"1\" />";
      col5.innerHTML = "<select name=\"prddtype[]\" class=\"discount-type\" id=\"prd_dtype"+newlineno+"\" >"+document.getElementById("prd_dtype1").innerHTML+"</select>";
      col6.innerHTML = "<input type=\"text\" name=\"prddamount[]\" id=\"prd_damount"+newlineno+"\" onKeyUp=\"calprice2(this.value,'"+newlineno+"');\"  />";
      col7.innerHTML = "<input readonly=\"readonly\" name=\"prdprice[]\" id=\"prd_price"+newlineno+"\" value=\"0\" />";

      var table = document.getElementById("tableToModify"); // find table to append to
      table.appendChild(row); // append row to table
    }  

Now upto this point everything is fine. Now when I am trying to insert one product name in 1st column and the values are being populated from the database then it should show calculation. For the cacculation I have done js like

function calprice1(q,line) {
  var cost=document.getElementById("prd_cost"+line).value;
  var damount=document.getElementById("prd_damount"+line).value;
  document.getElementById("prd_price"+line).value=parseFloat((cost*q)*(100-damount)/100).toFixed(2);
  totalprice();
 }

Now for the bottom total price where all the price for individual price will be added I am using total price function. The function is something like this.

 function totalprice(){
  var sum=0;
  var price = document.forms[0].elements["prdprice[]"];
  console.log(price);
  for(var i=0, n=price.length;i<n;i++) {
  sum+=parseFloat(price[i].value);
  }
  document.getElementById("total").innerHTML=parseFloat(sum).toFixed(2);

  }

Now here the value for first row after all the calculation is not showing in totalprice but when I am adding another line by addrow button it is showing the totalprice with correct amount(all the values for rows are getting added). So can someone kindly tell me what is the issue here. Any help and suggestions are highly appreciable. Thanks.

Now here the value for first row after all the calculation is not showing in totalprice but when I am adding another line by addrow button it is showing the totalprice with correct amount(all the values for rows are getting added).

So in the beginning, you have only one row, and therefor only one single form element with the name prdprice[] , correct?

Well, that's the problem right there: document.forms[0].elements["prdprice[]"] only returns a NodeList if there's more than one element with that name – otherwise, it will return the reference to that single DOM node directly.

So, when you get the reference to a single DOM node, it has no length property, and by trying to read it, you will only get undefined .

And since 0 < undefined evaluates to false, your for-loop is not iterated over a single time …


An easy way to work around this is the following:

var price = document.forms[0].elements["prdprice[]"];
if(price.length === undefined) { price = [price]; }

If price is not a NodeList, but a reference to a single DOM node – then we make it an array instead, that contains the reference to that single DOM node as its only element.

After that, price has a length in any case, so you can loop over it with your for-loop in the same way as if it was a NodeList.

There is a cave-at though: Since we are creating an array here, it behaves differently than a NodeList. NodeLists are “live”, that means any change in the DOM is reflected by them immediately – whereas our array is static. But as long as you are not adding/removing nodes to your DOM (nodes that this NodeList would “capture”, so only elements of that form with the name prdprice[] ), but are just looping over the previously existing ones, this does not matter.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM