I am trying to make a simple calculator which tells students their average university mark based on their grades.
JSFiddle
I'm trying to get the formula to do this:
Step 1: (Mark * Credit Point)
Step 2: Add these totals together
Step 3: Get this total and divide it by the number of user inputs.
Having trouble with steps 2 and 3.
Right now when calculate is clicked, it just appends the single answer of each row one after the other. I want to add these values then divide it by the number of inputs.(As the amount of subjects will vary between users)
Any help is really appreciated.
HTML:
<div>
<table class='table'>
<tr>
<th> Unit Code </th>
<th> Mark </th>
<th> Credit Point </th>
</tr>
<tr>
<td> <input type="text"></td>
<td> <input type="text" class='mark'> </td>
<td> <input type="text" class='creditPoint'> </td>
</tr>
<tr>
<td> <input type="text"></td>
<td> <input type="text" class='mark'> </td>
<td> <input type="text" class='creditPoint'> </td>
</tr>
<tr>
<td> <input type="text"></td>
<td> <input type="text" class='mark'></td>
<td> <input type="text" class='creditPoint'> </td>
</tr>
</table>
</div>
Javascript:
$('#wam').click(function() {
$('.table tr').each(function() {
var mark = $(this).find('input.mark').val();
var cp = $(this).find('input.creditPoint').val();
var total = ((mark * cp));
// Find the total then divide by the number of entries
$('body').append(total);
});
});
You need to use a shared variable in the loop
$('#wam').click(function () {
var total = 0,
count = 0;
$('input.mark').each(function () {
var mark = this.value;
var cp = $(this).parent().next().find('input.creditPoint').val();
var t = mark * cp || 0;//if both the fields are not entered don't add them
if (t) {
//if the product is 0 then don't count the value
count++;
}
total += t;
});
$('#total').text(total);
$('#total2').text(count ? total / count : 0);//the ternary condition to prevent division by 0
});
Demo: Fiddle
Related
I can't figure out a method that allows me to carry the data from a number input box to a loop and allows me to add it and average it. I've narrowed the problem down to the one line in my program.
I'll provide partial code in the hope that someone can tell me where I'm going wrong. I either get "NaN, null, undefined, or my html textbox code eg <input type=.... >.
Here is the code:
function calcGrades() {
for (var i = 1; i < rows.length; i++) {
var cells = rows[i].cells;
var sum = 0;
for (var x = 3; x < cells.length; x++) {
var cell = cells[x];
// sum += parseInt(cell.innerHTML)
// var test = document.getElementById(cell);
//sum += document.getElementById(table.rows[i].cells[x].value);
//sum += (table.rows[i].cells[x].innerHTML)
//sum += document.getElementById();
//sum += (table.rows[i].cells[x].children[0].value);
//sum += document.getElementById(table.rows.cell).value;
}
var average = sum / cells.length;
rows[i].innerHTML += "<td>" + average + "</td>";
}
}
function constraint(val) {
if (Number(val.value) > 100) {
val.value = 100
}
}
<table id="tbl">
<tr>
<th> Name </th>
<th> ID </th>
<th> 1 (%)</th>
<th> 2 (%)</th>
<th> 3 (%)</th>
<th> 4 (%)</th>
<th> 5 (%)</th>
<th> Final % </th>
</tr>
<tr>
<td align=center> John Doe </td>
<td> 1 </td>
<td> <input type="number" placeholder="-" size="2" maxlength="3" id="s1g1" oninput="constraint(this)"> </td>
<td> <input type="number" placeholder="-" size="2" maxlength="3" id="s1g2" oninput="constraint(this)"> </td>
<td> <input type="number" placeholder="-" size="2" maxlength="3" id="s1g3" oninput="constraint(this)"> </td>
<td> <input type="number" placeholder="-" size="2" maxlength="3" id="s1g4" oninput="constraint(this)"> </td>
<td> <input type="number" placeholder="-" size="2" maxlength="3" id="s1g5" oninput="constraint(this)"> </td>
<!-- <td id="s1gf"> - </td> -->
</tr>
</table>
<button id="calcGrades" onclick="calcGrades()">Calculate Final Grades</button>
I've tried every one of the commented out lines, some give NaN, some undefined, some null etc.
I'd rather not hardcode all student grades as I have to do 10 students, which will mean changing a lot of IDs.
Assuming rows is something like document.getElementsByTagName('tr'):
sum += parseInt(cell.getElementsByTagName('input')[0].value)
Here we search for input inside each cell and getting the inputs value. Since the value is of type String we need to cast it to Number before adding to sum
Also, keep in mind that arrays and array-like objects are zero-indexed in js.
So if you want to take cells from 3rd one, we should start from index 2
for (var x = 2; x < cells.length; x++) {
P.S. in HTML5 there's not need for constrain function - there's max input attribute for your case
P.P.S Here's more compact solution off the top of my head https://jsfiddle.net/pj2L6h4d/3/
I have two number that calculates the amount and vat amount using JavaScript. Now how will I be able to do this?
<tr>
<th>Amount: </th>
<td><input id="amount" type="text" name="amount" class="form-control" required />
</td>
</tr>
<tr>
<th>VAT 20% Amt: </th>
<td>
<input id="vatAmt" type="text" name="vatAmount" class="form-control" />
</td>
</tr>
<tr>
<th>Total Amount: </th>
<td>
<span id="totalAmount"></span>
</td>
</tr>
then the amount due
<div class="col-md-6" >
<h3>Amount Due: £ <span id="amountValue"></span></h3>
</div>
My JavaScript code is below:
$("#amount").keyup(function () {
var value = $(this).val();
$("#amountValue").text(value);
});
$("#vatAmt").keyup(function () {
var valueVat = $(this).val();
var sum = value + valueVat;
$("#totalAmount").text(sum);
}).keyup();
Can someone help me figured this thing out? Any help is muchly appreciated. TIA
value isn't defined in your second keyup handler. You need to define it:
$("#vatAmt").keyup(function () {
var value = $("#amount").val(); // <--- here
var valueVat = $(this).val();
var sum = value + valueVat;
$("#totalAmount").text(sum);
}).keyup();
When you define a variable inside a function, it's only available within that function. Another option could be to define it globally, but I generally prefer keeping scope limited to only where you need it. Within your keyup handler for #varAmt you need two values, so you would have two calls to .val() to get two values.
Note: It's possible you may also want to use parseInt or something similar to perform your addition:
$("#vatAmt").keyup(function () {
var value = parseInt($("#amount").val()); // <--- here
var valueVat = parseInt($(this).val()); // <--- and here
var sum = value + valueVat;
$("#totalAmount").text(sum);
}).keyup();
JavaScript is pretty forgiving about types, but sometimes bugs can creep in if you rely on that. And .val() returns a string because the input is text, even if that text happens to be numeric characters.
This will do
<tr>
<th>Amount: </th>
<td><input id="amount" type="number" name="amount" class="form-control" required />
</td>
</tr>
<tr>
<th>VAT 20% Amt: </th>
<td>
<input id="vatAmt" type="number" name="vatAmount" class="form-control" />
</td>
</tr>
<tr>
<th>Total Amount: </th>
<td>
<span id="totalAmount"></span>
</td>
</tr>
<div class="col-md-6">
<h3>Amount Due: £ <span id="amountValue"></span></h3>
</div>
var value;
$("#amount").keyup(function() {
value = $(this).val();
$("#amountValue").text(value);
})
$("#vatAmt").keyup(function() {
var valueVat = $(this).val();
var sum = Number(value) + Number(valueVat);
$("#totalAmount").text(sum);
}).keyup();
I have an old ASP site that needs a change. I need a basic grid to set pricing.
I want to enter a price in one column and have it display text of "Debit" or "Credit" in another column based on positive or negative input. I also want to calculate the extended price based on qty. I've just started with the first (text display) one for now, and can't get it to work.
The grid could have n number of rows based on the data set returned so I have a counter which I concatenate to the input IDs to indicate the row number. The counter is working fine and I can see the id's increment correctly. I've tried to pass the correct input value and id but when the function fires it updates the wrong rows. Actually it updates all the rows below the row I've changed. I have spent WAY too much time banging my head on what I thought would be a 15 min issue. Need a few more pairs of eyes.
<script>
function myFunction(val) {
data_length = document.getElementById("datalength").value;
i = 0;
while(i++ < data_length)
if (val > 0) {
document.getElementById("chargepay" +i).innerHTML = "Credit";
}
else
{
document.getElementById("chargepay" +i).innerHTML = "Debit";
}
}
</script>
Here is the row in the grid loop that has the input field to pass the amount value:
<td align="center"><input id="AMNT<%=count%>" size="10" name="AMNT"
onchange="myFunction(this.value)"/></td>
Here is the row in the grid to display the update from the onchange
<td align="center"><p id="chargepay<%=count%>"</p>td>
When I update the value in the input box in first row, it updates all rows below but not that row. I have a loop, I think. I only want it to update one row at a time as I change the values.
Any help / direction would be appreciated.
If you haven't included you need to include the JQuery library from local system or CDN.
https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js
You need to add the change even for every input involved in your mathematical calculation. Here 'this; is passed as argument, so that we can find the parent row(through which all other controls contained in it can be searched.
onchange="myFunction(this)"
Inside the function 'myFunction', We at first finds the closest/parent 'tr'.
Again we selects the input field corresponding to Quantity, Amount etc(you can add more if required). The selection can be based on Id, Name, Class etc
var qty = currentRow.find('input[name=QTY]').val();
//or (id starting with 'QTY')
var qty = currentRow.find('input[id*=QTY]').val();
//or (give any class name and replace it instead of 'class-name')
var qty = currentRow.find('input.class-name').val();
We need to convert the string value to float to perform accurate mathematical calculations. While parsing empty string we may end up with 'NAN' - Not a Number. So we need to check before parsing.
qty = (qty == "" ? 0 : parseFloat(qty));
After all this you can use this value for any math calculation and setting it as text of the tag or any other.
If its p, div, span you need to set it as 'text'
currentRow.find('input[name=TOT]').text(totalAmount);
And if its input you need to set it as 'value'
currentRow.find('p[name=TOT]').val(totalAmount);
function myFunction(elem) {
var currentRow = $(elem).closest('tr');
var qty = currentRow.find('input[name=QTY]').val();
var amt = currentRow.find('input[name=AMNT]').val();
qty = (qty == "" ? 0 : parseFloat(qty));
amt = (amt == "" ? 0 : parseFloat(amt));
var totalAmount = qty * amt;
currentRow.find('p[name=TOT]').text(totalAmount);
currentRow.find('p[name=TYPE]').text(totalAmount > 0 ? 'Credit' : 'Debit');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr>
<td align="center">
<input id="QTY1" size="10" name="QTY" onchange="myFunction(this)" />
</td>
<td align="center">
<input id="AMNT1" size="10" name="AMNT" onchange="myFunction(this)" />
</td>
<td align="center">
<p id="TOT1" name="TOT"></p>
</td>
<td align="center">
<p id="chargepay1" name="TYPE"></p>
</td>
</tr>
<tr>
<td align="center">
<input id="QTY2" size="10" name="QTY" onchange="myFunction(this)" />
</td>
<td align="center">
<input id="AMNT2" size="10" name="AMNT" onchange="myFunction(this)" />
</td>
<td align="center">
<p id="TOT2" name="TOT"></p>
</td>
<td align="center">
<p id="chargepay2" name="TYPE"></p>
</td>
</tr>
<tr>
<td align="center">
<input id="QTY3" size="10" name="QTY" onchange="myFunction(this)" />
</td>
<td align="center">
<input id="AMNT3" size="10" name="AMNT" onchange="myFunction(this)" />
</td>
<td align="center">
<p id="TOT3" name="TOT"></p>
</td>
<td align="center">
<p id="chargepay3" name="TYPE"></p>
</td>
</tr>
</table>
Trying to self create a validation that compares Gross and Tare values in the table using jQuery validation plugin. Tare should always be smaller than Gross.
Here is the JS code:
$.validator.addMethod('lessThan', function (value, element, param) {
if (this.optional(element)) return true;
var i = parseInt(value);
var j = parseInt($(param).val());
return i <= j;
}, "Tare must less than Gross");
$('#myForm').validate({rules: {tare: {lessThan: ".gross"}}});
And my HTML:
<form id="myForm">
<table id="lineItemTable">
<thead>
<th>
<tr>
<td>Gross</td>
<td>Tare</td>
</tr>
</th>
</thead>
<tbody>
<tr>
<td><input type="text" name='gross' class="gross"/></td>
<td><input type="text" name='tare' class="tare"/></td>
</tr>
<tr>
<td><input type="text" name='gross' class="gross"/></td>
<td><input type="text" name='tare' class="tare"/></td>
</tr>
</tbody>
</table>
</form>
This code works fine when only have one row involved.
When comes two table rows, it compares the 2nd row tare value with the 1st row gross value. Apparently I want it to compare 2nd row tare value with 2nd row gross value. Also for some reason the error message shows up at the 1st row.
Here is one screen shot:
Please advise how do I change my code to make it working properly.
And here is the CDN that I am using:
<script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.14.0/jquery.validate.min.js"></script>
Looking for $('.gross').val() will always retrieve the value of the first matched element (in the whole document).
Instead, look only in the row containing the element being validated:
var j = parseInt($(element).closest('tr').find(param).val());
$.validator.addMethod('lessThan', function(value, element, param) {
console.log(element);
if (this.optional(element)) return true;
var i = parseInt(value);
var j = parseInt($(element).closest('tr').find(param).val());
return i <= j;
}, "Tare must less than Gross");
$('#myForm').validate({
rules: {
tare: {
lessThan: ".gross"
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.14.0/jquery.validate.min.js"></script>
<form id="myForm">
<table id="lineItemTable">
<thead>
<th>
<tr>
<td>Gross</td>
<td>Tare</td>
</tr>
</th>
</thead>
<tbody>
<tr>
<td>
<input type="text" name='gross' class="gross" />
</td>
<td>
<input type="text" name='tare' class="tare" />
</td>
</tr>
<tr>
<td>
<input type="text" name='gross' class="gross" />
</td>
<td>
<input type="text" name='tare' class="tare" />
</td>
</tr>
</tbody>
</table>
</form>
thanks to peoples help on here I have nearly finished what I set out to do yesterday/
I have included a fiddle here http://jsfiddle.net/uzW5e/
I would like it that when someone enters a value greater than 85 in the column headed Percentage Grade (class percGrade) the value 1 is put in the column headed Pass Level (class passLevel) but it isn't working?
<table align="center">
<tr>
<th>
Module
</th>
<th>
Percentage Grade
</th>
<th>
Credits
</th>
<th>
Pass Level
</th>
<th>
WGC
</th>
</tr>
<tr class="multRow">
<td>
<input name="module" />
</td>
<td>
<input name="percentageGrade" class="percGrade" />
</td>
<td>
<input name="credits" class="credits"/>
</td>
<td>
<input name="passLevel" class="passLevel"/>
</td>
<td>
<span class="multTotal">0.00</span>
</td>
</tr>
<tr>
<td colspan="5" align="right">
Total <span id="grandTotal">0</span>
</td>
<script>
$(document).ready(function () {
$(".multRow input").keyup(multInputs);
function multInputs() {
var mult = 0;
// for each row:
$("tr.multRow").each(function () {
// check value entered for Percentage Grade
// & change Pass Level to value accordingly
var $num = 0;
if ($('.percGrade', this).val() > 85) {
$num = 1;
$('.passLevel',this).text($num);
}
// get the values from this row:
var $val1 = $('.credits', this).val();
var $val3 = $('.percGrade', this).val();
var $val2 = $('.passLevel', this).val();
var $total = ($val1 * 1) * ($val2 * 1)
$('.multTotal',this).text($total);
mult += $total;
});
$("#grandTotal").text(mult);
}
});
</script>
Since .passLevel is a text field, you should use .val instead of .text:
$('.passLevel',this).val($num);