There are a lot of pieces to what you are wanting, so keeping things simple helps to ensure that success is not hard to achieve.
I will create a generic example here where a field of data is entered. That should be relatively easy for you or anyone else to expand to meet your own individual needs.
Start with a form, with a button to add data, and to submit the form data. You do not want to leave the user confused about what to do, or how to do it.
When the line of data has been entered, the user can either click the add button, or they can type “tab + space” to trigger it with the keyboard.
Right now, an empty form.
<form id="data" submit="processData.php">
<p>Please enter some data</p>
<fieldset>
<legend>Data</legend>
</fieldset>
<p><input type="button" name="add" value="Add more data">
<p><input type="submit" value="Submit all data"></p>
</form>
The purpose of the fieldset is just to provide a useful location to contain the data. It could just be another div, but we want a relatively easy way to find all data sections and hide them, so containing them in a fieldet is a useful technique because we can easily search for that.
Why is there no data field there yet? Because we can have the script trigger the “add more data” button when the page loads, which will add one to the form for us. That’s the last line of this script which is placed at the end of the body, just before the </body> tag.
var form = document.getElementById('data');
form.elements.add.onclick = addNewData;
form.elements.add.click();
The addNewData function is going to hide any divs that are already there, before adding a new data set to the end of the fieldset. When it adds the new data set, it can even set the focus to the first input field of that data set.
function addNewData() {
var form = this.form,
fieldset = form.getElementsByTagName('fieldset')[0],
divs = fieldset.getElementsByTagName('div'),
data = newData(divs.length + 1);
hideAll(divs);
fieldset.appendChild(data);
data.getElementsByTagName('input')[0].focus();
}
The newData function just returns a div element that contains the other form fields we want to see.
function newData(index) {
var div = document.createElement('div'),
span = document.createElement('span'),
text = document.createTextNode('Item ' + index + ' '),
data = document.createElement('input');
data.name = 'data[]';
span.appendChild(text);
div.appendChild(span);
div.appendChild(data);
return div;
}
The hideAll function loops through all divs in the fieldset, checking if they have been hidden of not, so that it can hide ones that have not yet been hidden.
function hideAll(elements) {
var len = elements.length,
i;
for (i = 0; i < len; i += 1) {
if (elements[i].style.display !== 'none') {
hide(elements[i]);
}
}
}
Finally we hide the div row, using a style declaration.
.hidden {
display: none;
}
function hide(element) {
element.className = 'hidden';
}
Here’s the fully working test demo of the auto-adding data form.
<html>
<head>
<style type="text/css">
.hidden {
display: none;
}
</style>
</head>
<body>
<form id="data" submit="processData.php">
<p>Please enter some data</p>
<fieldset>
<legend>Data</legend>
</fieldset>
<p><input type="button" name="add" value="Add more data">
<p><input type="submit" value="Submit all data"></p>
</form>
<script>
function hide(element) {
element.className = 'hidden';
}
function hideAll(elements) {
var len = elements.length,
i;
for (i = 0; i < len; i += 1) {
if (elements[i].style.display !== 'none') {
hide(elements[i]);
}
}
}
function newData(index) {
var div = document.createElement('div'),
span = document.createElement('span'),
text = document.createTextNode('Item ' + index + ' '),
data = document.createElement('input');
data.name = 'data[]';
span.appendChild(text);
div.appendChild(span);
div.appendChild(data);
return div;
}
function addNewData() {
var form = this.form,
fieldset = form.getElementsByTagName('fieldset')[0],
divs = fieldset.getElementsByTagName('div'),
data = newData(divs.length + 1);
hideAll(divs);
fieldset.appendChild(data);
data.getElementsByTagName('input')[0].focus();
}
var form = document.getElementById('data');
form.elements.add.onclick = addNewData;
form.elements.add.click();
</script>
</body>
</html>