[jQuery] Automatically expanding input form --- please help to port it to jQuery!
Quite frequently, I need an input form with a variable number of
records/rows --- as many as the visitor wants to enter (which is not
known before hand).
Please check the following example (tested with Firefox):
http://www.yaakovnet.net/AutoForm/input.html
As soon as the visitor selects an option from the select box, a new
input row is appended --- allowing unlimited input. The visitor can
also delete a record by selecting the option '---' from the select
box.
I would like to improve my JavaScript and turn it into a generally
usable jQuery module (unless such feature already exists and the work
is not necessary). As I am new to jQuery, I request the guidance of
experienced jQuery programmers how to do it "the right way".
Of course, I am a programmer --- I can follow your hints, read
documentation, implement code and test it. Here I am just asking for
guidance. In particular, pointing out which of the many available
jQuery features are usable in this project will be very helpful.
Here is a description of how I implemented the current version --- I
am happy for any feedback (in particular criticism).
=== 1. Getting started ===
The document contains an empty table with id="searchinput".
The body tag has an event onload="init_searchinput();"
The function init_searchinput() creates the two initial input rows by
calling the add_row() function with the appropriate HTML text of the
rows:
function init_searchinput() {
add_row('<tr><td_align=""center>... /// pre-formatted html text ///
</td></tr>');
add_row('<tr><td_align=""center>... /// pre-formatted html text ///
</td></tr>');
')
The function add_row selects the searchinput table, adds a row to the
end and inserts the provided HTML:
function add_row(str) {
var row=document.getElementById('searchinput').insertRow(-1);
var id=++id_max;
row.innerHTML=str.replace(/#id#/g,id);
}
Note1: This is working but bad design: It would be much better to
start with a YAML list of the initial values and to build the input
elements from this data. But I don't yet know how to build tables and
input fields step by step in JavaScript. Hence, I used the innerHTML
feature. Any advice on building table rows and input fields in
JavaScript will greatly be appreciated.
Note2: I did make some experiments with building the input fields in
JavaScript ---- but it did not work: Even though HTML output *looked*
ok --- but the input fields were not connected to the input form: I
entered numbers and clicked on the "submit" button ---- but the data
was not sent to the server. I don't know why it did not work.
=== 2. Adding rows automatically ===
The select box in each row has an event:
onchange=changed_selection(this): this function will add or remove
rows as needed:
function changed_selection(x) {
var y=x.options[0]; var t=y.text; y.text="---";
if(x.options[x.selectedIndex].text=="---") {delete_row(x);}
if(t=="?"){add_row(new_row);}
}
The first option (x.options[0]) is "?" in the last row and "---" in
all other rows. When you change the selection in the last row, the
function changed_selection(x) noticed the value "?", changes it to
"---" and adds a new row to the input form. As it happens, in the new
row, x.options[0] is "?" --- so you always get a new row when you
change the selection in the bottom row.
=== 3. Deleting rows ===
If you change the selection to "---" (which is in the same place where
the "?" originally was), the delete_row(x) function deletes the
current row:
function delete_row(x) { var y=x;
while(x){if(x.deleteRow){
x.deleteRow(y.rowIndex);return;} x=(y=x).parentNode
}
}
This function does some DOM traversing --- it should definitely use
the appropriate jQuery methods instead of my hand-baked loop.
Basically, we move up the DOM tree from the current input form until
we find a parent x that has a deleteRow method. Once we found that
parent x, the previous step y refers to the table row that we want to
delete. We get it's rowIndex and delete it.
This code works on Firefox ---- but I am not sure that it's portable.
Again, any guidance on how to do this properly will be greatly
appreciated.
=== Moving on from here ===
Please point me to jQuery features (or more appropriate JavaScript
features) to achieve the same results as the current code (portable).
I would be quite happy to understand how I can build the input forms
and table rows without pre-formatted innerHTML.
Once the core functionality works properly, I will convert this to a
more standard jQery interface. Any suggestions about usable options
are appreciated.
Thanks,
Yaakov