The first question is I need help in delete function. I already tried the splice method but I still can't get it. When you click the delete item button, that row must be deleted.
The second question has ii already put the required attribute in the input form but it still submits the form when the field is empty.
var qtyTotal = 0;
var priceTotal = 0;
var products = [];
function addProduct() {
var productID = document.getElementById("productID").value;
var product_desc = document.getElementById("product_desc").value;
var qty = document.getElementById("quantity").value;
// qtyTotal = qtyTotal + parseInt(qty);
//document.getElementById("qtyTotals").innerHTML=qtyTotal;
var price = document.getElementById("price").value;
var newProduct = {
product_id : null,
product_desc : null,
product_qty : 0,
product_price : 0.00,
};
newProduct.product_id = productID;
newProduct.product_desc = product_desc;
newProduct.product_qty = qty;
newProduct.product_price = price;
products.push(newProduct);
//console.log("New Product " + JSON.stringify(newProduct))
//console.log("Products " + JSON.stringify(products))
var html = "<table border='1|1' >";
html+="<td>Product ID</td>";
html+="<td>Product Description</td>";
html+="<td>Quantity</td>";
html+="<td>Price</td>";
html+="<td>Action</td>";
for (var i = 0; i < products.length; i++) {
html+="<tr>";
html+="<td>"+products[i].product_id+"</td>";
html+="<td>"+products[i].product_desc+"</td>";
html+="<td>"+products[i].product_qty+"</td>";
html+="<td>"+products[i].product_price+"</td>";
html+="<td><button type='submit' onClick='deleteProduct();'/>Delete Item</button>   <button type='submit' onClick='addCart();'/>Add to Cart</button></td>";
html+="</tr>";
}
html+="</table>";
document.getElementById("demo").innerHTML = html;
document.getElementById("resetbtn").click()
}
function deleteProduct(product_id) {
for(var i = 0; i < products.length; i++) {
if (products[i].product_id == product_id) {
// DO NOT CHANGE THE 1 HERE
products.splice(i, 1);
}
}
}
<!DOCTYPE html>
<html>
<head>
<title>Shopping Cart Pure Javascript</title>
</head>
<body>
<form name="order" id="order">
<table>
<tr>
<td>
<label for="productID">Product ID:</label>
</td>
<td>
<input id="productID" name="product" type="text" size="28" required/>
</td>
</tr>
<tr>
<td>
<label for="product">Product Desc:</label>
</td>
<td>
<input id="product_desc" name="product" type="text" size="28" required/>
</td>
</tr>
<tr>
<td>
<label for="quantity">Quantity:</label>
</td>
<td>
<input id="quantity" name="quantity" width="196px" required/>
</td>
</tr>
<tr>
<td>
<label for="price">Price:</label>
</td>
<td>
<input id="price" name="price" size="28" required/>
</td>
</tr>
</table>
<input type="reset" name="reset" id="resetbtn" class="resetbtn" value="Reset" />
<input type="button" id="btnAddProduct" onclick="addProduct();" value="Add New Product" >
</form>
<br>
<p id="demo"></p>
</body>
</html>
Firstly, you will have to pass correct product_id to delete function. Also you need to know which element to remove, for this you can send the current element on which click is pressed and then access its parent node to remove it. You can replace your script with following code:
var qtyTotal = 0;
var priceTotal = 0;
var products = [];
function addProduct() {
var productID = document.getElementById("productID").value;
var product_desc = document.getElementById("product_desc").value;
var qty = document.getElementById("quantity").value;
// qtyTotal = qtyTotal + parseInt(qty);
//document.getElementById("qtyTotals").innerHTML=qtyTotal;
var price = document.getElementById("price").value;
var newProduct = {
product_id : null,
product_desc : null,
product_qty : 0,
product_price : 0.00,
};
newProduct.product_id = productID;
newProduct.product_desc = product_desc;
newProduct.product_qty = qty;
newProduct.product_price = price;
products.push(newProduct);
//console.log("New Product " + JSON.stringify(newProduct))
//console.log("Products " + JSON.stringify(products))
var html = "<table id='products-table' border='1|1' >";
html+="<td>Product ID</td>";
html+="<td>Product Description</td>";
html+="<td>Quantity</td>";
html+="<td>Price</td>";
html+="<td>Action</td>";
for (var i = 0; i < products.length; i++) {
html+="<tr>";
html+="<td>"+products[i].product_id+"</td>";
html+="<td>"+products[i].product_desc+"</td>";
html+="<td>"+products[i].product_qty+"</td>";
html+="<td>"+products[i].product_price+"</td>";
html+="<td><button type='submit' onClick='deleteProduct(\""+products[i].product_id +"\", this);'/>Delete Item</button>   <button type='submit' onClick='addCart();'/>Add to Cart</button></td>";
html+="</tr>";
}
html+="</table>";
document.getElementById("demo").innerHTML = html;
document.getElementById("resetbtn").click()
}
function deleteProduct(product_id, e) {
var pTbody = e.parentNode.parentNode.parentNode;
var pTable = pTbody.parentNode;
if((pTbody.children).length === 2)
pTable.parentNode.removeChild(pTable);
else
pTbody.removeChild(e.parentNode.parentNode);
for(var i = 0; i < products.length; i++) {
if (products[i].product_id == product_id) {
// DO NOT CHANGE THE 1 HERE
products.splice(i, 1);
}
}
}
Your main problem is that you're not passing the product id to the delete function, and you are expecting it on it.
Also, you can remove the HTML element itself.
I've done this snippet. I've added the product id as a the id for the row element of the table, so on your delete function you can remove it looking for that id.
Also, if the item to delete is the last on the table, the table will be removed too (I've added an id to the table so you can easily remove it)
var qtyTotal = 0;
var priceTotal = 0;
var products = [];
function addProduct() {
var productID = document.getElementById("productID").value;
var product_desc = document.getElementById("product_desc").value;
var qty = document.getElementById("quantity").value;
// qtyTotal = qtyTotal + parseInt(qty);
//document.getElementById("qtyTotals").innerHTML=qtyTotal;
var price = document.getElementById("price").value;
var newProduct = {
product_id : null,
product_desc : null,
product_qty : 0,
product_price : 0.00,
};
newProduct.product_id = productID;
newProduct.product_desc = product_desc;
newProduct.product_qty = qty;
newProduct.product_price = price;
products.push(newProduct);
//console.log("New Product " + JSON.stringify(newProduct))
//console.log("Products " + JSON.stringify(products))
var html = "<table id='products-table' border='1|1' >";
html+="<td>Product ID</td>";
html+="<td>Product Description</td>";
html+="<td>Quantity</td>";
html+="<td>Price</td>";
html+="<td>Action</td>";
for (var i = 0; i < products.length; i++) {
html+="<tr id='"+products[i].product_id+"'>";
html+="<td>"+products[i].product_id+"</td>";
html+="<td>"+products[i].product_desc+"</td>";
html+="<td>"+products[i].product_qty+"</td>";
html+="<td>"+products[i].product_price+"</td>";
html+="<td><button type='submit' onClick='deleteProduct("+products[i].product_id+");'/>Delete Item</button>   <button type='submit' onClick='addCart();'/>Add to Cart</button></td>";
html+="</tr>";
}
html+="</table>";
document.getElementById("demo").innerHTML = html;
document.getElementById("resetbtn").click()
}
function deleteProduct(product_id) {
for(var i = 0; i < products.length; i++) {
if (products[i].product_id == product_id) {
// DO NOT CHANGE THE 1 HERE
products.splice(i, 1);
var element = document.getElementById(product_id);
var tableElement = document.getElementById('products-table');
if(!products.length)
tableElement.parentNode.removeChild(tableElement);
else
tableElement.removeChild(element);
}
}
}
<!DOCTYPE html>
<html>
<head>
<title>Shopping Cart Pure Javascript</title>
</head>
<body>
<form name="order" id="order">
<table>
<tr>
<td>
<label for="productID">Product ID:</label>
</td>
<td>
<input id="productID" name="product" type="text" size="28" required/>
</td>
</tr>
<tr>
<td>
<label for="product">Product Desc:</label>
</td>
<td>
<input id="product_desc" name="product" type="text" size="28" required/>
</td>
</tr>
<tr>
<td>
<label for="quantity">Quantity:</label>
</td>
<td>
<input id="quantity" name="quantity" width="196px" required/>
</td>
</tr>
<tr>
<td>
<label for="price">Price:</label>
</td>
<td>
<input id="price" name="price" size="28" required/>
</td>
</tr>
</table>
<input type="reset" name="reset" id="resetbtn" class="resetbtn" value="Reset" />
<input type="button" id="btnAddProduct" onclick="addProduct();" value="Add New Product" >
</form>
<br>
<p id="demo"></p>
</body>
</html>
Hope this helps!
The problem is that you are modifying the array of products without actually changing the HTML displayed on the page.
If you added code to delete the specified table element, I believe the problem would be solved.
For instance:
You could attach an id that corresponds to product_id to each table when it's created, and then delete the table with that id.
var remove = document.getElementById(product_id);
remove.parentElement.removeChild(remove);
Your click handler is calling deleteProduct() which will call your function without passing a product_id value as a parameter so your if (products[i].product_id == product_id) will never evaluate to be true.
Try this:
html+="<td><button type='submit' onClick='deleteProduct(\""+products[i].product_id +"\");'/>Delete Item</button> <button type='submit' onClick='addCart();'/>Add to Cart</button></td>";
As far as the required fields make sure you have the type attribute set on all of your inputs and move <p id="demo"></p> inside of your form.
You must change delete button type from submit to button and you must add products[i].product_id paramater for deleteProduct function
html+="<td><button type='button' onClick='deleteProduct("+products[i].product_id+");'/>Delete Item</button>   <button type='submit' onClick='addCart();'/>Add to Cart</button></td>";
Related
I want to get the value of <td> with its id. When I am trying to get the value of <td>by the following code getting a null value.
function deletediv(ele){
var r = $("#row_ #price_"+ele).text();
alert(r);
}
here I am trying to fetch the value in <td>using for loop.
for(var i=0 ; i< data[1].product.length ; i++ ){
var product_name = data[1].product[i].product_name;
var product_code = data[1].product[i].product_code;
var product_price = data[1].product[i].price;
var product_qty = data[1].product[i].qty;
var row_count = i;
var cell = $('<tr id="row_'+row_count+'"><td>'+product_code+'</td><td>'+product_name+'</td><td id="price_'+row_count+'">'+product_price+'</td><td><input type="text" class="form-control" name="qty_'+row_count+'" value="'+product_qty+'" style="width: 50%;" /></td><td> <input id="box_'+row_count+'" type="checkbox" name="cond_'+row_count+'" /><label for="box_'+row_count+'"><?php echo $lang_good; ?></label> </td><td><a onclick="deletediv('+row_count+')" class="btn btn-danger" style="cursor:pointer"><i class="fa fa-trash-o"></i></a></td></tr><input type="hidden" class="form-control" name="pcode_'+row_count+'" value="'+product_code+'" />');
$('#addItemWrp').append(cell);
}
Your selector is wrong because there is nothing with id row_. Instead of looking for the row then the cell in the selector just look for the cell since ids should be unique.
var data = [0,{}];
data[1].product = [{
product_name: 'SO',
product_code: 0,
price: 1000000000,
qty: 1
}];
for(var i=0 ; i< data[1].product.length ; i++ ){
var product_name = data[1].product[i].product_name;
var product_code = data[1].product[i].product_code;
var product_price = data[1].product[i].price;
var product_qty = data[1].product[i].qty;
var row_count = i;
var cell = $('<tr id="row_'+row_count+'"><td>'+product_code+'</td><td>'+product_name+'</td><td id="price_'+row_count+'">'+product_price+'</td><td><input type="text" class="form-control" name="qty_'+row_count+'" value="'+product_qty+'" style="width: 50%;" /></td><td> <input id="box_'+row_count+'" type="checkbox" name="cond_'+row_count+'" /><label for="box_'+row_count+'"><?php echo $lang_good; ?></label> </td><td><a onclick="deletediv('+row_count+')" class="btn btn-danger" style="cursor:pointer"><i class="fa fa-trash-o"></i></a></td></tr><input type="hidden" class="form-control" name="pcode_'+row_count+'" value="'+product_code+'" />');
$('#addItemWrp').append(cell);
}
function deletediv(ele){
var r = $("#price_"+ele).text();
var row = $("#row_"+ele);
alert(r);
}
.btn{
width:2.5em;
height: 1em;
display:inline-block;
background-color:red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="addItemWrp"></table>
This isn't a correct selector var r = $("#row_ #price_"+ele).text();
ID suppose to be unique in entire document. So, do not combine your two ids as one selector. Use $('#row_'+ele) or $('#price_'+ele)
<table>
<tr>
<td>test1</td>
<td id="td1">test2</td>
</tr>
</table>
<script>
var sText = document.getElementById("td1").innerText;
alert (sText);
</script>
I'm trying to make something that makes it easier to write out a matrix/matrices.
You start with getting two number inputs for the dimensions of the matrix. And after that you "submit" the numbers and out comes several input boxes.
How do you write this code? Is it possible to do it in another function?
I was thinking of having the "submit" button have a validification to see if numbers are real, and if they are the function continues with for loops on how to "write" out the number boxes.
This is what I got right now:
function validate(){
var num;
num = document.getElementById("numberbox").value;
var myForm = document.getElementById('payForm'); //
while(myForm.hasChildNodes()){
myForm.removeChild(myForm.firstChild);
}
myForm = document.createElement("form");
myForm.setAttribute("method","post");
myForm.setAttribute("action","processChecking.php");
if(isNaN(num) || num<1){
document.getElementById("output").innerHTML = "invalid number!";
document.getElementById("numberbox").value = '';
} else {
document.getElementById("output").innerHTML = "number validated!";
array(num);
for (var i = 0; i <= num; i++) {
var input = document.createElement('input');
input.type = 'text';
input.name = 'myInput_' + i;
input.id = 'myInput_' + i;
myForm.appendChild(input);
}
}
}
<body>
<table>
<tr>
<td>
<p>
Enter number for how many number boxes you want:<br>
<input id="numberbox" type="number">
<button type="button" onclick="validate()">Validate</button>
<br>
<p id="output"></p>
<br>
</p>
</td>
<td style="text-align:right;">
<p id="payForm"></p>
</td>
</tr>
</table>
</body>
Here is what I made from your question so far. If it is on track, then we can build upon it.
function createTable() {
var num_rows = document.getElementById('rows').value;
var num_cols = document.getElementById('cols').value;
var theader = '<table border="1">\n';
var tbody = '';
for (var i = 0; i < num_rows; i++) {
tbody += '<tr>';
for (var j = 0; j < num_cols; j++) {
tbody += '<td>';
tbody += '<input type="number">'
tbody += '</td>'
}
tbody += '</tr>\n';
}
var tfooter = '</table>';
document.getElementById('wrapper').innerHTML = theader + tbody + tfooter;
}
<form name="tablegen">
<label>Input number of rows :
<input type="number" name="rows" id="rows" />
</label>
<br />
<label>Input number of columns :
<input type="number" name="cols" id="cols" />
</label>
<br/>
<input name="generate" type="button" value="Create Table!" onclick='createTable();' />
</form>
<div id="wrapper"></div>
i am creating a checkout page where users can purchase goods. i have managed to give each product its price but what I cant do is give them its quantity. i simply do no know how to do it. i created a quantity box for them but i can link the two.
my goal is to update the quantity and total price should be displayed on the checkout form.
since this is my homework for college, this must be done in strictly javascript if a solution arrives.
<script type="text/javascript">
function total(frm) {
var tot = 0;
for (var i = 0; i < frm.elements.length; i++) {
if (frm.elements[i].type == "checkbox") {
if (frm.elements[i].checked) tot += Number(frm.elements[i].value);
}
}
document.getElementById("totalDiv").firstChild.data = "£" + tot;
type = "text/javascript" > total(document.getElementById("theForm"));
}
</script>
<form action="nextpage" method="post" id="theForm">
<fieldset>
<legend>Choose your Products</legend>
<table style="padding:2px">
<tr>
<td>
<img src="http://placehold.it/200x200" />
</td>
<td>
<img src="http://placehold.it/200x200" />
</td>
<td>
<img src="http://placehold.it/200x200" />
</td>
<td>
<img src="http://placehold.it/200x200" />
</td>
</tr>
<tr>
<td class="buttons">
<div>
<input type="checkbox" name="r" value="25" onclick="total(this.form);" />£25</div>
<input min="0" max="5" type="number" class="quantity" name="quantity" value="1" />
</td>
<td class="buttons">
<div>
<input type="checkbox" name="7" value="50" onclick="total(this.form);" />£50</div>
<input min="0" max="5" type="number" class="quantity" name="quantity" value="1" />
</td>
<td class="buttons">
<div>
<input type="checkbox" name="asd7" value="75" onclick="total(this.form);" />£75</div>
<input min="0" max="5" type="number" class="quantity" name="quantity" value="1" />
</td>
<td class="buttons">
<div>
<input type="checkbox" name="rasd7" value="100" onclick="total(this.form);" />£100</div>
<input min="0" max="5" type="number" class="quantity" name="quantity" value="1" />
</td>
</tr>
</table>
<div id="totalDiv">£0</div>
<div>
<input type="submit" value="Place Order" />
</div>
</fieldset>
</form>
http://jsfiddle.net/isherwood/96qkr/
Simple and fast solution
Well the simplest solution would be:
Number(frm.elements[i].value) * Number(frm.elements[i+1].value);
Since the quantity element always comes AFTER the checkbox element.
The JavaScript then becomes:
function total(frm)
{
var tot = 0;
for (var i = 0; i < frm.elements.length; i++) {
if (frm.elements[i].type == "checkbox") {
if (frm.elements[i].checked) tot +=
Number(frm.elements[i].value) * Number(frm.elements[i+1].value);
}
}
document.getElementById("totalDiv").firstChild.data = "£" + tot;
}
You can see this works here.
To guarantee that the total div also gets updated when quantity is changed, you should add the onclick="total(this.form);" event to the class="quantity" input elements as well.
You can see how nicely this works here.
More advanced solution
Personally, I would use tabIndex to group the checkbox and quality inputs.
For example, for the first product:
<td class="buttons">
<div>
<input tabindex="1" name="checkbox" type="checkbox" value="25" onclick="total(this.form);" />£25</div>
<input tabindex="1" name="quantity" min="0" max="5" type="number" class="quantity" value="1" onclick="total(this.form);"/>
</td>
As you can see, I have explicitly defined the tabIndex and names.
Now for the JavaScript, I now use:
function total(frm)
{
var tot = 0;
var checkboxes = document.forms[frm.id].elements["checkbox"];
var quants = document.forms[frm.id].elements["quantity"];
for (var i = 0; i < checkboxes.length; i++)
{
if (checkboxes[i].checked)
{
// if tabIndex correctly specified
if (checkboxes[i].tabIndex == quants[i].tabIndex)
// add to total
tot += Number(checkboxes[i].value) * Number(quants[i].value);
else
// notify of bug
alert('Bug in code: tabIndex of checkbox '+i+' is not the same as tabIndex quantity '+i);
}
}
document.getElementById("totalDiv").firstChild.data = "£" + tot;
}
By doing it this way you get the following advantages:
Your HTML code makes more sense (input elements are grouped per tabIndex)
Your code is checked for bugs
You are absolutely sure that you multiply the correct input elements
You can find this code in this jsFiddle.
Good luck! I hope this helps you out!
Update
To create a sort of checkout system, you could go over all the elements again and store them in a variable.
Then make sure that the form implements a function upon submit:
action="javascript:checkout()"
so in total:
<form action="javascript:checkout()" id="theForm">
Easiest way to create the message would be to use one variable like so:
function checkout()
{
var message = "";
var checkboxes = document.forms["theForm"].elements["checkbox"];
var quants = document.forms["theForm"].elements["quantity"];
for (var i = 0; i < checkboxes.length; i++)
{
if (checkboxes[i].checked)
{
switch(checkboxes[i].tabIndex)
{
case 1: message += "iPhone"; break;
case 2: message += "Screen"; break;
case 3: message += "Laptop"; break;
case 4: message += "Coffee"; break;
default: message += "";
}
message += " Quantity: " + Number(quants[i].value) + " Price: £" + Number(checkboxes[i].value) * Number(quants[i].value) + "\n";
}
}
message += "\nTotal: " + document.getElementById("totalDiv").firstChild.data;
alert(message);
}
You can find a working implementation of this here.
Fancy solution
Or if you would like to make it a little bit more fancy, you could do the following:
Add the following HTML:
HTML
<br><br>
<div id="checkout">
<table id="myTable" border="1">
<tr>
<td>Product</td>
<td>Quantity</td>
<td>Price</td>
</tr>
</table>
</div>
Add the following JavaScript function:
JavaScript
function checkout()
{
document.getElementById("checkout").innerHTML = '<table id="myTable" border="1"><tr><td><b>Product</b></td><td><b>Quantity</b></td><td><b>Price</b></td></tr></table>';
// Find a <table> element with id="myTable":
var table = document.getElementById("myTable");
var count = 0;
var max = 0;
var checkboxes = document.forms["theForm"].elements["checkbox"];
var quants = document.forms["theForm"].elements["quantity"];
for (var i = 0; i < checkboxes.length; i++)
{
if (checkboxes[i].checked)
{
switch(checkboxes[i].tabIndex)
{
case 1: message = "iPhone"; break;
case 2: message = "Screen"; break;
case 3: message = "Laptop"; break;
case 4: message = "Coffee"; break;
}
count += Number(quants[i].value);
max += 1;
// Create an empty <tr> element and add it to the table:
var row = table.insertRow(max);
// Insert new cells (<td> elements) at the 1st, 2nd and 3rd position
var cell1 = row.insertCell(0);
var cell2 = row.insertCell(1);
var cell3 = row.insertCell(2);
// Add some text to the new cells:
cell1.innerHTML = message;
cell2.innerHTML = Number(quants[i].value);
cell3.innerHTML = "£" + Number(checkboxes[i].value) * Number(quants[i].value);
}
}
// Calculate total
var row = table.insertRow(max+1);
var cell1 = row.insertCell(0);
var cell2 = row.insertCell(1);
var cell3 = row.insertCell(2);
cell1.innerHTML = "<b>Total</b>";
cell2.innerHTML = count;
cell3.innerHTML = document.getElementById("totalDiv").firstChild.data;
}
The result looks like this:
You can find the corresponding jsFiddle HERE.
Hope that helps you out!
I'm a bit stuck with javascript again. Basically when you click a button a new row of fields will appear, giving them a new name just a different number.
I now need these fields to be able to auto sum by themself, i can do this with the first row I just don't know how to do them with the new generated ones.
The Javascript code:
<script language="javascript" type="text/javascript">
var i=2;
function addRow()
{
var tbl = document.getElementById('customersAdd');
var lastRow = tbl.rows.length;
var iteration = lastRow - 1;
var row = tbl.insertRow(lastRow);
var firstCell = row.insertCell(0);
var el = document.createElement('input');
el.placeholder = 'Quantity';
el.type = 'text';
el.name = 'quantity' + i;
el.id = 'quantity' + i;
firstCell.appendChild(el);
var secondCell = row.insertCell(1);
var el2 = document.createElement('input');
el2.placeholder = 'Description';
el2.type = 'text';
el2.name = 'description' + i;
el2.id = 'description' + i;
secondCell.appendChild(el2);
var thirdCell = row.insertCell(2);
var el3 = document.createElement('input');
el3.placeholder = 'Rate';
el3.type = 'text';
el3.name = 'rate' + i;
el3.id = 'rate' + i;
thirdCell.appendChild(el3);
var forthCell = row.insertCell(3);
var el4 = document.createElement('input');
el4.placeholder = 'Amount';
el4.type = 'text';
el4.name = 'amount' + i;
el4.id = 'amount' + i;
forthCell.appendChild(el4);
// alert(i);
i++;
// alert(i);
}
function startCalc(){
interval = setInterval("calc()",1);
}
function calc(){
one = document.main.quantity1.value;
two = document.main.rate1.value;
document.main.amount1.value = (one * 1) * (two * 1);
}
function stopCalc(){
clearInterval(interval);
}
</script>
The HTML code:
<form action="submit.php" name="main" method="post">
<table style="border-collapse: collapse;" border="0" align="center" width="50%" class="horiz" id="customersAdd">
<tr>
<td align="center"><br/>
<input class="text" style="width:100%" type="button" align="middle"value="Add Aditional Row" onClick="addRow()" /></td>
</tr>
<tr align="center">
<td>
<br />
<input placeholder="Quantity" type="text" name="quantity1" id="quantity1" onFocus="startCalc();" onBlur="stopCalc();" />
<br /></td>
<td>
<br />
<input placeholder="Description" type="text" name="description1" id="description1"/>
<br /></td>
<td>
<br />
<input placeholder="Rate" type="text" name="rate1" id="rate1" onFocus="startCalc();" onBlur="stopCalc();"/>
<br /></td>
<td>
<br />
<input placeholder="Amount" type="text" name="amount1" id="amount1" onBlur="stopCalc();" onFocus="startCalc();" readonly="true" />
<br /></td>
</tr>
</table></form>
To make things easier for anyone who could help me I have made this in JSBin to see it easier of what i want to do. Any suggestions are appreciated.
http://jsbin.com/atabaz/1/edit
Thanks
In the end I managed to find a way on how to do this myself, if anyone is interested take a look at this:
http://jsfiddle.net/2sYgE/
var currentItem = 1;
$('#customersAdd').on('keyup', '.quantity, .rate, .amount', calculateRow);
$('#addnew').click(function() {
currentItem++;
$('#customersAdd').append('<tr><td><input placeholder="Quantity" type="text" name="quantity' + currentItem +'" id="quantity' + currentItem +'" class="qty form-input-rate" /></td><td><input placeholder="Description" type="text" name="description' + currentItem +'" id="description' + currentItem +'" class="form-input-rate"/></td><td><input placeholder="Rate" type="text" name="rate' + currentItem +'" id="rate' + currentItem +'" class="rate form-input-rate"/></td><td><input placeholder="Amount" type="text" name="amount' + currentItem +'" id="amount' + currentItem +'" class="cal form-input-rate"/></td></tr>'
);
});
function calculateSum() {
var sum = 0;
$(".cal").each(function () {
if (!isNaN(this.value) && this.value.length != 0) {
sum += parseFloat(this.value);
}
});
}
function calculateRow() {
var cost = 0;
var $row = $(this).closest("tr");
var qty = parseFloat($row.find('.qty').val());
// changed the following line to only look within the current row
var rate = parseFloat($row.find('.rate').val());
cost = qty * rate;
if (isNaN(cost)) {
$row.find('.cal').val("0");
} else {
$row.find('.cal').val(cost);
}
calculateSum();
}
Polling for changes is a very inefficient and error–prone way to do form updates. Listening for change events is a better way to go as it uses fewer resources and waits until the user has finished updating the control before doing anything. There is also an input event that can be used, but it's not suitable here as it will update the form as the user enters values. Much better to wait for the user to finish entering values, then do the update.
I've re–factored your code below, it's not ready for production but it should give you some idea of how to go about it. Table rows are cloned as it's much faster than creating all the elements from scratch. Then names are modified, though this isn't really necessary. There is no need for ID attributes.
Cloning only works reliably here if inline listeners are used on the form controls. If the initial listeners are dynamically attached, you'll have to add them each time a row is added as listeners added using addEventListener are not cloned.
I haven't included any input validation, if the user puts in junk, they get junk back. You should validate input to check that appropriate values are being entered, and also format the displayed values for presentation.
<script type="text/javascript">
function addRow(element) {
var form = element.form;
var table = form.getElementsByTagName('table')[0];
var tbody = table.tBodies[0];
var num = tbody.rows.length - 1;
var row = table.rows[1].cloneNode(true);
var input, inputs = row.getElementsByTagName('input')
// Update input names
for (var i=0, iLen=inputs.length; i<iLen; i++) {
input = inputs[i];
input.name = input.name.replace(/\d+$/,num);
input.value = '';
}
tbody.insertBefore(row, tbody.rows[tbody.rows.length - 1]);
}
function updateRow(element) {
var form = element.form;
var num = element.name.replace(/^\D+/,'');
var value = form['quantity' + num].value * form['rate' + num].value;
form['amount' + num].value = (value == 0)? '' : value;
updateTotal(form);
}
function updateTotal(form) {
var elements = form.elements;
var name = /^amount/;
var total = 0;
var value;
for (var i=0, iLen=elements.length; i<iLen; i++) {
if (name.test(elements[i].name)) {
total += parseFloat(elements[i].value);
}
}
form.total.value = total;
}
</script>
<form action="submit.php" name="main" method="post">
<table style="border-collapse: collapse;" border="0" align="center"
width="50%" class="horiz" id="customersAdd">
<tr>
<td><br>
<input class="text" style="width:100%" type="button"
align="middle"value="Add Aditional Row" onclick="addRow(this)">
</td>
</tr>
<tr>
<td>
<input placeholder="Quantity" name="quantity1" onblur="updateRow(this);">
</td>
<td>
<input placeholder="Description" type="text" name="description1">
</td>
<td>
<input placeholder="Rate" name="rate1" onchange="updateRow(this);">
</td>
<td>
<input placeholder="Amount" name="amount1" readonly>
</td>
</tr>
<tr>
<td colspan="3" style="text-align: right">Total
<td><input name="total" readonly>
</tr>
</table>
<input type="reset">
</form>
I am developing this for use in Internet Explorer 8 (because at work we have to use it). I have a page that has a table withing a form. The table has a button to "clone" rows, "AddScheduleRow()". That part works good. Each row has a button to delete that row "DeleteRow(r)". That part works well too. I also have a script to rename/renumber each row, "RenumberRows()". It almost works good. I can rename the text fields (for example what was previously StartDate3 now becomes StartDate2). However, in each row is an input that is type="image" and it is named like you should with any input. The name of it is "StartDateCal". The problem is that during the renaming process, when it hits the image input (TheForm.StartDateCal[i].name = "StartDateCal" + TempCounter;), I get a JavaScript error "'TheForm.StartDateCal' is null or not an object". I cannot figure this one out and it's standing in the way of moving on.
What can I do to try to rename an < input type = image /> ?
Below is the necessary code:
HTML
<html>
<head>
</head>
<body>
<form name="UpdateSchedule" method="post" action="DoSchedule.asp">
<input type="hidden" name="NumRows" value="0">
<input type="hidden" name="RowsAdded" value="0">
<table id="ClassScheduleTable">
<tr id="ScheduleRow" style="display:none;">
<td>
<input type="text" name="RowNum" value="0" size="1" onclick="alert(this.name)">
</td>
<td>
<b>Start Date</b> <input type="text" name="StartDate" value="" onclick="alert(this.name);" size="8">
<input type="image" name="StartDateCal" src="http://www.CumminsNorthwest.com/ATT/Img/Calendar3.png" style="border-style:none;" onClick="alert('name = ' + this.name);return false;">
</td>
<td>
<input type="button" value="Del." name="DelRow" class="subbuttonb" onclick="DeleteRow(this);">
</td>
</tr>
<tr>
<td colspan="3" style="text-align:right">
<input type="button" value="Add Class Date" class="SubButton" onclick="AddScheduleRow();">
</td>
</tr>
</table>
</form>
</body>
<script language="JavaScript">
JS
var TheForm = document.forms.UpdateSchedule;
var NumRows =0;
var RowsAdded =0;
function AddScheduleRow(){
NumRows++;
TheForm.NumRows.value = NumRows;
RowsAdded++;
TheForm.RowsAdded.value = RowsAdded;
var TableRowId = "ScheduleRow";
var RowToClone = document.getElementById(TableRowId);
var NewTableRow = RowToClone.cloneNode(true);
NewTableRow.id = TableRowId + NumRows ;
NewTableRow.style.display = "table-row";
var NewField = NewTableRow.children;
for (var i=0;i<NewField.length;i++){
var TheInputFields = NewField[i].children;
for (var x=0;x<TheInputFields.length;x++){
var InputName = TheInputFields[x].name;
if (InputName){
TheInputFields[x].name = InputName + NumRows;
//alert(TheInputFields[x].name);
}
var InputId = TheInputFields[x].id;
if (InputId){
TheInputFields[x].id = InputId + NumRows;
//alert(TheInputFields[x].id);
}
}
}
var insertHere = document.getElementById(TableRowId);
insertHere.parentNode.insertBefore(NewTableRow,insertHere);
RenumberRows();
}
AddScheduleRow();
function DeleteRow(r){
var i=r.parentNode.parentNode.rowIndex;
document.getElementById("ClassScheduleTable").deleteRow(i);
NumRows--;
TheForm.NumRows.value = NumRows;
RenumberRows();
}
function RenumberRows(){
var TempCounter = 0;
for (var i=0;i<=RowsAdded;i++){
if (TheForm.RowNum[i]){
TempCounter++;
TheForm.RowNum[i].name = "RowNum" + TempCounter;
TheForm.RowNum[i].value = TempCounter;
TheForm.StartDate[i].name = "StartDate" + TempCounter;
TheForm.StartDateCal[i].name = "StartDateCal" + TempCounter;
}
}
}
</script>
</html>
might be to do with your DTD,
try HTML4 Strict:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
You can use
document.getElementsByName('StartDateCal')[i].name = "StartDateCal" + TempCounter;
instead of
TheForm.StartDateCal[i].name = "StartDateCal" + TempCounter;