DESIGN: Dropdown+Label+Button and Repeating row wise - javascript

I have a design related question.
I have a bill to add product. One product is added per line.
One Product added per line image
When I add a product, I also display its warranty in the Warranty column:
Selected product shows warranty in Warranty Column
But when I add any other product, I cannot display its Warranty.
Cannot Display Warranty in subsequent products
My HTML where dropdown options are coming dynamically:
<tbody style="border: 1px solid rgba(0,0,0,0.35); height: 34px; line-height: 34px;">
<tr class="text-center">
<td>
<select id="myDropdown" name="bill_product[]" onChange="dropdownTip(this.value)">
<option disabled selected value="">Select Product</option>
<option id="1" value="31/01/2020">Product #1</option>
<option id="2" value="31/01/2030">Product #2</option>
<option id="3" value="31/01/2040">Product #3</option>
</select>
</td>
<td>
<input name="txtbox" type="text" id="txtbox" />
</td>
<td>
<button type="button" class="btn btn-danger btn-xs disabled">
<i class="fa fa-times"></i>
</button>
</td>
</tr>
</tbody>
My JS for adding row to bill:
$(document).ready(function () {
var counter = 0;
$("#addrow").on("click", function () {
var newRow = $("<tr class='text-center'>");
var cols = "";
cols += '<td><select name="bill_product[]"><option disabled selected value="">Select Product</option><cms:pages masterpage="product.php"><option value="<cms:show k_page_id />"><cms:show k_page_title /></option></cms:pages></select></td>';
cols += '<td><input type="text" id="txtbox" name="txtbox" /></td>';
cols += '<td><button type="button" class="ibtnDel btn btn-danger btn-xs"><i class="fa fa-times"></i></button></td>';
newRow.append(cols);
$("table.order-list").append(newRow);
counter++;
});
$("table.order-list").on("click", ".ibtnDel", function (event) {
$(this).closest("tr").remove();
counter -= 1
});
});
My Code to display the warranty end date:
$(document).ready(function() {
$("#myDropdown").change(function() {
var selectedValue = $(this).val();
$("#txtbox").val(selectedValue);
});
});
ISSUE: I am unable to display the value of the warranty date on any product after the first one.
Please help.
P.S.: I am using CouchCMS to dynamically bring my values to the option tag of select.

Here's the solution I propose, I get rid off not-native JS by the way, it allows it to fit with any solution :
<tbody style="border: 1px solid rgba(0,0,0,0.35); height: 34px; line-height: 34px;">
<tr class="text-center">
<td>
<select id="myDropdown" name="bill_product[]" onChange="dropdownTip(this.value)">
<option disabled selected value="">Select Product</option>
<option id="1" value="31/01/2020">Product #1</option>
<option id="2" value="31/01/2030">Product #2</option>
<option id="3" value="31/01/2040">Product #3</option>
</select>
</td>
<td>
<input name="txtbox" type="text" id="txtbox" />
</td>
<td>
<button type="button" class="btn btn-danger btn-xs disabled">
Delete
</button>
</td>
</tr>
</tbody>
// Line removal
let delBtns = document.querySelectorAll(".del-btn");
[].forEach.call(delBtns, function(delBtn){
delBtn.addEventListener('click', function(event){
let line = event.target.dataset.line;
let lineToRemove = document.querySelector("#line-"+line);
lineToRemove.remove();
})
});
// Input update
let productDropDowns = document.querySelectorAll("select");
[].forEach.call(productDropDowns, function(dropDown){
dropDown.addEventListener('change', function(event){
let line = event.target.dataset.line;
document.querySelector('#line-'+line+' input').value = event.target.value;
})
});
// New line button
let count = 0;
let newLineButton = document.querySelector("#newLineTrigger");
newLineButton.addEventListener('click', function(){
count++;
let tableBody = document.querySelector('tbody');
let newLine = document.createElement('tr');
newLine.id = 'line-' + count;
tableBody.appendChild(newLine);
newLine = document.querySelector('#line-' + count);
let col1 = document.createElement('td');
let select = document.createElement('select');
select.id = 'drop' + count;
select.dataset.line = count;
select.addEventListener('change', function(event){
let line = event.target.dataset.line;
document.querySelector('#line-'+line+' input').value = event.target.value;
})
for(let i=0; i<3; i++){
let option = document.createElement('option');
option.value = i;
option.innerText = 'option ' + i;
select.appendChild(option);
}
col1.appendChild(select);
let col2 = document.createElement('td');
let textBox = document.createElement('input');
textBox.id = 'textBox'+count;
textBox.name = 'textBox'+count;
col2.appendChild(textBox);
let col3 = document.createElement('td');
let newDelBtn = document.createElement('button');
newDelBtn.className = "del-btn";
newDelBtn.dataset.line = count;
newDelBtn.innerText = "Delete";
newDelBtn.addEventListener('click', function(event){
let line = event.target.dataset.line;
let lineToRemove = newLine;
lineToRemove.remove();
});
col3.appendChild(newDelBtn);
newLine.appendChild(col1);
newLine.appendChild(col2);
newLine.appendChild(col3);
tableBody.appendChild(newLine);
});

I don't see the triggerring element '#addrow' which adds the row. Could you update the fiddle to include this button, please?

The ids for all warranty input field is same, which is "txtbox". You can use the counter variable to have separate ids for all warranty fields.

Related

Save input data to table on same page? HTML and Javascript

I am brand new to JavaScript and HTML, and am trying to make a rehersal booking app which collects the info needed and displays it in a table on the same page.
I have been trying for hours on end to get it to work with various methods and I feel like it's just getting worse. I have probably made some silly mistakes but I cant seem to work out what I need to change to make it work.
Here is my HTML:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html" xmlns="http://www.w3.org/1999/html">
<head>
<meta charset="UTF-8">
<title>White Noise Studios - Home</title>
<script type="text/javascript" src="Homepage.js"></script>
<style>
body, html
{
height: 100%;
background: url(Media/background.png);
background-size: cover;
}
</style>
</head>
<body>
<header style="color:white;font-family:'Calibri'">
<h1> Rehearsal Bookings</h1>
<p>Please let us know what gear you require in order for us to have the room ready for you. Leave the equipment section blank if you wish to bring your own gear. </p>
</header>
<form name="booking" id="booking">
<table style="color:white;font-family:'Yu Gothic UI Semibold'">
<tr>
<td><form action="Homepage.html"><input type="image" src="Media/homebutton.png"></form></td>
<td><form action="Homepage.html"><input type="submit" value="Book My Rehearsal"></form></td>
<td>Artist Name:</td><td><input type="text" name="Artist" size="50" id="Artist" /></td>
<td>Contact Number:</td><td><input type="text" name="Contact" size="50" id="Contact" /></td>
</tr>
<td>Equipment Needed:</td>
<td><label>Microphone</label>
<select id = "Microphone" name="Microphone">
<option value = "0">0</option>
<option value = "1">1</option>
<option value = "2">2</option>
<option value = "3">3</option>
</select></td>
<td><label>Guitars</label>
<select id = "Guitar" name="Guitar">
<option value = "0">0</option>
<option value = "1">1</option>
<option value = "2">2</option>
<option value = "3">3</option>
</select></td>
<td><label>Bass</label>
<select id = "Bass" name="Bass">
<option value = "0">0</option>
<option value = "1">1</option>
<option value = "2">2</option>
</select></td>
<td><label>Drums</label>
<select id = "Drums" name="Drums">
<option value = "0">None</option>
<option value = "1">Mapex Mars 5 Piece Full Kit</option>
<option value = "2">Ludwig LC17611 5 Piece Acoustic Kit</option>
<option value = "3">Roland TD 25KV V-Drums Kit</option>
</select></td>
<td><label>Amp</label>
<select id = "Amp" name="Amp">
<option value = "0">None</option>
<option value = "1">Marshall DSL100H</option>
<option value = "2">Marshall MG100GFX</option>
<option value = "3">Mesa Boogie triple Rectifier 100w</option>
</select></td> </tr>
<tr>
<td>Date:</td><td><input type="date" name="Date" id="Date" /></td>
</tr>
<tr>
<td>Time:</td><td><input type="time" name="Time" id="Time" /></td>
</tr>
</table>
</form>
<input type="submit" name="Book" value="Book my Rehearsal">
<button id="cancel" name="Cancel" onclick="myFunction()" value="Reset form">Cancel</button>
<hr/>
<div id="table">
</div>
<body>
<body style=”font-family:”arial black”; >
And my JavaScript:
var ArtistField, ContactField, MicrophoneSelect, GuitarSelect, BassSelect, DrumsSelect, AmpSelect, DateSelect, TimeSelect, BookSelect, CancelSelect;
var Booking = function (Artist, Contact, Microphone, Guitar, Bass, Drums, Amp, Date, Time ) {
this.Artist = Artist;
this.Contact = Contact;
this.Microphone = Microphone;
this.Guitar = Guitar;
this.Bass = Bass;
this.Drums = Drums;
this.Amp = Amp;
this.Date = new Date ;
this.Time = Time;
};
function myFunction() {
document.getElementById("booking").reset();
}
var Bookings = []
Booking.prototype.tableRow = function(){
var tr = "<tr><td>" + this.Artist + "</td><td>" +
this.Contact + "</td><td>" + this.Microphone +
"<tr><td>" + this.Guitar + "<tr><td>" + this.Bass + "<tr><td>" + this.Drums + "<tr><td>" + this.Amp +"<tr><td>"
+ this.getDate() + "</td><td>" + this.Time+ "</td><td>" + "</td></tr> ";
return tr;
};
Booking.prototype.getDate = function(){
return this.Date.toDateString();
};
var clickBook = function() {
addbooking(ArtistField, ContactField, MicrophoneSelect, GuitarSelect, BassSelect, DrumsSelect, AmpSelect, DateSelect, TimeSelect,);
showTable();
};
var showTable = function(){
var tableDiv = document.getElementById("table"), table = "<table border='1'>" +
"<thead><th>Artist</th><th>Contact</th><th>Microphone</th><th>Guitar</th><th>Bass</th><th>Drums</th><th>Amp</th</thead>";
for(var i=0, j=Bookings.length; i<j; i++){
var appt = Bookings[i];
table += appt.tableRow();
}
table+="</table>";
tableDiv.innerHTML = table;
};
window.onload = function(){
ArtistField = document.getElementById("Artist");
ContactField = document.getElementById("Contact");
MicrophoneSelect = document.getElementById("Microphone");
GuitarSelect = document.getElementById("Guitar");
BassSelect = document.getElementById("Bass");
DrumsSelect = document.getElementById("Drums");
AmpSelect = document.getElementById("Amp");
DateSelect = document.getElementById("Date");
TimeSelect = document.getElementById("Time");
//var roleChoice = roleField.options[roleField.selectedIndex].text;
Book = document.getElementById("Book");
Book.onclick = clickBook();
showTable();
};

Table Add More Row using javascript

I am adding dynamic row to table. But when adding new row, I want to replace some string on new row. But it is not working.
<table id="testTable">
<tr id="row_1">
<td>
<select onchange="changeCustomCategory(this.value,'1');" id="_cid" name="_cid[0]" >
<option value="">--Select Product--</option>
<option value="test">Test</option>
</select>
<input type="text" onchange="_doVariation(1);" value="1" id="_qty" name="_qty[0]"/>
<input type="text" class="textfield" value="0.00" id="item1_total" name="item1_total" readonly>
</td>
</tr>
</table>
<input type="hidden" value="1" id="total_row">
<input type="button" onclick="addRow()" value="Add Row">
This is my HTML code.
function addRow(){
var total_row = document.getElementById("total_row").value;
var _previousId = parseInt(total_row);
var new_id = parseInt(total_row) + 1;
document.getElementById("total_row").value = new_id;
var table = document.getElementById("testTable");
jQuery("#"+ table.rows[0].id).clone().appendTo("#testTable");
var totalTableRow = table.rows.length;
var currentRow = table.rows[totalTableRow-1];
currentRow.id = "row_"+new_id;
currentRow.innerHTML = currentRow.innerHTML.replace('_cid\['+ new_id-1 +'\]','_cid['+new_id+']');
currentRow.innerHTML = currentRow.innerHTML.replace(new RegExp("changeCustomCategory(this.value,'"+_previousId+"')","g"),'changeCustomCategory(this.value,'+new_id+')');
currentRow.innerHTML = currentRow.innerHTML.replace('_doVariation('+_previousId+')','_doVariation('+new_id+')');
}
You can perform your changes as the following:
//....
var newRow = jQuery("#"+ table.rows[0].id).clone().appendTo("#testTable");
//Change1
newRow.attr('name', '_cid['+new_id+']');
//Change2:
newRow.find('select').removeAttr('onchange').change(function() {
changeCustomCategory(this.value, new_id);
});
//Change3:
newRow.find('input:first').removeAttr('onchange').change(function() {
_doVariation(new_id);
});
//....
Demo: https://jsfiddle.net/4c0v2d50/
I would suggest sticking to jquery functions and not mixing too much with plain javascript. It makes it easier to code and follow.
I believe this is what your trying to do:
change HTML
id="_cid" name="_cid[0]"//change in select to
class="_cid" name="_cid[]"//_cid[] will automatically increment
id="_qty" name="_qty[0]"//same in input
class="_qty" name="_qty[]"
//you should also change
id="item1_total"
class="item1_total"
Javascript
function addRow(){
var new_id = $("#total_row").val() + 1;
$("#total_row").val(new_id);
var $currentRow = $("#testTable tr:first").clone();
$("#testTable").append(currentRow);
$currentRow.attr(id,"row_"+new_id);
$currentRow.find('select').attr('onclick',"changeCustomCategory(this.value,'"+new_id+"')");
$currentRow.find('._qty').attr('onchange','_doVariation('+new_id+')');
}
Removed the inline binding and bound to the element in the logic. Started changing the first thing you were trying to do with a regex. You can see how you like this approach.
jQuery(function($) {
//cache selectors
var $total_row = $("#total_row"),
$table = $("#testTable");
$(".addRow").on('click', function addRow() {
var total_row = $total_row.val(),
_previousId = parseInt(total_row),
new_id = _previousId + 1;
$total_row.val(new_id);
var $new_row = $table.find("tr").eq(0).clone();
$new_row.attr("id", "row_"+ new_id);
$new_row.find("select").attr("name", "_cid["+ (new_id - 1) +"]");
$table.append($new_row);
// currentRow.innerHTML = currentRow.innerHTML.replace('_cid\[' + new_id - 1 + '\]', '_cid[' + new_id + ']');
// currentRow.innerHTML = currentRow.innerHTML.replace(new RegExp("changeCustomCategory(this.value,'" + _previousId + "')", "g"), 'changeCustomCategory(this.value,' + new_id + ')');
// currentRow.innerHTML = currentRow.innerHTML.replace('_doVariation(' + _previousId + ')', '_doVariation(' + new_id + ')');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table id="testTable">
<tr id="row_1">
<td>
<select onchange="changeCustomCategory(this.value,'1');" id="_cid" name="_cid[0]">
<option value="">--Select Product--</option>
<option value="test">Test</option>
</select>
<input type="text" onchange="_doVariation(1);" value="1" id="_qty" name="_qty[0]" />
<input type="text" class="textfield" value="0.00" id="item1_total" name="item1_total" readonly>
</td>
</tr>
</table>
<input type="hidden" value="1" id="total_row">
<input type="button" value="Add Row" class="addRow">
function addRow(){
var total_row = parseInt(document.getElementById("total_row").value);
var _previousId = parseInt(total_row);
var new_id = parseInt(total_row) + 1;
var total_row = $("#total_row").val();
var _previousId = parseInt(total_row);
var new_id = parseInt(total_row) + 1;
$("#total_row").val(new_id);
var currentRow = $("#testTable tr:first").clone();
$("#testTable").append(currentRow);
$(currentRow).find('#_cid').attr("name","_cid["+new_id+"]");
$(currentRow).find('#_qty').attr("name","_qty["+new_id+"]");
$(currentRow).attr("id","row_"+new_id);
$(currentRow).find('#_cid').attr('onclick',"changeCustomCategory(this.value,'"+new_id+"')");
$(currentRow).find('#_qty').attr('onclick','_doVariation('+new_id+')');}
Working fiddle.
The id attribute should be unique so you could replace the duplicate ones by class attributen example :
<select class="_cid" name="_cid[0]" >
<input type="text" value="1" class="_qty" name="_qty[0]"/>
Better if you could avoid the inline-event onclick() and the overriding of parameters in every clone and define a general event one time and it will work for all the element, example :
$('body').on('change','._cid', function(){
//You code here
})
You don't need to increment the names you have just to leave the array signs empty [] and it will be incremented automatically, example :
<select class="_cid" name="_cid[]" >
<input type="text" value="1" class="_qty" name="_qty[]"/>
Hope this helps.
$(function(){
$('body').on('change','._cid', function(){
var id_number = $(this).parents('tr').attr('id').split('_')[1];
changeCustomCategory($(this).val(),id_number);
})
$('body').on('change','._qty', function(){
var id_number = $(this).parents('tr').attr('id').split('_')[1];
_doVariation(id_number);
})
})
function addRow()
{
var new_id = $('.row').length + 1;
var new_row = $("#testTable tr:first").clone().attr('id','row_'+new_id);
$("#testTable").append(new_row);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="testTable">
<tr id="row_1" class="row">
<td>
<select class="_cid" name="_cid[]" >
<option value="">--Select Product--</option>
<option value="test">Test</option>
</select>
<input type="text" value="1" class="_qty" name="_qty[]"/>
<input type="text" class="textfield" value="0.00" class="item1_total" name="item1_total" readonly>
</td>
</tr>
</table>
<input type="button" onclick="addRow()" value="Add Row">

Javascript form calculation errors

Im getting uncaught type error for estimateCost, also im having issues with how to double the price with spouse. I'm suppose to have an alert window that displays the estimate cost based on selections made from city, number of days, and other options. TY!
<html>
<head>
<script language="JavaScript">
var city_prices = new Array();
city_prices["New York City"] = 0;
city_prices["Boston"] = 0;
city_prices["San Francisco"] = 200;
city_prices["Los Angeles"] = 200;
// getCityPrice() finds the price based on the city .
// Here, we need to take user's the selection from radio button selection
function getCityPrice() {
var cityPrice = 0;
//Get a reference to the form id="cakeform"
var theForm = document.forms["form1"];
//Get a reference to the cake the user Chooses name=radCity":
var selectedCity = theForm.elements["radCity"];
//Here since there are 4 radio buttons selectedCity.length = 4
//We loop through each radio buttons
for (var i = 0; i < selectedCity.length; i++) {
//if the radio button is checked
if (selectedCity[i].checked) {
//we set cityPrice to the value of the selected radio button
//i.e. if the user choose NYC we set to 0
//by using the city_prices array
//We get the selected Items value
//For example city_prices["New York City".value]"
cityPrice = city_prices[selectedCity[i].value];
//If we get a match then we break out of this loop
//No reason to continue if we get a match
break;
}
}
//We return the cityPrice
return cityPrice;
}
var number_days = new Array();
number_days["3"] = 450;
number_days["4"] = 600;
number_days["5"] = 750;
number_days["6"] = 900;
number_days["7"] = 1050;
number_days["8"] = 1350;
number_days["9"] = 1500;
number_days["10"] = 1650;
number_days["11"] = 1800;
number_days["12"] = 1950;
number_days["13"] = 2100;
number_days["14"] = 2250;
number_days["15"] = 2400;
//This function finds the day price based on the
//drop down selection
function getDayPrice() {
var dayPrice = 0;
//Get a reference to the form id="form1"
var theForm = document.forms["form1"];
//Get a reference to the select id="selNumberDays"
var selectedDays = theForm.elements["selNumberDays"];
//set dayPrice equal to value user chose
//For example number_days["3".value] would be equal to 450
dayPrice = number_days[selectedDays.value];
//finally we return dayPrice
return dayPrice;
}
//chksFirst() finds the candles price based on a check box selection
function chksFirst() {
var chkFirst = 0;
//Get a reference to the form id="form1"
var theForm = document.forms["form1"];
//Get a reference to the checkbox id="chkFirst"
var includeFirst = theForm.elements["chkFirst"];
//If they checked the box set first class to 500
if (includeFirst.checked == true) {
chkFirst = 500;
}
//finally we return the firstClass
return chkFirst;
}
//chksSpouse() finds the candles price based on a check box selection
function chksSpouse() {
var chkSpouse = 0;
//Get a reference to the form id="form1"
var theForm = document.forms["form1"];
//Get a reference to the checkbox id="chkSpouse"
var includeSpouse = theForm.elements["chkSpouse"];
//If they checked the box set Total 2x
if (includeSpouse.checked == true) {
totalPrice = totalPrice * 2;
}
//finally we return the firstClass
return totalPrice;
}
function estimateCost() {
//Here we get the estimate price by calling our function
//Each function returns a number so by calling them we add the values they return together
var totalPrice = getCityPrice() + getDayPrice() +
chksFirst() + chksSpouse();
alert(totalPrice);
}
</script>
</head>
<body>
<table align="left" width="600px" border="0" cellpadding="5px">
<tr>
<td>
<form name="form1" id="form1">
<table border="0">
<tr>
<td width="300px"><strong>Last Name: </strong>
</td>
<td width="300px">
<input type="text" name="txtFirstName" value=" " size="20" />
</td>
</tr>
<tr>
<td><strong>First Name: </strong>
</td>
<td>
<input type="text" name="txtLastName" value=" " size="20" />
</td>
</tr>
<tr>
<td><strong>Nationality: </strong>
</td>
<td>
<select name="selNationality">
<option value="amer">USA</option>
<option value="can">Canada</option>
<option value="mex">Mexico</option>
<option value="ger">Germany</option>
<option value="fra">France</option>
</select>
</td>
</tr>
<tr>
<td><strong>City you wish to visit: </strong>
</td>
<td>
<input type="radio" name="radCity" value="New York City" />New York City
<br />
<input type="radio" name="radCity" value="Boston" />Boston
<br />
<input type="radio" name="radCity" value="San Francisco" />San Francisco ($200 surcharge)
<br />
<input type="radio" name="radCity" value="Los Angeles" />Los Angeles ($200 surcharge)
<br/>
</td>
</tr>
<tr>
<td><strong>Number of days ($150 per day): </strong>
</td>
<td>
<select name="selNumberDays" id="selNumberDays">
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="14">14</option>
<option value="15">15</option>
</td>
</tr>
<tr>
<td><strong>Other options: </strong>
</td>
<td>
<input type="checkbox" name="chkFirst" id="chkFirst" />First Class Only ($500 surcharge)
<br />
<input type="checkbox" name="chkSpouse" id="chkSpouse" />Traveling with Spouse (All costs doubled)
<br />
</td>
</tr>
<tr>
<td align="right">
<input type="button" value="Give me an estimate!" onClick="estimateCost()" id="estimateCost" />
</td>
<td align="left">
<input type="reset" />
</td>
</tr>
</table>
</form>
</td>
</tr>
</table>
</body>
</html>
On the button input with the onClick="estimateCost()" code, remove the id="estimateCost". It's causing the error for some reason. You should really be using an onClick listener though instead of an inline onclick:
Inline onclick JavaScript variable
For the total with spouse, you might want to rework it to something like this where you pass the pre-spouse price into the chksSpouse function and use it's return as the total price.
//chksSpouse() finds the candles price based on a check box selection
function chksSpouse(totalPrice) {
var chkSpouse = 0;
//Get a reference to the form id="form1"
var theForm = document.forms["form1"];
//Get a reference to the checkbox id="chkSpouse"
var includeSpouse = theForm.elements["chkSpouse"];
//If they checked the box set Total 2x
if (includeSpouse.checked == true) {
totalPrice = totalPrice * 2;
}
//finally we return the firstClass
return totalPrice;
}
function estimateCost() {
//Here we get the estimate price by calling our function
//Each function returns a number so by calling them we add the values they return together
var preSpouseTotal = getCityPrice() + getDayPrice() + chksFirst();
var totalPrice = chksSpouse(preSpouseTotal);
alert(totalPrice);
}

implementing quantity to update price of product and total price

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!

Autosum with generated fields JS

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>

Categories