For instance, I want to have a html form that looks like this:
<table>
<tr>
<td>Field A:</td>
<td><input type='text' name='fielda[1]'></td>
<td>Field B:</td>
<td><textarea name='fieldb[1]'></textarea></td>
</tr>
</table>
What I want is to add a button that duplicates my entire above form, but changes the 1 to a 2 for all of the fields. Not just one field, but the entire section of code, including the table.There will be more/different fields than the ones I posted as well.
I've already tried this solution, which does exactly what I need:
.html
But for some reason, could not duplicate the functionality when copying the code examples to test. I even tried literally copying the entire page source to get it to work, with no avail.
For instance, I want to have a html form that looks like this:
<table>
<tr>
<td>Field A:</td>
<td><input type='text' name='fielda[1]'></td>
<td>Field B:</td>
<td><textarea name='fieldb[1]'></textarea></td>
</tr>
</table>
What I want is to add a button that duplicates my entire above form, but changes the 1 to a 2 for all of the fields. Not just one field, but the entire section of code, including the table.There will be more/different fields than the ones I posted as well.
I've already tried this solution, which does exactly what I need:
http://www.quirksmode/dom/domform.html
But for some reason, could not duplicate the functionality when copying the code examples to test. I even tried literally copying the entire page source to get it to work, with no avail.
Share Improve this question asked Sep 22, 2009 at 19:30 CitizenCitizen 13k27 gold badges79 silver badges119 bronze badges5 Answers
Reset to default 6There's a technique called supplant that does this. I didn't write it, I think Douglas Crockford did. But I'll quote it:
Now that your JavaScript program has received the data, what can it do with it? One of the simplest things is client-side HTML generation.
var template = '<table border="{border}"><tr><th>Last</th><td>{last}</td></tr>' +
'<tr><th>First</th><td>{first}</td></tr></table>';
Notice that we have an HTML template with three variables in it. Then we'll obtain a JSON object containing members that match the variables.
var data = {
"first": "Carl",
"last": "Hollywood",
"border": 2
};
We can then use a supplant method to fill in the template with the data.
mydiv.innerHTML = template.supplant(data);
JavaScript strings do not e with a supplant method, but that is ok because JavaScript allows us to augment the built-in types, giving them the features we need.
String.prototype.supplant = function (o) {
return this.replace(/{([^{}]*)}/g,
function (a, b) {
var r = o[b];
return typeof r === 'string' ?
r : a;
}
);
};
From http://www.json/fatfree.html
One technique I've seen to avoid that messy variable assignment of a template is to do:
<script id="rowTemplate" type="text/html">
<tr>
<td>Field A:</td>
<td><input type='text' name='fielda[{id}]'></td>
<td>Field B:</td>
<td><textarea name='fieldb[{id}]'></textarea></td>
</tr>
</script>
This will let your write much prettier code as you can reference it with getElementById.
So in your case, rather than populating it with a JSON object, you would just look over however many rows you need to add and replace the id's.
The example you are linking to, has a hidden version of the form that is used as a template. This template has an ID (readroot
), that allows it to be easily selected (getElementById
), then cloned (node.cloneNode()
) and injected into the DOM above (node.insertBefore()
) a second marker in the source (writeroot
).
The number of duplications is kept accounted for in the variable counter
. Its' contents are updated (incremented) on every cloning, and its' value is then appended to all the field names in the cloned node. (The original template-nodes' fields have no numeric suffix.)
It's all really very simple, just study the javascript in the head-portion of the webpage. Google the parts you can't understand, and you will achieve what you're looking for, and will learn some in the process. Profit!
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3/1999/xhtml">
<head>
<script src="http://ajax.googleapis./ajax/libs/jquery/1.3/jquery.min.js" type="text/javascript"></script>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<script type="text/javascript">
(function($){
$countForms = 1;
$.fn.addForms = function(){
var myform = "<table>"+
" <tr>"+
" <td>Field A ("+$countForms+"):</td>"+
" <td><input type='text' name='fielda["+$countForms+"]'></td>"+
" <td>Field B ("+$countForms+"):</td>"+
" <td><textarea name='fieldb["+$countForms+"]'></textarea></td>"+
" <td><button>remove</button></td>"+
" </tr>"+
"</table>";
myform = $("<div>"+myform+"</div>");
$("button", $(myform)).click(function(){ $(this).parent().parent().remove(); });
$(this).append(myform);
$countForms++;
};
})(jQuery);
$(function(){
$("#mybutton").bind("click", function(){
$("#container").addForms();
});
});
</script>
</head>
<body>
<button id="mybutton">add form</button>
<div id="container"></div>
</body>
</html>
I think you should use some kind of library like jQuery, as some have suggested. It'll pay off.
Regarding making a template and cloning it in javascript, there are some problems when using IE (all versions as far as I know). IE will disregard any programmatical changes to 'name' property when duplicating e.g. radio buttons in a form. So unless you create custom event handlers for the radio buttons, they will not work as expected when you copy them across sections (e.g. checking a button in one section will cause a button in another section to be unchecked).
Oops, read you question incorrectly. This is better:
function duplicate(frm) {
newfrm = $(frm).clone();
$(newfrm).each(function(i,o) {
if (o.name != null) { // or if ($(o).attr("name"))
o.name = replaceIndex(o.name);
}
});
$(frm).parent().append(newfrm);
}
Not sure about actual syntax. E.g. how do you test for attribute presence. Easy to find in google, though. Here replaceIndex(string) uses lastIndexOf() to find last [x] and replace it to [x+1].