9 <td><input type="text" name="field1"></td>
10 <td><select name="field2">...</td>
14 <& /elements/auto-table.html,
16 template_row = 'mytemplate',
18 { field1 => 'foo', field2 => 'CA', ... },
19 { field1 => 'bar', field2 => 'TX', ... }, ...
25 fieldorder => [ 'field1', 'field2', ... ],
31 In the process/ handler, something like:
33 my %vars = $cgi->Vars;
34 for my $k ( keys %vars ) {
35 $k =~ /^${pre}magic(\d+)$/ or next;
37 # find all submitted names ending in this rownum
39 map { $_ => $vars{$_} }
40 grep /^(.*[\d])$rownum$/, keys %vars;
41 $thisrow->{num} = delete $thisrow{"${pre}magic$rownum"};
45 <tbody id="<%$pre%>autotable"></tbody>
46 <script type="text/javascript">
49 var <%$pre%>next_rownum;
50 var <%$pre%>set_rownum;
52 var <%$pre%>deleteRow;
53 var <%$pre%>fieldorder = <% to_json($fieldorder) %>;
55 function <%$pre%>possiblyAddRow_factory(obj) {
56 var callback = obj.onchange;
58 if ( obj.rownum == <%$pre%>tbody.lastChild.rownum ) {
59 // then this is the last row, and it's being changed, so spawn a new row
68 function <%$pre%>set_rownum(obj, rownum) {
71 obj.id = obj.id + rownum;
74 obj.name = obj.name + rownum;
75 // also, in this case it's a form field that will be part of the record
76 // so set up an onchange handler
77 obj.onchange = <%$pre%>possiblyAddRow_factory(obj);
79 for (var i = 0; i < obj.children.length; i++) {
80 if ( obj.children[i] instanceof Node ) {
81 <%$pre%>set_rownum(obj.children[i], rownum);
86 function <%$pre%>addRow(data) {
88 // warning: cloneNode doesn't clone event handlers that were set through
90 // if 'data' is an object, prepopulate the row's fields with the object's
92 // returns the rownum of the new row
93 var row = <%$pre%>template.cloneNode(true);
94 <%$pre%>tbody.appendChild(row);
95 var this_rownum = <%$pre%>next_rownum;
96 <%$pre%>set_rownum(row, this_rownum);
97 if(data instanceof Array) {
98 for (i = 0; i < data.length && i < <%$pre%>fieldorder.length; i++) {
99 var el = document.getElementsByName(<%$pre%>fieldorder[i] + this_rownum)[0];
104 } else if (data instanceof Object) {
105 for (var field in data) {
106 var el = document.getElementsByName(field + this_rownum)[0];
108 el.value = data[field];
109 % # doesn't work for checkbox
113 <%$pre%>next_rownum++;
117 function <%$pre%>deleteRow(rownum) {
118 if ( rownum == <%$pre%>tbody.lastChild.rownum ) {
119 // if this is the last row, spawn another one after it
122 var r = document.getElementById('<%$pre%>row' + rownum);
123 <%$pre%>tbody.removeChild(r);
126 function <%$pre%>init() {
127 <%$pre%>template = document.getElementById(<% $template_row |js_string%>);
128 <%$pre%>tbody = document.getElementById('<%$pre%>autotable');
129 <%$pre%>next_rownum = <%$pre%>template.sectionRowIndex;
130 // detach the template row
131 var table = <%$pre%>template.parentNode;
132 table.removeChild(<%$pre%>template);
134 <%$pre%>template.id = <%$pre |js_string%> + 'row';
135 // and a magic identifier so we know it's been submitted
136 var magic = document.createElement('INPUT');
137 magic.setAttribute('type', 'hidden');
138 magic.setAttribute('name', '<%$pre%>magic');
140 // and a delete button
141 %# should this be enclosed in an actual <button> for aesthetics?
142 var delete_button = document.createElement('IMG');
143 delete_button.id = 'delete_button';
144 delete_button.src = '<%$fsurl%>images/cross.png';
145 delete_button.alt = 'X';
146 // use an inline string for this so that it will be cloned properly
147 delete_button.setAttribute('onclick', "<%$pre%>deleteRow(this.rownum);");
148 var delete_cell = document.createElement('TD');
149 delete_cell.appendChild(delete_button);
150 delete_cell.appendChild(magic); // it has to go somewhere
151 <%$pre%>template.appendChild(delete_cell);
154 var rows = <% to_json(\@rows) %>;
155 for (var i = 0; i < rows.length; i++) {
156 <%$pre%>addRow(rows[i]);
167 $pre = $opt{'table'} . '_' if $opt{'table'};
168 my $template_row = $opt{'template_row'}
169 or die "auto-table requires template_row\n"; # a DOM id
171 # rows that we will preload, as hashrefs of name => value
172 my @rows = @{ $opt{'data'} || [] };
174 # allow an array of FS::Record objects to be passed
175 if ( blessed($_) and $_->isa('FS::Record') ) {
179 my $fieldorder = $opt{'fieldorder'} || [];