use strict;
use vars qw($VERSION);
-$VERSION = '0.03';
+$VERSION = '0.06';
=head1 NAME
'options' => \%options,
'form_name' => 'dummy',
'form_action' => 'process.cgi',
- 'form_text' => [ qw( textfield1 textfield2 ) ],
- 'form_checkbox' => [ qw( checkbox1 ) ],
- 'form_radio' => [ qw( radio1 ) ],
- 'form_select' => [ qw( select1 ) ],
+
+ #new code auto-detects form types (radio not yet supported)
+ #'form_elements' => [ qw( textfield1 textfield2 checkbox1 radio1 select1 ) ],
+ 'form_elements' => [ qw( textfield1 textfield2 checkbox1 radio1 select1 ) ],
+
+ #deprecated style still works for now
+ #'form_text' => [ qw( textfield1 textfield2 ) ],
+ #'form_checkbox' => [ qw( checkbox1 ) ],
+ #'form_radio' => [ qw( radio1 ) ],
+ #'form_select' => [ qw( select1 ) ],
+
'layer_callback' => sub {
my $layer = shift;
my $html = qq!<INPUT TYPE="hidden" NAME="layer" VALUE="$layer">!;
},
);
- print '<FORM NAME=dummy>'.
+ print '<FORM NAME=dummy STYLE="margin-top: 0; margin-bottom: 0">'.
'<INPUT TYPE="text" NAME="textfield1">'.
'<INPUT TYPE="text" NAME="textfield2">'.
'<INPUT TYPE="checkbox" NAME="checkbox1" VALUE="Y">'.
example see http://www.420.am/selectlayers/
This HTML generated by this module uses JavaScript, but nevertheless attempts
-to be as cross-browser as possible, testing for features via DOM support rather
-than specific browsers or versions. It has been tested under Mozilla 0.9.8,
-Netscape 4.77, IE 5.5, Konqueror 2.2.2, and Opera 5.0.
+to be as cross-browser as possible. The 0.05 release drops Navigator 4
+compatibility and has been tested under Mozilla Firefox 1.0.6, MSIE 6.0,
+Konqueror 3.3.2, and Opera 8.0.2 (2006 note: still working under newer
+browsers such as IE7, Firefox 2.0, etc.).
=head1 FORMS
-Not all browsers seem happy with forms that span layers. The generated HTML
-will have a E<lt>/FORME<gt> tag before the layers and will generate
-E<lt>FORME<gt> and E<lt>/FORME<gt> tags for each layer. To facilitate
+My understanding is that forms cannot span E<lt>DIVE<gt>s elements. The
+generated HTML will have a E<lt>/FORME<gt> tag before the layers and will
+generate E<lt>FORME<gt> and E<lt>/FORME<gt> tags for each layer. To facilitate
E<lt>SUBMITE<gt> buttons located within the layers, you can pass a form name
and element names, and the relevant values will be copied to the layer's form.
See the B<form_> options below.
form_action - Form action
+form_elements - (optional) Array reference of form fields to copy from the
+ B<form_name> form. Field type is autodetected; currently
+ text, hidden, checkbox, and select (single) fiels are
+ supported. Select (multiple) and radio fields are not yet
+ supported.
+
form_text - (optional) Array reference of text (or hidden) form fields to copy
from the B<form_name> form.
html_beween - (optional) HTML between the E<lt>SELECTE<gt> and the layers.
+under_position - (optional) specifies the positioning of any HTML appearing after the widget. I<static>, the default, positions subsequent HTML underneath the current layer (or immediately under the select box if no layer has yet been selected), reflowing when layers are changed. I<absolute> calculates the size of the largest layer and keeps the subsequent HTML in a single position underneath it. Note that I<absolute> works by positioning subsequent HTML in a E<lt>DIVE<gt>, so you should probably close it yourself with a E<lt>/DIVE<gt> before your E<lt>/HTMLE<gt> end tag. I<absolute> is a bit experimental and might have some quirks with truncating the end of the page under IE; you might have better results by just making all your layers the exact same size at the moment.
+
=cut
sub new {
my $between = exists($self->{html_between}) ? $self->{html_between} : '';
my $options = $self->{options};
my $form_action = exists($self->{form_action}) ? $self->{form_action} : '';
+
+ my $form_elements =
+ exists($self->{form_elements}) ? $self->{form_elements} : [];
my $form_text =
exists($self->{form_text}) ? $self->{form_text} : [];
my $form_checkbox =
my $form_select =
exists($self->{form_select}) ? $self->{form_select} : [];
+ my $under_position =
+ exists($self->{under_position}) ? $self->{under_position} : 'static';
+ my $hidden = lc($under_position) eq 'absolute'
+ ? 'visibility: hidden; position: absolute; z-index: 0'
+ : 'display: none; z-index: 0';
+ #my $show = lc($under_position) eq 'absolute'
+ # ? 'visibility: visible'
+ # : 'display: "" ';
+
my $html = $self->_safeonload.
$self->_visualize.
"<SCRIPT>SafeAddOnLoad(${key}visualize)</SCRIPT>".
$self->_changed.
$self->_fixup.
- $self->_select. $between. '</FORM>';
+ $self->_select. $between. '</FORM>'.
+ "<SCRIPT>var ${key}maxHeight = 0;</SCRIPT>";
#foreach my $layer ( 'konq_kludge', keys %$options ) {
foreach my $layer ( keys %$options ) {
#start layer
- my $visibility = "hidden";
+
$html .= <<END;
- <SCRIPT>
- if (document.getElementById) {
- document.write("<DIV ID=\\"${key}d$layer\\" STYLE=\\"visibility: $visibility; position: absolute\\">");
- } else {
-END
- $visibility="show" if $visibility eq "visible";
- $html .= <<END;
- document.write("<LAYER ID=\\"${key}l$layer\\" VISIBILITY=\\"$visibility\\">");
- }
- </SCRIPT>
+ <DIV ID="${key}d$layer" STYLE="$hidden">
END
#form fields
$html .= <<END;
- <FORM NAME="${key}$layer" ACTION="$form_action" METHOD=POST onSubmit="${key}fixup(this)">
+ <FORM NAME="${key}$layer" ACTION="$form_action" METHOD=POST onSubmit="${key}fixup(this)" STYLE="margin-top: 0; margin-bottom: 0">
END
- foreach my $f ( @$form_text, @$form_checkbox, @$form_radio, @$form_select )
+ foreach my $f ( @$form_elements, @$form_text, @$form_checkbox, @$form_radio, @$form_select )
{
$html .= <<END;
<INPUT TYPE="hidden" NAME="$f" VALUE="">
#end form & layer
$html .= <<END
</FORM>
-
+ </DIV>
<SCRIPT>
- if (document.getElementById) {
- document.write("</DIV>");
- } else {
- document.write("</LAYER>");
- }
+ if ( document.getElementById('${key}d$layer').offsetHeight > ${key}maxHeight )
+ ${key}maxHeight = document.getElementById('${key}d$layer').offsetHeight;
</SCRIPT>
END
}
+ if ( $under_position eq 'absolute' ) {
+ $html .= <<END;
+ <SCRIPT>
+ //var max = ${key}maxHeight;
+ document.write("<DIV STYLE=\\\"position:relative; top: " + ${key}maxHeight + "px\\\">");
+ </SCRIPT>
+END
+ }
+
$html;
}
my $self = shift;
my $key = exists($self->{unique_key}) ? $self->{unique_key} : '';
my $form_name = $self->{form_name} or return '';
+
+ my $form_elements =
+ exists($self->{form_elements}) ? $self->{form_elements} : [];
my $form_text =
exists($self->{form_text}) ? $self->{form_text} : [];
my $form_checkbox =
exists($self->{form_radio}) ? $self->{form_radio} : [];
my $form_select =
exists($self->{form_select}) ? $self->{form_select} : [];
- my $html = "
+ my $html = <<END;
<SCRIPT>
+
+function copyelement(from, to) {
+ if ( from == undefined ) {
+ to.value = '';
+ } else if ( from.type == 'select-one' ) {
+ to.value = from.options[from.selectedIndex].value;
+ //alert(from + " (" + from.type + "): " + to.name + " => (" + from.selectedIndex + ") " + to.value);
+ } else if ( from.type == 'checkbox' ) {
+ if ( from.checked ) {
+ to.value = from.value;
+ } else {
+ to.value = '';
+ }
+// } else if ( from.type == 'radio' ) {
+ } else {
+ if ( from.value == undefined ) {
+ to.value = '';
+ } else {
+ to.value = from.value;
+ }
+ }
+ //alert(from + " (" + from.type + "): " + to.name + " => " + to.value);
+}
+END
+
+ $html .= "
function ${key}fchanged(what) {
${key}fixup(what.form);
}
function ${key}fixup(what) {\n";
+ foreach my $f ( @$form_elements ) {
+ $html .= "copyelement( document.$form_name.elements['$f'],
+ what.elements['$f']
+ )\n";
+ }
+
foreach my $f ( @$form_text ) {
$html .= "what.$f.value = document.$form_name.$f.value;\n";
}
foreach my $f ( @$form_radio ) {
$html .= "what.$f.value = '';
for ( i=0; i< document.$form_name.$f.length; i++ )
- if ( document.$form_name.${f}[i].checked )
- what.$f.value = document.$form_name.${f}[i].value;\n";
+ if ( document.$form_name.$f\[i].checked )
+ what.$f.value = document.$form_name.$f\[i].value;\n";
}
foreach my $f ( @$form_select ) {
<SELECT NAME=\"${key}select\" SIZE=$size onChange=\"${key}changed(this);\">
";
foreach my $option ( keys %$options ) {
- $html .= "<OPTION VALUE=\"$option\"";
+ $html .= qq(<OPTION VALUE="$option");
$html .= ' SELECTED' if $option eq $selected;
$html .= '>'. $options->{$option}. '</OPTION>';
}
my $self = shift;
my $key = exists($self->{unique_key}) ? $self->{unique_key} : '';
my $options = $self->{options};
+ my $under_position =
+ exists($self->{under_position}) ? $self->{under_position} : 'static';
+
my $html = "
<SCRIPT>
var ${key}layer = null;
function ${key}changed(what) {
${key}layer = what.options[what.selectedIndex].value;\n";
foreach my $layer ( keys %$options ) {
- $html .= "if (${key}layer == \"$layer\" ) {\n";
+ $html .= qq( if (${key}layer == "$layer" ) {\n);
foreach my $not ( grep { $_ ne $layer } keys %$options ) {
- $html .= "
- if (document.getElementById) {
- document.getElementById('${key}d$not').style.visibility = \"hidden\";
- } else {
- document.${key}l$not.visibility = \"hidden\";
- }\n";
- }
- $html .= "
- if (document.getElementById) {
- document.getElementById('${key}d$layer').style.visibility = \"visible\";
+ my $element_style = "document.getElementById('${key}d$not').style";
+ if ( $under_position eq 'absolute' ) {
+ $html .= qq( $element_style.visibility = "hidden";\n);
} else {
- document.${key}l$layer.visibility = \"visible\";
+ $html .= qq( $element_style.display = "none";\n);
}
- }\n";
+ $html .= qq( $element_style.zIndex = 0;\n);
+ }
+ my $element_style = "document.getElementById('${key}d$layer').style";
+ if ( $under_position eq 'absolute' ) {
+ $html .= qq( $element_style.visibility = "visible";\n);
+ } else {
+ $html .= qq( $element_style.display = "";\n);
+ }
+ $html .= qq( $element_style.zIndex = 1;\n);
+ $html .= " }\n";
}
$html .= "}\n</SCRIPT>";
$html;
my $key = exists($self->{unique_key}) ? $self->{unique_key} : '';
return '' unless exists($self->{selected_layer});
my $selected = $self->{selected_layer};
+ my $under_position =
+ exists($self->{under_position}) ? $self->{under_position} : 'static';
+ my $display = ( $under_position eq 'absolute' )
+ ? 'visibility = "visible"'
+ : 'display = ""';
<<END;
<SCRIPT>
function ${key}visualize() {
- if (document.getElementById) {
- document.getElementById('${key}d$selected').style.visibility = "visible";
- } else {
- document.${key}l$selected.visibility = "visible";
- }
+ document.getElementById('${key}d$selected').style.$display;
+ document.getElementById('${key}d$selected').style.zIndex = 1;
}
</SCRIPT>
END
=head1 COPYRIGHT
-Copyright (c) 2002 Ivan Kohler
+Copyright (c) 2002-2005 Ivan Kohler
All rights reserved.
This program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.
JavaScript
+All the different form_* options are unnecessary, could use .type to auto-sense
+
+Could give you a function or something for copying variables out of the
+layered forms.
+
=head1 SEE ALSO
L<perl>. L<Tie::IxHash>, http://www.xs4all.nl/~ppk/js/dom.html,