9 # name: LJ::html_datetime
11 # des: Creates date and time control HTML form elements.
12 # info: Parse output later with [func[LJ::html_datetime_decode]].
20 my $lang = $opts->{'lang'} || "EN";
21 my ($yyyy, $mm, $dd, $hh, $nn, $ss);
23 my $name = $opts->{'name'};
24 my $id = $opts->{'id'};
25 my $disabled = $opts->{'disabled'} ?
1 : 0;
28 foreach (grep { ! /^(name|id|disabled|seconds|notime|lang|default)$/ } keys %$opts) {
29 $extra_opts{$_} = $opts->{$_};
32 if ($opts->{'default'} =~ /^(\d\d\d\d)-(\d\d)-(\d\d)(?: (\d\d):(\d\d):(\d\d))?/) {
33 ($yyyy, $mm, $dd, $hh, $nn, $ss) = ($1 > 0 ?
$1 : "",
40 $ret .= html_select
({ 'name' => "${name}_mm", 'id' => "${id}_mm", 'selected' => $mm, 'class' => 'select',
41 'disabled' => $disabled, %extra_opts },
42 map { $_, LJ
::Lang
::ml
(LJ
::Lang
::month_long_langcode
($_)) } (1..12));
43 $ret .= html_text
({ 'name' => "${name}_dd", 'id' => "${id}_dd", 'size' => '2', 'class' => 'text',
44 'maxlength' => '2', 'value' => $dd,
45 'disabled' => $disabled, %extra_opts });
46 $ret .= html_text
({ 'name' => "${name}_yyyy", 'id' => "${id}_yyyy", 'size' => '4', 'class' => 'text',
47 'maxlength' => '4', 'value' => $yyyy,
48 'disabled' => $disabled, %extra_opts });
49 unless ($opts->{'notime'}) {
51 $ret .= html_text
({ 'name' => "${name}_hh", 'id' => "${id}_hh", 'size' => '2',
52 'maxlength' => '2', 'value' => $hh,
53 'disabled' => $disabled }) . ':';
54 $ret .= html_text
({ 'name' => "${name}_nn", 'id' => "${id}_nn", 'size' => '2',
55 'maxlength' => '2', 'value' => $nn,
56 'disabled' => $disabled });
57 if ($opts->{'seconds'}) {
59 $ret .= html_text
({ 'name' => "${name}_ss", 'id' => "${id}_ss", 'size' => '2',
60 'maxlength' => '2', 'value' => $ss,
61 'disabled' => $disabled });
69 # name: LJ::html_datetime_decode
71 # des: Parses output of HTML form controls generated by [func[LJ::html_datetime]].
77 sub html_datetime_decode
81 my $name = $opts->{'name'};
82 return sprintf("%04d-%02d-%02d %02d:%02d:%02d",
83 $hash->{"${name}_yyyy"},
84 $hash->{"${name}_mm"},
85 $hash->{"${name}_dd"},
86 $hash->{"${name}_hh"},
87 $hash->{"${name}_nn"},
88 $hash->{"${name}_ss"});
92 # name: LJ::html_select
94 # des: Creates a drop-down box or listbox HTML form element (the <select> tag).
97 # des-opts: A hashref of options. Special options are:
98 # 'raw' - inserts value unescaped into select tag;
99 # 'noescape' - won't escape key values if set to 1;
100 # 'disabled' - disables the element;
101 # 'include_ids' - bool. If true, puts id attributes on each element in the drop-down.
102 # ids are off by default, to reduce page sizes with large drop-down menus;
103 # 'multiple' - creates a drop-down if 0, a multi-select listbox if 1;
104 # 'selected' - if multiple, an arrayref of selected values; otherwise,
105 # a scalar equalling the selected value;
106 # All other options will be treated as HTML attribute/value pairs.
107 # returns: The generated HTML.
113 my $ehtml = $opts->{'noescape'} ?
0 : 1;
116 $ret .= " $opts->{'raw'}" if $opts->{'raw'};
117 $ret .= " disabled='disabled'" if $opts->{'disabled'};
118 $ret .= " multiple='multiple'" if $opts->{'multiple'};
119 foreach (grep { ! /^(raw|disabled|selected|noescape|multiple)$/ } keys %$opts) {
120 $ret .= " $_=\"" . ($ehtml ? ehtml
($opts->{$_}) : $opts->{$_}) . "\"";
124 # build hashref from arrayref if multiple selected
126 $selref = { map { $_, 1 } @
{$opts->{'selected'}} }
127 if $opts->{'multiple'} && ref $opts->{'selected'} eq 'ARRAY';
130 while (defined (my $value = shift @items)) {
132 # items can be either pairs of $value, $text or a list of $it hashrefs (or a mix)
138 $value = $it->{value
};
140 $js_data = $it->{js_data
};
142 $text = shift @items;
146 my @sub_items = @
$text;
148 $ret .= "<optgroup label='$value'>";
150 while (defined (my $value = shift @sub_items)) {
156 $value = $it->{value
};
159 $text = shift @sub_items;
163 # multiple-mode or single-mode?
164 if (ref $selref eq 'HASH' && $selref->{$value} ||
165 $opts->{'selected'} eq $value && !$did_sel++) {
167 $sel = " selected='selected'";
169 $value = $ehtml ? ehtml
($value) : $value;
172 if ($opts->{'include_ids'} && $opts->{'name'} ne "" && $value ne "") {
173 $id = " id='$opts->{'name'}_$value'";
176 # is this individual option disabled?
177 my $dis = $it->{'disabled'} ?
" disabled='disabled' style='color: #999;'" : '';
179 $ret .= "<option value=\"$value\"$id$sel$dis>" .
180 ($ehtml ? ehtml
($text) : $text) . "</option>\n";
183 $ret .= "</optgroup>";
184 } else { # non-grouped options
186 # multiple-mode or single-mode?
187 if (ref $selref eq 'HASH' && $selref->{$value} ||
188 $opts->{'selected'} eq $value && !$did_sel++) {
190 $sel = " selected='selected'";
192 $value = $ehtml ? ehtml
($value) : $value;
195 if ($opts->{'include_ids'} && $opts->{'name'} ne "" && $value ne "") {
196 $id = " id='$opts->{'name'}_$value'";
199 # is this individual option disabled?
200 my $dis = $it->{'disabled'} ?
" disabled='disabled' style='color: #999;'" : '';
202 $ret .= "<option value=\"$value\"$id$sel$dis $js_data>" .
203 ($ehtml ? ehtml
($text) : $text) . "</option>\n";
211 # name: LJ::html_check
213 # des: Creates HTML checkbox button, and radio button controls.
214 # info: Labels for checkboxes are through LJ::labelfy.
215 # It does this safely, by not including any HTML elements in the label tag.
217 # des-type: Valid types are 'radio' or 'checkbox'.
218 # des-opts: A hashref of options. Special options are:
219 # 'disabled' - disables the element;
220 # 'selected' - if multiple, an arrayref of selected values; otherwise,
221 # a scalar equalling the selected value;
222 # 'raw' - inserts value unescaped into select tag;
223 # 'noescape' - won't escape key values if set to 1;
224 # 'label' - label for checkbox;
231 my $disabled = $opts->{'disabled'} ?
" disabled='disabled'" : "";
232 my $ehtml = $opts->{'noescape'} ?
0 : 1;
234 if ($opts->{'type'} eq "radio") {
235 $ret .= "<input type='radio'";
237 $ret .= "<input type='checkbox'";
239 if ($opts->{'selected'}) { $ret .= " checked='checked'"; }
240 if ($opts->{'raw'}) { $ret .= " $opts->{'raw'}"; }
241 foreach (grep { ! /^(disabled|type|selected|raw|noescape|label)$/ } keys %$opts) {
242 $ret .= " $_=\"" . ($ehtml ? ehtml
($opts->{$_}) : $opts->{$_}) . "\"" if $_;
244 $ret .= "$disabled />";
245 my $e_label = ($ehtml ? ehtml
($opts->{'label'}) : $opts->{'label'});
246 $e_label = LJ
::labelfy
($opts->{id
}, $e_label);
247 $ret .= $e_label if $opts->{'label'};
251 # given a string and an id, return the string
252 # in a label, respecting HTML
254 my ($id, $text) = @_;
268 # name: LJ::html_text
270 # des: Creates a text input field, for single-line input.
271 # info: Allows 'type' => 'password' flag.
274 # returns: The generated HTML.
280 my $disabled = $opts->{'disabled'} ?
" disabled='disabled'" : "";
281 my $ehtml = $opts->{'noescape'} ?
0 : 1;
282 my $type = $opts->{'type'} eq 'password' || $opts->{'type'} eq 'search' ?
$opts->{'type'} : 'text';
284 $ret .= "<input type=\"$type\"";
285 foreach (grep { ! /^(type|disabled|raw|noescape)$/ } keys %$opts) {
286 $ret .= " $_=\"" . ($ehtml ? ehtml
($opts->{$_}) : $opts->{$_}) . "\"";
288 if ($opts->{'raw'}) { $ret .= " $opts->{'raw'}"; }
289 $ret .= "$disabled />";
294 # name: LJ::html_textarea
296 # des: Creates a text box for multi-line input (the <textarea> tag).
300 # returns: The generated HTML.
306 my $disabled = $opts->{'disabled'} ?
" disabled='disabled'" : "";
307 my $ehtml = $opts->{'noescape'} ?
0 : 1;
310 foreach (grep { ! /^(disabled|raw|value|noescape)$/ } keys %$opts) {
311 $ret .= " $_=\"" . ($ehtml ? ehtml
($opts->{$_}) : $opts->{$_}) . "\"";
313 if ($opts->{'raw'}) { $ret .= " $opts->{'raw'}"; }
314 $ret .= "$disabled>" . ($ehtml ? ehtml
($opts->{'value'}) : $opts->{'value'}) . "</textarea>";
319 # name: LJ::html_color
321 # des: A text field with attached color preview and button to choose a color.
322 # info: Depends on the client-side Color Picker.
324 # des-opts: Valid options are: 'onchange' argument, which happens when
325 # color picker button is clicked, or when focus is changed to text box;
326 # 'disabled'; and 'raw' , for unescaped input.
333 my $htmlname = ehtml
($opts->{'name'});
334 my $des = ehtml
($opts->{'des'}) || "Pick a Color";
337 ## Output the preview box and picker button with script so that
338 ## they don't appear when JavaScript is unavailable.
339 $ret .= "<script language=\"JavaScript\"><!--\n".
340 "document.write('<span style=\"border: 1px solid #000000; ".
341 "padding-left: 2em; background-color: " . ehtml
($opts->{'default'}) . ";\" ".
342 "id=\"${htmlname}_disp\"";
343 if ($opts->{no_btn
}) {
344 $ret .= " onclick=\"spawnPicker(findel(\\'${htmlname}\\')," .
345 "findel(\\'${htmlname}_disp\\'),\\'$des\\'); " .
346 LJ
::ejs
($opts->{'onchange'}) .
349 $ret .= "> </span>'); ".
352 # 'onchange' argument happens when color picker button is clicked,
353 # or when focus is changed to text box
355 $ret .= html_text
({ 'size' => 8, 'maxlength' => 7, 'name' => $htmlname, 'id' => $htmlname,
356 'onchange' => "setBGColorWithId(findel('${htmlname}_disp'),'${htmlname}');",
357 'onfocus' => $opts->{'onchange'},
358 'disabled' => $opts->{'disabled'}, 'value' => $opts->{'default'},
359 'noescape' => 1, 'raw' => $opts->{'raw'},
362 unless ($opts->{no_btn
}) {
363 my $disabled = $opts->{'disabled'} ?
"disabled=\'disabled\'" : '';
364 $ret .= "<script language=\"JavaScript\"><!--\n".
365 "document.write('<button ".
366 "onclick=\"spawnPicker(findel(\\'${htmlname}\\')," .
367 "findel(\\'${htmlname}_disp\\'),\\'$des\\'); " .
368 LJ
::ejs
($opts->{'onchange'}) .
369 " return false;\"$disabled>Choose...</button>'); ".
373 # A little help for the non-JavaScript folks
374 $ret .= "<noscript> (#<var>rr</var><var>gg</var><var>bb</var>)</noscript>";
380 # name: LJ::html_hidden
382 # des: Makes the HTML for a hidden form element.
383 # args: name, val, opts
384 # des-name: Name of form element (will be HTML escaped).
385 # des-val: Value of form element (will be HTML escaped).
386 # des-opts: Can optionally take arguments that are hashrefs
387 # and extract name/value/other standard keys from that. Can also be
388 # mixed with the older style key/value array calling format.
400 if (ref $name eq 'HASH') {
403 $val = $opts->{value
};
404 $name = $opts->{name
};
406 $ehtml = $opts->{'noescape'} ?
0 : 1;
407 foreach (grep { ! /^(name|value|raw|noescape)$/ } keys %$opts) {
408 $extra .= " $_=\"" . ($ehtml ? ehtml
($opts->{$_}) : $opts->{$_}) . "\"";
411 $extra .= " $opts->{'raw'}" if $opts->{'raw'};
417 $ret .= "<input type='hidden'";
418 # allow override of these in 'raw'
419 $ret .= " name=\"" . ($ehtml ? ehtml
($name) : $name) . "\"" if $name;
420 $ret .= " value=\"" . ($ehtml ? ehtml
($val) : $val) . "\"" if defined $val;
427 # name: LJ::html_submit
429 # des: Makes the HTML for a submit button.
430 # info: If only one argument is given it is
431 # assumed LJ::html_submit(undef, 'value') was meant.
432 # args: name, val, opts?, type
433 # des-name: Name of form element (will be HTML escaped).
434 # des-val: Value of form element, and label of button (will be HTML escaped).
435 # des-opts: Optional hashref of additional tag attributes.
436 # A hashref of options. Special options are:
437 # 'raw' - inserts value unescaped into select tag;
438 # 'disabled' - disables the element;
439 # 'noescape' - won't escape key values if set to 1;
440 # des-type: Optional. Value format is type => (submit|reset). Defaults to submit.
445 my ($name, $val, $opts) = @_;
447 # if one argument, assume (undef, $val)
453 my ($eopts, $disabled, $raw);
457 if ($opts && ref $opts eq 'HASH') {
458 $disabled = " disabled='disabled'" if $opts->{'disabled'};
459 $raw = " $opts->{'raw'}" if $opts->{'raw'};
460 $type = 'reset' if $opts->{'type'} eq 'reset';
462 $ehtml = $opts->{'noescape'} ?
0 : 1;
463 foreach (grep { ! /^(raw|disabled|noescape|type)$/ } keys %$opts) {
464 $eopts .= " $_=\"" . ($ehtml ? ehtml
($opts->{$_}) : $opts->{$_}) . "\"";
467 my $ret = "<input type='$type'";
468 # allow override of these in 'raw'
469 $ret .= " name=\"" . ($ehtml ? ehtml
($name) : $name) . "\"" if $name;
470 $ret .= " value=\"" . ($ehtml ? ehtml
($val) : $val) . "\"" if defined $val;
471 $ret .= "$eopts$raw$disabled />";