]> git.donarmstrong.com Git - biopieces.git/blob - code_perl/Maasha/XHTML.pm
7fd5f69221b8147cad07943befd3170253badadf
[biopieces.git] / code_perl / Maasha / XHTML.pm
1 package Maasha::XHTML;
2
3 # Copyright (C) 2005 Martin A. Hansen.
4
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.
9
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.
14
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.
18
19 # http://www.gnu.org/copyleft/gpl.html
20
21
22 # Version 1.1
23
24 # Martin A. Hansen, July 2005.
25 # mail@maasha.dk
26
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.
30
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.
36
37 # NB! do use w3's excellent HTML Validator while designing HTML layout (http://validator.w3.org/)
38
39 # NB! alternatively use Dave Raggett's TIDY (http://tidy.sourceforge.net/)
40
41 # Example:   $name = &XHTML::text( name => "NAME", value => $name_def || "", size => 25, maxlength => 20 );
42
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/
48
49
50 # WISHLIST:
51
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>
58
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.
66
67 # buttons with action:
68 #
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')"> 
71
72 use strict;
73 use warnings;
74 use Data::Dumper;
75
76 use vars qw( @ISA @EXPORT );
77
78 require Exporter;
79
80 @ISA = qw( Exporter );
81
82
83 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> HEADERS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
84
85
86 sub html_header 
87 {
88     # Martin A. Hansen, July 2005.
89
90     # Creates HTML header
91
92     my ( %args,   # arguments
93        ) = @_;
94
95     # Returns string
96
97     my ( @html );
98
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;
110
111     return join "\n", @html;
112 }
113
114
115 sub cgi_header
116 {
117     # Martin A. Hansen, July 2005.
118
119     # Header for CGI scripts.
120
121     return "Content-Type: text/html; charset=ISO-8859-1\n\n";
122 }
123
124
125 sub doc_type
126 {
127     # Martin A. Hansen, July 2005.
128
129     # Header for XHTML 1.0 Strict
130
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">);
135 }
136
137
138 sub head_beg
139 {
140     # Martin A. Hansen, July 2005.
141
142     # HTML <head> element
143
144     return "<head>";
145 }
146
147
148 sub title
149 {
150     # Martin A. Hansen, July 2005.
151
152     # HTML <title> element.
153
154     my ( $title,   # docuement title
155        ) = @_;
156
157     warn qq(WARNING: no title given\n) if not $title;
158
159     return &tag_pair( "title", { txt => $title } );
160 }
161
162
163 sub css
164 {
165     # Martin A. Hansen, July 2005.
166
167     # Links external CSS file.
168
169     my ( $css_file,   # path to external CSS file
170        ) = @_;
171
172     warn qq(WARNING: could not locate CSS file "$css_file"\n) if not -f $css_file;
173
174     return &tag_single( "link", { rel => "stylesheet", type => "text/css", href => $css_file } );
175 }
176
177
178 sub icon
179 {
180     # Martin A. Hansen, July 2005.
181
182     # Links flavicon.
183
184     my ( $icon_file,   # path to flavicon file
185        ) = @_;
186
187     warn qq(WARNING: could not locate icon file "$icon_file"\n) if not -f $icon_file;
188
189     return &tag_single( "link", { rel => "shortcut icon", href => $icon_file } );
190 }
191
192
193 sub author
194 {
195     # Martin A. Hansen, July 2005.
196
197     # HTML meta tag containing author information.
198
199     my ( $author,   # name of webpage author
200        ) = @_;
201
202     warn qq(WARNING: no author given\n) if not $author;
203
204     return &tag_single( "meta", { name => "author", content => $author } );
205 }
206
207
208 sub description
209 {
210     # Martin A. Hansen, July 2005.
211
212     # HTML meta tag containing webpage description.
213
214     my ( $description,    # webpage description
215        ) = @_;
216        
217     warn qq(WARNING: no description given\n) if not $description;
218
219     return &tag_single( "meta", { name => "description", content => $description } );
220 }
221
222
223 sub keywords
224 {
225     # Martin A. Hansen, July 2005.
226
227     # HTML meta tag contining webpage keywords for webcrawlers.
228
229     my ( $keywords,   # list of keywords
230        ) = @_;
231
232     my ( $keyword );
233
234     warn qq(WARNING: no keywords given\n) if not $keywords;
235
236     $keyword = join ", ", @{ $keywords };
237     
238     return &tag_single( "meta", { name => "keywords", content => $keyword } );
239 }
240
241
242 sub no_cache
243 {
244     # Martin A. Hansen, July 2005.
245     
246     # HTML meta tags disabling browser caching.
247     # (uncomfirmed behaviour - works sometimes - sometimes not)
248
249     my @html;
250
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" } );
253
254     return join "\n", @html;
255 }
256
257
258 sub head_end
259 {
260     # Martin A. Hansen, July 2005.
261
262     # HTML </head> element
263
264     return "</head>";
265 }
266
267
268 sub body_beg
269 {
270     # Martin A. Hansen, July 2005.
271
272     # HTML <body> element
273
274     return "<body>";
275 }
276
277
278 sub javascript
279 {
280     # Martin A. Hansen, July 2005.
281
282     # Links external java script file
283
284     # Must be located in the HTML body section
285     # (after <body> and before </body>)
286
287     my ( $js_file,   # path to javascript file
288        ) = @_;
289
290     warn qq(WARNING: could not locate javascript file "$js_file"\n) if not -f $js_file;
291
292     return qq(<script src="$js_file" type="text/javascript"></script>);
293 }
294
295
296 sub body_end
297 {
298     # Martin A. Hansen, July 2005.
299
300     # HTML </body> element
301
302     return "</body>";
303 }
304
305
306 sub html_end
307 {
308     # Martin A. Hansen, July 2005.
309
310     # HTML </html> element
311
312     return "</html>";
313 }
314
315
316 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> HEADINGS & PARAGRAPH <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
317
318
319 sub h1
320 {
321     # Martin A. Hansen, July 2005.
322
323     # HTML <h1> element
324
325     my ( %args,
326        ) = @_;
327
328     # Returns string
329
330     return &tag_pair( "h1", \%args );
331 }
332
333
334 sub h2
335 {
336     # Martin A. Hansen, July 2005.
337
338     # HTML <h2> element
339     
340     my ( %args,
341        ) = @_;
342
343     # Returns string
344
345     return &tag_pair( "h2", \%args );
346 }
347
348
349 sub h3
350 {
351     # Martin A. Hansen, July 2005.
352
353     # HTML <h3> element
354     
355     my ( %args,
356        ) = @_;
357
358     # Returns string
359
360     return &tag_pair( "h3", \%args );
361 }
362
363
364 sub h4
365 {
366     # Martin A. Hansen, July 2005.
367
368     # HTML <h4> element
369     
370     my ( %args,
371        ) = @_;
372
373     # Returns string
374
375     return &tag_pair( "h4", \%args );
376 }
377
378
379 sub h5
380 {
381     # Martin A. Hansen, July 2005.
382
383     # HTML <h5> element
384     
385     my ( %args,
386        ) = @_;
387
388     # Returns string
389
390     return &tag_pair( "h5", \%args );
391 }
392
393
394 sub h6
395 {
396     # Martin A. Hansen, July 2005.
397
398     # HTML <h6> element
399     
400     my ( %args,
401        ) = @_;
402
403     # Returns string
404
405     return &tag_pair( "h6", \%args );
406 }
407
408
409 sub p
410 {
411     # Martin A. Hansen, July 2005.
412
413     # HTML <p> element
414     
415     my ( %args,
416        ) = @_;
417
418     # Returns string
419
420     return &tag_pair( "p", \%args );
421 }
422
423
424 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> LISTS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
425
426
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.
430
431
432 sub ul_simple
433 {
434     # Martin A. Hansen, July 2005.
435
436     # HTML <ul> element
437
438     my ( %args,
439        ) = @_;
440
441     # Returns string
442
443     warn qq(WARINING: no ul_simple items given\n) if not $args{ "li" };
444
445     return &list_simple( "ul", \%args );
446 }
447
448
449 sub ol_simple
450 {
451     # Martin A. Hansen, July 2005.
452
453     # HTML <ul> element
454
455     my ( %args,
456        ) = @_;
457
458     # Returns string
459
460     warn qq(WARINING: no ol_simple items given\n) if not $args{ "li" };
461
462     return &list_simple( "ol", \%args );
463 }
464
465
466 sub ul_advanced
467 {
468     # Martin A. Hansen, July 2005.
469
470     # HTML <ul> element
471
472     my ( %args,
473        ) = @_;
474
475     # Returns string
476
477     warn qq(WARINING: no ul_advanced items given\n) if not $args{ "li" };
478
479     return &list_advanced( "ul", \%args );
480 }
481
482
483 sub ol_advanced
484 {
485     # Martin A. Hansen, July 2005.
486
487     # HTML <ol> element
488
489     my ( %args,
490        ) = @_;
491
492     # Returns string
493
494     warn qq(WARINING: no ol_advanced items given\n) if not $args{ "li" };
495
496     return &list_advanced( "ol", \%args );
497 }
498
499
500 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> LABEL <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
501
502
503 sub label
504 {
505     # Martin A. Hansen, July 2005.
506
507     # HTML <label> element
508
509     my ( %args,
510        ) = @_;
511
512     # Returns string
513     
514     warn qq(WARNING: no "for" given in label\n) if not $args{ "for" };
515
516     return &tag_pair( "label", \%args );
517 }
518
519
520 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> LINE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
521
522
523 sub hr
524 {
525     # Martin A. Hansen, July 2005.
526
527     # HTML <hr> element
528
529     # NB - rather use proper CSS than <hr>!
530
531     my ( %args,
532        ) = @_;
533
534     # Returns string
535
536     return &tag_single( "hr", \%args );
537 }
538
539
540 sub br
541 {
542     # Martin A. Hansen, July 2005.
543
544     # HTML <br> element
545
546     # NB - rather use proper CSS than <br>!
547
548     my ( %args,
549        ) = @_;
550
551     # Returns string
552
553     return &tag_single( "br", \%args );
554 }
555
556
557 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> LINK <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
558
559
560 sub ln
561 {
562     # Martin A. Hansen, July 2005.
563
564     # HTML <ln> element
565     
566     my ( %args,
567        ) = @_;
568
569     # Returns string
570
571     my ( @html );
572
573     warn qq(WARNING: no link href given\n) if not $args{ "href" };
574     
575     $args{ "href" } =~ s/&/&amp;/g;
576     
577     if ( $args{ "txt" } ) {
578         return &tag_pair( "a", \%args );
579     } else {
580         return &tag_single( "a", \%args );
581     }
582 }
583
584
585 sub anchor
586 {
587     # Martin A. Hansen, July 2005.
588
589     # HTML anchor
590
591     my ( %args,
592        ) = @_;
593
594     # Returns string
595
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" };
598
599     return &tag_pair( "a", \%args );
600 }
601
602
603 sub mailto
604 {
605     # Martin A. Hansen, July 2005.
606
607     # HTML mailto
608     
609     my ( %args,
610        ) = @_;
611
612     # Returns string
613
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" };
616
617     $args{ "href" } = "mailto:" . $args{ "email" };
618
619     delete $args{ "email" };
620
621     return &tag_pair( "a", \%args );
622 }
623
624
625 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> IMG & OBJECT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
626
627
628 sub img
629 {
630     # Martin A. Hansen, July 2005.
631
632     # HTML <img> element
633     
634     my ( %args,
635        ) = @_;
636
637     # Returns string
638
639     return &tag_single( "img", \%args );
640 }
641
642
643 sub object
644 {
645     # Martin A. Hansen, October 2009.
646
647     # HTML <object> element
648
649     my ( %args,
650        ) = @_;
651
652     # Returns string
653
654     return &tag_single( "object", \%args );
655 }
656
657
658 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> DIV & SPAN <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
659
660
661 sub div
662 {
663     # Martin A. Hansen, July 2005.
664
665     # HTML <div> element
666
667     my ( %args,
668        ) = @_;
669
670     # Returns string
671
672     my ( @html, $lines );
673
674     $lines  = $args{ "txt" };
675
676     if ( $lines )
677     {
678         $args{ "txt" } = $lines;
679
680         return &tag_pair( "div", \%args );
681     }
682     else
683     {
684         return &tag_single( "div", \%args );
685     }
686 }
687
688
689 sub span
690 {
691     # Martin A. Hansen, July 2005.
692
693     # HTML <span> element
694
695     my ( %args,
696        ) = @_;
697
698     # Returns string
699
700     warn qq(WARNING: no span given\n) if not $args{ "txt" };
701
702     return &tag_pair( "span", \%args );
703 }
704
705
706 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> MAP <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
707
708
709 sub map_beg
710 {
711     # Martin A. Hansen, July 2005.
712
713     # HTML <map> element
714     
715     my ( %args,
716        ) = @_;
717
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" };
720
721     my $arg = &format_args( \%args );
722
723     return qq(<map $arg>);
724 }
725
726
727 sub map_end
728 {
729     # Martin A. Hansen, July 2005.
730
731     # HTML </map> element
732
733     return qq(</map>);
734 }
735
736
737 sub area
738 {
739     # Martin A. Hansen, October 2009.
740
741     # HTML <area> element
742
743     my ( %args,
744        ) = @_;
745
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" };
749
750     return tag_single( "area", \%args )
751 }
752
753
754 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> PRE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
755
756
757 sub pre
758 {
759     # Martin A. Hansen, July 2005.
760
761     # HTML <pre> element
762     
763     my ( %args,
764        ) = @_;
765
766     # Returns string
767
768     warn qq(WARNING: no pre lines given\n) if not $args{ "txt" };
769
770     $args{ "txt" } =~ s/&/&amp;/g;
771     $args{ "txt" } =~ s/>/&gt;/g;
772     $args{ "txt" } =~ s/</&lt;/g;
773
774     return &tag_pair( "pre", \%args );
775 }
776
777
778 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FORMS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
779
780
781 sub form_beg
782 {
783     # Martin A. Hansen, July 2005.
784
785     # HTML <form> element
786
787     my ( %args,
788        ) = @_;
789
790     my ( $arg );
791
792     $arg = &format_args( \%args );
793
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/;
796
797     return qq(<form $arg>);
798 }
799
800
801 sub form_end
802 {
803     # Martin A. Hansen, July 2005.
804
805     # HTML </form> element
806
807     return qq(</form>);
808 }
809
810
811 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> BUTTONS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
812
813
814 sub submit
815 {
816     # Martin A. Hansen, July 2005.
817
818     # HTML submit button
819
820     my ( %args,
821        ) = @_;
822
823     # Returns string
824
825     return &input_field( "submit", \%args );
826 }
827
828
829 sub reset
830 {
831     # Martin A. Hansen, July 2005.
832
833     # HTML reset button
834
835     return &input_field( "reset" );
836 }
837
838
839 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FIELDS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
840
841
842 sub text
843 {
844     # Martin A. Hansen, July 2005.
845
846     # HTML text field
847
848     my ( %args,
849        ) = @_;
850
851     # Returns string
852
853     return &input_field( "text", \%args );
854 }
855
856
857 sub password
858 {
859     # Martin A. Hansen, July 2005.
860
861     # HTML password field
862
863     my ( %args,
864        ) = @_;
865
866     # Returns string
867
868     return &input_field( "password", \%args );
869 }
870
871
872 sub file
873 {
874     # Martin A. Hansen, July 2005.
875
876     # HTML file field
877
878     my ( %args,
879        ) = @_;
880
881     # Returns string
882
883     return &input_field( "file", \%args );
884 }
885
886
887 sub checkbox
888 {
889     # Martin A. Hansen, July 2005.
890
891     # HTML checkbox field
892
893     my ( %args,
894        ) = @_;
895
896     # Returns string
897
898     return &input_field( "checkbox", \%args );
899 }
900
901
902 sub radio
903 {
904     # Martin A. Hansen, July 2005.
905
906     # HTML radio button field
907
908     my ( %args,
909        ) = @_;
910
911     # Returns string
912
913     return &input_field( "radio", \%args );
914 }
915
916
917 sub hidden
918 {
919     # Martin A. Hansen, July 2005.
920
921     # HTML hidden field
922
923     my ( %args,
924        ) = @_;
925
926     # Returns string
927
928     warn qq(WARNING: no hidden value given\n) if not $args{ "value" };
929
930     return &input_field( "hidden", \%args );
931 }
932
933
934 sub menu
935 {
936     # Martin A. Hansen, July 2005.
937
938     # HTML popup/drowdown menu
939     
940     my ( %args,    # name of variable
941        ) = @_;
942
943     # Returns string
944
945     my ( @html, $name, $selected, $options, $option, $value );
946  
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" };
949  
950     $name     = $args{ "name" };
951     $selected = $args{ "selected" };
952     $options  = $args{ "options" };
953  
954     push @html, qq(<select name="$name">);
955
956     push @html, &tag_pair( "option", { selected => "selected", value => $selected, txt => $selected } ) if exists $args{ "selected" };
957
958     foreach $option ( @{ $options } ) {
959         push @html, &tag_pair( "option", { value => "$option", txt => $option } );
960     }
961
962     push @html, qq(</select>);
963
964     return join "\n", @html;
965 }
966
967
968 sub textarea
969 {
970     # Martin A. Hansen, July 2005.
971
972     # HTML textarea field
973
974     my ( %args,
975        ) = @_;
976
977     # Returns string
978
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" };
982
983     return &tag_pair( "textarea", \%args );
984 }
985
986
987 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> TABLE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
988
989
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)
996
997
998 sub table_beg
999 {
1000     # Martin A. Hansen, July 2005.
1001
1002     # HTML <table> element
1003
1004     my ( %args,
1005        ) = @_;
1006
1007     my $arg = &format_args( \%args );
1008
1009     if ( $arg ) {
1010         return "<table $arg>";
1011     } else {
1012         return "<table>";
1013     }
1014 }
1015
1016
1017 sub table_end
1018 {
1019     # Martin A. Hansen, July 2005.
1020
1021     # HTML </table> element
1022
1023     return "</table>";
1024 }
1025
1026
1027 sub table_head_beg
1028 {
1029     # Martin A. Hansen, July 2005.
1030
1031     # HTML <thead> element
1032
1033     my ( %args,
1034        ) = @_;
1035
1036     my $arg = &format_args( \%args );
1037
1038     if ( $arg ) {
1039         return "<thead $arg>";
1040     } else {
1041         return "<thead>";
1042     }
1043 }
1044
1045
1046 sub table_head_end
1047 {
1048     # Martin A. Hansen, July 2005.
1049
1050     # HTML </thead> element
1051
1052     return "</thead>";
1053 }
1054
1055
1056 sub table_foot_beg
1057 {
1058     # Martin A. Hansen, July 2005.
1059
1060     # HTML <tfoot> element
1061
1062     my ( %args,
1063        ) = @_;
1064
1065     my $arg = &format_args( \%args );
1066
1067     if ( $arg ) {
1068         return "<tfoot $arg>";
1069     } else {
1070         return "<tfoot>";
1071     }
1072 }
1073
1074
1075 sub table_foot_end
1076 {
1077     # Martin A. Hansen, July 2005.
1078
1079     # HTML </tfoot> element
1080
1081     return "</tfoot>";
1082 }
1083
1084
1085 sub table_body_beg
1086 {
1087     # Martin A. Hansen, July 2005.
1088
1089     # HTML <tbody> element
1090
1091     my ( %args,
1092        ) = @_;
1093
1094     my $arg = &format_args( \%args );
1095
1096     if ( $arg ) {
1097         return "<tbody $arg>";
1098     } else {
1099         return "<tbody>";
1100     }
1101 }
1102
1103
1104 sub table_body_end
1105 {
1106     # Martin A. Hansen, July 2005.
1107
1108     # HTML </tbody> element
1109
1110     return "</tbody>";
1111 }
1112
1113
1114 sub table_caption
1115 {
1116     # Martin A. Hansen, July 2005.
1117
1118     # HTML <caption> element
1119
1120     my ( %args,
1121        ) = @_;
1122
1123     # Returns string
1124
1125     my @html = &tag_pair( "caption", \%args );
1126     
1127     return wantarray ? @html : \@html;
1128 }
1129
1130
1131 sub table_row_simple
1132 {
1133     # Martin A. Hansen, July 2005.
1134
1135     # HTML simple row
1136
1137     my ( %args,
1138        ) = @_;
1139
1140     # Returns string
1141
1142     my ( @html, $arg, $cells, $cell );
1143
1144     warn qq(WARNING: no simple row given\n) if not $args{ "tr" };
1145
1146     $cells = $args{ "tr" };
1147     
1148     delete $args{ "tr" };
1149
1150     $arg = &format_args( \%args );
1151
1152     if ( $arg ) {
1153         push @html, "<tr $arg>";
1154     } else {
1155         push @html, "<tr>";
1156     }
1157
1158     foreach $cell ( @{ $cells } ) {
1159         push @html, &tag_pair( "td", { txt => $cell } );
1160     }
1161
1162     push @html, "</tr>";
1163         
1164     return join "\n", @html;
1165 }
1166
1167
1168 sub table_row_advanced
1169 {
1170     # Martin A. Hansen, July 2005.
1171
1172     # HTML advanced row
1173
1174     my ( %args,
1175        ) = @_;
1176
1177     # Returns string
1178
1179     my ( @html, $arg, $cells, $cell );
1180
1181     warn qq(WARNING: no advanced row given\n) if not $args{ "tr" };
1182
1183     $cells = $args{ "tr" };
1184     
1185     delete $args{ "tr" };
1186
1187     $arg = &format_args( \%args );
1188
1189     if ( $arg ) {
1190         push @html, "<tr $arg>";
1191     } else {
1192         push @html, "<tr>";
1193     }
1194
1195     foreach $cell ( @{ $cells } )
1196     {
1197         $cell->{ "txt" } = $cell->{ "td" };
1198
1199         delete $cell->{ "td" };
1200     
1201         push @html, &tag_pair( "td", $cell );
1202     }
1203
1204     push @html, "</tr>";
1205         
1206     return join "\n", @html;
1207 }
1208
1209
1210 sub table_header_simple
1211 {
1212     # Martin A. Hansen, July 2005.
1213
1214     # HTML simple header rww
1215
1216     my ( %args,
1217        ) = @_;
1218
1219     # Returns string
1220
1221     my ( @html, $arg, $cells, $cell );
1222
1223     warn qq(WARNING: no simple header given\n) if not $args{ "tr" };
1224
1225     $cells = $args{ "tr" };
1226     
1227     delete $args{ "tr" };
1228
1229     $arg = &format_args( \%args );
1230
1231     if ( $arg ) {
1232         push @html, "<tr $arg>";
1233     } else {
1234         push @html, "<tr>";
1235     }
1236
1237     foreach $cell ( @{ $cells } ) {
1238         push @html, &tag_pair( "th", { txt => $cell } );
1239     }
1240
1241     push @html, "</tr>";
1242         
1243     return join "\n", @html;
1244 }
1245
1246
1247 sub table_header_advanced
1248 {
1249     # Martin A. Hansen, July 2005.
1250
1251     # HTML advanced header row
1252
1253     my ( %args,
1254        ) = @_;
1255
1256     # Returns string
1257
1258     my ( @html, $arg, $cells, $cell );
1259
1260     warn qq(WARNING: no advanced header given\n) if not $args{ "tr" };
1261
1262     $cells = $args{ "tr" };
1263     
1264     delete $args{ "tr" };
1265
1266     $arg = &format_args( \%args );
1267
1268     if ( $arg ) {
1269         push @html, "<tr $arg>";
1270     } else {
1271         push @html, "<tr>";
1272     }
1273
1274     foreach $cell ( @{ $cells } )
1275     {
1276         $cell->{ "txt" } = $cell->{ "th" };
1277
1278         delete $cell->{ "th" };
1279     
1280         push @html, &tag_pair( "th", $cell );
1281     }
1282
1283     push @html, "</tr>";
1284         
1285     return join "\n", @html;
1286 }
1287
1288
1289 sub table_colgroup
1290 {
1291     # Martin A. Hansen, July 2005.
1292
1293     # HTML colgroup row
1294
1295     my ( %args,
1296        ) = @_;
1297
1298     # Returns string
1299
1300     my ( @html, $arg, $cells, $cell );
1301
1302     warn qq(WARNING: no colgroup given\n) if not $args{ "colgroup" };
1303
1304     $cells = $args{ "colgroup" };
1305     
1306     delete $args{ "colgroup" };
1307
1308     $arg = &format_args( \%args );
1309
1310     if ( $arg ) {
1311         push @html, "<colgroup $arg>";
1312     } else {
1313         push @html, "<colgroup>";
1314     }
1315
1316     foreach $cell ( @{ $cells } ) {
1317         push @html, &tag_single( "col", $cell );
1318     }
1319
1320     push @html, "</colgroup>";
1321         
1322     return join "\n", @html;
1323 }
1324
1325
1326 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> HTML COMMENT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
1327
1328
1329 sub comment
1330 {
1331     # Martin A. Hansen, July 2005.
1332
1333     # HTML comment
1334
1335     my ( %args,
1336        ) = @_;
1337
1338     my $comment = $args{ "txt" };
1339
1340     warn qq(WARNING: no comment given\n) if not $comment;
1341
1342     return "\n<!-- $comment -->\n";
1343 }
1344
1345
1346 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> VALIDATOR BUTTONS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
1347
1348
1349 sub validate_xhtml
1350 {
1351     # Martin A. Hansen, July 2005.
1352
1353     # returns an image link to w3.orgs validator page
1354
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" );
1357 }
1358
1359
1360 sub validate_css
1361 {
1362     # Martin A. Hansen, July 2005.
1363
1364     # returns an image link to w3.orgs css validator page
1365
1366     my ( $url,   # url or uri to the CSS file
1367        ) = @_;
1368
1369     warn qq(WARNING: no url given for validate css\n) if not $url;
1370
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" );
1373 }
1374
1375
1376 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> HELPERS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
1377
1378
1379 sub format_args
1380 {
1381     # Martin A. Hansen, July 2005.
1382
1383     # given a hash with arguments reformat ( foo => "bar", foo2 => "bar2" ... )
1384     # these to HTML type argument str      ( foo = "bar" foo2 = "bar2" ... )
1385
1386     my ( $args,   # hashref
1387        ) = @_;
1388
1389     # Returns string
1390
1391     my ( $str, $arg, @list );
1392
1393     foreach $arg ( sort keys %{ $args } ) {
1394         push @list, qq($arg=") . $args->{ $arg } . qq(");
1395     }
1396
1397     $str = join " ", @list;
1398
1399     return $str;
1400 }
1401
1402
1403 sub tag_pair
1404 {
1405     # Martin A. Hansen, July 2005.
1406
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.
1409
1410     my ( $tag,   # HTML element type
1411          $args,  # hashref
1412        ) = @_;
1413
1414     # Returns string
1415
1416     my ( @html, $txt, $arg, $embed );
1417
1418     $txt = $args->{ "txt" };
1419
1420     delete $args->{ "txt" };
1421
1422     warn qq(WARNING: no $tag given\n) if not $tag;
1423
1424     $arg = &format_args( $args );
1425
1426     if ( $txt =~ /(<[^>]+>)/ )
1427     {
1428         if ( $1 =~ /^<(input|textarea|a |img)/ ) {
1429             $embed = "true";
1430         }
1431     }
1432     else
1433     {
1434         $embed = "true";
1435     }
1436
1437     if ( $embed )
1438     {
1439         if ( $arg ) {
1440             push @html, "<$tag $arg>$txt</$tag>";
1441         } else {
1442             push @html, "<$tag>$txt</$tag>";
1443         }
1444     }
1445     else
1446     {
1447         if ( $arg )
1448         {
1449             push @html, "<$tag $arg>";
1450             push @html, $txt;
1451             push @html, "</$tag>";
1452         }
1453         else
1454         {
1455             push @html, "<$tag>";
1456             push @html, $txt;
1457             push @html, "</$tag>";
1458         }
1459     }
1460
1461     return join "\n", @html;
1462 }
1463
1464
1465 sub tag_single
1466 {
1467     # Martin A. Hansen, July 2005.
1468
1469     # handles HTML single element such as <meta>
1470     # where the tag hold optional arguments.
1471
1472     my ( $tag,   # HTML tag type
1473          $args,  # args
1474        ) = @_;
1475
1476     # Returns string
1477
1478     my ( $arg );
1479
1480     $arg = &format_args( $args );
1481
1482     if ( $arg ) {
1483         return "<$tag $arg />";
1484     } else {
1485         return "<$tag />";
1486     }
1487 }
1488
1489
1490 sub list_simple
1491 {
1492     # Martin A. Hansen, July 2005.
1493
1494     # formats simple ordered and unordered lists.
1495     # attributes can only be assigned to the list
1496     # type element.
1497
1498     my ( $tag,
1499          $args,
1500        ) = @_;
1501
1502     # Returns string
1503
1504     my ( @html, $arg, $items, $item );
1505
1506     $items = $args->{ "li" };
1507
1508     delete $args->{ "li" };
1509
1510     $arg = &format_args( $args );
1511     
1512     if ( $arg ) {
1513         push @html, "<$tag $arg>";
1514     } else {
1515         push @html, "<$tag>";
1516     }
1517
1518     foreach $item ( @{ $items } )
1519     {
1520         push @html, &tag_pair( "li", { txt => $item } );
1521     }
1522
1523     push @html, "</$tag>";
1524
1525     return join "\n", @html;
1526 }
1527
1528
1529 sub list_advanced
1530 {
1531     # Martin A. Hansen, July 2005.
1532
1533     # formats advanced ordered and unordered lists.
1534     # attributes can be assigned to both the list
1535     # type element and the list elements.
1536     
1537     my ( $tag,
1538          $args,
1539        ) = @_;
1540
1541     # Returns string
1542
1543     my ( @html, $arg, $items, $item, $li );
1544
1545     $items = $args->{ "li" };
1546
1547     delete $args->{ "li" };
1548
1549     $arg = &format_args( $args );
1550     
1551     if ( $arg ) {
1552         push @html, "<$tag $arg>";
1553     } else {
1554         push @html, "<$tag>";
1555     }
1556
1557     foreach $item ( @{ $items } )
1558     {
1559         warn qq(WARNING: no list item found in list_advanced\n) if not $item->{ "li" };
1560
1561         $li = $item->{ "li" };
1562
1563         delete $item->{ "li" };
1564
1565         $item->{ "txt" } = $li;
1566
1567         push @html, &tag_pair( "li", $item );
1568     }
1569
1570     push @html, "</$tag>";
1571
1572     return join "\n", @html;
1573 }
1574
1575
1576 sub input_field
1577 {
1578     # Martin A. Hansen, July 2005.
1579
1580     # generic routine to handle the different
1581     # flavors of input types.
1582
1583     my ( $type,
1584          $args,
1585        ) = @_;
1586
1587     # Returns string
1588
1589     my ( $arg, $txt );
1590
1591     warn qq(WARNING no input name given\n) if $type ne "reset" and not $args->{ "name" };
1592
1593     $arg = &format_args( $args );
1594
1595     if ( $arg ) {
1596         return qq(<input type="$type" $arg />);
1597     } else {
1598         return qq(<input type="$type" />);
1599     }
1600 }
1601
1602
1603 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> DEBUG <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
1604
1605
1606 sub hdump
1607 {
1608     # Martin A. Hansen, November 2009.
1609     #
1610     # Primitive debug routine that returns given data
1611     # in <pre> tags as HTML lines.
1612
1613     my ( $data,   # data to dump
1614        ) = @_;
1615
1616     # Returns a list
1617
1618     my ( @html );
1619
1620     @html = "Content-Type: text/html; charset=ISO-8859-1\n\n";
1621
1622     push @html, "<pre>\n";
1623     push @html, Dumper( $data );
1624     push @html, "</pre>\n";
1625
1626     return wantarray ? @html : \@html;
1627 }
1628
1629
1630 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
1631
1632 1;
1633