[Bio] / Sprout / SearchHelper.pm Repository:
ViewVC logotype

Diff of /Sprout/SearchHelper.pm

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.16, Wed Nov 15 12:02:46 2006 UTC revision 1.24, Fri Dec 15 03:27:20 2006 UTC
# Line 257  Line 257 
257    
258  =over 4  =over 4
259    
260  =item query  =item cgi
261    
262  The CGI query object for the current script.  The CGI query object for the current script.
263    
# Line 267  Line 267 
267    
268  sub new {  sub new {
269      # Get the parameters.      # Get the parameters.
270      my ($class, $query) = @_;      my ($class, $cgi) = @_;
271      # Check for a session ID.      # Check for a session ID.
272      my $session_id = $query->param("SessionID");      my $session_id = $cgi->param("SessionID");
273      my $type = "old";      my $type = "old";
274      if (! $session_id) {      if (! $session_id) {
275          # Here we're starting a new session. We create the session ID and          # Here we're starting a new session. We create the session ID and
276          # store it in the query object.          # store it in the query object.
277          $session_id = NewSessionID();          $session_id = NewSessionID();
278          $type = "new";          $type = "new";
279          $query->param(-name => 'SessionID', -value => $session_id);          $cgi->param(-name => 'SessionID', -value => $session_id);
280      }      }
281      # Compute the subclass name.      # Compute the subclass name.
282      $class =~ /SH(.+)$/;      my $subClass;
283      my $subClass = $1;      if ($class =~ /SH(.+)$/) {
284            # Here we have a real search class.
285            $subClass = $1;
286        } else {
287            # Here we have a bare class. The bare class cannot search, but it can
288            # process search results.
289            $subClass = 'SearchHelper';
290        }
291      # Insure everybody knows we're in Sprout mode.      # Insure everybody knows we're in Sprout mode.
292      $query->param(-name => 'SPROUT', -value => 1);      $cgi->param(-name => 'SPROUT', -value => 1);
293      # Generate the form name.      # Generate the form name.
294      my $formName = "$class$formCount";      my $formName = "$class$formCount";
295      $formCount++;      $formCount++;
# Line 290  Line 297 
297      # as well as an indicator as to whether or not the session is new, plus the      # as well as an indicator as to whether or not the session is new, plus the
298      # class name and a placeholder for the Sprout object.      # class name and a placeholder for the Sprout object.
299      my $retVal = {      my $retVal = {
300                    query => $query,                    query => $cgi,
301                    type => $type,                    type => $type,
302                    class => $subClass,                    class => $subClass,
303                    sprout => undef,                    sprout => undef,
# Line 454  Line 461 
461      my ($self, $title) = @_;      my ($self, $title) = @_;
462      # Get the CGI object.      # Get the CGI object.
463      my $cgi = $self->Q();      my $cgi = $self->Q();
464      # Start the form.      # Start the form. Note we use the override option on the Class value, in
465        # case the Advanced button was used.
466      my $retVal = "<div class=\"search\">\n" .      my $retVal = "<div class=\"search\">\n" .
467                   $cgi->start_form(-method => 'POST',                   $cgi->start_form(-method => 'POST',
468                                    -action => $cgi->url(-relative => 1),                                    -action => $cgi->url(-relative => 1),
469                                    -name => $self->FormName()) .                                    -name => $self->FormName()) .
470                   $cgi->hidden(-name => 'Class',                   $cgi->hidden(-name => 'Class',
471                                -value => $self->{class}) .                                -value => $self->{class},
472                                  -override => 1) .
473                   $cgi->hidden(-name => 'SPROUT',                   $cgi->hidden(-name => 'SPROUT',
474                                -value => 1) .                                -value => 1) .
475                   $cgi->h3($title);                   $cgi->h3($title);
# Line 670  Line 679 
679          push @colNames, $self->DefaultFeatureColumns();          push @colNames, $self->DefaultFeatureColumns();
680          # Add any additional columns requested by the feature filter.          # Add any additional columns requested by the feature filter.
681          push @colNames, FeatureQuery::AdditionalColumns($self);          push @colNames, FeatureQuery::AdditionalColumns($self);
682            Trace("Full column list determined.") if T(3);
683          # Save the full list.          # Save the full list.
684          $self->{cols} = \@colNames;          $self->{cols} = \@colNames;
685          # Write out the column headers. This also prepares the cache file to receive          # Write out the column headers. This also prepares the cache file to receive
686          # output.          # output.
687            Trace("Writing column headers.") if T(3);
688          $self->WriteColumnHeaders(map { $self->FeatureColumnTitle($_) } @{$self->{cols}});          $self->WriteColumnHeaders(map { $self->FeatureColumnTitle($_) } @{$self->{cols}});
689            Trace("Column headers written.") if T(3);
690      }      }
691      # Get the feature ID.      # Get the feature ID.
692      my $fid = $fd->FID();      my $fid = $fd->FID();
# Line 947  Line 959 
959    
960  =head3 ComputeFASTA  =head3 ComputeFASTA
961    
962  C<< my $fasta = $shelp->ComputeFASTA($incomingType, $desiredType, $sequence); >>  C<< my $fasta = $shelp->ComputeFASTA($desiredType, $sequence); >>
963    
964  Parse a sequence input and convert it into a FASTA string of the desired type. Note  Parse a sequence input and convert it into a FASTA string of the desired type.
 that it is possible to convert a DNA sequence into a protein sequence, but the reverse  
 is not possible.  
965    
966  =over 4  =over 4
967    
 =item incomingType  
   
 C<dna> if this is a DNA sequence, C<prot> if this is a protein sequence.  
   
968  =item desiredType  =item desiredType
969    
970  C<dna> to return a DNA sequence, C<prot> to return a protein sequence. If the  C<dna> to return a DNA sequence, C<prot> to return a protein sequence.
 I<$incomingType> is C<prot> and this value is C<dna>, an error will be thrown.  
971    
972  =item sequence  =item sequence
973    
# Line 984  Line 989 
989    
990  sub ComputeFASTA {  sub ComputeFASTA {
991      # Get the parameters.      # Get the parameters.
992      my ($self, $incomingType, $desiredType, $sequence) = @_;      my ($self, $desiredType, $sequence) = @_;
993      # Declare the return variable. If an error occurs, it will remain undefined.      # Declare the return variable. If an error occurs, it will remain undefined.
994      my $retVal;      my $retVal;
995      # This variable will be cleared if an error is detected.      # This variable will be cleared if an error is detected.
996      my $okFlag = 1;      my $okFlag = 1;
997      # Create variables to hold the FASTA label and data.      # Create variables to hold the FASTA label and data.
998      my ($fastaLabel, $fastaData);      my ($fastaLabel, $fastaData);
999      Trace("FASTA incoming type is $incomingType, desired type is $desiredType.") if T(4);      Trace("FASTA desired type is $desiredType.") if T(4);
1000      # Check for a feature specification.      # Check for a feature specification.
1001      if ($sequence =~ /^\s*(\w+\|\S+)\s*$/) {      if ($sequence =~ /^\s*(\w+\|\S+)\s*$/) {
1002          # Here we have a feature ID in $1. We'll need the Sprout object to process          # Here we have a feature ID in $1. We'll need the Sprout object to process
# Line 1004  Line 1009 
1009          # exist.          # exist.
1010          my ($figID) = $sprout->FeaturesByAlias($fid);          my ($figID) = $sprout->FeaturesByAlias($fid);
1011          if (! $figID) {          if (! $figID) {
1012              $self->SetMessage("No feature found with the ID \"$fid\".");              $self->SetMessage("No gene found with the ID \"$fid\".");
1013              $okFlag = 0;              $okFlag = 0;
1014          } else {          } else {
1015              # Set the FASTA label.              # Set the FASTA label.
# Line 1021  Line 1026 
1026                  Trace(length $fastaData . " characters returned for DNA of $fastaLabel.") if T(3);                  Trace(length $fastaData . " characters returned for DNA of $fastaLabel.") if T(3);
1027              }              }
1028          }          }
     } elsif ($incomingType eq 'prot' && $desiredType eq 'dna') {  
         # Here we're being asked to do an impossible conversion.  
         $self->SetMessage("Cannot convert a protein sequence to DNA.");  
         $okFlag = 0;  
1029      } else {      } else {
1030          Trace("Analyzing FASTA sequence.") if T(4);          Trace("Analyzing FASTA sequence.") if T(4);
1031          # Here we are expecting a FASTA. We need to see if there's a label.          # Here we are expecting a FASTA. We need to see if there's a label.
# Line 1037  Line 1038 
1038              Trace("No label found in match to sequence:\n$sequence") if T(4);              Trace("No label found in match to sequence:\n$sequence") if T(4);
1039              # Here we have no label, so we create one and use the entire sequence              # Here we have no label, so we create one and use the entire sequence
1040              # as data.              # as data.
1041              $fastaLabel = "User-specified $incomingType sequence";              $fastaLabel = "User-specified $desiredType sequence";
1042              $fastaData = $sequence;              $fastaData = $sequence;
1043          }          }
1044          # The next step is to clean the junk out of the sequence.          # The next step is to clean the junk out of the sequence.
1045          $fastaData =~ s/\n//g;          $fastaData =~ s/\n//g;
1046          $fastaData =~ s/\s+//g;          $fastaData =~ s/\s+//g;
1047          # Finally, if the user wants to convert to protein, we do it here. Note that          # Finally, verify that it's DNA if we're doing DNA stuff.
1048          # we've already prevented a conversion from protein to DNA.          if ($desiredType eq 'dna' && $fastaData =~ /[^agctxn]/i) {
1049          if ($incomingType ne $desiredType) {              $self->SetMessage("Invalid characters detected. Is the input really a DNA sequence?");
             $fastaData = Sprout::Protein($fastaData);  
             # Check for bad characters.  
             if ($fastaData =~ /X/) {  
                 $self->SetMessage("Invalid characters detected. Is the input really of type $incomingType?");  
                 $okFlag = 0;  
             }  
         } elsif ($desiredType eq 'dna' && $fastaData =~ /[^agct]/i) {  
             $self->SetMessage("Invaid characters detected. Is the input really a DNA sequence?");  
1050              $okFlag = 0;              $okFlag = 0;
1051          }          }
1052      }      }
# Line 1367  Line 1360 
1360          # the search box. This allows the user to type text and have all genomes containing          # the search box. This allows the user to type text and have all genomes containing
1361          # the text selected automatically.          # the text selected automatically.
1362          my $searchThingName = "${menuName}_SearchThing";          my $searchThingName = "${menuName}_SearchThing";
1363          push @lines, "<br>Select genomes containing <INPUT type=\"text\" name=\"$searchThingName\" " .          push @lines, "<br />" .
1364                       "size=\"30\" onBlur=\"selectViaSearch($menuName, $searchThingName); $showSelect\" />";                       "<INPUT type=\"button\" name=\"Search\" class=\"button\" value=\"Select genomes containing\" onClick=\"selectViaSearch($menuName, $searchThingName); $showSelect\" />&nbsp;" .
1365                         "<INPUT type=\"text\" name=\"$searchThingName\" size=\"30\" />";
1366          # Next are the buttons to set and clear selections.          # Next are the buttons to set and clear selections.
1367          push @lines, "<br />";          push @lines, "<br />";
1368          push @lines, "<INPUT type=\"button\" name=\"ClearAll\" class=\"bigButton\"  value=\"Clear All\" onClick=\"clearAll($menuName); $showSelect\" />";          push @lines, "<INPUT type=\"button\" name=\"ClearAll\" class=\"bigButton\"  value=\"Clear All\" onClick=\"clearAll($menuName); $showSelect\" />";
# Line 1493  Line 1487 
1487    
1488  =head3 SubmitRow  =head3 SubmitRow
1489    
1490  C<< my $htmlText = $shelp->SubmitRow(); >>  C<< my $htmlText = $shelp->SubmitRow($caption); >>
1491    
1492  Returns the HTML text for the row containing the page size control  Returns the HTML text for the row containing the page size control
1493  and the submit button. All searches should have this row somewhere  and the submit button. All searches should have this row somewhere
1494  near the top of the form.  near the top of the form.
1495    
1496    =over 4
1497    
1498    =item caption (optional)
1499    
1500    Caption to be put on the search button. The default is C<Go>.
1501    
1502    =item RETURN
1503    
1504    Returns a table row containing the controls for submitting the search
1505    and tuning the results.
1506    
1507    =back
1508    
1509  =cut  =cut
1510    
1511  sub SubmitRow {  sub SubmitRow {
1512      # Get the parameters.      # Get the parameters.
1513      my ($self) = @_;      my ($self, $caption) = @_;
1514      my $cgi = $self->Q();      my $cgi = $self->Q();
1515        # Compute the button caption.
1516        my $realCaption = (defined $caption ? $caption : 'Go');
1517      # Get the current page size.      # Get the current page size.
1518      my $pageSize = $cgi->param('PageSize');      my $pageSize = $cgi->param('PageSize');
1519      # Get the incoming external-link flag.      # Get the incoming external-link flag.
# Line 1516  Line 1525 
1525                                                      -default => $pageSize) . " " .                                                      -default => $pageSize) . " " .
1526                                     $cgi->checkbox(-name => 'ShowURL',                                     $cgi->checkbox(-name => 'ShowURL',
1527                                                    -value => 1,                                                    -value => 1,
1528                                                    -label => 'Show URL')),                                                    -label => 'Show URL',
1529                                                      -checked => 1)),
1530                            $cgi->td($cgi->submit(-class => 'goButton',                            $cgi->td($cgi->submit(-class => 'goButton',
1531                                                  -name => 'Search',                                                  -name => 'Search',
1532                                                  -value => 'Go')));                                                  -value => $realCaption)));
1533      # Return the result.      # Return the result.
1534      return $retVal;      return $retVal;
1535  }  }
# Line 1613  Line 1623 
1623          $seg_id =~ s/:/--/g;          $seg_id =~ s/:/--/g;
1624          Trace("Show limits are ($show_start,$show_stop) in genome $genomeID with ref $seg_id.") if T(3);          Trace("Show limits are ($show_start,$show_stop) in genome $genomeID with ref $seg_id.") if T(3);
1625          # Assemble all the pieces.          # Assemble all the pieces.
1626          $retVal = "gbrowse.cgi/GB_$genomeID?ref=$seg_id&start=$show_start&stop=$show_stop";          $retVal = "gbrowse.cgi/GB_$genomeID?ref=$seg_id;start=$show_start;stop=$show_stop";
1627      }      }
1628      # Return the result.      # Return the result.
1629      return $retVal;      return $retVal;
# Line 1706  Line 1716 
1716    
1717  =head3 ComputeSearchURL  =head3 ComputeSearchURL
1718    
1719  C<< my $url = $shelp->ComputeSearchURL(); >>  C<< my $url = $shelp->ComputeSearchURL(%overrides); >>
1720    
1721  Compute the GET-style URL for the current search. In order for this to work, there  Compute the GET-style URL for the current search. In order for this to work, there
1722  must be a copy of the search form on the current page. This will always be the  must be a copy of the search form on the current page. This will always be the
# Line 1716  Line 1726 
1726  main complication is that if the user specified all genomes, we'll want to  main complication is that if the user specified all genomes, we'll want to
1727  remove the parameter entirely from a get-style URL.  remove the parameter entirely from a get-style URL.
1728    
1729    =over 4
1730    
1731    =item overrides
1732    
1733    Hash containing override values for the parameters, where the parameter name is
1734    the key and the parameter value is the override value. If the override value is
1735    C<undef>, the parameter will be deleted from the result.
1736    
1737    =item RETURN
1738    
1739    Returns a GET-style URL for invoking the search with the specified overrides.
1740    
1741    =back
1742    
1743  =cut  =cut
1744    
1745  sub ComputeSearchURL {  sub ComputeSearchURL {
1746      # Get the parameters.      # Get the parameters.
1747      my ($self) = @_;      my ($self, %overrides) = @_;
1748      # Get the database and CGI query object.      # Get the database and CGI query object.
1749      my $cgi = $self->Q();      my $cgi = $self->Q();
1750      my $sprout = $self->DB();      my $sprout = $self->DB();
# Line 1761  Line 1785 
1785              if ($allFlag) {              if ($allFlag) {
1786                  @values = ();                  @values = ();
1787              }              }
1788            } elsif (exists $overrides{$parmKey}) {
1789                # Here the value is being overridden, so we skip it for now.
1790                @values = ();
1791          }          }
1792          # If we still have values, create the URL parameters.          # If we still have values, create the URL parameters.
1793          if (@values) {          if (@values) {
1794              push @urlList, map { "$parmKey=" . uri_escape($_) } @values;              push @urlList, map { "$parmKey=" . uri_escape($_) } @values;
1795          }          }
1796      }      }
1797        # Now do the overrides.
1798        for my $overKey (keys %overrides) {
1799            # Only use this override if it's not a delete marker.
1800            if (defined $overrides{$overKey}) {
1801                push @urlList, "$overKey=" . uri_escape($overrides{$overKey});
1802            }
1803        }
1804      # Add the parameters to the URL.      # Add the parameters to the URL.
1805      $retVal .= "?" . join(";", @urlList);      $retVal .= "?" . join(";", @urlList);
1806      # Return the result.      # Return the result.
# Line 2198  Line 2232 
2232    
2233  =head2 Feature Column Methods  =head2 Feature Column Methods
2234    
2235  The methods in this column manage feature column data. If you want to provide the  The methods in this section manage feature column data. If you want to provide the
2236  capability to include new types of data in feature columns, then all the changes  capability to include new types of data in feature columns, then all the changes
2237  are made to this section of the source file. Technically, this should be implemented  are made to this section of the source file. Technically, this should be implemented
2238  using object-oriented methods, but this is simpler for non-programmers to maintain.  using object-oriented methods, but this is simpler for non-programmers to maintain.
# Line 2273  Line 2307 
2307      } elsif ($colName =~ /^keyword:(.+)$/) {      } elsif ($colName =~ /^keyword:(.+)$/) {
2308          $retVal = ucfirst $1;          $retVal = ucfirst $1;
2309      } elsif ($colName eq 'orgName') {      } elsif ($colName eq 'orgName') {
2310          $retVal = "Feature Name";          $retVal = "Organism and Gene ID";
2311      } elsif ($colName eq 'protlink') {      } elsif ($colName eq 'protlink') {
2312          $retVal = "NMPDR Protein Page";          $retVal = "NMPDR Protein Page";
2313      } elsif ($colName eq 'subsystem') {      } elsif ($colName eq 'subsystem') {
# Line 2346  Line 2380 
2380          ($retVal) = $record->Value('Feature(assignment)');          ($retVal) = $record->Value('Feature(assignment)');
2381      } elsif ($colName eq 'gblink') {      } elsif ($colName eq 'gblink') {
2382          # Here we want a link to the GBrowse page using the official GBrowse button.          # Here we want a link to the GBrowse page using the official GBrowse button.
2383          my $gurl = "GetGBrowse.cgi?fid=$fid";          $retVal = FakeButton('GBrowse', "GetGBrowse.cgi", undef,
2384          $retVal = $cgi->a({ href => $gurl, title => "GBrowse for $fid" },                            fid => $fid);
                           $cgi->img({ src => "../images/button-gbrowse.png",  
                                       border => 0 })  
                          );  
2385      } elsif ($colName eq 'group') {      } elsif ($colName eq 'group') {
2386          # Get the NMPDR group name.          # Get the NMPDR group name.
2387          my (undef, $group) = $self->OrganismData($fid);          my (undef, $group) = $self->OrganismData($fid);
# Line 2367  Line 2398 
2398          $retVal = $self->FeatureName($fid);          $retVal = $self->FeatureName($fid);
2399      } elsif ($colName eq 'protlink') {      } elsif ($colName eq 'protlink') {
2400          # Here we want a link to the protein page using the official NMPDR button.          # Here we want a link to the protein page using the official NMPDR button.
2401          my $hurl = HTML::fid_link($cgi, $fid, 0, 1);          $retVal = FakeButton('NMPDR', "protein.cgi", undef,
2402          $retVal = $cgi->a({ href => $hurl, title => "Protein page for $fid" },                            prot => $fid, SPROUT => 1, new_framework => 0,
2403                            $cgi->img({ src => "../images/button-nmpdr.png",                            user => '');
                                      border => 0 })  
                          );  
2404      }elsif ($colName eq 'subsystem') {      }elsif ($colName eq 'subsystem') {
2405          # Another run-time column: subsystem list.          # Another run-time column: subsystem list.
2406          $retVal = "%%subsystem=$fid";          $retVal = "%%subsystem=$fid";
# Line 2438  Line 2467 
2467          # Get the subsystems.          # Get the subsystems.
2468          Trace("Generating subsystems for feature $fid.") if T(4);          Trace("Generating subsystems for feature $fid.") if T(4);
2469          my %subs = $sprout->SubsystemsOf($fid);          my %subs = $sprout->SubsystemsOf($fid);
2470          # Convert them to links.          # Extract the subsystem names.
2471          my @links = map { HTML::sub_link($cgi, $_) } sort keys %subs;          my @names = map { HTML::sub_link($cgi, $_) } sort keys %subs;
2472          # String them into a list.          # String them into a list.
2473          $retVal = join(", ", @links);          $retVal = join(", ", @names);
2474      } elsif ($type =~ /^keyword:(.+)$/) {      } elsif ($type =~ /^keyword:(.+)$/) {
2475          # Here the caller wants the value of the named keyword. The text is the          # Here the caller wants the value of the named keyword. The text is the
2476          # feature ID.          # feature ID.
# Line 2563  Line 2592 
2592      if (! @wordList) {      if (! @wordList) {
2593          if ($required) {          if ($required) {
2594              $self->SetMessage("No search words specified.");              $self->SetMessage("No search words specified.");
2595            } else {
2596                $retVal = 1;
2597          }          }
2598      } elsif (! @plusWords) {      } elsif (! @plusWords) {
2599          $self->SetMessage("At least one keyword must be positive. All the keywords entered are preceded by minus signs.");          $self->SetMessage("At least one keyword must be positive. All the keywords entered are preceded by minus signs.");
# Line 2573  Line 2604 
2604      return $retVal;      return $retVal;
2605  }  }
2606    
2607    =head3 FakeButton
2608    
2609    C<< my $html = SearchHelper::FakeButton($caption, $url, $target, %parms); >>
2610    
2611    Create a fake button that hyperlinks to the specified URL with the specified parameters.
2612    Unlike a real button, this one won't visibly click, but it will take the user to the
2613    correct place.
2614    
2615    The parameters of this method are deliberately identical to L</Formlet> so that we
2616    can switch easily from real buttons to fake ones in the code.
2617    
2618    =over 4
2619    
2620    =item caption
2621    
2622    Caption to be put on the button.
2623    
2624    =item url
2625    
2626    URL for the target page or script.
2627    
2628    =item target
2629    
2630    Frame or target in which the new page should appear. If C<undef> is specified,
2631    the default target will be used.
2632    
2633    =item parms
2634    
2635    Hash containing the parameter names as keys and the parameter values as values.
2636    These will be appended to the URL.
2637    
2638    =back
2639    
2640    =cut
2641    
2642    sub FakeButton {
2643        # Get the parameters.
2644        my ($caption, $url, $target, %parms) = @_;
2645        # Declare the return variable.
2646        my $retVal;
2647        # Compute the target URL.
2648        my $targetUrl = "$url?" . join(";", map { "$_=" . uri_escape($parms{$_}) } keys %parms);
2649        # Compute the target-frame HTML.
2650        my $targetHtml = ($target ? " target=\"$target\"" : "");
2651        # Assemble the result.
2652        return "<a href=\"$targetUrl\" $targetHtml><div class=\"button2 button\">$caption</div></a>";
2653    }
2654    
2655    =head3 Formlet
2656    
2657    C<< my $html = SearchHelper::Formlet($caption, $url, $target, %parms); >>
2658    
2659    Create a mini-form that posts to the specified URL with the specified parameters. The
2660    parameters will be stored in hidden fields, and the form's only visible control will
2661    be a submit button with the specified caption.
2662    
2663    Note that we don't use B<CGI.pm> services here because they generate forms with extra characters
2664    and tags that we don't want to deal with.
2665    
2666    =over 4
2667    
2668    =item caption
2669    
2670    Caption to be put on the form button.
2671    
2672    =item url
2673    
2674    URL to be put in the form's action parameter.
2675    
2676    =item target
2677    
2678    Frame or target in which the form results should appear. If C<undef> is specified,
2679    the default target will be used.
2680    
2681    =item parms
2682    
2683    Hash containing the parameter names as keys and the parameter values as values.
2684    
2685    =back
2686    
2687    =cut
2688    
2689    sub Formlet {
2690        # Get the parameters.
2691        my ($caption, $url, $target, %parms) = @_;
2692        # Compute the target HTML.
2693        my $targetHtml = ($target ? " target=\"$target\"" : "");
2694        # Start the form.
2695        my $retVal = "<form method=\"POST\" action=\"$url\"$target>";
2696        # Add the parameters.
2697        for my $parm (keys %parms) {
2698            $retVal .= "<input type=\"hidden\" name=\"$parm\" value=\"$parms{$parm}\" />";
2699        }
2700        # Put in the button.
2701        $retVal .= "<input type=\"submit\" name=\"submit\" value=\"$caption\" class=\"button\" />";
2702        # Close the form.
2703        $retVal .= "</form>";
2704        # Return the result.
2705        return $retVal;
2706    }
2707    
2708  =head2 Virtual Methods  =head2 Virtual Methods
2709    
2710  =head3 Form  =head3 Form

Legend:
Removed from v.1.16  
changed lines
  Added in v.1.24

MCS Webmaster
ViewVC Help
Powered by ViewVC 1.0.3