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