I've just created a simple VAT calculator. The script works fine though some animations seem a little buggy. Being a javascript beginner I'd like to ask more experienced programmers their opinion about my code. Do you have any helpful criticism to make my code more performant?
document.addEventListener('DOMContentLoaded',function(){
//animation after DOM loaded
var all = document.querySelectorAll('p, h1, h4, input, button');
for(var i=0 ; i<all.length ; i++) {
all[i].animate({
opacity: [ 0, 1 ],
transform: [ 'translateY(50%)','translateY(0%)' ]
}, 1000);
};
//general variables
var btnNew = document.getElementById('newEntry');
var btnArray = [];
var btnList = document.getElementById('showListe');
var list = document.getElementById('liste');
var listHeight = list.getBoundingClientRect().height;
var startHeight = listHeight;
list.classList.add('hide');
var animer = document.querySelector('.animate');
var resultBlock = document.getElementById('resultats');
//details button (opne and close the list) + animations
btnList.addEventListener('click',function(){
list.classList.toggle('animate-up');
list.classList.toggle('animate-down');
if (list.classList.contains('animate-down')){
animer.animate({
opacity: [ 0, 1 ],
transform: ['translateY(-100%)','translateY(0%)']
}, 500);
list.classList.toggle('hide');
resultBlock.animate({
transform: ['translateY('+-startHeight+'px)','translateY(0%)']
}, 500);
} else {
animer.animate({
opacity: [ 1, 0 ],
transform: ['translateY(0%)','translateY(-100%)']
}, 500);
setTimeout(function(){list.classList.toggle('hide')},500);
var listHeight = list.getBoundingClientRect().height;
resultBlock.animate({
transform: ['translateY(0%)','translateY('+-listHeight+'px)']
}, 500);
};
});
function countTotal() {
//calculate sums then display them in the DOM
var arrayHT = document.querySelectorAll('#addHT');
var countHT = 0;
for (var i=0 ; i<arrayHT.length ; i++) {
countHT+=parseFloat(arrayHT[i].innerHTML);
};
var arrayTTC = document.querySelectorAll('#addTTC');
var countTTC = 0;
for (var i=0 ; i<arrayTTC.length ; i++) {
countTTC+=parseFloat(arrayTTC[i].innerHTML);
};
document.getElementById('totalHT').value = Math.round(countHT*100)/100;
document.getElementById('totalTTC').value =Math.round(countTTC*100)/100;
};
//reinitialise input fields to default value
function reinitialiseInput() {
document.getElementById('nom').value ='';
document.getElementById('qte').value ='';
document.getElementById('prix').value ='';
};
//calculate and add new entry to DOM
btnNew.addEventListener('click', function(){
//create basic values
var VATrate = document.getElementById('txTVA').value;
var entryName = document.getElementById('nom').value;
var quantity = document.getElementById('qte').value;
var price = document.getElementById('prix').value;
var sumHT = price*quantity;
var VAT = (VATrate/100)*sumHT;
var sumTTC = sumHT+VAT;
//create html elements and assign them a value
var elementName = document.createElement('p');
elementName.innerHTML = entryName;
var elementUnitPrice = document.createElement('p');
elementUnitPrice.innerHTML= price;
var elementQuantity = document.createElement('p');
elementQuantity.innerHTML = quantity;
var elementVATrate = document.createElement('p');
elementVATrate.innerHTML = VATrate+'%';
var elementVAT = document.createElement('p');
elementVAT.innerHTML = VAT.toFixed(2);
var elementSumHT = document.createElement('p');
elementSumHT.innerHTML = sumHT;
elementSumHT.id ="addHT";
var elementSumTTC = document.createElement('p');
elementSumTTC.innerHTML = sumTTC;
elementSumTTC.id ="addTTC";
var btnDelete = document.createElement('button');
btnDelete.innerHTML = 'Effacer';
btnDelete.classList.add('btn', 'btn-danger');
btnDelete.id = "deleteBtn";
var newRow = document.createElement('div');
newRow.classList.add('row', 'list-row');
//put all elements in array
var elementArray = [elementName,elementUnitPrice,elementQuantity,elementVATrate,elementVAT,elementSumHT,elementSumTTC,btnDelete];
//loop this array to add a class to each element, then add them into a row
for (var i=0 ; i<elementArray.length ; i++) {
elementArray[i].classList.add('list-element');
newRow.appendChild(elementArray[i]);
};
//add new row to the list
list.appendChild(newRow);
//animation when adding a new row with list openned
var rowHeight = newRow.getBoundingClientRect().height;
if (list.classList.contains('animate-down')){
newRow.animate({
opacity: [ 0, 1 ],
transform: [ 'translateY(-100%)','translateY(0%)' ]
}, 500);
resultBlock.animate({
transform: ['translateY('+-rowHeight+'px)','translateY(0%)']
}, 500);
} ;
//reinitialise inputs and calculate sums
reinitialiseInput()
countTotal();
//delete row + animation
btnArray.push(btnDelete);
(function(){
btnArray[btnArray.length-1].addEventListener('click',function(){
var thisRow = this.parentNode;
var thisRowHeight = thisRow.getBoundingClientRect().height;
thisRow.animate({
opacity: [ 1, 0 ],
transform: [ 'translateY(0%)','translateY(-100%)' ]
}, 500);
setTimeout(function(){
thisRow.parentNode.removeChild(thisRow);
},500);
resultBlock.animate({
transform: ['translateY(0%)','translateY('+(-thisRowHeight)*0.75+'px)']
}, 500);
setTimeout(function(){
countTotal();
},500);
});
}());
});
});
.container{
display: flex;
flex-flow: column nowrap;
}
.section {
margin-top: 0.5em;
margin-bottom: 0.5em;
}
.section:not(.section1):not(.section4){
display:flex;
flex-flow: row nowrap;
}
.section2 {align-items: baseline;}
.section3 {
justify-content: space-between;
align-items: flex-end;
}
.section3 div {flex-grow: 1;}
.section3 button {flex-grow: 6;}
.section4 {flex-flow: column nowrap;}
.section5, .section6 {justify-content: flex-end;}
.section1, .section2, .section4 {justify-content: flex-start;}
input{
border: 1px solid #d3d3d3;
text-align: right;
}
.list-container {
overflow: hidden;
}
.list-row{
display: flex;
flex-flow: row nowrap;
margin-bottom: 0.5em;
overflow: hidden;
}
.list-element {
width:12.5%;
}
.hide {
display: none;
}
<!DOCTYPE html>
<html>
<head>
<title>Cacul TVA</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6 section section1">
<h1>Calcul de TVA</h1>
<p>Entrez vos dépenses hors-taxe ci-dessous afin d'obtenir le total HT et le total TTC.</p>
</div>
</div>
<div class="row">
<div class="col-md-8 section section2">
<p>Taux de TVA:</p>
<input type="number" value="20" id="txTVA">
<p>%</p>
</div>
</div>
<div class="row">
<div class="col-md-8 section section3">
<div class="input_block">
<p>Nom</p>
<input type="text" id="nom">
</div>
<div class="input_block">
<p>Quantité</p>
<input type="number" id="qte">
</div>
<div class="input_block">
<p>Prix</p>
<input type="number" id="prix">
</div>
<button class="btn btn-primary" id="newEntry">Entrée</button>
</div>
</div>
<div class="row ">
<div class="col-md-8 section section4">
<h4 id="showListe">Détails<span class="caret"></span></h4>
</div>
</div>
<div class="row list-container">
<div class="col-md-8 section section4 animate animate-up" id="liste">
<div class="row list-row">
<h5 class="list-element">Nom</h5>
<h5 class="list-element">Prix Unitaire</h5>
<h5 class="list-element">Quantité</h5>
<h5 class="list-element">Taux TVA</h5>
<h5 class="list-element">TVA</h5>
<h5 class="list-element">Somme HT</h5>
<h5 class="list-element">Somme TTC</h5>
<h5></h5>
</div>
<hr>
</div>
</div>
<div id="resultats">
<div class="row">
<div class="col-md-8 section section5">
<h4>Total HT:</h4>
<input type="number" name="" placeholder="0" id="totalHT" readonly="true">
</div>
</div>
<div class="row">
<div class="col-md-8 section section6">
<h4>Total TTC:</h4>
<input type="number" name="" placeholder="0" id="totalTTC" readonly="true">
</div>
</div>
<hr>
</div>
</div>
<script type="text/javascript" src="script.js"></script>
</body>
</html>
1 Answer 1
A lot of your code is concerned with handling the animations. There are a number of ways to get animations with less work (and code) involved.
bootstrap collapse
Since you're already using bootstrap, an easy way to show/hide the Details section might be to use a bootstrap collapse.
CSS3 transitions
If you need more control over the animations (and what you animate) and if you can use CSS3 in your project, you might want to consider using CSS3 transitions for animating the collapsible content.
$('#toggle').click(function() {
$('#the-list').toggleClass('collapsed');
});
ul {
transition: all 0.5s ease-in-out;
max-height: 100vh;
}
ul.collapsed {
max-height: 0;
opacity: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="toggle">toggle list</button>
<ul id="the-list" class="collapsed">
<li>This is a list item</li>
<li>This is a list item</li>
<li>This is a list item</li>
<li>This is a list item</li>
<li>This is a list item</li>
</ul>
<p>some more content here</p>
Explore related questions
See similar questions with these tags.
Nom
,Quantité
andPrix
equal0,99
, andTaux de TVA
equal12%
, result is1,1088
and as suchTotal TTC
should read1,11
, while it reads1,10
. When talking money and such, always operate on cents (more generally, smallest indivisible unit). Flaws like that has been used in the past to steal relatively large amounts. \$\endgroup\$