]> git.donarmstrong.com Git - biopieces.git/blob - code_perl/Maasha/XHTML.pm
added XHTML
[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 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
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 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> DIV & SPAN <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
644
645
646 sub div
647 {
648     # Martin A. Hansen, July 2005.
649
650     # HTML <div> element
651
652     my ( %args,
653        ) = @_;
654
655     # Returns string
656
657     my ( @html, $lines );
658
659     $lines  = $args{ "txt" };
660
661     if ( $lines )
662     {
663         $args{ "txt" } = $lines;
664
665         return &tag_pair( "div", \%args );
666     }
667     else
668     {
669         return &tag_single( "div", \%args );
670     }
671 }
672
673
674 sub span
675 {
676     # Martin A. Hansen, July 2005.
677
678     # HTML <span> element
679
680     my ( %args,
681        ) = @_;
682
683     # Returns string
684
685     warn qq(WARNING: no span given\n) if not $args{ "txt" };
686
687     return &tag_pair( "span", \%args );
688 }
689
690
691 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> MAP <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
692
693
694 sub map_beg
695 {
696     # Martin A. Hansen, July 2005.
697
698     # HTML <map> element
699     
700     my ( %args,
701        ) = @_;
702
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" };
705
706     my $arg = &format_args( \%args );
707
708     return qq(<map $arg>);
709 }
710
711
712 sub map_end
713 {
714     # Martin A. Hansen, July 2005.
715
716     # HTML </map> element
717
718     return qq(</map>);
719 }
720
721
722 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> PRE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
723
724
725 sub pre
726 {
727     # Martin A. Hansen, July 2005.
728
729     # HTML <pre> element
730     
731     my ( %args,
732        ) = @_;
733
734     # Returns string
735
736     warn qq(WARNING: no pre lines given\n) if not $args{ "txt" };
737
738     $args{ "txt" } =~ s/&/&amp;/g;
739     $args{ "txt" } =~ s/>/&gt;/g;
740     $args{ "txt" } =~ s/</&lt;/g;
741
742     return &tag_pair( "pre", \%args );
743 }
744
745
746 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FORMS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
747
748
749 sub form_beg
750 {
751     # Martin A. Hansen, July 2005.
752
753     # HTML <form> element
754
755     my ( %args,
756        ) = @_;
757
758     my ( $arg );
759
760     $arg = &format_args( \%args );
761
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/;
764
765     return qq(<form $arg>);
766 }
767
768
769 sub form_end
770 {
771     # Martin A. Hansen, July 2005.
772
773     # HTML </form> element
774
775     return qq(</form>);
776 }
777
778
779 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> BUTTONS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
780
781
782 sub submit
783 {
784     # Martin A. Hansen, July 2005.
785
786     # HTML submit button
787
788     my ( %args,
789        ) = @_;
790
791     # Returns string
792
793     return &input_field( "submit", \%args );
794 }
795
796
797 sub reset
798 {
799     # Martin A. Hansen, July 2005.
800
801     # HTML reset button
802
803     return &input_field( "reset" );
804 }
805
806
807 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FIELDS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
808
809
810 sub text
811 {
812     # Martin A. Hansen, July 2005.
813
814     # HTML text field
815
816     my ( %args,
817        ) = @_;
818
819     # Returns string
820
821     return &input_field( "text", \%args );
822 }
823
824
825 sub password
826 {
827     # Martin A. Hansen, July 2005.
828
829     # HTML password field
830
831     my ( %args,
832        ) = @_;
833
834     # Returns string
835
836     return &input_field( "password", \%args );
837 }
838
839
840 sub file
841 {
842     # Martin A. Hansen, July 2005.
843
844     # HTML file field
845
846     my ( %args,
847        ) = @_;
848
849     # Returns string
850
851     return &input_field( "file", \%args );
852 }
853
854
855 sub checkbox
856 {
857     # Martin A. Hansen, July 2005.
858
859     # HTML checkbox field
860
861     my ( %args,
862        ) = @_;
863
864     # Returns string
865
866     return &input_field( "checkbox", \%args );
867 }
868
869
870 sub radio
871 {
872     # Martin A. Hansen, July 2005.
873
874     # HTML radio button field
875
876     my ( %args,
877        ) = @_;
878
879     # Returns string
880
881     return &input_field( "radio", \%args );
882 }
883
884
885 sub hidden
886 {
887     # Martin A. Hansen, July 2005.
888
889     # HTML hidden field
890
891     my ( %args,
892        ) = @_;
893
894     # Returns string
895
896     warn qq(WARNING: no hidden value given\n) if not $args{ "value" };
897
898     return &input_field( "hidden", \%args );
899 }
900
901
902 sub menu
903 {
904     # Martin A. Hansen, July 2005.
905
906     # HTML popup/drowdown menu
907     
908     my ( %args,    # name of variable
909        ) = @_;
910
911     # Returns string
912
913     my ( @html, $name, $selected, $options, $option, $value );
914  
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" };
917  
918     $name     = $args{ "name" };
919     $selected = $args{ "selected" };
920     $options  = $args{ "options" };
921  
922     push @html, qq(<select name="$name">);
923
924     push @html, &tag_pair( "option", { selected => "selected", value => $selected, txt => $selected } ) if exists $args{ "selected" };
925
926     foreach $option ( @{ $options } ) {
927         push @html, &tag_pair( "option", { value => "$option", txt => $option } );
928     }
929
930     push @html, qq(</select>);
931
932     return join "\n", @html;
933 }
934
935
936 sub textarea
937 {
938     # Martin A. Hansen, July 2005.
939
940     # HTML textarea field
941
942     my ( %args,
943        ) = @_;
944
945     # Returns string
946
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" };
950
951     return &tag_pair( "textarea", \%args );
952 }
953
954
955 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> TABLE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
956
957
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)
964
965
966 sub table_beg
967 {
968     # Martin A. Hansen, July 2005.
969
970     # HTML <table> element
971
972     my ( %args,
973        ) = @_;
974
975     my $arg = &format_args( \%args );
976
977     if ( $arg ) {
978         return "<table $arg>";
979     } else {
980         return "<table>";
981     }
982 }
983
984
985 sub table_end
986 {
987     # Martin A. Hansen, July 2005.
988
989     # HTML </table> element
990
991     return "</table>";
992 }
993
994
995 sub table_head_beg
996 {
997     # Martin A. Hansen, July 2005.
998
999     # HTML <thead> element
1000
1001     my ( %args,
1002        ) = @_;
1003
1004     my $arg = &format_args( \%args );
1005
1006     if ( $arg ) {
1007         return "<thead $arg>";
1008     } else {
1009         return "<thead>";
1010     }
1011 }
1012
1013
1014 sub table_head_end
1015 {
1016     # Martin A. Hansen, July 2005.
1017
1018     # HTML </thead> element
1019
1020     return "</thead>";
1021 }
1022
1023
1024 sub table_foot_beg
1025 {
1026     # Martin A. Hansen, July 2005.
1027
1028     # HTML <tfoot> element
1029
1030     my ( %args,
1031        ) = @_;
1032
1033     my $arg = &format_args( \%args );
1034
1035     if ( $arg ) {
1036         return "<tfoot $arg>";
1037     } else {
1038         return "<tfoot>";
1039     }
1040 }
1041
1042
1043 sub table_foot_end
1044 {
1045     # Martin A. Hansen, July 2005.
1046
1047     # HTML </tfoot> element
1048
1049     return "</tfoot>";
1050 }
1051
1052
1053 sub table_body_beg
1054 {
1055     # Martin A. Hansen, July 2005.
1056
1057     # HTML <tbody> element
1058
1059     my ( %args,
1060        ) = @_;
1061
1062     my $arg = &format_args( \%args );
1063
1064     if ( $arg ) {
1065         return "<tbody $arg>";
1066     } else {
1067         return "<tbody>";
1068     }
1069 }
1070
1071
1072 sub table_body_end
1073 {
1074     # Martin A. Hansen, July 2005.
1075
1076     # HTML </tbody> element
1077
1078     return "</tbody>";
1079 }
1080
1081
1082 sub table_caption
1083 {
1084     # Martin A. Hansen, July 2005.
1085
1086     # HTML <caption> element
1087
1088     my ( %args,
1089        ) = @_;
1090
1091     # Returns string
1092
1093     my @html = &tag_pair( "caption", \%args );
1094     
1095     return wantarray ? @html : \@html;
1096 }
1097
1098
1099 sub table_row_simple
1100 {
1101     # Martin A. Hansen, July 2005.
1102
1103     # HTML simple row
1104
1105     my ( %args,
1106        ) = @_;
1107
1108     # Returns string
1109
1110     my ( @html, $arg, $cells, $cell );
1111
1112     warn qq(WARNING: no simple row given\n) if not $args{ "tr" };
1113
1114     $cells = $args{ "tr" };
1115     
1116     delete $args{ "tr" };
1117
1118     $arg = &format_args( \%args );
1119
1120     if ( $arg ) {
1121         push @html, "<tr $arg>";
1122     } else {
1123         push @html, "<tr>";
1124     }
1125
1126     foreach $cell ( @{ $cells } ) {
1127         push @html, &tag_pair( "td", { txt => $cell } );
1128     }
1129
1130     push @html, "</tr>";
1131         
1132     return join "\n", @html;
1133 }
1134
1135
1136 sub table_row_advanced
1137 {
1138     # Martin A. Hansen, July 2005.
1139
1140     # HTML advanced row
1141
1142     my ( %args,
1143        ) = @_;
1144
1145     # Returns string
1146
1147     my ( @html, $arg, $cells, $cell );
1148
1149     warn qq(WARNING: no advanced row given\n) if not $args{ "tr" };
1150
1151     $cells = $args{ "tr" };
1152     
1153     delete $args{ "tr" };
1154
1155     $arg = &format_args( \%args );
1156
1157     if ( $arg ) {
1158         push @html, "<tr $arg>";
1159     } else {
1160         push @html, "<tr>";
1161     }
1162
1163     foreach $cell ( @{ $cells } )
1164     {
1165         $cell->{ "txt" } = $cell->{ "td" };
1166
1167         delete $cell->{ "td" };
1168     
1169         push @html, &tag_pair( "td", $cell );
1170     }
1171
1172     push @html, "</tr>";
1173         
1174     return join "\n", @html;
1175 }
1176
1177
1178 sub table_header_simple
1179 {
1180     # Martin A. Hansen, July 2005.
1181
1182     # HTML simple header rww
1183
1184     my ( %args,
1185        ) = @_;
1186
1187     # Returns string
1188
1189     my ( @html, $arg, $cells, $cell );
1190
1191     warn qq(WARNING: no simple header given\n) if not $args{ "tr" };
1192
1193     $cells = $args{ "tr" };
1194     
1195     delete $args{ "tr" };
1196
1197     $arg = &format_args( \%args );
1198
1199     if ( $arg ) {
1200         push @html, "<tr $arg>";
1201     } else {
1202         push @html, "<tr>";
1203     }
1204
1205     foreach $cell ( @{ $cells } ) {
1206         push @html, &tag_pair( "th", { txt => $cell } );
1207     }
1208
1209     push @html, "</tr>";
1210         
1211     return join "\n", @html;
1212 }
1213
1214
1215 sub table_header_advanced
1216 {
1217     # Martin A. Hansen, July 2005.
1218
1219     # HTML advanced header row
1220
1221     my ( %args,
1222        ) = @_;
1223
1224     # Returns string
1225
1226     my ( @html, $arg, $cells, $cell );
1227
1228     warn qq(WARNING: no advanced header given\n) if not $args{ "tr" };
1229
1230     $cells = $args{ "tr" };
1231     
1232     delete $args{ "tr" };
1233
1234     $arg = &format_args( \%args );
1235
1236     if ( $arg ) {
1237         push @html, "<tr $arg>";
1238     } else {
1239         push @html, "<tr>";
1240     }
1241
1242     foreach $cell ( @{ $cells } )
1243     {
1244         $cell->{ "txt" } = $cell->{ "th" };
1245
1246         delete $cell->{ "th" };
1247     
1248         push @html, &tag_pair( "th", $cell );
1249     }
1250
1251     push @html, "</tr>";
1252         
1253     return join "\n", @html;
1254 }
1255
1256
1257 sub table_colgroup
1258 {
1259     # Martin A. Hansen, July 2005.
1260
1261     # HTML colgroup row
1262
1263     my ( %args,
1264        ) = @_;
1265
1266     # Returns string
1267
1268     my ( @html, $arg, $cells, $cell );
1269
1270     warn qq(WARNING: no colgroup given\n) if not $args{ "colgroup" };
1271
1272     $cells = $args{ "colgroup" };
1273     
1274     delete $args{ "colgroup" };
1275
1276     $arg = &format_args( \%args );
1277
1278     if ( $arg ) {
1279         push @html, "<colgroup $arg>";
1280     } else {
1281         push @html, "<colgroup>";
1282     }
1283
1284     foreach $cell ( @{ $cells } ) {
1285         push @html, &tag_single( "col", $cell );
1286     }
1287
1288     push @html, "</colgroup>";
1289         
1290     return join "\n", @html;
1291 }
1292
1293
1294 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> HTML COMMENT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
1295
1296
1297 sub comment
1298 {
1299     # Martin A. Hansen, July 2005.
1300
1301     # HTML comment
1302
1303     my ( %args,
1304        ) = @_;
1305
1306     my $comment = $args{ "txt" };
1307
1308     warn qq(WARNING: no comment given\n) if not $comment;
1309
1310     return "\n<!-- $comment -->\n";
1311 }
1312
1313
1314 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> VALIDATOR BUTTONS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
1315
1316
1317 sub validate_xhtml
1318 {
1319     # Martin A. Hansen, July 2005.
1320
1321     # returns an image link to w3.orgs validator page
1322
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" );
1325 }
1326
1327
1328 sub validate_css
1329 {
1330     # Martin A. Hansen, July 2005.
1331
1332     # returns an image link to w3.orgs css validator page
1333
1334     my ( $url,   # url or uri to the CSS file
1335        ) = @_;
1336
1337     warn qq(WARNING: no url given for validate css\n) if not $url;
1338
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" );
1341 }
1342
1343
1344 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> HELPERS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
1345
1346
1347 sub format_args
1348 {
1349     # Martin A. Hansen, July 2005.
1350
1351     # given a hash with arguments reformat ( foo => "bar", foo2 => "bar2" ... )
1352     # these to HTML type argument str      ( foo = "bar" foo2 = "bar2" ... )
1353
1354     my ( $args,   # hashref
1355        ) = @_;
1356
1357     # Returns string
1358
1359     my ( $str, $arg, @list );
1360
1361     foreach $arg ( sort keys %{ $args } ) {
1362         push @list, qq($arg=") . $args->{ $arg } . qq(");
1363     }
1364
1365     $str = join " ", @list;
1366
1367     return $str;
1368 }
1369
1370
1371 sub tag_pair
1372 {
1373     # Martin A. Hansen, July 2005.
1374
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.
1377
1378     my ( $tag,   # HTML element type
1379          $args,  # hashref
1380        ) = @_;
1381
1382     # Returns string
1383
1384     my ( @html, $txt, $arg, $embed );
1385
1386     $txt = $args->{ "txt" };
1387
1388     delete $args->{ "txt" };
1389
1390     warn qq(WARNING: no $tag given\n) if not $tag;
1391
1392     $arg = &format_args( $args );
1393
1394     if ( $txt =~ /(<[^>]+>)/ )
1395     {
1396         if ( $1 =~ /^<(input|textarea|a |img)/ ) {
1397             $embed = "true";
1398         }
1399     }
1400     else
1401     {
1402         $embed = "true";
1403     }
1404
1405     if ( $embed )
1406     {
1407         if ( $arg ) {
1408             push @html, "<$tag $arg>$txt</$tag>";
1409         } else {
1410             push @html, "<$tag>$txt</$tag>";
1411         }
1412     }
1413     else
1414     {
1415         if ( $arg )
1416         {
1417             push @html, "<$tag $arg>";
1418             push @html, $txt;
1419             push @html, "</$tag>";
1420         }
1421         else
1422         {
1423             push @html, "<$tag>";
1424             push @html, $txt;
1425             push @html, "</$tag>";
1426         }
1427     }
1428
1429     return join "\n", @html;
1430 }
1431
1432
1433 sub tag_single
1434 {
1435     # Martin A. Hansen, July 2005.
1436
1437     # handles HTML single element such as <meta>
1438     # where the tag hold optional arguments.
1439
1440     my ( $tag,   # HTML tag type
1441          $args,  # args
1442        ) = @_;
1443
1444     # Returns string
1445
1446     my ( $arg );
1447
1448     $arg = &format_args( $args );
1449
1450     if ( $arg ) {
1451         return "<$tag $arg />";
1452     } else {
1453         return "<$tag />";
1454     }
1455 }
1456
1457
1458 sub list_simple
1459 {
1460     # Martin A. Hansen, July 2005.
1461
1462     # formats simple ordered and unordered lists.
1463     # attributes can only be assigned to the list
1464     # type element.
1465
1466     my ( $tag,
1467          $args,
1468        ) = @_;
1469
1470     # Returns string
1471
1472     my ( @html, $arg, $items, $item );
1473
1474     $items = $args->{ "li" };
1475
1476     delete $args->{ "li" };
1477
1478     $arg = &format_args( $args );
1479     
1480     if ( $arg ) {
1481         push @html, "<$tag $arg>";
1482     } else {
1483         push @html, "<$tag>";
1484     }
1485
1486     foreach $item ( @{ $items } )
1487     {
1488         push @html, &tag_pair( "li", { txt => $item } );
1489     }
1490
1491     push @html, "</$tag>";
1492
1493     return join "\n", @html;
1494 }
1495
1496
1497 sub list_advanced
1498 {
1499     # Martin A. Hansen, July 2005.
1500
1501     # formats advanced ordered and unordered lists.
1502     # attributes can be assigned to both the list
1503     # type element and the list elements.
1504     
1505     my ( $tag,
1506          $args,
1507        ) = @_;
1508
1509     # Returns string
1510
1511     my ( @html, $arg, $items, $item, $li );
1512
1513     $items = $args->{ "li" };
1514
1515     delete $args->{ "li" };
1516
1517     $arg = &format_args( $args );
1518     
1519     if ( $arg ) {
1520         push @html, "<$tag $arg>";
1521     } else {
1522         push @html, "<$tag>";
1523     }
1524
1525     foreach $item ( @{ $items } )
1526     {
1527         warn qq(WARNING: no list item found in list_advanced\n) if not $item->{ "li" };
1528
1529         $li = $item->{ "li" };
1530
1531         delete $item->{ "li" };
1532
1533         $item->{ "txt" } = $li;
1534
1535         push @html, &tag_pair( "li", $item );
1536     }
1537
1538     push @html, "</$tag>";
1539
1540     return join "\n", @html;
1541 }
1542
1543
1544 sub input_field
1545 {
1546     # Martin A. Hansen, July 2005.
1547
1548     # generic routine to handle the different
1549     # flavors of input types.
1550
1551     my ( $type,
1552          $args,
1553        ) = @_;
1554
1555     # Returns string
1556
1557     my ( $arg, $txt );
1558
1559     warn qq(WARNING no input name given\n) if $type ne "reset" and not $args->{ "name" };
1560
1561     $arg = &format_args( $args );
1562
1563     if ( $arg ) {
1564         return qq(<input type="$type" $arg />);
1565     } else {
1566         return qq(<input type="$type" />);
1567     }
1568 }
1569
1570
1571 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<