]>
Commit | Line | Data |
---|---|---|
aff192e6 DM |
1 | package PVE::HTMLForm; |
2 | ||
3 | use strict; | |
4 | use HTML::Entities; | |
5 | use PVE::I18N; | |
6 | use PVE::HTMLTable; | |
7 | ||
8 | sub new { | |
9 | my ($type, $formdata, $name) = @_; | |
10 | my $self = {}; | |
11 | ||
12 | $self->{formdata} = $formdata; | |
13 | $self->{elements} = 0;# internal element counter | |
14 | $self->{submit} = 0; | |
15 | $self->{name} = $name ? $name : "frm"; | |
16 | ||
17 | bless($self, $type); | |
18 | ||
19 | $self->{action} = $self->{formdata}->{"form_$self->{name}_submit"}; | |
20 | ||
21 | $self->postaction; | |
22 | ||
23 | return $self; | |
24 | } | |
25 | ||
26 | sub postaction { | |
27 | my ($self) = @_; | |
28 | ||
29 | my ($key, %d); | |
30 | ||
31 | # Rebuild Date for IP, Bool and Time fields | |
32 | foreach $key (sort keys (%{$self->{formdata}})) { | |
33 | if ($key =~ m/ip_[0-9]+_(.*)/) { | |
34 | if (!(exists ($d{$1}))) { | |
35 | $d{$1}=1; | |
36 | defined ($self->{formdata}->{"ip_0_$1"}) || | |
37 | ($self->{formdata}->{"ip_0_$1"} = '0'); | |
38 | defined ($self->{formdata}->{"ip_1_$1"}) || | |
39 | ($self->{formdata}->{"ip_1_$1"} = '0'); | |
40 | defined ($self->{formdata}->{"ip_2_$1"}) || | |
41 | ($self->{formdata}->{"ip_2_$1"} = '0'); | |
42 | defined ($self->{formdata}->{"ip_3_$1"}) || | |
43 | ($self->{formdata}->{"ip_3_$1"} = '0'); | |
44 | $self->{formdata}->{"$1"} = | |
45 | $self->{formdata}->{"ip_0_$1"} . "." . | |
46 | $self->{formdata}->{"ip_1_$1"} . "." . | |
47 | $self->{formdata}->{"ip_2_$1"} . "." . | |
48 | $self->{formdata}->{"ip_3_$1"}; | |
49 | } | |
50 | } | |
51 | if ($key =~ m/time_[0-9]+_(.*)/) { | |
52 | if (!(exists ($d{$1}))) { | |
53 | $d{$1}=1; | |
54 | defined ($self->{formdata}->{"time_0_$1"}) || | |
55 | ($self->{formdata}->{"time_0_$1"} = '00'); | |
56 | defined ($self->{formdata}->{"time_1_$1"}) || | |
57 | ($self->{formdata}->{"time_1_$1"} = '00'); | |
58 | $self->{formdata}->{"$1"} = | |
59 | $self->{formdata}->{"time_0_$1"} . ":" . | |
60 | $self->{formdata}->{"time_1_$1"}; | |
61 | } | |
62 | } | |
63 | if ($key =~ m/cb_n_(.*)/) { | |
64 | if (!(exists ($d{$1}))) { | |
65 | my $name = $1; | |
66 | $d{$name} = 1; | |
67 | my $val = ""; | |
68 | my $tmp; | |
69 | foreach my $k (keys (%{$self->{formdata}})) { | |
70 | if ($k =~ m/cb__(\w+)_$name/) { | |
71 | $tmp->{$1} = 1; | |
72 | } | |
73 | } | |
74 | foreach my $k (keys (%$tmp)) { | |
75 | $val .= " " if $val; | |
76 | $val .= $k; | |
77 | } | |
78 | $self->{formdata}->{"$1"} = $val; | |
79 | } | |
80 | } | |
81 | if ($key =~ m/bool_n_(.*)/) { | |
82 | if (!(exists ($d{$1}))) { | |
83 | $d{$1}=1; | |
84 | my $val = "0"; | |
85 | if ($self->{formdata}->{"bool_$1"}) { | |
86 | $val = "1"; | |
87 | } | |
88 | $self->{formdata}->{"$1"} = $val; | |
89 | } | |
90 | } | |
91 | } | |
92 | } | |
93 | ||
94 | sub action { | |
95 | my ($self) = @_; | |
96 | return $self->{action}; | |
97 | } | |
98 | ||
99 | sub create_element { | |
100 | my ($self, $name, $type, $value, $opt, $width) = @_; | |
101 | ||
102 | my $out = ''; | |
103 | ||
104 | my $class = 'normal'; | |
105 | ||
106 | my $encvalue = encode_entities ($value); | |
107 | ||
108 | $width = 200 if !$width; | |
109 | ||
110 | my $innerwidth = $width - 5; # width - margin - border - padding | |
111 | ||
112 | my $widthstr = "style='width:${innerwidth}px;'"; | |
113 | ||
114 | # normal text | |
115 | if ($type eq "text") { | |
116 | $out .= "<input $widthstr class='$class' type='text' name=$name value='$encvalue'/>"; | |
117 | } | |
118 | elsif ($type eq "textarea") { | |
119 | my $rows = $opt || 4; | |
120 | my $rh = int ($rows*int(1.2*12+1)); | |
121 | $out .= "<textarea class='$class' name=$name style='width:${innerwidth}px;height:${rh}px;' ROWS=$rows>$value</textarea>"; | |
122 | } | |
123 | elsif ($type eq "viewonly") { | |
124 | $out .= "<input $widthstr disabled class='$class' readonly type='text' value='$encvalue'></input>"; | |
125 | } | |
126 | # read only text | |
127 | elsif ($type eq "rotext") { | |
128 | $out .= "<input readonly $widthstr class='$class rotext' type='text' " . | |
129 | "name=${name} title='$encvalue' value='$encvalue'/>"; | |
130 | } | |
131 | # server time | |
132 | elsif ($type eq "rotime") { | |
133 | my $uid = PVE::HTMLControls::get_uid('mytimer'); | |
134 | $out .= "<div $widthstr class='bool input' id='$uid'>$encvalue</div>"; | |
135 | $out .= PVE::HTMLControls::create_time_viewer ($uid); | |
136 | } | |
137 | # time of day | |
138 | elsif ($type eq "time") { | |
139 | my @tmp = split(/:/, $value); | |
140 | for my $i (0..1) { | |
141 | $out .= "<input type=text name=time_${i}_$name class='$class time' value='$tmp[$i]' />"; | |
142 | $out .= " : " if !$i; | |
143 | } | |
144 | } | |
145 | # password | |
146 | elsif ($type eq "password") { | |
147 | $out .= "<input $widthstr class='$class' type='password' name=$name value='$encvalue'/>"; | |
148 | } | |
149 | # number | |
150 | elsif ($type eq "number") { | |
151 | $out .= "<input $widthstr class='$class' type='text' id='$name' name='$name' value='$encvalue'/>"; | |
152 | } | |
153 | # float | |
154 | elsif ($type eq "float") { | |
155 | $out .= "<input $widthstr class='$class' type='text' id='$name' name='$name' value='$encvalue'/>"; | |
156 | } | |
157 | # boolean value (0, 1) | |
158 | elsif ($type eq "bool" || $type eq "robool" || $type eq 'dynamicbool' || $type eq "nbool") { | |
159 | my $checked = $value ? 'checked' : ''; | |
160 | my $id = "bool_$name"; | |
161 | ||
162 | $out .= "<label><div class='$class bool' style='width:${innerwidth}px;text-align:center;vertical-align:bottom;'>"; | |
163 | $out .= " "; | |
164 | if ($type eq 'dynamicbool') { | |
165 | $out .= "<input type='checkbox' name='$id' id='$id' $checked " . | |
166 | "onClick='javascript:pve_form_save(\"$self->{name}\", \"post\");'/>"; | |
167 | } elsif ($type eq "robool") { | |
168 | $out .= "<input type='checkbox' disabled name='${id}_ro' $checked/>"; | |
169 | } else { | |
170 | $out .= "<input type='checkbox' name='$id' id='$id' $checked/>"; | |
171 | } | |
172 | ||
173 | $out .= " "; | |
174 | $out .= "</div></label>"; | |
175 | if ($type eq "robool") { | |
176 | $out .= "<input type='hidden' name='$id' id='$id' $checked/>"; | |
177 | } | |
178 | $out .= "<input type='hidden' name='bool_n_$name' id='bool_n_$name' value='1'/>"; | |
179 | } | |
180 | # dropdown | |
181 | elsif ($type eq "dropdown" || $type eq "dynamicdropdown") { | |
182 | ||
183 | my $table = PVE::HTMLTable->new ([]); | |
184 | ||
185 | my $titles; | |
186 | my $values; | |
187 | my $defvalue; | |
188 | if (ref($opt) eq 'ARRAY') { | |
189 | $values = $opt; | |
190 | } else { | |
191 | $values = $opt->{values}; | |
192 | $defvalue = $opt->{default}; | |
193 | foreach my $head (@{$opt->{titles}}) { | |
194 | push @$titles, 1, undef, $head; | |
195 | } | |
196 | } | |
197 | ||
198 | $table->add_headline ($titles) if $titles; | |
199 | ||
200 | if (defined($value)) { | |
201 | my $found; | |
202 | my $first; | |
203 | foreach my $elem (@$values) { | |
204 | my ($ev, $et, @da); | |
205 | if (ref ($elem) eq 'ARRAY') { | |
206 | ($ev, $et, @da) = @$elem; | |
207 | } else { | |
208 | $ev = $et = $elem; | |
209 | } | |
210 | $first = $ev if !$first; | |
211 | $found = 1 if $ev eq $value; | |
212 | } | |
213 | if (!$found) { | |
214 | $value = defined ($defvalue) ? $defvalue : $first; | |
215 | } | |
216 | } | |
217 | ||
218 | foreach my $elem (@$values) { | |
219 | my ($ev, $et, @da); | |
220 | if (ref ($elem) eq 'ARRAY') { | |
221 | ($ev, $et, @da) = @$elem; | |
222 | } else { | |
223 | $ev = $et = $elem; | |
224 | } | |
225 | ||
226 | push @da, $et if !scalar (@da); | |
227 | ||
228 | if (!defined($value)) { | |
229 | $value = defined ($defvalue) ? $defvalue : $ev; | |
230 | } | |
231 | ||
232 | my $checked = ($ev eq $value) ? 'checked="checked"' : ''; | |
233 | ||
234 | my $inp = "<input type='radio' short='$et' name='$name' value='$ev' $checked />"; | |
235 | my @line; | |
236 | foreach my $dv (@da) { | |
237 | if ($inp) { | |
238 | push @line, "$inp$dv"; | |
239 | $inp = undef; | |
240 | } else { | |
241 | push @line, $dv; | |
242 | } | |
243 | } | |
244 | ||
245 | $table->add_row ('', @line); | |
246 | } | |
247 | ||
248 | my $width1 = $width - 25; | |
249 | $out .= "<div class='selectblock' style='width:${width}px;position:relative;' id='selectblock_$name'>"; | |
250 | $out .= "<div class='$class bool' style='white-space:nowrap;overflow:hidden;'><div style='display:block;float:right;'><img alt='' src='/images/tarrdown.png'></div><div style='width:${width1}px;overflow:hidden;'><span>$value</span></div></div>"; | |
251 | ||
252 | $out .= "<div class='selectbox'>"; | |
253 | $out .= $table->out_table(); | |
254 | $out .= "</div>"; | |
255 | $out .= "</div>"; | |
256 | ||
257 | $out .= "<script language='javascript' type='text/javascript'>"; | |
258 | if ($type eq "dynamicdropdown") { | |
259 | $out .= "new Selectbox('selectblock_$name','$self->{name}');"; | |
260 | } else { | |
261 | $out .= "new Selectbox('selectblock_$name');"; | |
262 | } | |
263 | $out .= "</script>"; | |
264 | } | |
265 | # checkbox | |
266 | elsif ($type eq "checkbox") { | |
267 | my ($rows, $elref) = @$opt; | |
268 | my $sel; | |
269 | my @element = @$elref; | |
270 | map { $sel->{$_} = 1; } split ('\s', $value); | |
271 | $out .= "<table cellspacing=2 style='width:${width}px;' class='checkbox'>"; | |
272 | for my $i (0 .. $#element/$rows) { | |
273 | $out .= "<tr>"; | |
274 | for (my $j = 0; $j < $rows; $j++) { | |
275 | my $ind = $i*$rows + $j; | |
276 | last if $ind > $#element; | |
277 | my ($ev, $et) = ($element[$ind][0], $element[$ind][1]); | |
278 | my $val = $sel->{$ev} ? 'checked=true' : ''; | |
279 | $out .= "<td><label>$et <input $val type=checkbox name='cb__${ev}_$name'></input></label></td>"; | |
280 | } | |
281 | $out .= "</tr>"; | |
282 | } | |
283 | $out .= "</table>"; | |
284 | $out .= "<input type=hidden name='cb_n_$name' value='$#element'/>"; | |
285 | } | |
286 | # ip address | |
287 | elsif ($type eq "ip") { | |
288 | my @tmp = split(/\./, $value); | |
289 | ||
290 | $out .= "<table border=0 cellspacing=0 cellpadding=0><tr>"; | |
291 | for my $i (0..3) { | |
292 | my $id = "ip_${i}_$name"; | |
293 | my $nextid = $i < 3 ? "ip_" . ($i+1) . "_$name" : ''; | |
294 | my $float = "style='float:left;"; | |
295 | $out .= <<__EOD; | |
296 | <td><input class='$class ip' type='text' id='$id' name='$id' value='$tmp[$i]' | |
297 | onKeyUp="pve_form_validate_natural('$id', 255);" | |
298 | onKeyDown="return pve_form_ip_keyfilter(event,'$id','$nextid');" | |
299 | /> | |
300 | __EOD | |
301 | if ($i != 3) { | |
302 | $out .= "<td align=center style='width:8px;font-family:ARIAL;" . | |
303 | "font-weight:bold; font-size:14px;'>.</td>"; | |
304 | } | |
305 | } | |
306 | $out .= "</tr></table>"; | |
307 | ||
308 | } | |
309 | # file upload | |
310 | elsif ($type eq "file") { | |
311 | # most wrowsers (firefox) ignore setting 'width', dont know how to fix | |
312 | $out .= "<input $widthstr class='$class' type='file' id='$name' name='$name'/>"; | |
313 | } | |
314 | # hidden input | |
315 | elsif ($type eq "hidden") { | |
316 | if (defined ($value)) { | |
317 | $out .= "<input type='hidden' id='$name' name=$name value='$encvalue'/>"; | |
318 | } | |
319 | } | |
320 | # Day of week | |
321 | elsif ($type eq "dow") { | |
322 | my $cl = { mon => '', tue => '', wed => '', thu => '', | |
323 | fri => '', sat => '', sun => '' }; | |
324 | foreach my $day (split (/\s+/, $value)) { | |
325 | $cl->{$day} = 'checked'; | |
326 | } | |
327 | my @dn = split (/\s+/, __("Mon Tue Wed Thu Fri Sat Sun")); | |
328 | my $w='15%'; | |
329 | $out .= "<div $widthstr class='bool'><table border=0 cellspacing=2 cellpadding=0>"; | |
330 | $out .= "<tr align=center><td width='$w'>$dn[0]<td width='$w'>$dn[1]<td width='$w'>$dn[2]"; | |
331 | $out .= "<td width='$w'>$dn[3]<td width='$w'>$dn[4]<td width='$w'>$dn[5]<td width='$w'>$dn[6]</tr>"; | |
332 | $out .= "<tr align=center>"; | |
333 | $out .= "<td><input type=checkbox $cl->{mon} name='$name' value=mon>"; | |
334 | $out .= "<td><input type=checkbox $cl->{tue} name='$name' value=tue>"; | |
335 | $out .= "<td><input type=checkbox $cl->{wed} name='$name' value=wed>"; | |
336 | $out .= "<td><input type=checkbox $cl->{thu} name='$name' value=thu>"; | |
337 | $out .= "<td><input type=checkbox $cl->{fri} name='$name' value=fri>"; | |
338 | $out .= "<td><input type=checkbox $cl->{sat} name='$name' value=sat>"; | |
339 | $out .= "<td><input type=checkbox $cl->{sun} name='$name' value=sun>"; | |
340 | $out .= "</tr></table></div>"; | |
341 | } | |
342 | else { | |
343 | die "unknown elemet type '$type'"; | |
344 | } | |
345 | ||
346 | $out .= "\n"; | |
347 | ||
348 | return $out; | |
349 | } | |
350 | ||
351 | sub create_cmdbutton { | |
352 | my ($self, $type, $text) = @_; | |
353 | ||
354 | my $href = "javascript:pve_form_save(\"$self->{name}\", \"$type\");"; | |
355 | ||
356 | my $out = "<img alt='' style='vertical-align:text-bottom;width:15px; height:15px;' src='/images/tarrright.png'> "; | |
357 | ||
358 | $text = $type if !$text; | |
359 | ||
360 | if ($type eq "save") { | |
361 | $text = __('save'); | |
362 | } elsif ($type eq "search") { | |
363 | $text = __('search'); | |
364 | } elsif ($type eq "create") { | |
365 | $text = __('create'); | |
366 | } elsif ($type eq "upload") { | |
367 | $text = __('upload'); | |
368 | } | |
369 | ||
370 | $out .= "<a href='$href' class='frmsubmit'>$text</a>"; | |
371 | ||
372 | return $out; | |
373 | } | |
374 | ||
375 | sub create_header { | |
376 | my ($self, $action) = @_; | |
377 | ||
378 | $action = '' if !$action; | |
379 | ||
380 | return "<form style='margin:0px;' id='$self->{name}' action='$action' method='POST' ENCTYPE='multipart/form-data' accept-charset='UTF-8'>"; | |
381 | } | |
382 | ||
383 | sub create_footer { | |
384 | my $self = shift; | |
385 | ||
386 | my $out = $self->create_element("form_$self->{name}_submit", 'hidden', 'post'); | |
387 | $out .= "</form>"; | |
388 | ||
389 | return $out; | |
390 | } | |
391 | ||
392 | 1; |