Where do I implement the getElementById in my JavaScript function? - javascript

Background: For my website I have to count the number of checked checkboxes in a table. Depending on the result, there is then a different 'output'. As long as fewer than or equal to 2 checkboxes are checked --> output A. If more than 2 boxes are checked OR the first checkbox is checked --> output B.
Now to my problem: I specifically don't understand this line of code:
const checked = [...this.querySelectorAll(".choice:checked")].map(inp => +inp.value);
If I understand correctly, it checks all input fields in the form, adds and converts the results. But how can I implement an ID here that I only give to the first checkbox in order to solve the problem?
And another question: Can I then link the values ​​with a logical operator?
My code:
.hide {
display: none;
}
<form id="listForm">
<table>
<tbody>
<tr id="G">
<td><b>G</b></td>
<td></td>
<td><input type="checkbox" class="choice" id="cbg" name="choiceG" value="1"></td>
</tr>
<tr>
<td id="A"><b>A</b></td>
<td></td>
<td><input type="checkbox" class="choice" name="choiceA" value="1"></td>
</tr>
<tr>
<td id="B"><b>B</b></td>
<td></td>
<td><input type="checkbox" class="choice" name="choiceB" value="1"></td>
</tr>
<tr>
<td id="C"><b>C</b></td>
<td></td>
<td><input type="checkbox" class="choice" name="choiceC" value="1"></td>
</tr>
<tr>
<td colspan="2" ;="" style="text-align:right;"><b>Sum:</b></td>
<td><input disabled="" type="text" size="2" name="total" id="total" value="0"></td>
</tr>
</tbody>
</table>
</form>
<div id="showwhen2" class="hide">
<p>2 or less boxes checked; first box is unchecked</p>
</div>
<div id="showwhen3" class="hide">
<p>first box or more than two boxes are checked</p>
</div>
<script>
document.getElementById("listForm").addEventListener("input", function() {
let sum = 0;
let sumg = 0;
const checked = [...this.querySelectorAll(".choice:checked")].map(inp => +inp.value);
const checkedg = [...this.querySelectorAll(".choice:checked")].map(inp => +inp.value);
if (checked.length > 0) sum = checked.reduce((a, b) => a + b);
if (checkedg.length > 0) sumg = checkedg.reduce((a, b) => a + b);
console.log(sum);
console.log(sumg);
document.getElementById("total").value = sumg + sum;
document.getElementById("showwhen3").classList.toggle("hide", sum < 3 || sumg <1);
document.getElementById("showwhen2").classList.toggle("hide", sum > 2);
});
</script>

This seems really overcomplicated.
const checkedCount = this.querySelectorAll(".choice:checked").length
if (checkedCount > 2 || this.querySelector('input#cbg').checked) {
//output B
} else {
//output A
}
querySelectorAll returns a list of all elements that match the selector (i. e. all checked inputs) and querySelector just one element. # is selector syntax for element ids.

Related

Select only checkboxes that are checked in a column

I have an html table that has 5 columns. 2 columns are checkboxes (entry and high) and the other 3 are data. I have 2 buttons, one is called entry and the other high. When a user clicks on the high button, I'm trying to check the column (high) only and get all that is checked, take those values and average them.
The same with entry, when the entry button is clicked, check only the checkboxes in column (entry) and take those values and average them.
So far I have a function to check both columns but not sure how to separately check and separate the columns to each button function only. I have tried the below, but the GetHigh function doesn't work.
Any points in the right direction would be appreciated!
Table
<td><input type="checkbox" class="entry" id="entry" value="{{$sup->entry}}" name="rows[]"></td>
<td><input type="checkbox" class="high" id="high" value="{{$sup->high}}" name="rows[]"></td>
<td><span style="color: #007E33">{{$sup->entry}} </span></td>
<td><span style="color: #007E33">{{$sup->high}} </span></td>
<td><span style="color: #007E33">{{$sup->days}} </span></td>
Buttons
<a href="#here" class="btn btn-primary btn-pill w-10" id="entry" onclick="GetEntry()">
Entry Average
</a>
<a href="#here" class="btn btn-primary btn-pill w-10" id="high" onclick="GetHigh()">
High Average
</a>
Javascript
function GetEntry() {
//Create an Array.
var selected = new Array();
//Reference the Table.
var supTable = document.getElementById("supTable");
//Reference all the CheckBoxes in Table. I WANT ONLY THE ENTRY COLUMN
var entry = supTable.getElementsByTagName("INPUT");
// Loop and push the checked CheckBox value in Array.
for (var i = 0; i < entry.length; i++) {
if (entry[i].checked) {
selected.push(entry[i].value);
}
}
// alert("Average: " + calculate(selected));
$(".text-message").text("Average: " + calculate(selected)).show();
}
function GetHigh() {
//Create an Array.
var selected = new Array();
//Reference the Table.
var supTable = document.getElementById("supTable");
//Reference all the CheckBoxes in Table. I WANT ONLY THE ENTRY COLUMN
var entry = supTable.getElementsByName("High");
// Loop and push the checked CheckBox value in Array.
for (var i = 0; i < high.length; i++) {
if (high[i].checked) {
selected.push(high[i].value);
}
}
// alert("Average: " + calculate(selected));
$(".text-message").text("Average: " + calculate(selected)).show();
}
getElementsByName is used to select HTML where their name="" attribute matches what you've entered, in this case 'High'. But your HTML in the example shows a different name.
You want to use querySelectorAll('high') to get all of the elements that have class="high" set.
You can use a css selector to get the cells of your table
const getCheckboxes = columnIndex =>document.querySelectorAll(`tbody td:nth-child(${columnIndex}) input:checked`);
Or add a common class and select by the class to the checkboxes
const getCheckboxes = className =>document.querySelectorAll(`tbody .${className}:checked`);
Basic example:
const getCheckedCheckboxesClassName = className => document.querySelectorAll(`tbody .${className}:checked`);
const getCheckedCheckboxesByIndex = columnIndex =>document.querySelectorAll(`tbody td:nth-child(${columnIndex}) input:checked`);
const sumValues = cbs => [...cbs].reduce((total, cb) => total + +cb.value, 0);
const getTotal = (group) => {
const cbs = getCheckedCheckboxesClassName(group);
const value = sumValues(cbs);
console.log(value);
}
const getTotalIndex = (index) => {
const cbs = getCheckedCheckboxesByIndex(index);
const value = sumValues(cbs);
console.log(value);
}
<button type="button" onclick="getTotal('low'); getTotalIndex(1)">low</button>
<button type="button" onclick="getTotal('high'); getTotalIndex(2)">high</button>
<table>
<tbody>
<tr>
<td><input class="low" type="checkbox" value="1" /></td>
<td><input class="high" type="checkbox" value="10" /></td>
</tr>
<tr>
<td><input class="low" type="checkbox" value="2" /></td>
<td><input class="high" type="checkbox" value="20" /></td>
</tr>
<tr>
<td><input class="low" type="checkbox" value="3" /></td>
<td><input class="high" type="checkbox" value="30" /></td>
</tr>
<tr>
<td><input class="low" type="checkbox" value="4" /></td>
<td><input class="high" type="checkbox" value="40" /></td>
</tr>
<tr>
<td><input class="low" type="checkbox" value="5" /></td>
<td><input class="high" type="checkbox" value="50" /></td>
</tr>
</tbody>
</table>

How to read input values based on checkbox checked?

How can I get the input value inside of the table that is associated with the next checkbox? I just need to get only those input values whose checkbox is checked. Display the value as an innerHTML of div comma separated.
I can get all the input value but I am not able to apply the logic for the checkbox
I tried for all the input box values.
let olist = [...document.querySelectorAll('table tbody tr')].map(row => {
const childs = row.querySelectorAll("input");
return {
oKey: parseInt(childs[1].value),
}
})
function checkboxChecked(event) {
let final = document.getElementById("final");
}
<table>
<thead>
<tr>
<td>Checbox</td>
<td>Key</td>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" onclick="checkboxChecked(event)"></td>
<td><input type="number" value=1></td>
</tr>
<tr>
<td><input type="checkbox" onclick="checkboxChecked(event)"></td>
<td><input type="number" value=2></td>
</tr>
<tr>
<td><input type="checkbox" onclick="checkboxChecked(event)"></td>
<td><input type="number" value=3></td>
</tr>
</tbody>
</table>
<div id="final"></div>
You are using the Array.prototype.map() function to create an array with transformed values. That's fine. But you want to include only values where the corresponding checkbox is checked. You can do that by adding a call to the Array.prototype.filter() function.
There are multiple ways to do this. One of the easiest solutions would be to first call map() to create an array with items containing the checkbox values and the corresponding number values, then use filter() to create an array with only the checked items, and then use map() again to get an array with the resulting number values. Something like this:
let olist =
[...document.querySelectorAll('table tbody tr')]
.map(row => {
const children = row.querySelectorAll('input');
return {
checked: children[0].checked,
value: parseInt(children[1].value)
}
})
.filter(item => item.checked)
.map(item => item.value)
document.getElementById('final').innerHTML = olist.join(', ')
Note that you can probably omit the parseInt call inside the first map callback function as well, because afterwards you are just concatenating those values into a string again.
Edit
An even shorter alternative would be something like this:
let olist =
[...document.querySelectorAll('table tbody tr')]
.filter(row => row.querySelector('input[type=checkbox]').checked)
.map(row => row.querySelector('input[type=number]').value)
document.getElementById('final').innerHTML = olist.join(', ')
function checkboxChecked(event) {
let checkBox=event.path[0]
let input=event.path[2].children[1].children[0]
console.log(`Box Checked: ${checkBox.checked}\nValue: ${input.value}`)
}
<table>
<thead>
<tr>
<td>Checbox</td>
<td>Key</td>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" onclick="checkboxChecked(event)"></td>
<td><input type="number" value=1></td>
</tr>
<tr>
<td><input type="checkbox" onclick="checkboxChecked(event)"></td>
<td><input type="number" value=2></td>
</tr>
<tr>
<td><input type="checkbox" onclick="checkboxChecked(event)"></td>
<td><input type="number" value=3></td>
</tr>
</tbody>
</table>
<div id="final"></div>

Use JavaScript to get value of the for each

I'm new using JavaScript. I need to get the value ${prdcts.precioUnidad} of the checked line. The idea is to set the total price in a dynamic way, so when the user checks or unchecks each line the value of total either adds the new value when checked, or subtracts the previous value when unchecked.
I tried to get the value using the getElement() methods, but I don't know how to access the value of the variable within that specific row.
This is the HTML:
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Ventas</title>
</head>
<body>
<center><h1>Venta de Productos</h1>
<form action="venta.htm" method="post">
<table id="tableID" border="4">
<tbody><tr>
<th>ID</th>
<th>Nombre</th>
<th>Valor</th>
<th>Comprado</th>
</tr>
<tr>
<td>2</td>
<td>Chupetin</td>
<td>5.0</td>
<td><input name="check" type="checkbox" value="2" label="2" path="prdcts"></td>
</tr>
<tr>
<td>3</td>
<td>Alfajor DDL</td>
<td>30.0</td>
<td><input name="check" type="checkbox" value="3" label="3" path="prdcts"></td>
</tr>
<tr>
<td>4</td>
<td>Sanguche Mila</td>
<td>60.0</td>
<td><input name="check" type="checkbox" value="4" label="4" path="prdcts"></td>
</tr>
</tbody></table>
<br>
<br>
<br>
<table border="4">
<tbody><tr>
<td>Total Compra: <input name="total" id="total" type="number" readonly="" value="0"></td>
</tr>
<tr>
<td>Monto Pagado: <input name="monto" id="monto" type="number" value="0"></td>
</tr>
<tr>
<td>Vuelto: <input name="vuelto" id="vuelto" type="number" readonly="" value="0"></td>
</tr>
<tr>
<td><input name="begin" onclick="calcularVuelto()" type="button" value="Calcular Vuelto"></td>
</tr>
</tbody></table>
<br>
<br>
<input name="clear" onclick="window.location.href = 'venta.htm'" type="button" value="Borrar venta">
<input name="begin" onclick="window.location.href = 'principal.htm'" type="button" value="Inicio">
<input name="confirm" type="submit" value="Confirmar Venta">
<br>
</form>
</center>
<script>
// Make it an Array with "Array.from" so we can use reduce() on it
var $$checkboxes = Array.from(document.querySelectorAll('input[name=check]')),
$total = document.getElementById('total');
// For each checkbox
$$checkboxes.forEach(function ($checkbox) {
// When its value changes, update total
$checkbox.addEventListener('change', updateTotal);
});
function updateTotal() {
// For each checkbox
alert("aca");
var total = $$checkboxes.reduce(function (sum, $checkbox) {
// If it's checked
alert("aca2")
if ($checkbox.checked) {
var price = $checkbox.parentNode.parentNode // parent <tr>
.querySelectorAll('td')[2].innerText.trim(); // remove spaces
// Add price to the sum
return sum + parseFloat(price);
} else {
// If it's not checked, just return the current sum
return sum;
}
}, 0);
$total.value = total.toFixed(2); // Always 2 decimals
}
function calcularVuelto() {
var total = document.getElementById("total").value;
var pago = document.getElementById("monto").value;
var fTotal = parseFloat(total);
var fPago = parseFloat(pago);
totalResta = fPago - fTotal;
document.getElementById("vuelto").value = totalResta;
}
</script>
</body></html>
You can use Array.prototype.reduce() to calculate the total:
// Make it an Array with "[].slice.call" so we can use reduce() on it
var $$checkboxes = [].slice.call(document.querySelectorAll('input[name=check]')),
$total = document.getElementById('total');
// For each checkbox
$$checkboxes.forEach(function ($checkbox) {
// When its value changes, update total
$checkbox.addEventListener('change', updateTotal);
});
function updateTotal() {
// For each checkbox
var total = $$checkboxes.reduce(function (sum, $checkbox) {
// If it's checked
if ($checkbox.checked) {
var price = $checkbox.parentNode.parentNode // parent <tr>
.querySelectorAll('td')[2].innerText.trim(); // remove spaces
// Add price to the sum
return sum + parseFloat(price);
} else {
// If it's not checked, just return the current sum
return sum;
}
}, 0);
$total.value = total.toFixed(2); // Always 2 decimals
}
<table border="4">
<tr><th>ID</th> <th>Nombre</th> <th>Valor</th> <th>Comprado</th> </tr>
<tr><td>x</td><td>X</td><td>5.99</td><td><input name="check" type="checkbox" value="x" label="X"/></td></tr>
<tr><td>y</td><td>Y</td><td>3.95</td><td><input name="check" type="checkbox" value="y" label="Y"/></td></tr>
<tr><td>z</td><td>Z</td><td>14.20</td><td><input name="check" type="checkbox" value="z" label="Z"/></td></tr>
</table>
<p>Total Compra: <input name="total" id="total" type="number" value="0" readonly/></p>
The checked flag is either on or off. It doesn't take an argument. So it looks like
<input type="checkbox" name="name" checked> checked </input>
<br/>
<input type="checkbox" name="name"> unchecked</input>
In your code you'll need something like: ${prdcts.idProducto ? "checked" : ""}

How to get values to the outside from three functions and update them in real time?

I have a table which lets users to add number of participants for an event. in it I used input type number field to get number of participants. then I calculate how much fee they have to pay for each passenger type. I have 3 passenger types.
My table looks like this,
I use keyup mouseup bind to get the input value by user and multiplied it with fee for one participant.
var totalAdults;
jQuery("#number_adults").bind('keyup mouseup', function () {
var numOfAdults = jQuery("#number_adults").val();
totalAdults = numOfAdults * adultFee;
});
I have 3 of above functions to calculate and real time display how much fee that they have to pay in each passenger type.
Now I need to get the total sum of all three passenger type fees and display/update it in real time to the user, at the end of my table.
I tried making each passenger type total value global and calculating it's sum, but I get an error saying missing semicolon error linked to this MDN article
I'm stuck here. how can I get total value on all three passenger types outside their respective functions and display that value correctly in real time? (when they update number of passengers, total for passenger type is changing, I need to change final total accordingly). please help
Update:
this is the html table that I used. this get repeated another two times for other two passenger types.
var adultFee = 150;
var finalTotal = 0;
jQuery("#number_adults").bind('keyup mouseup', function() {
var numOfAdults = jQuery("#number_adults").val();
totalAdults = numOfAdults * adultFee;
jQuery("#adult_amount").html(totalAdults);
// console.log(totalAdults);
finalTotal = finalTotal + totalAdults;
console.log(finalTotal);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<tr>
<td style="font-weight: 600;">Adult</td>
<td id="adult_price" name="adult_price">150.00</td>
<td>
<input id="number_adults" max="3" min="1" name="number_adults" type="number" value="0" class="form-control">
</td>
<td name="amount">
<p id="adult_amount"></p>
</td>
</tr>
This is how I tried to get the final total, it doesn't display any result
jQuery(document).on('change', '#adult_amount', function() {
finalTotal = finalTotal+totalAdults;
alert(finalTotal);
});
I made a working example for you.
$('.inputs').each(function(){
$(this).on('change keyup', function(){
let sumTotal = 0;
$('.inputs').each(function(){
sumTotal += $(this).val() * +$(this).parent().next().data('price');
});
$('.total').text(`${sumTotal} $`);
});
});
td:nth-child(3),
th:nth-child(3){
text-align:center;
}
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>
<body>
<div class="container">
<div class="row justify-content-center">
<div class="col-12">
<table class="table table-hover">
<thead>
<tr>
<th></th>
<th>QTY</th>
<th>Amount</th>
</tr>
</thead>
<tbody>
<tr>
<td>Child</td>
<td><input type="number" class="inputs form-control" value="0" min="0" max="999"></td>
<td class="price" data-price="150">150 $</td>
</tr>
<tr>
<td>Adult</td>
<td><input type="number" class="inputs form-control" value="0" min="0" max="999"></td>
<td class="price" data-price="200">200 $</td>
</tr>
<tr>
<td>Adult Plus</td>
<td><input type="number" class="inputs form-control" value="0" min="0" max="999"></td>
<td class="price" data-price="250">250 $</td>
</tr>
<tr>
<td>Total - </td>
<td></td>
<td class="total">0.00 $</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>
(https://codepen.io/bichiko/pen/JQWomy)
Here is a solution which should do what you need.
Compared to your code, the key changes are:
Use classes instead of IDs to identify the elements within each row. This means you can handle changes to all your fields using the same event handling code. I've given all your quantity fields the .qty class, and then bound the event to that class, so all elements with that class will run the same function.
Within the function, I've stripped out all direct references to fields - instead, to get the price field, and the total field for the relevant type, the code uses the positions of the fields relative to each other in the page, it uses the .parent(), .next(), and .prev() functions to find the total and amount fields which are within the same table row as the altered quantity field (which will always be this inside the event handler), so that it does the calculations on the right fields.
To calculate the final overall total, I've defined a separate function. Again this uses a class selector to identify all the "amount" fields, and add each of those values together to get the total. Since this function is triggered at the end of the event handler, it will always update the grand total whenever one of the quantities is updated.
Other minor changes:
use .on() instead of the deprecated .bind()
jQuery(".qty").on('keyup mouseup', function() {
var tdElement = jQuery(this).parent();
var qty = parseInt(this.value);
var fee = parseFloat(tdElement.prev(".price").text());
var typeTotal = qty * fee;
tdElement.next(".amount").html(typeTotal);
calcFinalTotal();
});
function calcFinalTotal()
{
var finalTotal = 0;
$(".amount").each(function() {
finalTotal += parseFloat($(this).text());
});
$("#total").text(finalTotal);
}
td, th
{
border: solid 1px #cccccc;
padding: 5px;
text-align:left;
}
table {
border-collapse: collapse;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<th>Passenger Type</th>
<th>Price</th>
<th>Quantity</th>
<th>Total</th>
<tr>
<th>Adult</th>
<td class="price">150.00</td>
<td>
<input max="3" min="1" name="number_adults" type="number" value="0" class="form-control qty">
</td>
<td class="amount">0
</td>
</tr>
<tr>
<th>Type 2</th>
<td class="price" id="type3_price">200.00</td>
<td>
<input max="3" min="1" name="number_type" type="number" value="0" class="form-control qty">
</td>
<td class="amount">0
</td>
</tr>
<tr>
<th>Type 3</th>
<td class="price" id="type3_price">200.00</td>
<td>
<input max="3" min="1" name="number_type" type="number" value="0" class="form-control qty">
</td>
<td class="amount">0
</td>
</tr>
<tr>
<th colspan="3">Grand Total</th>
<td id="total"></td>
</tr>
</table>
You can simply loop on every rows on the table and calculate the total sum and also the individual. Here i done by the dynamic method. if the total of each passenger is inserted in a unique input, then you can access from that input. Otherwise please follow the method
$(document).on('keyup mouseup','.qty', function() {
calculate();
});
function calculate(){
var finalTotal = 0;
var old = 0;
var mature = 0;
var adult = 0;
$('.qty').each(function(key,value){
$qty = $(this).val();
$type = $(this).attr('data-type');
$amount = $(this).parent().siblings('.adult_price').html();
$total = Number($qty) * parseFloat($amount);
$(this).parent().siblings('.amount').html($total);
finalTotal += $total;
if($type == 'adult')
adult += parseFloat($total);
else if($type == 'mature')
mature += parseFloat($total);
else if($type == 'old')
old += parseFloat($total);
});
$('.grandTotal').html(finalTotal);
// console.log('Adult',adult);
// console.log('Mature',mature);
// console.log('Old',old);
}
table {
border-collapse: collapse;
width: 80%;
}
th, td {
text-align: left;
padding: 8px;
}
tr:nth-child(even){background-color: #f2f2f2}
th {
background-color: #4CAF50;
color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<th>Passenger Types</th>
<th>Amount</th>
<th>Qty</th>
<th>Total</th>
</tr>
</thead>
<tbody>
<tr>
<td><b>Adult</b></td>
<td class="adult_price" name="adult_price">150.00</td>
<td>
<input max="3" min="1" name="number_adults" type="number" value="0" class="form-control qty" data-type="adult">
</td>
<td name="amount" class='amount'></td>
</tr>
<tr>
<td><b>Mature</b></td>
<td class="adult_price" name="adult_price">200.50</td>
<td>
<input max="3" min="1" name="number_adults" type="number" value="0" class="form-control qty" data-type="mature">
</td>
<td name="amount" class='amount'></td>
</tr>
<tr>
<td><b>Old</b></td>
<td class="adult_price" name="adult_price">150.00</td>
<td>
<input max="3" min="1" name="number_adults" type="number" value="0" class="form-control qty" data-type="old">
</td>
<td name="amount" class='amount'></td>
</tr>
<tr>
<td colspan="3"><b>Grand Total</b></td>
<td class='grandTotal'>100</td>
</tr>
</tbody>
</table>
jQuery is very flexible use class instead of id. If you use inputs, selects, etc you should delegate the input or change event to them.
$('input').on('input', function() {...
input event will trigger as soon as user types or selects on or to an input tag. change event will trigger when a user types or selects on or to an input and then clicks (unfocus or blur event) elsewhere.
The HTML is slightly modified for consistency. Note that there are 2 extra inputs per <tr>.
When using input inside tables you can traverse the DOM by first referencing the imputed/changed/clicked tag as $(this) then climb up to the parent <td> and from there either go to the next <td> using .next() or go to the previous <td> using .prev(). Once you get to a neighboring <td> use .find() to get the input within. When extracting a number from an input it is normally a string but with jQuery method .val() it should extract input value as a number automatically. Details commented in demo.
/*
//A - Any tag with the class of .qty that the user inputs data into triggers a function
//B - Get the value of the imputed .qty (ie $(this))
//C - reference $(this) parent <td> go to the next <td> then find a tag with the class .price and get its value
//D - reference $(this) parent <td> go to the previous <td> then find a tag with the class of .total then set its value to the product of qty and price and fix it with hundredths (.00 suffix)
//E - Declare an empty array
//F - Get the value of each .total, convert it into a number then push the number into the empty array
//G - Use .reduce() to get the sum of all values within the array then fix it with hundredths (.00 suffix) and set it as the value of .grand
*/
$('.qty').on('input', function() { //A
var qty = $(this).val(); //B
var price = $(this).parent().prev('td').find('.price').val(); //C
$(this).parent().next('td').find('.total').val((qty * price).toFixed(2)); //D
var totals = []; //E
$('.total').each(function() {
totals.push(Number($(this).val()));
}); //F
$('.grand').val(totals.reduce((sum, cur) => sum + cur).toFixed(2)); //G
});
table {
table-layout: fixed;
}
td {
width: 6ch
}
[readonly] {
border: 0;
width: 6ch;
text-align: right
}
[type=number] {
text-align: right
}
<table>
<tr>
<td style="font-weight: 600;">Adult</td>
<td><input class="price" name='price' value='150.00' readonly></td>
<td>
<input class="qty" name="qty" min="0" max="3" type="number" value="0" class="form-control">
</td>
<td>
<input class="total" name='total' readonly>
</td>
</tr>
<tr>
<td style="font-weight: 600;">Senior</td>
<td><input class="price" name='price' value='100.00' readonly></td>
<td>
<input class="qty" name="qty" min="0" max="3" type="number" value="0" class="form-control">
</td>
<td>
<input class="total" name='total' readonly>
</td>
</tr>
<tr>
<td style="font-weight: 600;">Child</td>
<td><input class="price" name='price' value='75.00' readonly></td>
<td>
<input class="qty" name="qty" min="0" max="3" type="number" value="0">
</td>
<td>
<input class="total" name='total' readonly>
</td>
</tr>
<tr>
<td colspan='3' style='text-align:right;'>Total</td>
<td><input class='grand' name='grand' value='0' readonly></td>
</table>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
This is axample of yours problem, try using object
var data = {a:0, b:0, c: 0}
function one (){
data.a = data.a + 10
console.log(data.a)
total()
}
function two (){
data.b = data.b + 10
total()
console.log(data.b)
}
function three () {
data.c = data.c + 30
total()
console.log(data.c)
}
function total () {
var totaly = data.a + data.b + data.c
console.log('Total input :', totaly)
}
<button onclick="one()"> get A </button>
<button onclick="two()"> get B</button>
<button onclick="three()"> get C </button>

How to access HTML array object in javascript?

sorry for asking simple question. I am really a beginner in Javascript. I need to access my HTML array form object in my javascript, but I don't know how to do it.
The goal is to trigger the alert in javascript so the browser will display message according to the condition in javascript. Here is my code :
checkScore = function()
{
//I don't know how to access array in HTML Form, so I just pretend it like this :
var student = document.getElementByName('row[i][student]').value;
var math = document.getElementByName('row[i][math]').value;
var physics = document.getElementByName('row[i][physics]').value;
if (parseInt(math) >= 80 ) {
alert(student + " ,You are good at mathematic");
}
if (parseInt(physics) >= 80 ){
alert(student + " ,You are good at physics");
}
student_score.row[i][otherinfo].focus();
student_score.row[i][otherinfo].select();
}
<h2>HTML Forms</h2>
<form name="student_score" action="/action_page.php">
<table border=1>
<thead>
<td>Student</td>
<td>Math Score</td>
<td>Physics Score</td>
<td>Other info</td>
</thead>
<tbody>
<tr>
<td><input type="text" name="row[1][student]"></td>
<td><input type="number" name="row[1][math]" onblur="checkScore()" min="0" max="100"></td>
<td><input type="number" name="row[1][physics]" onblur="checkScore()" min="0" max="100"></td>
<td><input type="text" name="row[1][otherinfo]"></td>
</tr>
<tr>
<td><input type="text" name="row[2][student]"></td>
<td><input type="number" name="row[2][math]" onblur="checkScore()" min="0" max="100"></td>
<td><input type="number" name="row[2][physics]" onblur="checkScore()" min="0" max="100"></td>
<td><input type="text" name="row[2][otherinfo]"></td>
</tr>
<tr>
<td>
<input type="submit" value="Submit">
</td>
</tr>
</tbody>
</table>
</form>
<p>If you click the "Submit" button, it will save the data.</p>
We are going to leverage few things here to streamline this.
The first is Event Listeners, this removes all javascript from your HTML. It also keeps it more dynamic and easier to refactor if the table ends up having rows added to it via javascript.
Next is parentNode, which we use to find the tr that enclosed the element that was clicked;
Then we use querySelectorAll with an attribute selector to get our target fields from the tr above.
/*This does the work*/
function checkScore(event) {
//Get the element that triggered the blur
var element = event.target;
//Get our ancestor row (the parent of the parent);
var row = element.parentNode.parentNode;
//Use an attribute selector to get our infor from the row
var student = row.querySelector("[name*='[student]']").value;
var math = row.querySelector("[name*='[math]']").value;
var physics = row.querySelector("[name*='[physics]']").value;
var otherField = row.querySelector("[name*='[otherinfo]']");
if (parseInt(math, 10) >= 80) {
alert(student + " ,You are good at mathematic");
}
if (parseInt(physics, 10) >= 80) {
alert(student + " ,You are good at physics");
}
otherField.focus();
otherField.select();
}
/*Wire Up the event listener*/
var targetElements = document.querySelectorAll("input[name*='math'], input[name*='physics']");
for (var i = 0; i < targetElements.length; i++) {
targetElements[i].addEventListener("blur", checkScore);
}
<h2>HTML Forms</h2>
<form name="student_score" action="/action_page.php">
<table border=1>
<thead>
<tr>
<td>Student</td>
<td>Math Score</td>
<td>Physics Score</td>
<td>Other info</td>
</tr>
</thead>
<tbody>
<tr>
<td><input type="text" name="row[1][student]" class='student'></td>
<td><input type="number" name="row[1][math]" min="0" max="100"></td>
<td><input type="number" name="row[1][physics]" min="0" max="100"></td>
<td><input type="text" name="row[1][otherinfo]"></td>
</tr>
<tr>
<td><input type="text" name="row1[2][student]"></td>
<td><input type="number" name="row[2][math]" min="0" max="100"></td>
<td><input type="number" name="row[2][physics]" min="0" max="100"></td>
<td><input type="text" name="row[2][otherinfo]"></td>
</tr>
<tr>
<td>
<input type="submit" value="Submit">
</td>
</tr>
</tbody>
</table>
</form>
Well, it follows your line of code exactly as it is (because you said you do not want to change the code too much).
<h2>HTML Forms</h2>
<form name="student_score" action="/action_page.php">
<table border=1>
<thead>
<td>Student</td>
<td>Math Score</td>
<td>Physics Score</td>
<td>Other info</td>
</thead>
<tbody>
<tr>
<td><input type="text" name="row[1][student]"></td>
<td><input type="number" name="row[1][math]" onblur="checkScore(this)" min="0" max="100"></td>
<td><input type="number" name="row[1][physics]" onblur="checkScore(this)" min="0" max="100"></td>
<td><input type="text" name="row[1][otherinfo]"></td>
</tr>
<tr>
<td><input type="text" name="row1[2][student]"></td>
<td><input type="number" name="row[2][math]" onblur="checkScore(this)" min="0" max="100"></td>
<td><input type="number" name="row[2][physics]" onblur="checkScore(this)" min="0" max="100"></td>
<td><input type="text" name="row[2][otherinfo]"></td>
</tr>
<tr>
<td>
<input type="submit" value="Submit">
</td>
</tr>
</tbody>
</table>
</form>
JavaScript [Edited again using part of the #Jon P code, the query selector is realy more dynamic, and the value of the "other" field you requested is commented out]
//pass element to function, in html, only add [this] in parenteses
checkScore = function (element) {
//Get our ancestor row (the parent of the parent);
var row = element.parentNode.parentNode;
//Use an attribute selector to get our infor from the row
var student = row.querySelector("[name*='[student]']").value;
var math = row.querySelector("[name*='[math]']").value;
var physics = row.querySelector("[name*='[physics]']").value;
var other = row.querySelector("[name*='[otherinfo]']");
if (parseInt(math) >= 80) {
//other.value = student + " ,You are good at mathematic";
alert(student + " ,You are good at mathematic");
}
if (parseInt(physics) >= 80) {
//other.value = student + " ,You are good at physics";
alert(student + " ,You are good at physics");
}
otherField.focus();
otherField.select();
}
Tested :), and sorry about my english!
Try that, haven't tested it
var form = document.getElementsByName("student_score")[0];
var students = form.getElementsByTagName("tr");
for(var i = 0; i < students.length; i++){
var student = students[i].childnodes[0].value;
var math = students[i].childnodes[1].value;
var physics = students[i].childnodes[2].value;
if (parseInt(math) >= 80 ) {
alert(student + " ,You are good at mathematic");
}
if (parseInt(physics) >= 80 ){
alert(student + " ,You are good at physics");
}
}

Categories

Resources