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 & OBJECT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
630 # Martin A. Hansen, July 2005.
639 return &tag_single( "img", \%args );
645 # Martin A. Hansen, October 2009.
647 # HTML <object> element
654 return &tag_single( "object", \%args );
658 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> DIV & SPAN <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
663 # Martin A. Hansen, July 2005.
672 my ( @html, $lines );
674 $lines = $args{ "txt" };
678 $args{ "txt" } = $lines;
680 return &tag_pair( "div", \%args );
684 return &tag_single( "div", \%args );
691 # Martin A. Hansen, July 2005.
693 # HTML <span> element
700 warn qq(WARNING: no span given\n) if not $args{ "txt" };
702 return &tag_pair( "span", \%args );
706 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> MAP <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
711 # Martin A. Hansen, July 2005.
718 warn qq(WARNING: no map name given\n) if not $args{ "name" };
719 warn qq(WARNING: no map id given \n) if not $args{ "id" };
721 my $arg = &format_args( \%args );
723 return qq(<map $arg>);
729 # Martin A. Hansen, July 2005.
731 # HTML </map> element
739 # Martin A. Hansen, October 2009.
741 # HTML <area> element
746 warn qq(WARNING: no area href given\n) if not $args{ "href" };
747 warn qq(WARNING: no area shape given \n) if not $args{ "shape" };
748 warn qq(WARNING: no area coords given \n) if not $args{ "coords" };
750 return tag_single( "area", \%args )
754 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> PRE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
759 # Martin A. Hansen, July 2005.
768 warn qq(WARNING: no pre lines given\n) if not $args{ "txt" };
770 $args{ "txt" } =~ s/&/&/g;
771 $args{ "txt" } =~ s/>/>/g;
772 $args{ "txt" } =~ s/</</g;
774 return &tag_pair( "pre", \%args );
778 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FORMS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
783 # Martin A. Hansen, July 2005.
785 # HTML <form> element
792 $arg = &format_args( \%args );
794 warn qq(WARNING: no form method given\n) if not $args{ "method" };
795 warn qq(WARNING: "method" must be eihter "post" or "get" - not ") . $args{ "method" } . qq("\n) if not $args{ "method" } =~ /get|post/;
797 return qq(<form $arg>);
803 # Martin A. Hansen, July 2005.
805 # HTML </form> element
811 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> BUTTONS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
816 # Martin A. Hansen, July 2005.
825 return &input_field( "submit", \%args );
831 # Martin A. Hansen, July 2005.
835 return &input_field( "reset" );
839 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FIELDS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
844 # Martin A. Hansen, July 2005.
853 return &input_field( "text", \%args );
859 # Martin A. Hansen, July 2005.
861 # HTML password field
868 return &input_field( "password", \%args );
874 # Martin A. Hansen, July 2005.
883 return &input_field( "file", \%args );
889 # Martin A. Hansen, July 2005.
891 # HTML checkbox field
898 return &input_field( "checkbox", \%args );
904 # Martin A. Hansen, July 2005.
906 # HTML radio button field
913 return &input_field( "radio", \%args );
919 # Martin A. Hansen, July 2005.
928 warn qq(WARNING: no hidden value given\n) if not $args{ "value" };
930 return &input_field( "hidden", \%args );
936 # Martin A. Hansen, July 2005.
938 # HTML popup/drowdown menu
940 my ( %args, # name of variable
945 my ( @html, $name, $selected, $options, $option, $value );
947 warn qq(WARNING: no menu name given\n) if not $args{ "name" };
948 warn qq(WARNING: no menu options given\n) if not $args{ "options" };
950 $name = $args{ "name" };
951 $selected = $args{ "selected" };
952 $options = $args{ "options" };
954 push @html, qq(<select name="$name">);
956 push @html, &tag_pair( "option", { selected => "selected", value => $selected, txt => $selected } ) if exists $args{ "selected" };
958 foreach $option ( @{ $options } ) {
959 push @html, &tag_pair( "option", { value => "$option", txt => $option } );
962 push @html, qq(</select>);
964 return join "\n", @html;
970 # Martin A. Hansen, July 2005.
972 # HTML textarea field
979 warn qq(WARNING: no textarea name given\n) if not $args{ "name" };
980 warn qq(WARNING: no textarea rows given\n) if not $args{ "rows" };
981 warn qq(WARNING: no textarea cols given\n) if not $args{ "cols" };
983 return &tag_pair( "textarea", \%args );
987 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> TABLE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
990 # XHTML allows several forms of tables: table, thead, tbody, and tfoot.
991 # All are supported in the below routines, considering that each of these
992 # table types are generically handled in two flavors - simple and advanced.
993 # simple tables takes a list of rows as arguments, while advamced tables
994 # takes a list of rows each cell is specified.
995 # NB! the order of tables is important thead->tfoot->tbody (if used)
1000 # Martin A. Hansen, July 2005.
1002 # HTML <table> element
1007 my $arg = &format_args( \%args );
1010 return "<table $arg>";
1019 # Martin A. Hansen, July 2005.
1021 # HTML </table> element
1029 # Martin A. Hansen, July 2005.
1031 # HTML <thead> element
1036 my $arg = &format_args( \%args );
1039 return "<thead $arg>";
1048 # Martin A. Hansen, July 2005.
1050 # HTML </thead> element
1058 # Martin A. Hansen, July 2005.
1060 # HTML <tfoot> element
1065 my $arg = &format_args( \%args );
1068 return "<tfoot $arg>";
1077 # Martin A. Hansen, July 2005.
1079 # HTML </tfoot> element
1087 # Martin A. Hansen, July 2005.
1089 # HTML <tbody> element
1094 my $arg = &format_args( \%args );
1097 return "<tbody $arg>";
1106 # Martin A. Hansen, July 2005.
1108 # HTML </tbody> element
1116 # Martin A. Hansen, July 2005.
1118 # HTML <caption> element
1125 my @html = &tag_pair( "caption", \%args );
1127 return wantarray ? @html : \@html;
1131 sub table_row_simple
1133 # Martin A. Hansen, July 2005.
1142 my ( @html, $arg, $cells, $cell );
1144 warn qq(WARNING: no simple row given\n) if not $args{ "tr" };
1146 $cells = $args{ "tr" };
1148 delete $args{ "tr" };
1150 $arg = &format_args( \%args );
1153 push @html, "<tr $arg>";
1158 foreach $cell ( @{ $cells } ) {
1159 push @html, &tag_pair( "td", { txt => $cell } );
1162 push @html, "</tr>";
1164 return join "\n", @html;
1168 sub table_row_advanced
1170 # Martin A. Hansen, July 2005.
1179 my ( @html, $arg, $cells, $cell );
1181 warn qq(WARNING: no advanced row given\n) if not $args{ "tr" };
1183 $cells = $args{ "tr" };
1185 delete $args{ "tr" };
1187 $arg = &format_args( \%args );
1190 push @html, "<tr $arg>";
1195 foreach $cell ( @{ $cells } )
1197 $cell->{ "txt" } = $cell->{ "td" };
1199 delete $cell->{ "td" };
1201 push @html, &tag_pair( "td", $cell );
1204 push @html, "</tr>";
1206 return join "\n", @html;
1210 sub table_header_simple
1212 # Martin A. Hansen, July 2005.
1214 # HTML simple header rww
1221 my ( @html, $arg, $cells, $cell );
1223 warn qq(WARNING: no simple header given\n) if not $args{ "tr" };
1225 $cells = $args{ "tr" };
1227 delete $args{ "tr" };
1229 $arg = &format_args( \%args );
1232 push @html, "<tr $arg>";
1237 foreach $cell ( @{ $cells } ) {
1238 push @html, &tag_pair( "th", { txt => $cell } );
1241 push @html, "</tr>";
1243 return join "\n", @html;
1247 sub table_header_advanced
1249 # Martin A. Hansen, July 2005.
1251 # HTML advanced header row
1258 my ( @html, $arg, $cells, $cell );
1260 warn qq(WARNING: no advanced header given\n) if not $args{ "tr" };
1262 $cells = $args{ "tr" };
1264 delete $args{ "tr" };
1266 $arg = &format_args( \%args );
1269 push @html, "<tr $arg>";
1274 foreach $cell ( @{ $cells } )
1276 $cell->{ "txt" } = $cell->{ "th" };
1278 delete $cell->{ "th" };
1280 push @html, &tag_pair( "th", $cell );
1283 push @html, "</tr>";
1285 return join "\n", @html;
1291 # Martin A. Hansen, July 2005.
1300 my ( @html, $arg, $cells, $cell );
1302 warn qq(WARNING: no colgroup given\n) if not $args{ "colgroup" };
1304 $cells = $args{ "colgroup" };
1306 delete $args{ "colgroup" };
1308 $arg = &format_args( \%args );
1311 push @html, "<colgroup $arg>";
1313 push @html, "<colgroup>";
1316 foreach $cell ( @{ $cells } ) {
1317 push @html, &tag_single( "col", $cell );
1320 push @html, "</colgroup>";
1322 return join "\n", @html;
1326 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> HTML COMMENT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
1331 # Martin A. Hansen, July 2005.
1338 my $comment = $args{ "txt" };
1340 warn qq(WARNING: no comment given\n) if not $comment;
1342 return "\n<!-- $comment -->\n";
1346 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> VALIDATOR BUTTONS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
1351 # Martin A. Hansen, July 2005.
1353 # returns an image link to w3.orgs validator page
1355 return &ln( txt => &img( src => "http://www.w3.org/Icons/valid-xhtml10", alt => "Valid XHTML 1.0!" ),
1356 href => "http://validator.w3.org/check?uri=referer", id => "validate_xhtml" );
1362 # Martin A. Hansen, July 2005.
1364 # returns an image link to w3.orgs css validator page
1366 my ( $url, # url or uri to the CSS file
1369 warn qq(WARNING: no url given for validate css\n) if not $url;
1371 return &ln( txt => &img( src => "http://jigsaw.w3.org/css-validator/images/vcss", alt => "Valid CSS!" ),
1372 href => "http://jigsaw.w3.org/css-validator/validator?uri=$url", id => "validate_css" );
1376 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> HELPERS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
1381 # Martin A. Hansen, July 2005.
1383 # given a hash with arguments reformat ( foo => "bar", foo2 => "bar2" ... )
1384 # these to HTML type argument str ( foo = "bar" foo2 = "bar2" ... )
1386 my ( $args, # hashref
1391 my ( $str, $arg, @list );
1393 foreach $arg ( sort keys %{ $args } ) {
1394 push @list, qq($arg=") . $args->{ $arg } . qq(");
1397 $str = join " ", @list;
1405 # Martin A. Hansen, July 2005.
1407 # handles HTML tags with a begin tab and a end tag such as <h1>string</h2>,
1408 # where the first tag hold optional arguments and the txt string is mandatory.
1410 my ( $tag, # HTML element type
1416 my ( @html, $txt, $arg, $embed );
1418 $txt = $args->{ "txt" };
1420 delete $args->{ "txt" };
1422 warn qq(WARNING: no $tag given\n) if not $tag;
1424 $arg = &format_args( $args );
1426 if ( $txt =~ /(<[^>]+>)/ )
1428 if ( $1 =~ /^<(input|textarea|a |img)/ ) {
1440 push @html, "<$tag $arg>$txt</$tag>";
1442 push @html, "<$tag>$txt</$tag>";
1449 push @html, "<$tag $arg>";
1451 push @html, "</$tag>";
1455 push @html, "<$tag>";
1457 push @html, "</$tag>";
1461 return join "\n", @html;
1467 # Martin A. Hansen, July 2005.
1469 # handles HTML single element such as <meta>
1470 # where the tag hold optional arguments.
1472 my ( $tag, # HTML tag type
1480 $arg = &format_args( $args );
1483 return "<$tag $arg />";
1492 # Martin A. Hansen, July 2005.
1494 # formats simple ordered and unordered lists.
1495 # attributes can only be assigned to the list
1504 my ( @html, $arg, $items, $item );
1506 $items = $args->{ "li" };
1508 delete $args->{ "li" };
1510 $arg = &format_args( $args );
1513 push @html, "<$tag $arg>";
1515 push @html, "<$tag>";
1518 foreach $item ( @{ $items } )
1520 push @html, &tag_pair( "li", { txt => $item } );
1523 push @html, "</$tag>";
1525 return join "\n", @html;
1531 # Martin A. Hansen, July 2005.
1533 # formats advanced ordered and unordered lists.
1534 # attributes can be assigned to both the list
1535 # type element and the list elements.
1543 my ( @html, $arg, $items, $item, $li );
1545 $items = $args->{ "li" };
1547 delete $args->{ "li" };
1549 $arg = &format_args( $args );
1552 push @html, "<$tag $arg>";
1554 push @html, "<$tag>";
1557 foreach $item ( @{ $items } )
1559 warn qq(WARNING: no list item found in list_advanced\n) if not $item->{ "li" };
1561 $li = $item->{ "li" };
1563 delete $item->{ "li" };
1565 $item->{ "txt" } = $li;
1567 push @html, &tag_pair( "li", $item );
1570 push @html, "</$tag>";
1572 return join "\n", @html;
1578 # Martin A. Hansen, July 2005.
1580 # generic routine to handle the different
1581 # flavors of input types.
1591 warn qq(WARNING no input name given\n) if $type ne "reset" and not $args->{ "name" };
1593 $arg = &format_args( $args );
1596 return qq(<input type="$type" $arg />);
1598 return qq(<input type="$type" />);
1603 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> DEBUG <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
1608 # Martin A. Hansen, November 2009.
1610 # Primitive debug routine that returns given data
1611 # in <pre> tags as HTML lines.
1613 my ( $data, # data to dump
1620 @html = "Content-Type: text/html; charset=ISO-8859-1\n\n";
1622 push @html, "<pre>\n";
1623 push @html, Dumper( $data );
1624 push @html, "</pre>\n";
1626 return wantarray ? @html : \@html;
1630 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<