0

So I'm pretty sure that I'm missing some pretty obvious things here, but having worked on many parts of a big project for the past many hours this has me breaking my head open.

Basically I am trying to calculate two values for each row in an HTML table. I want the values to auto calculate/update as the table is being filled out.

Currently neither the Revenue nor Value is being autoupdated/calculated, though I did add onkeyup = "getValues()" to the HTML code.

If the Number Used field is blank, then the value in Number in Package should be used to calculate the Revenue (price * inPackage). If it is not blank, then the value in the field should be used (price * numberUsed).

Pretty sure that I need to specify that this needs to be done for each row somewhere, but for the life of me have not been able to figure it out yet.

Here's a link to a JSFiddle (which shows the HTML but the js does not work): https://jsfiddle.net/wkts81u9/

Here's my HTML code:

    <table id='worksheet_table' class="table table-striped">
      <thead>
        <tr>
        <th>Package</th>
          <th>Number in Package</th>
          <th>Number Used</th>
          <th>Price</th>
          <th>Revenue</th>
          <th>Value</th>
        </tr>
      </thead>
      <tbody>
          <tr>
            <td id="package" name="package">1</td>
            <td id="inPackage" name="inPackage">50</td>
            <td><input type="text" name="numberUsed" id="numberUsed" class="form-control" onkeyup="getValues()" /></td>
            <td><input type="text" name="price" id="price" class="form-control" onkeyup="getValues()" /></td>
            <td name="revenue" id="revenue"></td>
            <td name="value" id="value"></td>
          </tr>
          <tr>
            <td id="package" name="package">2</td>
            <td id="inPackage" name="inPackage">100</td>
            <td><input type="text" name="numberUsed" id="numberUsed" class="form-control" onkeyup="getValues()" /></td>
            <td><input type="text" name="price" id="price" class="form-control" onkeyup="getValues()" /></td>
            <td name="revenue" id="revenue"></td>
            <td name="value" id="value"></td>
          </tr>
        </tbody>
      </table>

Here's my js:

    function getValues()
     {
      var numberUsed = Number(document.getElementById('numberUsed').value);
      var price = Number(document.getElementById('price').value);
      var inPackage = Number(document.getElementById('inPackage').value);
      var revenue = 0;
     if (numberUsed=="")
     {
       revenue = price * inPackage;
     }
     else
     {
       revenue = price * numberUsed;
     }
     var value = revenue * 5;
     document.getElementById("revenue").innerHTML = revenue;
     document.getElementById("value").innerHTML = value;
   }

(Sorry for any messed up formatting in my code.)

Can anybody tell me what it is missing here?

  • 1
    You have 2 elements with same ID: numberUsed. "The id global attribute defines a unique identifier (ID) which must be unique in the whole document. " Check this link: https://developer.mozilla.org/en/docs/Web/HTML/Global_attributes/id. And same with: price, revenue etc. – Leonard Lepadatu Sep 18 '16 at 19:03
  • @LeonardLepadatu that makes complete and total sense, but I don't want to have to hardcode the same calculation many times over with different IDs... Hence why I am looking for a way to loop through each row and reuse the calculations. – Poetical Scientist Sep 18 '16 at 19:16
  • Even if I use just one element with that name it still does not auto calculate/update... – Poetical Scientist Sep 18 '16 at 19:19
  • Then simple change the ID to class and use an each loop. If you use jQuery will be something like this: $(".numberUsed").each(function() { var $this = $(this), total=0; total += $this.val();} ... Well I hope that you are figured how, because it us hard to write code on mobile :D – Leonard Lepadatu Sep 18 '16 at 19:22
  • If use Vanilla will be something like: var number = document.querySelectorAll(".numberUsed"), total=0;; for(var i=0; i< number.length; i++) { number += number[i].value;} – Leonard Lepadatu Sep 18 '16 at 19:27
  • @LeonardLepadatu thank you for your help!! – Poetical Scientist Sep 18 '16 at 19:30
  • I will give the answer and you should accept it in order to help some other colleagues that will have same problem ... some how ... in future – Leonard Lepadatu Sep 18 '16 at 19:33

3 Answers3

0

I see the need to point out a lot of issues with your code. I created a working sample on JsBin* to help you: http://jsbin.com/gevocahihu/edit?html,output

  • First issue, you are using item IDs more than once. You cannot do that in an HTML file
  • You were accessing inPackage with the wrong attribute. You needed to access its innerHTML property, not value, since that wasn't an <input>.

Note: I took out one row in the example to simplify things. You can expand it to more than one row by adding constructors to your function to specify which row you are to edit, Ex: function getValues(row)

I had a lot of trouble getting this app to work in JSFiddle, which is likely a big in the site, so use JsBin for now.

fwjggYUKGFTYucfty
  • 136
  • 1
  • 2
  • 12
  • In the end this is what I had to end up using... I tried to loop through all of the rows and reuse the same code, but that didn't work so I did end up changing all of the id names so that they were unique. But this was the only code that actually made the auto update work, so thank you @mcpolo! – Poetical Scientist Sep 18 '16 at 21:20
0

You have 2 elements with same ID: numberUsed. "The id global attribute defines a unique identifier (ID) which must be unique in the whole document. " Check this Link

And same with: price, revenue etc.

For calculate simple change the ID to class and use an each loop. If you use jQuery will be something like this:

var total=0;
$(".numberUsed").each(function() { 
    var $this = $(this); 
    total += $this.val();
}

If use Vanilla will be something like:

var number = document.querySelectorAll(".numberUsed"), total=0;
for(var i=0; i< number.length; i++) {
    number += number[i].value;
}
Leonard Lepadatu
  • 606
  • 8
  • 14
0

I could see the issue with your code. You do have 2 input elements with the same Id and it would only take on of the elements into consideration, when executing getValues method.

Here is the thread link related to getElementById.

A Better alternative could be to use querySelector and querySelectorall.

I modified your code a bit to make it work.

HTML:

<table id='worksheet_table' class="table table-striped">
    <thead>
    <tr>
        <th>Package</th>
        <th>Number in Package</th>
        <th>Number Used</th>
        <th>Price</th>
        <th>Revenue</th>
        <th>Value</th>
    </tr>
    </thead>
    <tbody>
    <tr class="package-row">
        <td id="package" name="package">1</td>
        <td id="inPackage" name="inPackage">50</td>
        <td><input type="text" name="numberUsed" id="numberUsed" class="form-control" onkeyup="getValues()"/></td>
        <td><input type="text" name="price" id="price" class="form-control" onkeyup="getValues()"/></td>
        <td name="revenue" id="revenue"></td>
        <td name="value" id="value"></td>
    </tr>
    <tr class="package-row">
        <td id="package" name="package">2</td>
        <td id="inPackage" name="inPackage">100</td>
        <td><input type="text" name="numberUsed" id="numberUsed" class="form-control" onkeyup="getValues()"/></td>
        <td><input type="text" name="price" id="price" class="form-control" onkeyup="getValues()"/></td>
        <td name="revenue" id="revenue"></td>
        <td name="value" id="value"></td>
    </tr>
    </tbody>
</table>

JS:

    function getValues() {
            var rows = document.querySelectorAll("tr.package-row");
            rows.forEach(function (currentRow) {

                var numberUsed = Number(currentRow.querySelector('#numberUsed').value);
                var price = Number(currentRow.querySelector('#price').value);
                var inPackage = Number(currentRow.querySelector('#inPackage').value);
                var revenue = 0;

                document.querySelectorAll('numberUsed');

                if (numberUsed == "") {
                    if (isNaN(inPackage) || isNaN(price)) {
                        return;
                    }
                    revenue = price * inPackage;
                }
                else {
                    if (isNaN(numberUsed) || isNaN(price)) {
                        return;
                    }
                    revenue = price * numberUsed;
                }
                var value = revenue * 5;
                currentRow.querySelector("#revenue").innerHTML = revenue;
                currentRow.querySelector("#value").innerHTML = value;
            });

        }

Here is the link : Working Solution

Community
  • 1
  • 1
Sreekanth
  • 3,110
  • 10
  • 22