I've dynamically created rows in a table using javascript that I've altered to suit my needs, within this dynamically created table i want to multiply Qty with price and put that in the total box,
html
<table>
<tbody id="plateVolumes">
<tr>
<td><input type="checkbox" value="None" id="chk" name="chk[]" /></div></td>
<td><input type='text' name='qty' id='qty' class="qty" placeholder='Qty' /></td>
<td><select name="productdescription[]" class="productdescription" id="productdescription">
<option value="Product">Product</option>
<option value="Product01" label="Product01">Product01</option>
<option value="Product02" label="Product02">Product02</option>
<option value="Product03" label="Product03">Product03</option>
<option value="Product04" label="Product04">Product04</option>
<option value="Product05" label="Product05">Product05</option>
<option value="Product06" label="Product06">Product06</option>
</select></td>
<td><input type='text' name='price[]' id='price' class="price" placeholder='Price (£)' onChange="WO()" /></td>
<td><input type='text' name='totalprice[]' id='totalprice' class="price" placeholder='Total Price (£)' /></td>
</tr>
</tbody>
</table>
I am using this javascript code in order to add the values together but this will only work with the first line that isn't created by the code:
javascript
<script>
function WO() {
var qty = document.getElementById('qty').value;
var price = document.getElementById('price').value;
answer = (Number(qty) * Number(price)).toFixed(2);
document.getElementById('totalprice').value = answer;
}
</script>
I'm pretty new with javascript so I'm wondering if there is a way to apply this to the dynamic rows also but keep them separate for when I pass them over to my php mailer.
EDIT: I've been playing with the code and I'm a bit closer to getting the answer I need but I still don't know how to make this give me the answers that I want,
function WO() {
for (var i = 0; i < rowCount; i++) {
var qty = document.getElementsByClassName('qty').value;
var price = document.getElementsByClassName('price').value;
var answer = (Number(qty) * Number(price)).toFixed(2);
document.getElementsByClassName('totalprice[' + i + ']').innerHTML = answer;
}
}
this helped, I've asked a friend who's created this, just thought I'd add it in case anyone else wondered
function WO() {
var tbody = document.getElementById("plateVolumes");
for(var i = 0; i < tbody.rows.length; i++) {
var row = tbody.rows[i];
var qty = row.cells[1].childNodes[0].value;
var price = row.cells[3].childNodes[0].value;
var answer = (Number(qty) * Number(price)).toFixed(2);
row.cells[4].childNodes[0].value = answer;
}
}
In an HTML id should be unique. When you get element by id it always returns the first element it gets.
I would suggest to use class in stead. Run loop for rows and calculate total.
this will be a closer solution... I have not tested though.
var trNodes = document.getElementById('plateVolumes').childNodes;
for(var i=0; i < trNodes.length; i++) {
var qty = trNodes[i].getElementsByClassName('qty').value;
var price = trNodes[i].getElementsByClassName('price').value;
var answer = (Number(qty) * Number(price)).toFixed(2);
trNodes[i].getElementsByClassName('totalprice').innerHTML = answer;
}
reference
Related
I have a table, which has an input at the end of each line.
Here is the input:
<td><input data-price='<?= floatval($row['Prix']); ?>' ?>' type="number" name="quantity" id="quantity"></td>
I have a script that takes the price of the data-price in the input and multiplies
it with the number in the input. Right now my script starts off by adding all of the prices, but then it multiplies the total by only the first input in my table.
How can I change my code so that it multiplies each price by the quantity in the input?
Here is the script:
document.getElementById("submit").onclick = function giveTotal() {
var total = 0;
var grandTotal = document.getElementById('grandTotal');
var quantity = document.getElementById('quantity');
var nodes = document.getElementsByName('quantity');
[].forEach.call(nodes, function(node) {
console.log(quantity.value);
console.log(node.dataset.price);
total += (parseFloat(node.dataset.price) * quantity.value)
})
grandTotal.innerHTML = total;
console.log('Total: ' + total);
};
IDs are unique -- no two elements can have the same ID. When you use document.getElementById(), it will return only the first element that matches that ID and no other.
You already have access to each input from your nodes variable, and you're already iterating over them in your forEach loop. So instead of multiplying by quantity.value, you should just be multiplying by node.value so that you're using the value of each specific input.
You need to select each table row by itself like this:
(In this example I assume your table has the id orders)
document.getElementById("submit").onclick = function giveTotal() {
// Get the table element (id="orders")
const $table = document.getElementById('orders');
// Get the grand total element
const $grandTotal = document.getElementById('grandTotal');
// Temporary variable
let total = 0;
// For each input element in the table add the price*value to total
table.querySelectorAll('input').forEach($input => {
total += (parseFloat($input.dataset.price) * $input.value)
});
// Write total to $grandTotal element
$grandTotal.innerText = total;
// Debug output
console.log('Total: ' + total);
};
You can get table rows and process them. Something like this.
document.getElementById('submit').onclick = function() {
var total = Array.from(document.querySelector('#cart tbody')
.querySelectorAll('tr')) //get array
.reduce((acc, cur) => acc + cur.querySelector('td:first-child').innerText * cur.querySelector('input').value, 0);
console.log(total);
};
<table id="cart">
<thead>
<tr>
<th>Price</th>
<th>Qty</th>
</tr>
</thead>
<tbody>
<tr>
<td>5.45</td>
<td><input name="qty" type="text" value="0" />
<!--number is ok too -->
</td>
</tr>
<tr>
<td>7.80</td>
<td><input name="qty" type="text" value="0" />
<!--number is ok too -->
</td>
</tr>
<tr>
<td>0.95</td>
<td><input name="qty" type="text" value="0" />
<!--number is ok too -->
</td>
</tr>
</tbody>
</table>
<button type="button" id="submit">Submit</button>
I have a simple add function in my table.
I would like to post the name of each uploaded file on the table, but it seems like it's only working on the first 2 rows due to my var i = 0; is not working properly.
Here is my code:
<table id='datarows'>
<tr>
<td>Upload</td><td>Filename</td>
</tr>
<tr>
<td><input type="file" id="ProductImage" name="ProductImage0" onchange="getFileData(this);"/></td>
<td><input id="filename" name="filename0" type="text" /></td>
</tr>
</table>
ADD NEW PRODUCT<br />
<script>
var i = 0;
function addProduct() {
var str = '<tr><td><input type="file" id="ProductImage'+i+'"
name="ProductImage'+i+'" onchange="getFileData2(this);" /></td>'
str = str + '<td ><input id="filename'+i+'" name="filename'+i+'" type="text"
/></td></tr>';
$('#datterrows').append(str);
}
//----- Upload picture/file and add name table 1
function getFileData(myFile) {
var file = document.getElementById("ProductImage").value;
var msg = document.getElementById("filename");
msg.value = "test"+file;
}
//----- Upload picture/file and add name table 2
function getFileData2(myFile) {
var file = document.getElementById("ProductImage"+i).value;
var msg = document.getElementById("filename"+i);
msg.value = "test" + file;
}
</script>
I don't get any errors but all I see is the my input id keeps repeating it self to be productimage0 and not continuing for each element I add.
I hope someone can help, it's been pain in the a**
I have a table that makes automatically 2 calculations:
Calculation of numbers of days after the selection of arrived and departed date from two input date field with calendar, result is stored is field (nbjours)
Multiplication of 3 fields (nbcheveaux * days* price), result is stored ind field (total)
There is a button that when we click on it a new row is added. How can i reproduce the same automatic calculations on the news rows added after click ?
1- my add rows function
window. addRow = function addRow(btn) {
var parentRow = btn.parentNode.parentNode;
var table = parentRow.parentNode;
var tr = document.createElement("tr");
var tdNbC = document.createElement("td");
var tdDateArrive = document.createElement("td");
var tdDateDepart = document.createElement("td");
var tdNbJour = document.createElement("td");
var tdPrix = document.createElement("td");
var tdTotal = document.createElement("td");
var td3 = document.createElement("td");
var inputDateArrive = document.createElement("input");
var inputDateDepart = document.createElement("input");
inputDateArrive.type = "text";
inputDateDepart.type = "text";
inputDateArrive.setAttribute("class", "date");
inputDateDepart.setAttribute("class", "date1");
var inputNbrC = document.createElement("input");
var inputNbrJour = document.createElement("input");
var inputPrix = document.createElement("input");
var inputTotal = document.createElement("input");
var inputButton = document.createElement("button");
inputButton.type = "button";
inputButton.innerHTML = "+";
inputButton.onclick = function(){
addRow(this);
};
tdNbC.appendChild(inputNbrC);
tdDateArrive.appendChild(inputDateArrive);
tdDateDepart.appendChild(inputDateDepart);
tdNbJour.appendChild(inputNbrJour);
tdPrix.appendChild(inputPrix);
tdTotal.appendChild(inputTotal);
td3.appendChild(inputButton);
tr.appendChild(tdNbC);
tr.appendChild(tdDateArrive);
tr.appendChild(tdDateDepart);
tr.appendChild(tdNbJour);
tr.appendChild(tdPrix);
tr.appendChild(tdTotal);
tr.appendChild(td3);
table.appendChild(tr);
$(inputDateDepart).mask("99/99/9999");
$(inputDateArrive).mask("99/99/9999");
}
2- function that calculate numbers of days
$(document).ready(function() {
$('.date1').change(function() {
var start = $('.date').datepicker('getDate');
var end = $('.date1').datepicker('getDate');
if (start<end) {
var days = (end - start)/1000/60/60/24;
$('.days').val(days);
}
else {
alert ("Depated date must be greater that arrived date!");
$('.date').val("");
$('.date1').val("");
$('.days').val("");
}
}); //end change function
}); //end ready
3- Function that operate the multiplication
$('.nbrcevaux,.days,.price').keyup(function() {
var nbrcevaux = parseInt($('.nbrcevaux').val());
var days = parseInt($('.days').val());
var prix = parseInt($('.price').val());
$('.total').val(nbrcevaux * days * prix );
});
4- HTML Table
<table>
<tr>
<td class="centrer">Nbr de chevaux</td>
<td class="centrer">Arrived Date</td>
<td class="center">Departed Date</td>
<td class="centrer">Nb/Days</td>
<td class="centrer">Prix/jr/ cheval/boxe</td>
<td class="centrer"> Total</td>
</tr>
<tr>
<td><input type="text" name="nbrcevaux" class="nbrcevaux" /></td>
<td><input type="text" name="datearrive" class ="date"/> </td>
<td><input type="text" name="datedepart" class ="date1" /></td>
<td><input type="text" name="nbrjours" class ="days" /></td>
<td><input type="text" name="prix" class="price" /></td>
<td><input type="text" name="total" class="total" /></td>
<td><button type="button" onClick ="addRow(this)">+</button> </td>
</tr>
How can i integrate the functions calculate numbers of days and multiplication in the added new row displyed after click ?
So, I was bored and tackled your question, by rewriting it because you had quite a bit of superfluous code.
Your main issue (with the calculations on the added rows) stems from the fact that you were relying on classes to uniquely identify elements, but that won't cut it. Each new row and element within the row needs to have its own unique id.
I also took the liberty of making sure that there will only ever be one "Add row" button, as you'll see.
This working example has comments inline to help follow what's going on.
$(function() {
// Declare & initialize module wide variables to store DOM elements:
var $txtnbrcevaux = $("#nbrcevaux"), $txtDateArrive = $("#dateArrive"),
$txtDepart = $("#datedepart"), $txtnbrjours = $("#nbrjours"), $txtPrix = $("#prix"),
$txtTotal = $("#total"), $btnAdd = $("#btnAddRow"), $masterRow = $("#master1");
// Unique value that will identify new elements
var count = 1;
// Establish the date picker fields
$txtDateArrive.datepicker();
$txtDepart.datepicker();
// Wire up the button's click event:
$btnAdd.on("click", function(){
// Make a copy of the last row
var newTR = $("tr[id=master" + count + "]").clone(true);
// Update the new row's id to be unique
newTR[0].id = "master" + (count + 1);
// Loop through the child elements and modify their id's so that they are unique
newTR.children().each(function(index){
if(this.children.length > 0){
// Wipe out old (copied values)
this.firstChild.value = "";
var oldID = this.firstChild.id;
this.firstChild.id = oldID.substring(0, oldID.length) + (count + 1);
// Cloning datepickers creates problems because the clones remain bound to the
// original input element. Here, we'll create a new input element and then
// insert it where the current one is, then we'll remove the current one:
if($(this.firstChild).is(".date, .date1")){
var newPicker = document.createElement("input");
newPicker.id = this.firstChild.id;
newPicker.name = this.firstChild.name;
newPicker.setAttribute("class", this.firstChild.className.replace(" hasDatepicker", ""));
newPicker.style.width = "80px";
// Set up the new datepicker:
$(newPicker).insertAfter(this.firstChild);
$(this.firstChild).remove();
$(newPicker).datepicker();
}
}
});
// Increment the count so the next row will use the next number for its id's
count++;
// Hide the last row's button
this.style.display = "none";
// Add the new row to the table
$("table").append(newTR);
// Commented due to not having plugin available
// $(inputDateDepart).mask("99/99/9999");
// $(inputDateArrive).mask("99/99/9999");
});
$('.nbrcevaux, .days, .price').on("keyup", function() {
var nbrCevaux = this.parentElement.parentElement.querySelector(".nbrcevaux").value;
var days = this.parentElement.parentElement.querySelector(".days").value;
var prix = this.parentElement.parentElement.querySelector(".price").value;
// Your problem was that you were trying to work with values from
// classes and not specific elements. Changing the function to expect
// the data to be passed to it and having it return the answer allow
// you to control what goes in and where to put what comes out
this.parentElement.parentElement.querySelector(".total").value = nbrCevaux * days * prix;
});
$txtDepart.change(function() {
var start = $txtDateArrive.datepicker('getDate');
var end = $txtDepart.datepicker('getDate');
if (start < end) {
var days = (end - start)/1000/60/60/24;
$txtnbrjours.val(days);
} else {
alert ("Depated date must be greater that arrived date!");
$txtDateArrive.val("");
$txtDepart.val("");
$txtnbrjours.val("");
}
}); //end change function
}); //end ready
/* This is only added to shrink things down so they appear within the space allotted */
input[type=text] {width:80px;}
body {font-size:.5em;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://code.jquery.com/ui/1.11.3/jquery-ui.min.js"></script>
<table>
<tr>
<td class="centrer">Nbr de chevaux</td>
<td class="centrer">Arrived Date</td>
<td class="center">Departed Date</td>
<td class="centrer">Nb/Days</td>
<td class="centrer">Prix/jr/ cheval/boxe</td>
<td class="centrer"> Total</td>
</tr>
<tr id="master1">
<td><input type="text" id="nbrcevaux" name="nbrcevaux" class="nbrcevaux"></td>
<td><input type="text" id="dateArrive" name="dateArrive" class ="date"></td>
<td><input type="text" id="datedepart" name="dateDepart" class ="date1"></td>
<td><input type="text" id="nbrjours" name="nbrjours" class ="days"></td>
<td><input type="text" id="prix" name="prix" class="price"></td>
<td><input type="text" id="total" name="total" class="total"></td>
<td><button type="button" id="btnAddRow">+</button> </td>
</tr>
</table>
I have a form to add users to a select list from 2 textboxes (Last name and First name).
When I click on the "+" button, it adds an option with the last name and first name specified to the select element below. Right now, it adds the option with only one white space between last and first name, but I would like the first name to be aligned with the above "First name" textbox.
Here's a fiddle with my sample code: http://jsfiddle.net/fx37j71s/12/
<table>
<tr>
<td>Last Name</td>
<td>First Name</td>
</tr>
<tr>
<td><input type="text" id="txtlastname" /></td>
<td><input type="text" id="txtfirstname" /></td>
<td><input type="button" value="+" onclick="addemployee();" /></td>
</tr>
<tr>
<td colspan="2"><select id="lbxname" size="5" style="width:500px"></select></td>
<td valign="top"><input type="button" value="-"onclick="removeemployee();" /></td>
</tr>
</table>
And the addemployee() function:
function addemployee()
{
var lastname = document.getElementById('txtlastname');
var firstname = document.getElementById('txtfirstname');
var select = document.getElementById('lbxname');
var option = document.createElement('option');
var text = document.createTextNode(lastname.value + ' ' + firstname.value);
option.appendChild(text);
select.appendChild(option);
}
Is there a way to achieve this in JS or jquery or maybe CSS? I have tried to add a fixed amount of spaces minus the amount of characters in Last name, but the actual width of the string depends on the characters (i.e. "PPPPP" is wider than "lllll" even though they both have 5 characters). I also found the "clientWidth" property, but I can't seem to make it work properly.
Thank you :)
Instead of creating textNode can set innerHTML
Something like:
function addemployee()
{
var lastname = document.getElementById('txtlastname');
var firstname = document.getElementById('txtfirstname');
var select = document.getElementById('lbxname');
var option = document.createElement('option');
option.innerHTML = padStr(lastname.value) + firstname.value;
select.appendChild(option);
}
function padStr(str){
while(str.length < 500){
str += ' ';
}
return str
}
DEMO
Based on charlietfl's answer and Evilzebra's comment, this worked for me:
Updated fiddle: http://jsfiddle.net/vcfpd450/2/
function addemployee()
{
var lastname = document.getElementById('txtlastname');
var firstname = document.getElementById('txtfirstname');
var select = document.getElementById('lbxname');
var option = document.createElement('option');
option.innerHTML=padStr(lastname.value) + firstname.value;
select.appendChild(option);
}
function padStr(str){
var x = str.length;
while(x < 31){
str+=' ';
++x;
}
return str;
}
CSS:
#lbxname
{
font-family: monospace;
}
Basically, I add spaces to the string until I reach the desired width (31 in this case). Using a monospace font-family makes sure the width is consistent with the number of characters.
I have prepared this jsfiddle
The problem is that I have many rows containing product qty * price = sub total
This also must dynamically calculate grand total for all sub total amounts. And the biggest problem is the trigger since we may not have change trigger on the qty select fields.. really complicated for me.
I am so far stacked here:
$(document).ready(function() {
var qty=$('.qty').val();
var price = $('.price').val();
var sum = 0;
$('.amount').each(function() {
sum += parseFloat($(this).text());
});
});
Please give me idea for:
Which trigger to use so it can calculate on page load as well and if qty dropdown is changed too.
How to calculate each row first
thank you for your help and time in advance!
You have your answer here: http://jsfiddle.net/kY98p/10/
I changed the html to use the tags thead and tfoot for header and footer
Its just a cycle over the lines where you get the quantity and price and update the amount...
Here is the function that you should call:
function update_amounts()
{
var sum = 0.0;
$('#myTable > tbody > tr').each(function() {
var qty = $(this).find('option:selected').val();
var price = $(this).find('.price').val();
var amount = (qty*price)
sum+=amount;
$(this).find('.amount').text(''+amount);
});
//just update the total to sum
$('.total').text(sum);
}
And the event that you need is:
$('.qty').change(function() {
update_amounts();
});
UPDATE: jsfiddle with total: http://jsfiddle.net/kY98p/11/
Fiddle Demo
$(document).ready(function () {
var amt = $('.amount:gt(0)'), //select element with class greater than one
tot = $('#total'); // cache selectors
function calculator() {
amt.text(function () { // set text of class amount elements
var tr = $(this).closest('tr'); // get tr
var qty = tr.find('.qty').val(); // find it in current tr and get value of element with class qty
var price = tr.find('.price').val(); //get price
return parseFloat(qty) * parseFloat(price); // return product
});
tot.text(function () { //get total
var sum = 0; //set sum = 0
amt.each(function () { //run through all element with class amount
sum += parseFloat($(this).text()); // add text to sum
});
return sum; //set sum to total
});
}
calculator(); //call the above function
$('.qty,.price').change(calculator);// run calculator function when element with class qty or price is changed
});
You can try this one (I changed your html template). Solution work as you want:
1. Calculate each row (find closest input and get data from it)
2. Calculate total and put to span
3. If you will add more selected(with my work class) it will be work
$(".work").on("change", function(){
var total = 0;
$(".work").each(function(){
var val = $(this).closest("tr").find("input[type='text']").val();
total = total + ($(this).val()*val || 0);
});
$(".total").text(total);
});
And html
<table>
<tbody>
<tr>
<th>Product name</th>
<th>Qty</th>
<th>Price</th>
<th align="center"><span id="amount" class="amount">Amount</span></th>
</tr>
<tr>
<td>Product 1</td>
<td>
<select value="" class="qty work" name="qty">
<option value="1">1</option>
<option value="2">2</option>
</select>
</td>
<td><input type="text" value="11.60" class="price"></td>
<td align="center"><span id="amount" class="amount">0</span> eur</td></tr>
<tr>
<td>Product 2</td><td>
<select value="" class="qty work" name="qty">
<option value="1">1</option>
<option value="2">2</option>
</select>
</td>
<td><input type="text" value="15.26" class="price"></td>
<td align="center"><span id="amount" class="amount">0</span> eur</td></tr>
<tr>
<td colspan="2"></td>
<td align="right"><span id="total" class="total">TOTAL</span> </td>
</tr>
</tbody>
</table>
And work demo
Here is a solution that works in with your fiddle (http://jsfiddle.net/kY98p/20/) with one minor DOM update. I put the header of the table in a THEAD so that you can count on the TBODY TR rows to be those with data.
Here we have functions to compute the total of each row and of the whole table.
When you change a row, we recompute that row and then re compute the total.
When we load the page, we recompute everything.
$(document).ready(function () {
function computeRowTotal(row) {
var $row = $(row)
var qty = $row.find('.qty').val();
var price = $row.find('.price').val();
if (qty && price) {
$row.find('.amount').html(qty * price);
}
}
function computeTotal() {
var total = 0.0
$('tbody tr .amount').each(function () {
console.log('T', $(this).text());
total += parseFloat($(this).text());
})
$('tbody tr .total').html("Total: " + total);
}
function updateTable() {
$('tbody tr').each(function (row) {
computeRowTotal(this)
});
computeTotal(this)
};
$('select').bind('change', function () {
computeRowTotal($(this).closest('tr'));
computeTotal();
});
updateTable();
});