Beginner in javascript,
I would like to calculate the subtotals total in javascript and put it in my <p> #total.
Here is my code :
<?php
include 'main.php';
check_loggedin($pdo);
$minerals = $pdo->query('SELECT * FROM products WHERE category = "mineral"');
$alcools = $pdo->query('SELECT * FROM products WHERE category = "alcool"');
$foods = $pdo->query('SELECT * FROM products WHERE category = "food"');
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,minimum-scale=1">
<title>Caisse</title>
<link href="style.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css">
</head>
<body >
<?php include 'navigation.php' ;?>
<main>
<div >
<h2>Caisse</h2>
<div >
<div >
<form action="" method="post" >
<div >
<h3>Minérales</h3>
<table>
<colgroup>
<col width="5%">
<col width="35%">
<col width="20%">
<col width="20%">
<col width="20%">
</colgroup>
<thead>
<tr>
<td>QTY</td>
<td >Product</td>
<td>Unit</td>
<td>Price</td>
<td>Total</td>
</tr>
</thead>
<tbody>
<?php if (!$minerals): ?>
<tr>
<td colspan="5" style="text-align:center">There are no minerals</td>
</tr>
<?php endif; ?>
<?php foreach ($minerals as $mineral): ?>
<tr>
<td><input type="text" name="qty_mineral" onblur=Calcul_total() oninput="Calcul_Stotal(this)"></td>
<td ><?=$mineral['name']?></td>
<td><?=$mineral['unit']?></td>
<td ><?=$mineral['price']?></td>
<td ></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<div >
<h3>Alcool</h3>
<table>
<colgroup>
<col width="5%">
<col width="35%">
<col width="20%">
<col width="20%">
<col width="20%">
</colgroup>
<thead>
<tr>
<td>QTY</td>
<td >Product</td>
<td>Unit</td>
<td>Price</td>
<td>Total</td>
</tr>
</thead>
<tbody>
<?php if (!$alcools): ?>
<tr>
<td colspan="5" style="text-align:center">There are no alcools</td>
</tr>
<?php endif; ?>
<?php foreach ($alcools as $alcool): ?>
<tr>
<td><input type="text" name="qty_alcool" onblur=Calcul_total() oninput="Calcul_Stotal(this)"></td>
<td ><?=$alcool['name']?></td>
<td><?=$alcool['unit']?></td>
<td ><?=$alcool['price']?></td>
<td ></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</form>
</div>
<div >
<div ></div>
<button>Total</button>
<div >
<p id="total"></p>
</div>
</div>
</div>
</div>
</main>
</body>
</html>
<script>
function Calcul_Stotal(target) {
const parent = target.closest('tr');
var qty = parent.querySelector('.qty').value;
var price = parent.querySelector('.price').textContent;
_total = qty * price;
parent.querySelector('.total').innerText = _total;
}
function Calcul_total() {
var total = document.querySelectorAll('.total');
total.forEach(function(value){
console.log(value);
});
document.getElementById('total').innerText = "";
}
</script>
I tried to select all my subtotals (.total) with querySelectorAll. But I can't get only the value in the array.
How would it be possible to retrieve only the value in the array without html tags?
Is there any other solution than the querySelectorAll?
Waiting for an answer, thank you for your help.
CodePudding user response:
As suggested also by someone in the comments, for sure you were missing the logic to perform the sum in your Calcul_total
function.
I changed your html so that instead of having php logics inside looping through minerals and alchools elements, it just hosts 2 specific instances of mineral (gold) and alchool (vodka) with prefilled quantity and price values.
Plus I added the handling of the isNaN scenario so that both the subtotals and total don't get messed up when the number can't be computer for invalid input. In that step I also made sure to format the number to fixed point notation having 2 digits after decimal separator. Consider that you might have surprises coming from the floating point maths.
Anyway as a very important reccomendation, I suggest you to use parseFloat
when reading numbers from text so that they will be explicitely converted. That could be ignored because in many circumstances the type coercion will work in a transparent way.. but better makes things clear in my opinion.
function Calcul_Stotal(target) {
const parent = target.closest('tr');
const qty = parseFloat( parent.querySelector('.qty').value );
const price = parseFloat( parent.querySelector('.price').textContent );
let _total = qty * price;
if(isNaN(_total))
_total = '-';
else
_total.toFixed(2);
parent.querySelector('.total').innerText = _total;
}
function Calcul_total() {
const total = document.querySelectorAll('.total');
let sum = 0;
total.forEach(function(value) {
let thisTotal = parseFloat(value.innerText);
if (isNaN(thisTotal)) thisTotal = 0;
sum = thisTotal;
});
if(isNaN(sum))
sum = '-';
else
sum = sum.toFixed(2)
document.getElementById('total').innerText = sum;
}
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,minimum-scale=1">
<title>Caisse</title>
<link href="style.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css">
</head>
<body >
<?php include 'navigation.php' ;?>
<main>
<div >
<h2>Caisse</h2>
<div >
<div >
<form action="" method="post" >
<div >
<h3>Minérales</h3>
<table>
<colgroup>
<col width="5%">
<col width="35%">
<col width="20%">
<col width="20%">
<col width="20%">
</colgroup>
<thead>
<tr>
<td>QTY</td>
<td >Product</td>
<td>Unit</td>
<td>Price</td>
<td>Total</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<input
type="text"
name="qty_mineral"
onblur=Calcul_total()
oninput="Calcul_Stotal(this)">
</td>
<td >
Gold
</td>
<td>
13
</td>
<td >
75.22
</td>
<td ></td>
</tr>
</tbody>
</table>
</div>
<div >
<h3>Alcool</h3>
<table>
<colgroup>
<col width="5%">
<col width="35%">
<col width="20%">
<col width="20%">
<col width="20%">
</colgroup>
<thead>
<tr>
<td>QTY</td>
<td >Product</td>
<td>Unit</td>
<td>Price</td>
<td>Total</td>
</tr>
</thead>
<tbody>
<tr>
<td>
<input
type="text"
name="qty_alcool"
onblur="Calcul_total()"
oninput="Calcul_Stotal(this)">
</td>
<td >
Vodka
</td>
<td>
65
</td>
<td >
14.65
</td>
<td ></td>
</tr>
</tbody>
</table>
</div>
</form>
</div>
<hr>
<div >
<div ></div>
<button>Total</button>
<div >
<p id="total"></p>
</div>
</div>
</div>
</div>
</main>
</body>
</html>