Hi all,
I have table in Javascript and it has addrow, deleterow, submit, and functions.
when i click it automatically adds new row and it has select option to choose some of them
for ex. in added two rows one of them is Motherboard Asus and other is Motherboard Gigabyte.
What i want is when i choose motherboard Asus it added news row with select option Motherboard asus and disabled select option and second time when i click add button let it adds rows but among select options let it ejects Motherboard ASUS. and with this way at the last there will be no options to select
Here is my code.

Thanks beforehands

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head><title>dinamik sheet</title>
<script> 
var i=iteration;
function addrow(){
	var tbl = document.getElementById('sheet');
	var iteration = tbl.rows.length;
document.getElementById('count_rows').value = iteration;
	var row=tbl.insertRow(iteration);
 
	var cellLeft = row.insertCell(0);
	var textNode = document.createTextNode(iteration);
	cellLeft.appendChild(textNode);
 
	var cellRight = row.insertCell(1);
	var el = document.createElement('input');
	el.type = 'text';
	el.name = 'txtRow'+iteration;
	el.id = 'txtRow'+iteration;
	el.size = 15;
	el.value = '0';
	el.onblur = sum;
	cellRight.appendChild(el);
 
	var cellRight = row.insertCell(2);
	var elaz = document.createElement('input');
	elaz.type = 'text';
	elaz.name = 'txtRowaz'+iteration;
	elaz.id = 'txtRowaz'+iteration;
	elaz.size = 20;
	elaz.value = '0';
	elaz.onblur = sum;
	cellRight.appendChild(elaz);
 
 
 
	var cellRight1 = row.insertCell(3);
	var ela = document.createElement('input');
	ela.type = 'text';
	ela.name = 'txtRowe'+iteration;
	ela.id = 'txtRowe'+iteration;
	ela.size = 20;
	ela.value = '0';
	ela.onblur = sum;
	cellRight1.appendChild(ela);
 
	var cellRightsel = row.insertCell(4);
	var sel = document.createElement('select');
	sel.name = 'selRow' + iteration;
	sel.id = 'selRow' + iteration;
	sel.onchange = sum;
	sel.options[0] = new Option('MotherBoard ASUS', 'MotherBoard ASUS');
	sel.options[1] = new Option('MotherBoard Gigabyte', 'MotherBoard Gigabyte');
	sel.options[2] = new Option('MotherBoard MSI', 'MotherBoard MSI');
	sel.options[3] = new Option('Graphiqcard ASUS', 'Graphiqcard ASUS');
	sel.options[4] = new Option('GraphigCard ATI', 'GraphigCard ATI');
	sel.options[5] = new Option('GraphigCard GefORCE', 'GraphigCard GefORCE');
	cellRightsel.appendChild(sel);
	sum();
}
function removeRowFromTable()
{
  var tbl = document.getElementById('sheet');
  var lastRow = tbl.rows.length;
  if (lastRow > 2) tbl.deleteRow(lastRow - 1);
}
 
function sum(){
	var s1 = 0;
	var s2 = 0;
	var tbl=document.getElementById('sheet');
	var iteration=tbl.rows.length-1;
	for(var i=1; i<=iteration; i++){//loop through table rows
		var el1 = document.getElementById('txtRow'+i);//Row's Income field
		var el2 = document.getElementById('selRow'+i);//Row's percentage menu
		var ela = document.getElementById('txtRowe'+i);//Row's Tax cell
		var elaz=document.getElementById('txtRowaz'+i);
 
		if(!el1 || !el2 || !ela||!elaz) continue;
		var txt = el1.value;
		if(txt != ( '' + Number(txt) )) continue;  //reject non-numeric entries
 
var tax = Number(txt) * Number(130);
 
if(el2[el2.selectedIndex].value=="MotherBoard Gigabyte"){
	var  tax = Number(txt) * Number(150);
 
 
}
if(el2[el2.selectedIndex].value=="MotherBoard MSI"){
	var  tax = Number(txt) * Number(100);	
	
}
if(el2[el2.selectedIndex].value=="Graphiqcard ASUS"){
	var  tax = Number(txt) * Number(85);	
 
}
if(el2[el2.selectedIndex].value=="GraphigCard ATI"){
	var  tax = Number(txt) * Number(95);	
 
}
if (el2[el2.selectedIndex].value=="GraphigCard ATI")
{
 
		var tax = Number(txt) * Number(88);
}
 
		ela.value = tax.toFixed(2);
		elaz.value=tax.toFixed(2)/Number(txt);
		if(isNaN(elaz.value)){
		elaz.value=0;
		}
		s1 += Number(txt);
		s2 += tax;
	
}
	var t1 = document.getElementById('total');
	var t2 = document.getElementById('taxtotal');
	if(t1){ t1.value = s1.toFixed(2); }
	if(t2){ t2.value = s2.toFixed(2); }
}
 
onload = function(){
	addrow();
}
</script>
</head>
<body>
<form name="eval_edit" method="POST" action="part1.php?id=iteration-1">
<table align="center" width="75%">
<tr>
<td align="center">Balance sheet</td></tr>
<tr>
<td align="center">
	<table id="sheet" border="1">
	<tr><td>object</td><td>Total amount</td><td>One ITEM Price</td><td name="amount">Total Item Price </td><td>Name</td></tr>
 
	</table>
</td>
</tr>
<tr>
<td align="center">
<input type="hidden" name="count_rows" id="count_rows" />
<input type="button" value="Add" onclick="addrow()" />
<input type="button" value="Remove" onclick="removeRowFromTable()" />
<input type="button" value="SUM" onClick="sum()"/>
<input type="submit" value="Submit" /><br />
</td>
</tr>
<tr>
<td align="left">
<input id="total" name="total" type="text"/>total amount of products<br />
<input id="taxtotal" name="taxtotal" type="text"/>total price of products
</td>
</tr>
</table>
</form>
 
</body>
</html>
mikecronauer commented: very useful +1

Recommended Answers

All 19 Replies

U mean once u select the name from combobox, should not allow user to select same name in coming rows. is it correct??

yeah
as you said
thank you for your attention

Azegurb,

I have had a hack at your code and in the process come to the conclusion that you might consider something slighly different. Namely :

  • a single select menu, from which items are added to the table, and which is much easier to manage than one select menu per row.
  • one remove button per row, thus allowing any row to be removed, not just the bottom row. This (probably) requires the table rows to be renumbered but that's is quite easliy achieved.

Apart from these aspects, I think it meets your spec. Items are removed from the products menu when added to the "sheet" table, and are reinstated in the products menu if they are removed from the "sheet" table.

Here's the code:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>dinamik sheet</title>
<script> 
var products = [
	{ name:'MotherBoard ASUS',     value:'MotherBoard ASUS',     option:null },
	{ name:'MotherBoard Gigabyte', value:'MotherBoard Gigabyte', option:null },
	{ name:'MotherBoard MSI',      value:'MotherBoard MSI',      option:null },
	{ name:'Graphiqcard ASUS',     value:'Graphiqcard ASUS',     option:null },
	{ name:'GraphigCard ATI',      value:'GraphigCard ATI',      option:null },
	{ name:'GraphigCard GefORCE',  value:'GraphigCard GefORCE',  option:null }
];
products.init = function(menu, table, totalField, taxtotalField, countRowsField) {
	this.menu = menu;
	this.table = table;
	this.totalField = totalField;
	this.taxtotalField = taxtotalField;
	this.countRowsField = countRowsField;
	var i, that = this;
	for(i=0; i<this.length; i++) {
		this[i].option = document.createElement('option');
		this[i].option.innerHTML  = this[i].name;
		this[i].option.value      = this[i].value;
		this[i].option.activate   = function() { this.active = 1; }
		this[i].option.deactivate = function() { this.active = 0; }
		this[i].option.activate();
	}
	table.renumber = function() {
		var i;
		for(i=1; i<this.rows.length; i++) {
			this.rows[i].renumber(i);
		}
		that.countRowsField.value = this.rows.length - 1;
	}
	this.buildMenu();
}
products.buildMenu = function() {
	var i;
	while(this.menu.length >= 2) { this.menu.removeChild(this.menu[1]); }
	for(i=0; i<this.length; i++) {
		if(this[i].option.active) { this.menu.appendChild(this[i].option); }
	}
	this.menu.selectedIndex = 0;
}
products.addProductToTable = function() {
	var that = this;
	if(this.menu.selectedIndex == 0) { return; }
	var selectedOption = this.menu[this.menu.selectedIndex];
	var tbl = this.table;
	var row = tbl.insertRow( tbl.rows.length );
	row.remove = function() { this.parentNode.removeChild(this); }
	row.renumber = function(x) {
		cellLeft.innerHTML = x;
		el.name   = 'txtRow' + x;
		el.id     = 'txtRow' + x;
		elaz.name = 'txtRowaz' + x;
		elaz.id   = 'txtRowaz' + x;
		ela.name  = 'txtRowe' + x;
		ela.id    = 'txtRowe' + x;
	};
 
	var cellLeft = row.insertCell(0);
 
	var cellRight = row.insertCell(1);
	var el = document.createElement('input');
	el.type = 'text';
	el.size = 15;
	el.value = '0';
	el.onblur = function() { that.sum(); };
	cellRight.appendChild(el);
 
	var cellRight = row.insertCell(2);
	var elaz = document.createElement('input');
	elaz.type = 'text';
	elaz.size = 20;
	elaz.value = '0';
	elaz.onblur = function() { that.sum(); };
	cellRight.appendChild(elaz);
 
	var cellRight1 = row.insertCell(3);
	var ela = document.createElement('input');
	ela.type = 'text';
	ela.size = 20;
	ela.value = '0';
	ela.onblur = function() { that.sum(); };
	cellRight1.appendChild(ela);

	//*********

	var cellRightName = row.insertCell(4);
	var hiddenValue = document.createElement('input');
	hiddenValue.type = 'hidden';
	hiddenValue.value = selectedOption.value;
	cellRightName.appendChild(document.createTextNode(selectedOption.innerHTML));
	cellRightName.appendChild(hiddenValue);

	var cellRightRemove = row.insertCell(5);
	var removeButton = document.createElement('button');
	removeButton.innerHTML = 'Remove';
	removeButton.onclick = function() {
		selectedOption.activate();
		that.buildMenu();
		row.remove();
		that.table.renumber();
	};
	cellRightRemove.appendChild(removeButton);
	selectedOption.deactivate();
	this.buildMenu();
	this.table.renumber();
}
products.sum = function() {
	var i, s1=0, s2=0;
	var tbl = this.table;
	for(i=1; i<tbl.rows.length; i++){//loop through table rows
		var el1  = document.getElementById('txtRow'+i);//Row's Income field
		var el2  = document.getElementById('selRow'+i);//Row's percentage menu
		var ela  = document.getElementById('txtRowe'+i);//Row's Tax cell
		var elaz = document.getElementById('txtRowaz'+i);
 
		if(!el1 || !el2 || !ela|| !elaz) continue;
		var txt = el1.value;
		if(txt != ( '' + Number(txt) )) continue;  //reject non-numeric entries
 
		var tax = Number(txt) * Number(130);

		if(el2[el2.selectedIndex].value=="MotherBoard Gigabyte") {
			var tax = Number(txt) * Number(150);
		}
		if(el2[el2.selectedIndex].value=="MotherBoard MSI") {
			var tax = Number(txt) * Number(100);
		}
		if(el2[el2.selectedIndex].value=="Graphiqcard ASUS") {
			var tax = Number(txt) * Number(85);
		}
		if(el2[el2.selectedIndex].value=="GraphigCard ATI") {
			var tax = Number(txt) * Number(95);
		}
		if (el2[el2.selectedIndex].value=="GraphigCard ATI") {
			var tax = Number(txt) * Number(88);
		}
		ela.value = tax.toFixed(2);
		elaz.value = tax.toFixed(2)/Number(txt);
		if(isNaN(elaz.value)) {
			elaz.value=0;
		}
		s1 += Number(txt);
		s2 += tax;
	}
	if(this.totalField) { this.totalField.value = s1.toFixed(2); }
	if(this.taxtotalField) { this.taxtotalField.value = s2.toFixed(2); }
}

onload = function() {
	var menu           = document.getElementById('productOptions');
	var tbl            = document.getElementById('sheet');
	var totalField     = document.getElementById('total');
	var taxtotalField  = document.getElementById('taxtotal');
	var countRowsField = document.getElementById('count_rows');
	products.init(menu, tbl, totalField, taxtotalField, countRowsField);
};
</script>
</head>

<body>
<form name="eval_edit" method="POST" action="part1.php?id=iteration-1">
<table align="center" width="75%">
<tr>
<td align="center">Balance sheet</td></tr>
<tr>
<td align="center">
	<table id="sheet" border="1">
	<tr>
	<td>object</td>
	<td>Total amount</td>
	<td>One ITEM Price</td>
	<td name="amount">Total Item Price</td>
	<td>Name</td>
	<td>Action</td>
	</tr>
	</table>
</td>
</tr>
<tr>
<td align="center">
<input type="hidden" name="count_rows" id="count_rows" />
<input type="button" value="SUM" onClick="products.sum()"/>
<input type="submit" value="Submit" /><br />
</td>
</tr>
<tr>
<td align="left">
<select id="productOptions"><option value="">Select product</option></select>&nbsp;<button onclick="products.addProductToTable();return false;">Add</button><br />
<input id="total" name="total" type="text"/>&nbsp;total amount of products<br />
<input id="taxtotal" name="taxtotal" type="text"/>&nbsp;total price of products
</td>
</tr>
</table>
</form>
 
</body>
</html>

You will see that everything centres around the products array and its methods. This approach has two advantages:

  • It keeps the global namespace clean (just one member)
  • It should be easy to add further product menus connected to the same table or their own tables if this was ever necessary.

You may need to revisit your sum() function, which is largely unmodified.

Give it a try.

Airshow

Thanks very much.
you are my online teacher:icon_wink:
But one thing i didnt understand
what is

It keeps the global namespace clean (just one member)

and what does mean

option:null
that = this;
that.table.renumber();
this.table.renumber();
It keeps the global namespace clean (just one member)

Every variable/object/function within <script></script> tags is in the global namespace unless it is either "anonymous" or wrapped in something else (typically a function) and written in such a way as to make it local to its wrapper. As web pages get more and more complex, so the chances increase of conflicts within the global namespace - in other words, accidental double use of a variable/object/function name (each name is a "member"). As you will appreciate, this is a particularly important issue when two or more programmers work on the same web site, or when writing/using a general purpose javascript library (such as jQuery, Prototype or MooTools). Ultimately it is possible to write complex, multi-faceted code and put no more than one member into the global namespace. Once you appreciate the problem and have mastered the techniques, non-pollution of the global namespace can become obsessive.

option:null

This is not strictly necessary because:

  1. javascript does not require object properties to be declared.
  2. these nulls get overwritten almost immediately by the statement this[i].option = document.createElement('option'); in products.init.

These option:null statements are included as an at-a-glance cue to the total composition of the products objects. This sort of thing can be very useful when revisiting old code (by self or someone else).

that = this;
...
that.table.renumber();
...
this.table.renumber();

this is a contextual referrer. (It was well discussed here). When code gives rise to nested scopes (one scope within another), then an inner this applies to its (inner) scope; there is no syntactic way to refer directly to the outer this . The way round the problem is to make an alias for the outer this and the standard way is with that = this; in the outer scope. Hence, we can use that in the inner scope to refer unambiguously to this in the outer scope (as long as the inner scope doesn't have a that of its own).

Airshow

hi Airshow,
very sorry. I disturb you again. when we write

this

we mean

products

object. am I true?
thanks in advance

Aze,

You have the right idea but be careful. You have to look at the context each time this and that are used.

  • Lines 16-28, 35, 37, 41-45, 48-51, 110-111, 115, 151-152 : this refers to products .
  • Line 35, 48, 71, 79, 87, 104, 106 : that refers to products .
  • Lines 32-33, 35 : this refers to table .
  • Line 53 : this refers to row .

Airshow

Thank you very much
i understood

hi airshow.
if possible can you help me
i have one question about selecting chekboxes.
i have script form that adds dynamic rows and cheks/uncheks checkboxes. by default this form has one checkbox. There are functions which checks/uncehks only when i entered one row at least. when i dont enter any row it doesnt checks any checkboxes. can you explain and help me why?
thanks in advance
here is link
http://www.daniweb.com/forums/thread316653.html

hi Airshow.
can you explain it for me
why did you use here

while(this.menu.length >= 2) { this.menu.removeChild(this.menu[1]); }

what is

this.menu[1]

or

this.menu[1]

?
i understand this

row.remove = function() { this.parentNode.removeChild(this); }

but i dont understand

while(this.menu.length >= 2) { this.menu.removeChild(this.menu[1]); }

thanks again for attention

Aze,

It's some time since I wrote that. while(this.menu.length >= 2) { this.menu.removeChild(this.menu[1]); } is an efficient way to remove all menu options except the first this.menu[0] .

On removing the second option, this.menu[1] , all other options move up one place, giving a new this.menu[1] to be removed at the next iteration.

The test while(this.menu.length >= 2) ensures we don't try to remove a non-existent option and end on an error.

Airshow

Thank you Airshow. but i didnt understand again. this inside products.buildMenu.
this function initialises (builds) menu. on the one hand it builds menu like this

for(i=0; i<this.length; i++) {
		if(this[i].option.active) { this.menu.appendChild(this[i].option); }
	}

i dont understand that why we remove and then append options inside products.build function. I know i disturb you but if possible can you show simple example for this

while(this.menu.length >= 2) { this.menu.removeChild(this.menu[1]); }

thanks thanks thanks

Aze,

i dont understand that why we remove and then append options inside products.build function.

The reason is that if products.buildMenu() is called more than once, we don't want the menu to grow and grow. This is exactly what would happen if the previously-added options were not cleared out before adding new options.

The first time products.buildMenu() is called, there's nothing to clear (execution will drop straight through the while clause) but on any subsequent calls, clearing is necessary.

Airshow

thank you again Airshow. i understood the next for loop will append only active options, right?
Thank you very much. Sorry for convenience

i understood the next for loop will append only active options, right?

Yup. Only active options.

hi Airshow,
sorry for disturbing several times. one question arises the script you wrote
i cannot figure out what does mean

if(this[i].option.active)

?
may be this is like that.

if(this[i].option.activate())

? is this true
what does mean

this[i].option.activate   = function() { this.active = 1; }		this[i].option.deactivate = function() { this.active = 0; }

here i didnt understand

this.active=1

or

this.active=0

?
Thanks again for attention. this is really good script. and sorry for convenience for several times times

Aze, .active is a boolean flag that indicates whether or not to include each option. .activate and .deactivate are methods (functions) that set the flag to 1 and 0 respectively.

This approach allows the options to be excluded without actually deleting them.

Airshow

Aze, .active is a boolean flag that indicates whether or not to include each option. .activate and .deactivate are methods (functions) that set the flag to 1 and 0 respectively.

This approach allows the options to be excluded without actually deleting them.

Airshow

oooh i understand for ex:this.active=true equals this.active=1 and this.active=0 equals this.active=false
am i right?
Thank you ver much Airshow

That's exactly right.

Airshow

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.