Home > Blockchain >  sum input fields value if they have the same value
sum input fields value if they have the same value

Time:12-20

I'm getting stuck on the logic to use to accomplish this in javascript/jquery and could use some help if anyone had any ideas.

I have table which shows the per item cost of the products on an invoice.

The goal is to find all the products by their class(currently shirtcountrow and hoodiecountrow but there will be more later) and combine the ones that have the same value.

The table currently looks like this:

<table id="productmathtable">
<tr>    
<td>Shirt</td>       
<td><input  type="text" value="4" style="width:60px"> x <input  type="text" value="25" style="width:60px"> = </td>      
<td ><input  type="text" value="100" style="width:60px"></td>
</tr>
<tr>         
<td>Shirt</td>       
<td><input  type="text" value="2" style="width:60px"> x <input  type="text" value="25" style="width:60px"> = </td>       
<td ><input  type="text" value="50" style="width:60px"></td>       
</tr>
<tr>         
<td>Shirt</td>       
<td><input  type="text" value="2" style="width:60px"> x     <input  type="text" value="25" style="width:60px"> = </td>      
 <td ><input  type="text" value="50" style="width:60px"></td>     
 </tr><tr>       
<td>Hoodie</td>     
 <td><input  type="text" value="4" style="width:60px"> x <input  type="text" value="35" style="width:60px"> = </td>         
<td ><input  type="text" value="140" style="width:60px"></td>      
</tr>
<tr>         
 <td>Hoodie</td>        
 <td><input  type="text" value="4" style="width:60px"> x <input  type="text" value="35" style="width:60px"> = </td>         
<td ><input  type="text" value="140" style="width:60px"></td></tr>     
</table>

And I want it to look like this after a jquery/javascript function is preformed:

<table id="productmathtable">
<tr>    
<td>Shirt</td>       
<td><input  type="text" value="8" style="width:60px"> x <input  type="text" value="25" style="width:60px"> = </td>      
<td ><input  type="text" value="200" style="width:60px"></td>
</tr> 
<td>Hoodie</td>     
 <td><input  type="text" value="8" style="width:60px"> x <input  type="text" value="35" style="width:60px"> = </td>         
<td ><input  type="text" value="280" style="width:60px"></td>      
</tr>   
</table>

I am pretty sure i need to change my html so it's easier to identify each part that i want to change, but im not exactly sure how

CodePudding user response:

Granted your html is not optimized, but rather than rethink all that, here is a method to tally them up and then rewrite the table with the aggregate totals. The one thing I did change was in the class of the quantity field - I standardized them to all have the class 'quantity' instead.

let uniques = []
$('#productmathtable tr').each(function() {
  // do we have this one yet?
  let thisname = $(this).find('td').eq(0).text().trim()
  let exists = uniques.findIndex(u => u.name.toLowerCase() === thisname.toLowerCase())
  let q =  $(this).find('.quantity').val();
  let p =  $(this).find('.productpricerow').val();
  if (exists > -1) {
    uniques[exists].quantity  = q;
  } else {
    uniques.push({
      name: thisname,
      quantity: q,
      price: p
    });
  }
  $(this).remove();
})

uniques.forEach(o => {
  let row = `<tr>
    <td>${o.name}</td>
    <td><input  type="text" value="${o.quantity}" style="width:60px"> x <input  type="text" value="${o.price}" style="width:60px"> = </td>
    <td ><input  type="text" value="${o.quantity * o.price}" style="width:60px"></td>
  </tr>`;
  $('#productmathtable').append(row)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="productmathtable">
  <tr>
    <td>Shirt</td>
    <td><input  type="text" value="4" style="width:60px"> x <input  type="text" value="25" style="width:60px"> = </td>
    <td ><input  type="text" value="100" style="width:60px"></td>
  </tr>
  <tr>
    <td>Shirt</td>
    <td><input  type="text" value="2" style="width:60px"> x <input  type="text" value="25" style="width:60px"> = </td>
    <td ><input  type="text" value="50" style="width:60px"></td>
  </tr>
  <tr>
    <td>Shirt</td>
    <td><input  type="text" value="2" style="width:60px"> x <input  type="text" value="25" style="width:60px"> = </td>
    <td ><input  type="text" value="50" style="width:60px"></td>
  </tr>
  <tr>
    <td>Hoodie</td>
    <td><input  type="text" value="4" style="width:60px"> x <input  type="text" value="35" style="width:60px"> = </td>
    <td ><input  type="text" value="140" style="width:60px"></td>
  </tr>
  <tr>
    <td>Hoodie</td>
    <td><input  type="text" value="4" style="width:60px"> x <input  type="text" value="35" style="width:60px"> = </td>
    <td ><input  type="text" value="140" style="width:60px"></td>
  </tr>
</table>

CodePudding user response:

To re-formulate the question a bit more concretely... It appears that you are saying, for each classname in some list of classnames, you want to do the following transformation:

Find all the tr's in #productmathtable that contain an input with the given classname; set the first such input's "value" attribute to the sum of the matching "classname" inputs' "value" attributes; similarly sum the producttotalrows' "value" attributes; and then remove the other matching tr's.

Of course, it's easier to do this sort of manipulation on the raw data before creating the dom, if possible. But something like the following (untested) code should do the trick...

// Get an array of all the tr's.
var trlist = $("#productmathtable > tr").toArray();

// Apply tranformation function for each classname.
["shirtcountrow", "hoodiecountrow"].forEach(
    function(cname) {
        var ctotal = 0;
        var ptotal = 0;
        var combined = null;

        // Use Array.filter to get the set of matching tr's for this classname.
        var subset = trlist.filter(function (tr) {
            return ($("input." cname, tr).length > 0);
        });

        // Walk through this list, updating the dom as you go.
        subset.forEach(function (tr) {
            // Update cached values.
            ctotal  = parseInt($("input." cname, tr).attr("value"));
            ptotal  = parseInt($("input.producttotalrows", tr).attr("value"));

            if (combined === null) {
                // First item: just keep it, as-is.
                combined = tr;
            } else {
                // Subsequent items...
                // Update values in dom.
                $("input." cname, combined).attr("value", ctotal);
                $("input.producttotalrows", combined).attr("value", ptotal);

                // Remove now-extraneous tr from dom.
                $(tr).remove();
            }
        });
    }
);
  • Related