Dear All,
I have my link http://183.78.169.53/tm/layout.php. Basically I have two buttons one Add Single and one Add Double. When I press Add Single I want to have a new row with the single drop down list. On the other hand when I press the Add Double I want to have a new row with the two drop down list. How to achieve this any help please?

Recommended Answers

All 24 Replies

You will need to set an event that fires when each button is clicked. You should give your buttons id attributes in their HTML tags.

In the javascript, make a function that, depending on the id of the button that was clicked, appends the HTML for a new row consisting of one or two new list boxes.

So if "Double" was clicked, you would add:

<tr>
  <td>
    (Markup for one list)
  </td>
  <td>
    (Markup for one list)
  </td>
</tr>

To the bottom of your table. Also, you should have the buttons return false when they are clicked so you don't submit the form each time. I'm not exactly sure about what you're doing with this form, but if this is a purely javascript question (with no server-side processing necessary), you don't want to submit the form each time the buttons are clicked or else the page will reload, which will reset the form to its original state.

Dear TySkby,
You can view here the site http://183.78.169.53/tm/layout.php. Now when I click either one of the button will call the respective functions but I dont know how to add the rows accordingly. Finally I want to save all this data into mysql db via php.

Then there's some decisions to make here.

One thing you could do is add the rows locally (on the client side) and then once everything is complete, have another button (eg. "Save") that actually submits the form and saves the data to mysql.

Another solution(which would be a bit more advanced) would be to incorporate some Ajax functionality into your existing buttons, so that when they're clicked they make a call to a PHP script that saves the current form data to mysql, and then when it calls back successfully, you go ahead and run the javascript necessary to add the new row (and all of this would happen without reloading the page, since you'd be using Ajax). You would probably still want a save button for when you're all done but don't want to add any more rows.

Dear Tyskyby,
I think I will go with your first method. That looks a bit simpler and easier to implment right. So can you guide me how to add the rows?

Another solution(which would be a bit more advanced) would be to incorporate some Ajax functionality into your existing buttons, so that when they're clicked they make a call to a PHP script that saves the current form data to mysql, and then when it calls back successfully, you go ahead and run the javascript necessary to add the new row (and all of this would happen without reloading the page, since you'd be using Ajax). You would probably still want a save button for when you're all done but don't want to add any more rows.

Newbie14, Your decision is correct. Don't be tempted to try an ajax/mysql solution. Some simple javascript will do the job.

If I understand correctly, then the only javascript commands required in each of the two functions are:

  • .getElementById to find various DOM nodes (the two original TRs (single/double) and the TBODY)
  • .cloneNode to clone one of the TRs
  • .appendChild to insert the cloned row into the tbody

Airshow

Dear Airshow,
Can you show me for one of the row of on how to add it accordingly? I am now trying like this, but before that I try to separate the two dropdownlist into separate divs? But this method is not working either.

<th><button class="add" onclick="document.getElementById('one').style.display = 'block';">Single</button></th>
<th><button class="add" onclick="document.getElementById('two').style.display = 'block';">Double</button></th>

I think you need something as simple as this:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head> 
<link rel="stylesheet" type="text/css" href="my1.css" media="all"> 
<style> 
.dynatable {
  border: solid 1px #000; 
  border-collapse: collapse;
}
.dynatable th,
.dynatable td {
  background-color:#ccc; 
  font-size:14px;
  color:#ffffff;
  font-family:Calibri;
}
.dynatable .prototype {
}
label.error {
  display: block; 
  color:red;
}
td { vertical-align: top; }
</style>  

<script type="text/javascript">
onload = function(){
	var addSingle = document.getElementById("addSingle");
	var addDouble = document.getElementById("addDouble");
	var singleRow = document.getElementById("singleRow");
	var doubleRow = document.getElementById("doubleRow");
	var extraRows = document.getElementById("tbody1");
	addSingle.onclick = function(){
		var r = singleRow.cloneNode(true);
		extraRows.appendChild(r);
		return false;
	};
	addDouble.onclick = function(){
		var r = doubleRow.cloneNode(true);
		extraRows.appendChild(r);
		return false;
	};
};
</script>
</head>

<body> 

<div>
	<h2 class="form_desicription">Tyre Code</h2>
</div>

<form action="/tm/layout.php" method="post" name="form1" id="form1" onSubmit="return validateForm();">

<table> 
<tr>
<td width="700" valign="top">
	<table class="dynatable" id="layout">
	<thead>
	<tr>
	<th>In</th>
	<th>Out</th>
	<th><button id="addSingle" class="add">Single</button></th>
	<th><button id="addDouble" class="add">Double</button></th>
	</tr>
	</thead>
	<tbody id="tbody1">
	<tr id="singleRow">
	<td><select id='layoutSingle[1]' name='layoutSingle[1]' ><option value=''>-Select Code-</option><option value=1>F1L</option><option value=2>F1R</option><option value=7>R1L</option><option value=8>R1R</option><option value=9>R2L</option><option value=10>R2R</option><option value=11>R3L</option><option value=12>R3R</option></select></td>
	<td></td>
	<td></td>
	<td></td>
	</tr>
	<tr id="doubleRow">
	<td><select id='layoutSingle[1]' name='layoutSingle[1]' ><option value=''>-Select Code-</option><option value=3>FI1L</option><option value=4>FI1R</option><option value=5>FO1L</option><option value=6>FO1R</option><option value=13>RI1L</option><option value=14>RI1R</option><option value=15>RO1L</option><option value=16>RO1R</option><option value=17>RI2L</option><option value=18>RI2R</option><option value=19>RO2L</option><option value=20>RO2R</option></select></td>
	<td><select id='layoutSingle[1]' name='layoutSingle[1]' ><option value=''>-Select Code-</option><option value=3>FI1L</option><option value=4>FI1R</option><option value=5>FO1L</option><option value=6>FO1R</option><option value=13>RI1L</option><option value=14>RI1R</option><option value=15>RO1L</option><option value=16>RO1R</option><option value=17>RI2L</option><option value=18>RI2R</option><option value=19>RO2L</option><option value=20>RO2R</option></select></td>
	<td></td>
	<td></td>
	</tr>
	</tbody>
	</table>
</td>
</tr>
</table>

</form>

</body> 
</html>

Note that the button's onclick handlers are attached in javascript, not in the HTML. By doing this, and storing the results of several document.getElementById in the onload closure, we avoid the need to call document.getElementById within the onclick handlers every time one of the buttons is clicked. Hence the code is more efficient.

Airshow

commented: Nice example +4

Dear Airshow,
I will try out your code and I think is very good and simple to understand too.In addition to that I will be having a remove button on each row. So if accidently they remove the first two rows how recover them? Any idea?

You are right to be concerned over deletion of the prototype rows.

Two possible strategies are:

  • Hide the prototypes so they are never seen and cannot be removed
  • Hide the "remove" buttons in the prototypes, so they can't be deleted.

Airshow

Dear Airshow,
I think I will go with the first solution. How to do it just apply display:none will it work? Beside that how to make the remove the row accordingly so must I give each remove button a different id? Another think each time I add the row I want to change its id 'layoutSingle[1]' where the bracket value should grow. This is because I am going to post and add the values into database via php.

Yes, hide the prototype rows' buttons with display:none . But when the row is cloned, the new row will also have hidden buttons so you have to find the buttons within the cloned row and show them. Use r.getElementsByTagName('button') to obtain an array of buttons; there should be just one.

To make the remove buttons work, first find the tr relative to the button that was clicked using .parentNode().parentNode() . Then remove the row.

I've never tried this but I think that if you use name="layoutSingle[]" , then in php $_GET('layoutSingle') will be an array of values. No need to expressly index the elements.

Airshow

Dear Airshow,
How to hide the prototypes so they are never seen and cannot be removed? I feel I need the indexing because before submit I am going to check each dropdown list to make sure none of the dropdown list is having the same value selected. So I was planning to traverse based on the index to check the values?

can you describe the task u are trying to achieve (but from the user poin of view) and how - because I'm not being able to understand what needs to do what, nor how or why.
why are those optons single/double, or what's the deal with the deleting precaution, cause I dont see anything of a kind there; or why do you need more dups of the same options etc..., because the list is finite I think that your aproach to the problem may be wrong, but about this; latter.

Dear Troy,
Ok from the user point of view the use will click either single or doulbe button. Accordingly a new row with single or double dropdown list will be created. Why the single/double is actually representing the tyre positions? Thus I have labeled the tyres for eg. F1 it mean Front row 1. and another e.g R01 means Rear row 1. Thus I am creating each row of the tyre some row got only 2 (single dropdown list) and some got 4(double dropdownlist). So that is why I cannot allow any of the drop down list to have same value selected. I hope I am clearer to you now.

Why not have a checklist?!

Dear Troy,
I don't get you with your checklist idea can give me more details or
Snippet of codes.

I think Troy is right to ask if the overall concept is workable. My own understanding of tyres is limited. Let's see what emerges.

Airshow

Dear Airshow and Troy,
Appreciate you guys man for the help and time. Lets see how the checklist will work home it will do some work for me too. Thank you.

Excellent example, Airshow- that's pretty much what what I was going to suggest.

I do have one question, since you mentioned efficiency in your example and I was curious about it- could you explain a bit more? Specifically with this part of the example:

<script type="text/javascript">
onload = function(){
	var addSingle = document.getElementById("addSingle");
	var addDouble = document.getElementById("addDouble");
	var singleRow = document.getElementById("singleRow");
	var doubleRow = document.getElementById("doubleRow");
	var extraRows = document.getElementById("tbody1");
	addSingle.onclick = function(){
		var r = singleRow.cloneNode(true);
		extraRows.appendChild(r);
		return false;
	};
	addDouble.onclick = function(){
		var r = doubleRow.cloneNode(true);
		extraRows.appendChild(r);
		return false;
	};
};
</script>

I understand why it's more efficient to define the vars "singleRow", "doubleRow", and "extraRows" in the onload closure. But why is it better to have "addSingle" and "addDouble" defined there, as opposed to something like this:

<script type="text/javascript">
var singleRow = document.getElementById("singleRow");
var doubleRow = document.getElementById("doubleRow");
var extraRows = document.getElementById("tbody1");

function addSingleRow(){
	var r = singleRow.cloneNode(true);
	extraRows.appendChild(r);
	return false;
};

function addDoubleRow(){
	var r = doubleRow.cloneNode(true);
	extraRows.appendChild(r);
	return false;
};
</script>

and then have this in the HTML <body>:

<th><button id="addSingle" class="add" onclick="addSingleRow();">Single</button></th>
<th><button id="addDouble" class="add" onclick="addDoubleRow();">Double</button></th>

I'm basically just curious (not critical)- why would the extra declarations and the anonymous functions be better than no declarations for those two button elements with named functions? Would you mind explaining that?

Thanks,
Ty

PS- Not my intention here to hijack this thread- if the OP would like me to make this another discussion, I'd be happy to do so.

Ty,

It's generally considered "good practice" to attach event handlers in javascript but this needs some explanation.

The problem with onclick="whatever();" is that whatever would have to be a function in the global namespace; it would be out of scope inside another function, whether or not that other function formed a closure by other means.

Four main points:

  • It is good practice not to "pollute the global namespace".
  • document.getElementById is expensive, especially in a document with many nodes.
  • Any call of document.getElementById from outside a function (ie. from the global namespace) would fail because it would execute before the document had loaded. For this reason, your suggested script would not work.
  • Without using the global namespace or exploiting a closure, no event handler could possibly take advantage of the results of any previously executed document.getElementById call (or any other variable for that matter). Hence, the handler would have to execute every document.getElementById it needs, every time it was executed (potentially many times during the life of the page).

For me, an additional benefit of attaching handlers in javascript is the ability to see what's going on "at-a-glance" (ok, sometimes a pretty big glance).

The downside of attaching handlers in javascript is that you are forced also to discover the DOM elements to which the handlers must attach, using that horribly expensive document.getElementById. This is generally outweighed by the advantages.

Airshow

Awesome, thanks- that makes a lot of sense.

And yeah, I knew that my script would fail since there are calls to variables in other functions. I just wanted a quick example to show what I meant.

For me, an additional benefit of attaching handlers in javascript is the ability to see what's going on "at-a-glance" (ok, sometimes a pretty big glance).

Yeah, outside of the efficiency thing, that's something I would consider a huge benefit. It sucks to have to hunt around for every "onclick" event in the document body when you're not sure what all they might be. Definitely simpler to see them all defined at the top.

Thanks for clearing that up- I feel smarter already!

Dear All,
Any solution on how to handle the index for me to last capture this value when I post it over to php for processing? Anothering also how to make sure that each dropdown list from each row is selected and none of the dropdownlist from all the rows could be the same.

n14,

Any solution on how to handle the index for me to last capture this value when I post it over to php for processing?

Have you tried my suggestion, 2nd post on Page 2.

Airshow

Dear Airshow and Troy,
Appreciate you guys man for the help and time. Lets see how the checklist will work home it will do some work for me too. Thank you.

"50% of the solution lies in accurately describing the problem!" by Airshow
Thats because he's being humble since: accurately describing the problem yelds no less than 99.9% probability that somebody will find you a solution.

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.