Reputation: 1706
I am new to JavaScript.
Current issues I'm facing:
UPDATE
I have attempted to start it, getting NaN though and its only taking anything with a class="calculate" and adding to sub-total but it's a start I guess. I added qty but does not seem to play ball, vat and total I have not added.
JSFiddle: http://jsfiddle.net/morgjvg6/4/
JS:
$(document).ready(function () {
// copy customer details to shipping
$('input.copy-input').on("change keyup paste", function () {
var thisID = $(this).attr('id');
$('input#' + thisID + "_ship").val($(this).val());
});
// add new product row on invoice
$(".add-row").click(function () {
$("#invoice_table").each(function () {
var tds = '<tr>';
jQuery.each($('tr:last td', this), function (index, element) {
var html = $(this).html().replace(/invoice_product/g, 'invoice_product_' + index)
.replace(/invoice_product_desc/g, 'invoice_product_desc_' + index)
.replace(/invoice_product_qty/g, 'invoice_product_qty_' + index)
.replace(/invoice_product_price/g, 'invoice_product_price_' + index)
.replace(/invoice_product_sub/g, 'invoice_product_sub_' + index);
tds += '<td>' + html + '</td>';
});
tds += '</tr>';
if ($('tbody', this).length > 0) {
$('tbody', this).append(tds);
} else {
$(this).append(tds);
}
});
return false
});
// Adding the change events for the Price and
// quantity fields only..
// Changing the total should not affect anything
calculateTotal();
$('.calculate').on('change keyup paste', function() {
updateTotals(this);
calculateTotal();
});
function updateTotals(elem) {
// This will give the tr of the Element Which was changed
var $container = $(elem).parent().parent();
var quantity = $container.find('.calculate-qty').val();
var price = $container.find('.calculate').val();
var subtotal = parseInt(quantity) * parseFloat(price);
$container.find('.calculate-sub').text(subtotal.toFixed(2));
}
function calculateTotal(){
// This will Itearate thru the subtotals and
// claculate the grandTotal and Quantity here
var lineTotals = $('.calculate-sub');
var grandTotal = 0.0;
var totalQuantity = 0;
$.each(lineTotals, function(i){
grandTotal += parseFloat($(lineTotals[i]).text()) ;
});
$('.invoice-sub-total').text(parseFloat(grandTotal ).toFixed(2) );
}
});
Upvotes: 1
Views: 5556
Reputation: 9157
First, you have to use event delegation for input fields that were created dynamically:
// delegate events on #invoice_table:
$('#invoice_table').on('change keyup paste', '.calculate', function() {
updateTotals(this);
calculateTotal();
});
Next thing is that you used .text()
to update input field:
$container.find('.calculate-sub').text(subtotal.toFixed(2));
while you should use .val()
:
$container.find('.calculate-sub').val(subtotal.toFixed(2));
The same in calculateTotal()
method, where you should also use .val()
.
Next, this part is unnecesary :
$("#invoice_table").each(function () {
since you have only one table (and only one element in DOM can have that id
).
Finaly, I would not use id
attributes, and give array names for input fields. That way you don't have to play with .replace()
and you can easily send all the values to your back-end app as arrays.
Also, I'd clone()
the whole tr
element initially and use it later on, instead of setting loops for each click.
// copy customer details to shipping
$('input.copy-input').on("change keyup paste", function () {
$('input#' + this.id + "_ship").val($(this).val());
});
// add new product row on invoice
var cloned = $('#invoice_table tr:last').clone();
$(".add-row").click(function (e) {
e.preventDefault();
cloned.clone().appendTo('#invoice_table');
});
calculateTotal();
$('#invoice_table').on('change keyup paste', '.calculate', function() {
updateTotals(this);
calculateTotal();
});
function updateTotals(elem) {
var tr = $(elem).closest('tr'),
quantity = $('[name="invoice_product_qty[]"]', tr).val(),
price = $('[name="invoice_product_price[]"]', tr).val(),
percent = $('[name="invoice_product_discount[]"]', tr).val(),
subtotal = parseInt(quantity) * parseFloat(price);
// CALCULATE DISCOUNT PERCENTAGE:
if(percent && $.isNumeric(percent) && percent !== 0){
subtotal = subtotal - ((parseInt(percent) / 100) * subtotal);
}
$('.calculate-sub', tr).val(subtotal.toFixed(2));
}
function calculateTotal(){
var grandTotal = 0.0;
var totalQuantity = 0;
$('.calculate-sub').each(function(){
grandTotal += parseFloat($(this).val()) ;
});
$('.invoice-sub-total').text(parseFloat(grandTotal ).toFixed(2) );
}
JSFiddle (Note, I have removed id
attributes and added []
to the input fields names)
An example of how you could retrieve values sent to PHP
(Each iteration inside loop will be analogue to each tr
):
foreach($_POST['invoice_product'] as $key => $value){
$name = $value;
$qty = $_POST['invoice_product_qty'][$key];
$price = $_POST['invoice_product_price'][$key];
$discount = $_POST['invoice_product_discount'][$key];
// ...
}
Upvotes: 5