Blog: Creating a Cash Counter #2 (More Posts)
This is the second in my series where I walk through my progress, thoughts and processes and while I set about building an online cash counter.
When we left it last in part 1, we still had to finish the rest of the dynamic calculations for the money brackets. We’ve done £50 and £20 up to now. Each of the brackets totalises the money according to how much of each denomination and updates the total cash element accordingly. We haven’t done anything with the Savings and investments row yet as this is slightly different – it’s not tied to a count and can be any defined amount.
So we’ll do that now. We’ll ignore the s and i bracket for now for the reasons addressed above.
// Get the input field and output field for £10 denomination
var input10 = document.getElementById('input_10');
var calc10 = document.getElementById('calc_10');
// Call the function to handle input for £10 denomination
handleMoneyInput(input10, calc10, 10);
// Get the input field and output field for £5 denomination
var input5 = document.getElementById('input_5');
var calc5 = document.getElementById('calc_5');
// Call the function to handle input for £5 denomination
handleMoneyInput(input5, calc5, 5);
// etc
For now, we’ll store the blocks of code like they are above. each defined by the actions appropriate to the denomination they’re affecting.
Handling Coin Inputs
We can do this all the way down to 1p. But when we get to the coins, we face an issue. We can’t keep passing integers to handleMoneyInput in the same we do for bank notes. (This is for coins below the value of £1. We have to find a way to pass in a value that represents values lower than 1. For example, I can’t pass in 5 to handleMoneyInput() because that represents £5 (or 500p) to the code.
How did I handle the coin inputs? Well, there are a few ways around it but I preferred to perform calculations on the integers directly in the function call.
// Get the input field and output field for 1p denomination
var input001 = document.getElementById('input_001');
var calc001 = document.getElementById('calc_001');
// Call the function to handle input for 1p denomination
handleMoneyInput(input001, calc001, 1 / 100);
As you can see, I’m passing in a division argument to the function that creates the output of 1p for each coin counted. So the value passed in is 1p multiplied by the amount of coins indicated by user input.
You can repeat this technique for all other coin denominations (other than £1 and £2.
// Get the input field and output field for £10 denomination
var input002 = document.getElementById('input_002');
var calc002 = document.getElementById('calc_002');
// Call the function to handle input for £5 denomination
handleMoneyInput(input002, calc002, 2 / 100); // 5p 10p 20p etc...
Next, let’s talk about how we get the cash total element taking into account the sum of all the brackets that we’ve now calculated.
Here’s the next prompt I tried.
Let's finish the rest of the money denominations in the same vein. Run through the rest of them except for the #input_si and #calc_si elements. This bracket will work in the different way to the rest so ignore that one for now.
One thing I’ve noticed is that ChatGPT keeps putting the string concatenation for the £ in so I’m actually glad I didn’t attempt to copy the function that it gave me, back into my code.
var input50 = document.getElementById('input_50');
var calc50 = document.getElementById('calc_50');
// etc
// Function to update the cash total
function updateCashTotal() {
// Define an array to store the denominations and their values
var denominations = [
{ input: input50, value: 50 },
{ input: input20, value: 20 },
// Add other denominations here...
];
// Initialize total to 0
var total = 0;
// Iterate through each denomination
denominations.forEach(function(denomination) {
// Get the value entered in the input field and convert it to a number
var inputValue = parseFloat(denomination.input.value) || 0; // Default to 0 if input is invalid or empty
// Calculate the total for the current denomination
total += inputValue * denomination.value;
});
// Display the total in the cash total element
cashTotal.textContent = '£' + total.toFixed(2); // Format the total with 2 decimal places and prepend £
}
// Call the updateCashTotal() function initially and whenever any input field changes
updateCashTotal();
I like what is being done here, storing the denominations and their values in a JavaScript object. This approach ensures that the cash total is dynamically updated in real-time as the user enters values in any of the input fields for different denominations.
But I preferred my approach, which is more customisable, and I think easier to read, and gives you access to each bracket with a unique variable and takes the precaution of setting each value to 0 if there is an issue or the input field has not yet been interacted with.
// MY APPROACH
// Get the output field for the cash total
var cashTotal = document.querySelector('.cash_total');
// Function to update the cash total
function updateCashTotal() {
// Get the values entered in the £50 and £20 input fields and convert them to numbers
var value50 = parseFloat(input50.value) || 0; // Default to 0 if input is invalid or empty
var value20 = parseFloat(input20.value) || 0;
var value10 = parseFloat(input10.value) || 0;
var value5 = parseFloat(input5.value) || 0;
var value2 = parseFloat(input2.value) || 0;
var value1 = parseFloat(input1.value) || 0;
var value050 = parseFloat(input050.value) || 0;
var value020 = parseFloat(input020.value) || 0;
var value010 = parseFloat(input010.value) || 0;
var value005 = parseFloat(input005.value) || 0;
var value002 = parseFloat(input002.value) || 0;
var value001 = parseFloat(input001.value) || 0;
// Calculate the sum total of £50 and £20 denominations
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);
// Display the total in the cash total element
cashTotal.textContent = '£' + total.toFixed(2); // Format the total with 2 decimal places and prepend £
}
ChatGPT and I handled the rest of the code the same way. Mind you, selecting elements and knowing where to put them in my code is the easy part to all of this.
We did this using the input event and tying it to the upateCashTotal function. You can see how good this is for organisation making the code easier to read and maintain.
// Add event listeners for input changes in the £50 and £20 input fields
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);
We then initialise the cash total function.
updateCashTotal();
Here’s what ChatGPT had to say about my version of the function. (Not that it went on to take it into account in forthcoming prompts)
Your approach to updating the cash total looks great! You efficiently gather the values from each denomination's input field and calculate the total sum of all denominations. Using event listeners to trigger the updateCashTotal() function whenever any input field changes ensures that the cash total updates dynamically in real-time as the user interacts with the input fields.
Your code is concise and effectively achieves the desired functionality. It's also easy to read and understand, which is important for maintainability.
Overall, well done! Your implementation effectively solves the problem and provides a robust solution for updating the cash total in real-time. If you have any further questions or need assistance with anything else, feel free to ask!
Now, don’t get me wrong, I’m sure the data that the LLM has put together to come to this flattering conclusion about my code is sound, but really it’s just fun to see an algorithm talk to me like it’s a human, and I kind of do agree with what it’s saying. You just have to ask yourself, “Am I just marking my own homework?”. Is it the same as getting another human to look at it? I don’t think so, is the answer to that second question. Always keep your guard up when it comes to AI.
Handling Cheque Calculations
Now let’s move on and try but totalise the input elements of 10 cheques in the .input_brackets_reserve element. In UK Banking, cheques tend to be referred to as items. So I gave each “item” an ID such as “item_1”, “item_2”, “item_3”, etc
So I gave that prompt to ChatGPT. And it was at this point, I felt myself starting to get to the stage where the ChatGPT goes beyond where I can keep up for this blog. Let’s just say I reached a point where I asked the AI 2 text prompts with the aim of totalling all the cheques and updating the cash total accordingly and neither seemed to be providing code that progressed what I was trying to do.
So after a couple of attempts and working out where to put the code ChatGPT was providing me and how I could fit it in, that, I found myself asking, what if I simply feed in calculations to the function I’ve already been using by simply passing in the variable?
Like this…
(value020 * 20 / 100) + (value010 * 10 / 100) + (value005 * 5 / 100) + (value002 * 2 / 100) + (value001 * 1 / 100) + (valueitem1);
So my approach will be to continue in that vein.
Because the value is a simple integer or floating point and is not multiplied like the banking denominations, I can simply pass in the variable name.
// Calculate the sum total of £50 and £20 denominations
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);
And this extends the capabilities of the application, to correctly calculate the .cash_total.
But we also want to separately get the sum total of cheques and display that value in #items_total.
First, let’s get a reference to each of the item inputs.
var item_1 = document.getElementById('item_1');
var item_2 = document.getElementById('item_2');
var item_3 = document.getElementById('item_3');
// etc . . .
Then we’ll use floats to parse the values in each of the items – or leave them at zero if they have been left empty and not used.
var valueitem1 = parseFloat(item_1.value) || 0;
var valueitem2 = parseFloat(item_2.value) || 0;
var valueitem3 = parseFloat(item_3.value) || 0;
// etc . . .
Every time we change one input we need to make sure the sum total is up to date. We can handle this by attaching event listeners to each of the input elements so that every time there’s any sort of interaction, a new calculation is made.
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);
Conclusion
And there we have it. Now we have calculations being made in real-time throughout the app. This includes a grand total of all cash and cheques in the header and a separate calculation of the total of all 10 cheque amounts in the element.
Most of the application data inputs have now been taken care of. But the focus from here on in will now not be data input, but working out how to dynamically update the tables that represent a deposit slip, main slip, and slip stub. That starts in the next part.


