5 use CGI
'div','span','img','url';
7 our @EXPORT = ('toggle_section',
10 use constant PLUS
=> 'plus.png';
11 use constant MINUS
=> 'minus.png';
12 use constant JS
=> 'toggle.js';
13 use constant XCOOK
=> 'x_cook.js';
15 my $image_dir = '/gbrowse/images/buttons';
16 my $js_dir = '/gbrowse/js';
18 my $cookie_name = __PACKAGE__
;
19 $cookie_name =~ s/:/_/g;
22 .el_hidden {display:none}
23 .el_visible {display:inline}
32 .tctl { text-decoration:underline; }
36 my %args = @_ == 1 ?
(-title
=>shift) : @_;
38 $image_dir = $args{-gbrowse_images
} if defined $args{-gbrowse_images
};
39 $js_dir = $args{-gbrowse_js
} if defined $args{-gbrowse_js
};
41 delete $args{-gbrowse_images
};
42 delete $args{-gbrowse_js
};
44 # earlier versions of CGI.pm don't support multiple -style and -script args.
45 if ($CGI::VERSION
>= 3.05) {
47 $args{-style
}= [{src
=> $args{-style
}}] if !ref $args{-style
};
48 $args{-style
}= [$args{-style
}] if ref $args{-style
} && ref $args{-style
} ne 'ARRAY';
50 push @
{$args{-style
}},{code
=>$style};
53 $args{-script
} = [{src
=> $args{-script
}}] if !ref $args{-script
};
54 $args{-script
} = [$args{-script
}] if ref $args{-script
} && ref $args{-script
} ne 'ARRAY';
57 push @
{$args{-script
}},{src
=>"$js_dir/".JS
};
58 push @
{$args{-script
}},{src
=>"$js_dir/".XCOOK
};
61 my $result = CGI
::start_html
(%args);
63 if ($CGI::VERSION
< 3.05) {
64 my $style_section = join '',$CGI::Q
->_style({code
=>$style});
65 my $script_section = join '',$CGI::Q
->_script({src
=>"$js_dir/".JS
});
66 $result =~ s/<\/head>/$style_section\n$script_section\n<\
/head>/i;
72 # The weird playing around with class names is to accomodate the need to have
73 # a default setting of visibility that can be overridden by a stored cookie.
75 my %config = ref $_[0] eq 'HASH' ?
%{shift()} : ();
76 my ($name,$section_title,@section_body) = @_;
77 my $visible = $config{on
};
79 my $plus = $config{plus_img
} || "$image_dir/".PLUS
;
80 my $minus = $config{minus_img
} || "$image_dir/".MINUS
;
82 my $show_ctl = div
({-id
=>"${name}_show",
84 -style
=>$visible ?
'display:none' : 'display:inline',
85 -onClick
=>"visibility('$name',1)"
87 img
({-src
=>$plus,-alt
=>'+'}).' '.span
({-class=>'tctl'},$section_title));
88 my $hide_ctl = div
({-id
=>"${name}_hide",
89 -class=>'ctl_visible',
90 -style
=>$visible ?
'display:inline' : 'display:none',
91 -onClick
=>"visibility('$name',0)"
93 img
({-src
=>$minus,-alt
=>'-'}).' '.span
({-class=>'tctl'},$section_title));
94 my $content = div
({-id
=> $name,
95 -style
=>$visible ?
'display:inline' : 'display:none',
96 -class => 'el_visible'},
98 my @result = $config{nodiv
} ?
($show_ctl.$hide_ctl,$content) : div
(($show_ctl.$hide_ctl,$content));
100 return wantarray ?
@result : "@result";
109 CGI::Toggle -- Utility methods for collapsible sections
117 start_html('Toggle Test'),
119 toggle_section({on=>1},p('This section is on by default'),
120 toggle_section({on=>0},p('This section is off by default'),
121 toggle_section({plus_img=>'/icons/open.png',
122 minus_img=>'/icons/close.png'},
123 p('This section has custom open and close icons.')),
129 This package adds JavaScript-based support for collapsible sections by
130 adding a single new function toggle_section().
132 It overrides the CGI start_html() method, so CGI must be imported
133 before bringing this module in.
139 =item ($control,$content) = toggle_section([\%options],$section_title=>@section_content)
141 This method takes an optional \%options hashref, a section title and
142 one or more strings containing the section content and returns a list
143 of HTML fragments corresponding to the control link and the content.
144 In a scalar context the control and content will be concatenated
147 The option keys are as follows:
153 If true, the section will be on (visible) by default. The default is
158 URL of the icon to display next to the section title when the section
159 is collapsed. The default is /gbrowse/images/plus.png.
163 URL of the icon to display next to the section title when the section
164 is expanded.. The default is /gbrowse/images/minus.png.
168 If false (default), the state of the section will be remembered in a
169 cookie. If true, the initial state will be taken from the b<on>
170 option, ignoring the cookie (which will, however, still be generated).
183 Lincoln Stein E<lt>lstein@cshl.orgE<gt>.
185 Copyright (c) 2005 Cold Spring Harbor Laboratory
187 This library is free software; you can redistribute it and/or modify
188 it under the same terms as Perl itself. See DISCLAIMER.txt for
189 disclaimers of warranty.
191 The xGetCookie() and xSetCookie() JavaScript functions were derived
192 from www.cross-browser.com, and are copyright (c) 2004 Michael Foster,
193 and licensed under the LGPL (gnu.org).