Blog: Creating a Cash Counter #5 (More Posts)
First, we’re going to work on tidying up the script. Because we have everything we need to get the application working with 400 lines of code. But it can be a lot easier to read and maintain
// Function to handle input event for money denomination
function handleMoneyInput(inputField, outputField, denomination) {
inputField.addEventListener('input', function() {
// we handle the coin input calculations here. This is where
// that internal logic goes.
}
}
Below this function, we have several blocks of code reached grouped together for each money input. (1 for £50, one for £20 etc).
// Get the input field and output field for £50 denomination
var input50 = document.getElementById('input_50');
var calc50 = document.getElementById('calc_50');
// Call the function to handle input for £50 denomination
handleMoneyInput(input50, calc50, 50);
But this can be organised in a much better way; one that is readable and reduces the lines of code used. Below is a better way or organising the lines of code; now organised by task, (i.e. for the input selections, the calculated elements and the function calls.
// Get the input field and output field for £50 denomination
var input50 = document.getElementById('input_50');
/*
var input20 = document.getElementById('input_20');
// more inputs
*/
var calc50 = document.getElementById('calc_50');
/*
var calc20 = document.getElementById('calc_20');
// more inputs
*/
// Call the function to handle input for £50 denomination
handleMoneyInput(input50, calc50, 50);
handleMoneyInput(input20, calc20, 20);
handleMoneyInput(input10, calc10, 10);
/* More function calls.... */
Using this code structure I’ve managed to slash the number of lines in the script by at least 30.
An important part of code cleanup is looking for lines of code that are redundant or no longer needed. Sometimes you’ll write a variable that for whatever reason you no longer need and forgot to remove.
// Get the output field for the cash total
var cashTotal = document.querySelector('.cash_total');
You should also remove any commented code that doesn’t already affect the running of your application.
/* var coinInputs = document.querySelectorAll('.coins_container');
coinInputs.forEach(function(coinInput) {
var coinValue = parseFloat(coinInput.value) || 0;
totalCoins += coinValue;
}); */
The bones of the application is the updateCashTotal() function. Everything that makes the application perform is in it. It is called by event listeners rather than a standard function call. So I can remove any reference to the function that is not included in an event listener.
// Add event listeners for Input number fields - inputs all cash denominations
input50.addEventListener('input', updateCashTotal);
input20.addEventListener('input', updateCashTotal);
// more....
// remove function call
updateCashTotal();
We don’t actually need to explicitly call the function. So I’ll remove that from the code.
// Initialize the cash total when the page loads
//updateCashTotal();
Doing that provides a good opportunity to examine the function itself.
function updateCashTotal {
}
With such a large function, it’s easy for code to get lost in a huge mess. It’s like trying to untangle a big web of wires. So we’re going to try and into easier chunks. First, let’s examine some of the global variables and see how they relate to the script.
var total = ...
var totalItems = 0;
var totalCoins = 0;
var totalCash = 0;
var coinsTotal = 0;
These variable names, while serving me well in making this application are too vague and similar to each other. So below, I’ll look at each variable in turn and outline what they do.
total – This calculation defines the main application logic. It calculates the sum total of all cash and cheque brackets by adding together all the elements; multiplying by the cash amount in turn.
var total =
(value50 * 50) + (value20 * 20) + (value10 * 10) + (value5 * 5)
+ (value2 * 2) + (value1 * 1) + (value050 * 50 / 100) + (value020 * 20 / 100)
+ (value010 * 10 / 100) + (value005 * 5 / 100) + (value002 * 2 / 100) + (value001 * 1 / 100)
+ (valueitem1) + (valueitem2) + (valueitem3) + (valueitem4)
+ (valueitem5) + (valueitem6) + (valueitem7) + (valueitem8)
+ (valueitem9) + (valueitem10);
totalItems – This variable is used to track the total value of all 10 cheques. It remains at zero if none of them are used.
var totalItems = 0;
var itemInputs = document.querySelectorAll('.money_bracket_reverse');
itemInputs.forEach(function(itemInput) {
var itemValue = parseFloat(itemInput.value) || 0;
totalItems += itemValue;
});
And it is tied into so much of the updateCashTotal function. Without it, we not only can’t add up the cheques, but we can’t get the total sum of the banking slip. I called it totalItems because that is what a cheque is referred to on a banking slip.
cashTotal – performs the same function as totalItems
inputElements.forEach(function(inputElement) {
cashTotal += parseFloat(inputElement.value || 0);
});
But it is also the variable that keeps track of the total bank desposit.
An example of this in action is below.
var cashInputTotalElement = document.getElementById('cash_input_total');
cashInputTotalElement.textContent = cashTotal.toFixed(2);
cashTotal – Again, with this variable we’re getting a sum total of cash in the same way by iterating through all input fields.
var cashTotal = 0;
inputElements.forEach(function(inputElement) {
cashTotal += parseFloat(inputElement.value || 0);
});
totalCash – used to automate the total Cash in the main slip and slip stub.
var mainTotalCashElement = document.getElementById("main_cash");
var stubTotalCashElement = document.getElementById("stub_cash");
mainTotalCashElement.value = totalCash.toFixed(2);
stubTotalCashElement.value = totalCash.toFixed(2);
totalCoins – coinsTotal – Again, one variable is used to track the amounts, and the second is used to place the numbers in the “Main Slip” and “Slip Stub”.
// Update the #main_cash and #stub_
can be removed as it is a duplicate
cash elements with the calculated cash input total
/* var mainTotalCashElement = document.getElementById("main_cash");
var stubTotalCashElement = document.getElementById("stub_cash");
mainTotalCashElement.value = totalCash.toFixed(2);
stubTotalCashElement.value = totalCash.toFixed(2); */
So far the script has shrunk to around 330 lines.
Section of the script set aside for event listeners.
We don’t need this one as it has no effect on any of the calculations so it can be removed.
// Add event listeners to input elements to recalculate the cash total on input change
/* var inputElements = document.querySelectorAll('.input_brackets input[type="text"]');
inputElements.forEach(function(inputElement) {
inputElement.addEventListener('input', updateCashTotal);
}); */
We don’t need this one either.
/* event listeners */
// recalculate coins total on input change.
/* var coinInputs = document.querySelectorAll('.coins_calculation');
coinInputs.forEach(function(input) {
input.addEventListener('input', updateCashTotal);
}); */
It is left to the remaining event listeners to perform the actions that the application requires.
// Add event listeners for Input number fields -
// Calculates all Cash Denominations
input50.addEventListener('input', updateCashTotal);
input20.addEventListener('input', updateCashTotal);
input10.addEventListener('input', updateCashTotal);
input5.addEventListener('input', updateCashTotal);
input2.addEventListener('input', updateCashTotal);
input1.addEventListener('input', updateCashTotal);
input050.addEventListener('input', updateCashTotal);
input020.addEventListener('input', updateCashTotal);
input010.addEventListener('input', updateCashTotal);
input005.addEventListener('input', updateCashTotal);
input002.addEventListener('input', updateCashTotal);
input001.addEventListener('input', updateCashTotal);
// Add event listeners for input changes for the items (cheque) amounts
item_1.addEventListener('input', updateCashTotal);
item_2.addEventListener('input', updateCashTotal);
item_3.addEventListener('input', updateCashTotal);
item_4.addEventListener('input', updateCashTotal);
item_5.addEventListener('input', updateCashTotal);
item_6.addEventListener('input', updateCashTotal);
item_7.addEventListener('input', updateCashTotal);
item_8.addEventListener('input', updateCashTotal);
item_9.addEventListener('input', updateCashTotal);
item_10.addEventListener('input', updateCashTotal);
Those are the things I found that improve the script I first built. What did the AI have to say about how I might improve the script? Here’s one suggestion.
Refactor Total Calculation Logic: The updateCashTotal function currently calculates multiple totals in a single pass. While this works, separating the logic for calculating different totals (e.g., cash total, coin total, item total) into distinct functions could improve readability and maintainability.
So, nothing specific in terms of code but one thing I did latch on to was to update/refactor updateCashTotal. It’s very true that it is currently doing too much for one function.
We can separate what’s in it into 3 distinct functions.
/* function updateCashTotal() {
} */
/* function updateCoinTotal() {
} */
/* function updateChequeTotal() {
} */
The problem with the function as it is at the moment (updateCashTotal) is it ties together so many input types. There’s no way I can organise it without a breaking change. So I’m going to leave the blog there for now and get to work on styling the application. There’s always time to make further improvements to the script later.


