3 # Copyright (C) 2005 Martin A. Hansen.
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 # http://www.gnu.org/copyleft/gpl.html
24 # Martin A. Hansen, July 2005.
27 # Routines for generating XHTML code with CSS support.
28 # Intentionally as much layout control as possible is done with CSS.
29 # locate the 'xthml_examples' script for examples of usage.
31 # Caveat: these routines return one or more lines of HTML code, and generally
32 # does not know about the layout of a HTML document. HTML elements, such as
33 # a, input, select, textarea etc. that must be embedded in other elements such as,
34 # h1 .. h6, p, ol, ul, etc. will have to be considered carefully to get the embedding
35 # correct. Do have a look at the 'xthml_examples' script for examples of usage.
37 # NB! do use w3's excellent HTML Validator while designing HTML layout (http://validator.w3.org/)
39 # NB! alternatively use Dave Raggett's TIDY (http://tidy.sourceforge.net/)
41 # Example: $name = &XHTML::text( name => "NAME", value => $name_def || "", size => 25, maxlength => 20 );
43 # Suggested reading: XHTML standard -> http://www.w3.org/TR/xhtml1/
44 # CSS standard -> http://www.w3schools.com/css/css_reference.asp
45 # http://htmldog.com/guides/htmlbeginner/
46 # http://htmldog.com/guides/htmlintermediate/
47 # http://htmldog.com/guides/htmladvanced/
52 # intelligent insertion of \n in the HTML blocks so that
53 # 1) p( ln(), ln(), ln() ) behaves similar to
54 # 2) p( join( "\n", ln(), ln(), ln() ) or
55 # 3) p( join( "", ln(), ln(), ln() )
56 # all producing nicely layouted HTML code:
57 # <p><a href="#"></a><a href="#"></a><a href="#"></a></p>
59 # 1) is probably not wise to undertake..
60 # 2) + 3) should be doable but may also be unwise:
61 # this would imply that the tag_pair routine should parse the
62 # incomming txt string for HTML tags and make sure newlines are
63 # inserted in a logical way. this requires a recursive HTML parse
64 # routine. but then one might as well postprocess the entire list
65 # of HTML lines using TIDY.
67 # buttons with action:
69 # <input type='button' value='Print this page' name='print_page' onClick='window.print()'>
70 # <input TYPE='button' VALUE='Close this window' NAME='bouton_close' onClick="window.close('this')">
76 use vars qw( @ISA @EXPORT );
80 @ISA = qw( Exporter );
83 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> HEADERS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
88 # Martin A. Hansen, July 2005.
92 my ( %args, # arguments
99 push @html, &cgi_header if $args{ "cgi_header" };
100 push @html, &doc_type;
101 push @html, &head_beg;
102 push @html, &title( $args{ "title" } ) if $args{ "title" };
103 push @html, &css( $args{ "css_file" } ) if $args{ "css_file" };
104 push @html, &author( $args{ "author" } ) if $args{ "author" };
105 push @html, &description( $args{ "description" } ) if $args{ "description" };
106 push @html, &keywords( $args{ "keywords" } ) if $args{ "keywords" };
107 push @html, &no_cache( $args{ "no_cache" } ) if $args{ "no_cache" };
108 push @html, &head_end;
109 push @html, &body_beg;
111 return join "\n", @html;
117 # Martin A. Hansen, July 2005.
119 # Header for CGI scripts.
121 return "Content-Type: text/html; charset=ISO-8859-1\n\n";
127 # Martin A. Hansen, July 2005.
129 # Header for XHTML 1.0 Strict
131 return qq(<?xml version="1.0" encoding="utf-8"?>
132 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
133 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
134 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">);
140 # Martin A. Hansen, July 2005.
142 # HTML <head> element
150 # Martin A. Hansen, July 2005.
152 # HTML <title> element.
154 my ( $title, # docuement title
157 warn qq(WARNING: no title given\n) if not $title;
159 return &tag_pair( "title", { txt => $title } );
165 # Martin A. Hansen, July 2005.
167 # Links external CSS file.
169 my ( $css_file, # path to external CSS file
172 warn qq(WARNING: could not locate CSS file "$css_file"\n) if not -f $css_file;
174 return &tag_single( "link", { rel => "stylesheet", type => "text/css", href => $css_file } );
180 # Martin A. Hansen, July 2005.
184 my ( $icon_file, # path to flavicon file
187 warn qq(WARNING: could not locate icon file "$icon_file"\n) if not -f $icon_file;
189 return &tag_single( "link", { rel => "shortcut icon", href => $icon_file } );
195 # Martin A. Hansen, July 2005.
197 # HTML meta tag containing author information.
199 my ( $author, # name of webpage author
202 warn qq(WARNING: no author given\n) if not $author;
204 return &tag_single( "meta", { name => "author", content => $author } );
210 # Martin A. Hansen, July 2005.
212 # HTML meta tag containing webpage description.
214 my ( $description, # webpage description
217 warn qq(WARNING: no description given\n) if not $description;
219 return &tag_single( "meta", { name => "description", content => $description } );
225 # Martin A. Hansen, July 2005.
227 # HTML meta tag contining webpage keywords for webcrawlers.
229 my ( $keywords, # list of keywords
234 warn qq(WARNING: no keywords given\n) if not $keywords;
236 $keyword = join ", ", @{ $keywords };
238 return &tag_single( "meta", { name => "keywords", content => $keyword } );
244 # Martin A. Hansen, July 2005.
246 # HTML meta tags disabling browser caching.
247 # (uncomfirmed behaviour - works sometimes - sometimes not)
251 push @html, &tag_single( "meta", { "http-equiv" => "pragma", content => "no-cache" } );
252 push @html, &tag_single( "meta", { "http-equiv" => "cache-control", content => "no-store" } );
254 return join "\n", @html;
260 # Martin A. Hansen, July 2005.
262 # HTML </head> element
270 # Martin A. Hansen, July 2005.
272 # HTML <body> element
280 # Martin A. Hansen, July 2005.
282 # Links external java script file
284 # Must be located in the HTML body section
285 # (after <body> and before </body>)
287 my ( $js_file, # path to javascript file
290 warn qq(WARNING: could not locate javascript file "$js_file"\n) if not -f $js_file;
292 return qq(<script src="$js_file" type="text/javascript"></script>);
298 # Martin A. Hansen, July 2005.
300 # HTML </body> element
308 # Martin A. Hansen, July 2005.
310 # HTML </html> element
316 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> HEADINGS & PARAGRAPH <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
321 # Martin A. Hansen, July 2005.
330 return &tag_pair( "h1", \%args );
336 # Martin A. Hansen, July 2005.
345 return &tag_pair( "h2", \%args );
351 # Martin A. Hansen, July 2005.
360 return &tag_pair( "h3", \%args );
366 # Martin A. Hansen, July 2005.
375 return &tag_pair( "h4", \%args );
381 # Martin A. Hansen, July 2005.
390 return &tag_pair( "h5", \%args );
396 # Martin A. Hansen, July 2005.
405 return &tag_pair( "h6", \%args );
411 # Martin A. Hansen, July 2005.
420 return &tag_pair( "p", \%args );
424 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> LISTS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
427 # Lists comes in two flavors - simple and advanced.
428 # simple lists work on a simple list of items, while
429 # advamced lists work on a list where each item is specified.
434 # Martin A. Hansen, July 2005.
443 warn qq(WARINING: no ul_simple items given\n) if not $args{ "li" };
445 return &list_simple( "ul", \%args );
451 # Martin A. Hansen, July 2005.
460 warn qq(WARINING: no ol_simple items given\n) if not $args{ "li" };
462 return &list_simple( "ol", \%args );
468 # Martin A. Hansen, July 2005.
477 warn qq(WARINING: no ul_advanced items given\n) if not $args{ "li" };
479 return &list_advanced( "ul", \%args );
485 # Martin A. Hansen, July 2005.
494 warn qq(WARINING: no ol_advanced items given\n) if not $args{ "li" };
496 return &list_advanced( "ol", \%args );
500 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> LABEL <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
505 # Martin A. Hansen, July 2005.
507 # HTML <label> element
514 warn qq(WARNING: no "for" given in label\n) if not $args{ "for" };
516 return &tag_pair( "label", \%args );
520 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> LINE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
525 # Martin A. Hansen, July 2005.
529 # NB - rather use proper CSS than <hr>!
536 return &tag_single( "hr", \%args );
542 # Martin A. Hansen, July 2005.
546 # NB - rather use proper CSS than <br>!
553 return &tag_single( "br", \%args );
557 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> LINK <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
562 # Martin A. Hansen, July 2005.
573 warn qq(WARNING: no link href given\n) if not $args{ "href" };
575 $args{ "href" } =~ s/&/&/g;
577 if ( $args{ "txt" } ) {
578 return &tag_pair( "a", \%args );
580 return &tag_single( "a", \%args );
587 # Martin A. Hansen, July 2005.
596 warn qq(WARNING: no anchor txt given\n) if not $args{ "txt" };
597 warn qq(WARNING: no anchor name given\n) if not $args{ "name" };
599 return &tag_pair( "a", \%args );
605 # Martin A. Hansen, July 2005.
614 warn qq(WARNING: no mailto txt given\n) if not $args{ "txt" };
615 warn qq(WARNING: no mailto address given\n) if not $args{ "email" };
617 $args{ "href" } = "mailto:" . $args{ "email" };
619 delete $args{ "email" };
621 return &tag_pair( "a", \%args );
625 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> IMG <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
630 # Martin A. Hansen, July 2005.
639 return &tag_single( "img", \%args );
643 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> DIV & SPAN <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
648 # Martin A. Hansen, July 2005.
657 my ( @html, $lines );
659 $lines = $args{ "txt" };
663 $args{ "txt" } = $lines;
665 return &tag_pair( "div", \%args );
669 return &tag_single( "div", \%args );
676 # Martin A. Hansen, July 2005.
678 # HTML <span> element
685 warn qq(WARNING: no span given\n) if not $args{ "txt" };
687 return &tag_pair( "span", \%args );
691 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> MAP <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
696 # Martin A. Hansen, July 2005.
703 warn qq(WARNING: no map name given\n) if not $args{ "name" };
704 warn qq(WARNING: no map id given \n) if not $args{ "id" };
706 my $arg = &format_args( \%args );
708 return qq(<map $arg>);
714 # Martin A. Hansen, July 2005.
716 # HTML </map> element
722 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> PRE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
727 # Martin A. Hansen, July 2005.
736 warn qq(WARNING: no pre lines given\n) if not $args{ "txt" };
738 $args{ "txt" } =~ s/&/&/g;
739 $args{ "txt" } =~ s/>/>/g;
740 $args{ "txt" } =~ s/</</g;
742 return &tag_pair( "pre", \%args );
746 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FORMS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
751 # Martin A. Hansen, July 2005.
753 # HTML <form> element
760 $arg = &format_args( \%args );
762 warn qq(WARNING: no form method given\n) if not $args{ "method" };
763 warn qq(WARNING: "method" must be eihter "post" or "get" - not ") . $args{ "method" } . qq("\n) if not $args{ "method" } =~ /get|post/;
765 return qq(<form $arg>);
771 # Martin A. Hansen, July 2005.
773 # HTML </form> element
779 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> BUTTONS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
784 # Martin A. Hansen, July 2005.
793 return &input_field( "submit", \%args );
799 # Martin A. Hansen, July 2005.
803 return &input_field( "reset" );
807 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FIELDS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
812 # Martin A. Hansen, July 2005.
821 return &input_field( "text", \%args );
827 # Martin A. Hansen, July 2005.
829 # HTML password field
836 return &input_field( "password", \%args );
842 # Martin A. Hansen, July 2005.
851 return &input_field( "file", \%args );
857 # Martin A. Hansen, July 2005.
859 # HTML checkbox field
866 return &input_field( "checkbox", \%args );
872 # Martin A. Hansen, July 2005.
874 # HTML radio button field
881 return &input_field( "radio", \%args );
887 # Martin A. Hansen, July 2005.
896 warn qq(WARNING: no hidden value given\n) if not $args{ "value" };
898 return &input_field( "hidden", \%args );
904 # Martin A. Hansen, July 2005.
906 # HTML popup/drowdown menu
908 my ( %args, # name of variable
913 my ( @html, $name, $selected, $options, $option, $value );
915 warn qq(WARNING: no menu name given\n) if not $args{ "name" };
916 warn qq(WARNING: no menu options given\n) if not $args{ "options" };
918 $name = $args{ "name" };
919 $selected = $args{ "selected" };
920 $options = $args{ "options" };
922 push @html, qq(<select name="$name">);
924 push @html, &tag_pair( "option", { selected => "selected", value => $selected, txt => $selected } ) if exists $args{ "selected" };
926 foreach $option ( @{ $options } ) {
927 push @html, &tag_pair( "option", { value => "$option", txt => $option } );
930 push @html, qq(</select>);
932 return join "\n", @html;
938 # Martin A. Hansen, July 2005.
940 # HTML textarea field
947 warn qq(WARNING: no textarea name given\n) if not $args{ "name" };
948 warn qq(WARNING: no textarea rows given\n) if not $args{ "rows" };
949 warn qq(WARNING: no textarea cols given\n) if not $args{ "cols" };
951 return &tag_pair( "textarea", \%args );
955 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> TABLE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
958 # XHTML allows several forms of tables: table, thead, tbody, and tfoot.
959 # All are supported in the below routines, considering that each of these
960 # table types are generically handled in two flavors - simple and advanced.
961 # simple tables takes a list of rows as arguments, while advamced tables
962 # takes a list of rows each cell is specified.
963 # NB! the order of tables is important thead->tfoot->tbody (if used)
968 # Martin A. Hansen, July 2005.
970 # HTML <table> element
975 my $arg = &format_args( \%args );
978 return "<table $arg>";
987 # Martin A. Hansen, July 2005.
989 # HTML </table> element
997 # Martin A. Hansen, July 2005.
999 # HTML <thead> element
1004 my $arg = &format_args( \%args );
1007 return "<thead $arg>";
1016 # Martin A. Hansen, July 2005.
1018 # HTML </thead> element
1026 # Martin A. Hansen, July 2005.
1028 # HTML <tfoot> element
1033 my $arg = &format_args( \%args );
1036 return "<tfoot $arg>";
1045 # Martin A. Hansen, July 2005.
1047 # HTML </tfoot> element
1055 # Martin A. Hansen, July 2005.
1057 # HTML <tbody> element
1062 my $arg = &format_args( \%args );
1065 return "<tbody $arg>";
1074 # Martin A. Hansen, July 2005.
1076 # HTML </tbody> element
1084 # Martin A. Hansen, July 2005.
1086 # HTML <caption> element
1093 my @html = &tag_pair( "caption", \%args );
1095 return wantarray ? @html : \@html;
1099 sub table_row_simple
1101 # Martin A. Hansen, July 2005.
1110 my ( @html, $arg, $cells, $cell );
1112 warn qq(WARNING: no simple row given\n) if not $args{ "tr" };
1114 $cells = $args{ "tr" };
1116 delete $args{ "tr" };
1118 $arg = &format_args( \%args );
1121 push @html, "<tr $arg>";
1126 foreach $cell ( @{ $cells } ) {
1127 push @html, &tag_pair( "td", { txt => $cell } );
1130 push @html, "</tr>";
1132 return join "\n", @html;
1136 sub table_row_advanced
1138 # Martin A. Hansen, July 2005.
1147 my ( @html, $arg, $cells, $cell );
1149 warn qq(WARNING: no advanced row given\n) if not $args{ "tr" };
1151 $cells = $args{ "tr" };
1153 delete $args{ "tr" };
1155 $arg = &format_args( \%args );
1158 push @html, "<tr $arg>";
1163 foreach $cell ( @{ $cells } )
1165 $cell->{ "txt" } = $cell->{ "td" };
1167 delete $cell->{ "td" };
1169 push @html, &tag_pair( "td", $cell );
1172 push @html, "</tr>";
1174 return join "\n", @html;
1178 sub table_header_simple
1180 # Martin A. Hansen, July 2005.
1182 # HTML simple header rww
1189 my ( @html, $arg, $cells, $cell );
1191 warn qq(WARNING: no simple header given\n) if not $args{ "tr" };
1193 $cells = $args{ "tr" };
1195 delete $args{ "tr" };
1197 $arg = &format_args( \%args );
1200 push @html, "<tr $arg>";
1205 foreach $cell ( @{ $cells } ) {
1206 push @html, &tag_pair( "th", { txt => $cell } );
1209 push @html, "</tr>";
1211 return join "\n", @html;
1215 sub table_header_advanced
1217 # Martin A. Hansen, July 2005.
1219 # HTML advanced header row
1226 my ( @html, $arg, $cells, $cell );
1228 warn qq(WARNING: no advanced header given\n) if not $args{ "tr" };
1230 $cells = $args{ "tr" };
1232 delete $args{ "tr" };
1234 $arg = &format_args( \%args );
1237 push @html, "<tr $arg>";
1242 foreach $cell ( @{ $cells } )
1244 $cell->{ "txt" } = $cell->{ "th" };
1246 delete $cell->{ "th" };
1248 push @html, &tag_pair( "th", $cell );
1251 push @html, "</tr>";
1253 return join "\n", @html;
1259 # Martin A. Hansen, July 2005.
1268 my ( @html, $arg, $cells, $cell );
1270 warn qq(WARNING: no colgroup given\n) if not $args{ "colgroup" };
1272 $cells = $args{ "colgroup" };
1274 delete $args{ "colgroup" };
1276 $arg = &format_args( \%args );
1279 push @html, "<colgroup $arg>";
1281 push @html, "<colgroup>";
1284 foreach $cell ( @{ $cells } ) {
1285 push @html, &tag_single( "col", $cell );
1288 push @html, "</colgroup>";
1290 return join "\n", @html;
1294 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> HTML COMMENT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
1299 # Martin A. Hansen, July 2005.
1306 my $comment = $args{ "txt" };
1308 warn qq(WARNING: no comment given\n) if not $comment;
1310 return "\n<!-- $comment -->\n";
1314 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> VALIDATOR BUTTONS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
1319 # Martin A. Hansen, July 2005.
1321 # returns an image link to w3.orgs validator page
1323 return &ln( txt => &img( src => "http://www.w3.org/Icons/valid-xhtml10", alt => "Valid XHTML 1.0!" ),
1324 href => "http://validator.w3.org/check?uri=referer", id => "validate_xhtml" );
1330 # Martin A. Hansen, July 2005.
1332 # returns an image link to w3.orgs css validator page
1334 my ( $url, # url or uri to the CSS file
1337 warn qq(WARNING: no url given for validate css\n) if not $url;
1339 return &ln( txt => &img( src => "http://jigsaw.w3.org/css-validator/images/vcss", alt => "Valid CSS!" ),
1340 href => "http://jigsaw.w3.org/css-validator/validator?uri=$url", id => "validate_css" );
1344 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> HELPERS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
1349 # Martin A. Hansen, July 2005.
1351 # given a hash with arguments reformat ( foo => "bar", foo2 => "bar2" ... )
1352 # these to HTML type argument str ( foo = "bar" foo2 = "bar2" ... )
1354 my ( $args, # hashref
1359 my ( $str, $arg, @list );
1361 foreach $arg ( sort keys %{ $args } ) {
1362 push @list, qq($arg=") . $args->{ $arg } . qq(");
1365 $str = join " ", @list;
1373 # Martin A. Hansen, July 2005.
1375 # handles HTML tags with a begin tab and a end tag such as <h1>string</h2>,
1376 # where the first tag hold optional arguments and the txt string is mandatory.
1378 my ( $tag, # HTML element type
1384 my ( @html, $txt, $arg, $embed );
1386 $txt = $args->{ "txt" };
1388 delete $args->{ "txt" };
1390 warn qq(WARNING: no $tag given\n) if not $tag;
1392 $arg = &format_args( $args );
1394 if ( $txt =~ /(<[^>]+>)/ )
1396 if ( $1 =~ /^<(input|textarea|a |img)/ ) {
1408 push @html, "<$tag $arg>$txt</$tag>";
1410 push @html, "<$tag>$txt</$tag>";
1417 push @html, "<$tag $arg>";
1419 push @html, "</$tag>";
1423 push @html, "<$tag>";
1425 push @html, "</$tag>";
1429 return join "\n", @html;
1435 # Martin A. Hansen, July 2005.
1437 # handles HTML single element such as <meta>
1438 # where the tag hold optional arguments.
1440 my ( $tag, # HTML tag type
1448 $arg = &format_args( $args );
1451 return "<$tag $arg />";
1460 # Martin A. Hansen, July 2005.
1462 # formats simple ordered and unordered lists.
1463 # attributes can only be assigned to the list
1472 my ( @html, $arg, $items, $item );
1474 $items = $args->{ "li" };
1476 delete $args->{ "li" };
1478 $arg = &format_args( $args );
1481 push @html, "<$tag $arg>";
1483 push @html, "<$tag>";
1486 foreach $item ( @{ $items } )
1488 push @html, &tag_pair( "li", { txt => $item } );
1491 push @html, "</$tag>";
1493 return join "\n", @html;
1499 # Martin A. Hansen, July 2005.
1501 # formats advanced ordered and unordered lists.
1502 # attributes can be assigned to both the list
1503 # type element and the list elements.
1511 my ( @html, $arg, $items, $item, $li );
1513 $items = $args->{ "li" };
1515 delete $args->{ "li" };
1517 $arg = &format_args( $args );
1520 push @html, "<$tag $arg>";
1522 push @html, "<$tag>";
1525 foreach $item ( @{ $items } )
1527 warn qq(WARNING: no list item found in list_advanced\n) if not $item->{ "li" };
1529 $li = $item->{ "li" };
1531 delete $item->{ "li" };
1533 $item->{ "txt" } = $li;
1535 push @html, &tag_pair( "li", $item );
1538 push @html, "</$tag>";
1540 return join "\n", @html;
1546 # Martin A. Hansen, July 2005.
1548 # generic routine to handle the different
1549 # flavors of input types.
1559 warn qq(WARNING no input name given\n) if $type ne "reset" and not $args->{ "name" };
1561 $arg = &format_args( $args );
1564 return qq(<input type="$type" $arg />);
1566 return qq(<input type="$type" />);
1571 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<