开发者

JQuery sum all data in specific table row

开发者 https://www.devze.com 2023-02-15 00:06 出处:网络
I have a table with inputs in each cell, except one (.total) which specifies the total of each table row.When one of the inputs are changed I would like the sum to change for that row. Below is far as

I have a table with inputs in each cell, except one (.total) which specifies the total of each table row. When one of the inputs are changed I would like the sum to change for that row. Below is far as I have been able to get. The HTML:

<table>
   <tr>
      <td><input value = "100"/></td>
      <td><input value = "100"/></td>
      <td><input value = "100"/></td>
      <td class="total">300</开发者_StackOverflowtd>
   </tr>
   <tr>
      <td><input value = "200"/></td>
      <td><input value = "200"/></td>
      <td><input value = "200"/></td>
      <td class="total">600</td>
   </tr>
</table>

Now for the jQuery:

    //add keyup handler
    $(document).ready(function(){
        $("input").each(function() {
            $(this).keyup(function(){
                newSum();
            });
        });
    });

    function newSum() {
        var sum = 0;
        var thisRow = $(this).closest('tr');

        //iterate through each input and add to sum
        $(thisRow).("td:not(.total) input:text").each(function() {
                sum += this.value;            
        });

        //change value of total
        $(thisRow).(".total").html(sum);
    }

Any help in finding out what I've done wrong will be greatly appreciated. Thanks!


Your main problem is the use of this in your function. If you place the body of that function directly in the keyup handler, it should work. But this in the body of a separately declared function will refer, essentially, to the object of which it is a method. And that object, in the case above, would be window.

Try this:

$(document).ready(function(){
    $("input").each(function() {
        var that = this; // fix a reference to the <input> element selected
        $(this).keyup(function(){
            newSum.call(that); // pass in a context for newsum():
                               // call() redefines what "this" means
                               // so newSum() sees 'this' as the <input> element
        });
    });
});

You also have some more superficial errors in newSum():

function newSum() {
  var sum = 0;
  var thisRow = $(this).closest('tr');

  thisRow.find('td:not(.total) input:text').each( function(){
    sum += parseFloat(this.value); // or parseInt(this.value,10) if appropriate
  });

  thisRow.find('td.total input:text').val(sum); // It is an <input>, right?
}


There are a few things wrong that the below should resolve.

  1. newSum is called with the wrong context (the default window context, not the context of the DOM object)
  2. an invalid selector is used to find the input fields
  3. the values you're summing will be treated as text unless you use parseInt

Code:

//add keyup handler
$(document).ready(function(){
    $("input").each(function() {
        $(this).keyup(function(){
            newSum.call(this);
        });
    });
});

function newSum() {
    var sum = 0;
    var thisRow = $(this).closest('tr');
    //iterate through each input and add to sum
    $(thisRow).find("td:not(.total) input").each(function() {
            sum += parseInt(this.value);    
    });

    //change value of total
    $(thisRow).find(".total").html(sum);
}


I can find a couple of problems and improvements

  1. summing text values will concatenate all the input values, not the numeric values. You have to cast the text value to a number using e.g. parseInt or parseFloat.
  2. $(this).closest('tr') doesn't return a set. You can change this to $(event.target).closest('tr') if you pass the event object from the event handler. The reason for this is that this is evaluated in the default context not in the context of the event.
  3. You should probably use the onchange event instead of onkeyup event: There is no need to update the sum with incomplete information.
  4. You can bind the event using $(selector).keyup(function() {}), you don't need to use the .each function.
  5. JSLint will warn you if you use a function before defining it.
  6. td:not(.total) input:text is a bit specific in the current context - it can be simplified.

Solution with some modifications

function newSum(event) {
    var sum = 0;
    var thisRow = $(event.target).closest('tr');
    thisRow.find("td input").each(function() {
        sum += parseInt(this.value);
    });


    thisRow.find(".total").html(sum);
}

$("input").change(function(event) {
    newSum(event);
});

The composition might be better if the newSum-function didn't have to know about the context as much e.g.

function sumInputsIn(inputs) {
    var sum = 0;
    inputs.each(function() {
        sum += parseInt(this.value, 10);
    });
    return sum;
}

$("input").change(function(event) {
    var row = $(event.target).closest('tr');
    row.find('.total').html(sumInputsIn(row.find('td input')));
});


$(document).ready(function(){  
    $("input").keyup(function(){
        var suma = 0; 
        $(this).parents("tr").children("td").children().each(function(){
            suma+= parseInt($(this).val());
        });
        $(this).parent().parent().children(":last").text(suma);
    });
});
0

精彩评论

暂无评论...
验证码 换一张
取 消