rlm@0: #!C:/strawberry/perl/bin/perl.exe
rlm@0: 
rlm@0: # CGI-Ajax: example script 'pjx_combo.pl'
rlm@0: #
rlm@0: # INSTALL: place in an apache location that can execute perl scripts
rlm@0: #
rlm@0: # this script demonstrates a set of dynamic select boxes, where the
rlm@0: # selection in a box changes other select box contents, or html div
rlm@0: # values.  The data in each select box comes from the data anonymous
rlm@0: # hash, but could just as easily come from a database connection, etc.
rlm@0: #
rlm@0: # N.B. this requires CGI__Ajax version >=0.49
rlm@0: #
rlm@0: # Also, this example has lots of stderr output, so follow your apache
rlm@0: # log files to see what's going on.
rlm@0: #
rlm@0: use strict;
rlm@0: use CGI::Ajax 0.49;
rlm@0: use CGI;
rlm@0: use vars qw( $data );
rlm@0: 
rlm@0: # This is our data - top level keys get put in the leftmost select
rlm@0: # box, next level of keys get the second select box.  Values will end
rlm@0: # up in the resultdiv html element
rlm@0: $data = {
rlm@0:   'A' => { '1' => "A1", '2' => "A2", '3' => "A3", '42' => "A42" },
rlm@0:   'B' => { 'green' => "Bgreen", 'red' => "Bred" },
rlm@0:   'something' => { 'firefly' => "great show" },
rlm@0:   'final_thing' => { 'email' => "chunkeylover53", 'name' => "homer",
rlm@0:                      'address' => "742 Evergreen Terrace" }
rlm@0: };
rlm@0: 
rlm@0: my $q = new CGI;  # need a new CGI object
rlm@0: 
rlm@0: # compose our list of functions to export to js
rlm@0: my %hash = ( 'SetA'         => \&set_listA,
rlm@0:              'SetB'         => \&set_listB,
rlm@0:              'ShowResult'   => \&show_result );
rlm@0: 
rlm@0: my $pjx = CGI::Ajax->new( %hash ); # this is our CGI::Ajax object
rlm@0: $pjx->js_encode_function('encodeURIComponent');
rlm@0: 
rlm@0: $pjx->DEBUG(1);   # turn on debugging
rlm@0: $pjx->JSDEBUG(1); # turn on javascript debugging, which will place a
rlm@0:                   #  new div element at the bottom of our page showing
rlm@0:                   #  the asynchrously requested URL
rlm@0: 
rlm@0: print $pjx->build_html( $q, \&Show_HTML ); # this builds our html
rlm@0:                                            #  page, inserting js
rlm@0: 
rlm@0: # This subroutine is responsible for outputting the HTML of the web
rlm@0: # page.  Note that I've added an additional javascript function to
rlm@0: # erase/reset contents.  This prevents strange effects from
rlm@0: # overwriting a div without clearing it out first.
rlm@0: sub Show_HTML {
rlm@0:   my $html = <<EOT;
rlm@0: <HTML>
rlm@0: <HEAD><title>Combo Example</title>
rlm@0: <SCRIPT>
rlm@0: 
rlm@0: // define some reset functions to properly clear out the divs
rlm@0: function resetdiv( ) {
rlm@0:   if ( arguments.length ) {
rlm@0:     // reset a specific div
rlm@0:     for(var i = 0; i < arguments.length; i++ ) {
rlm@0:       document.getElementById(arguments[i]).innerHTML = "";
rlm@0:     }
rlm@0:   } else {
rlm@0:     // just reset all the divs
rlm@0:     document.getElementById("listAdiv").innerHTML = "";
rlm@0:     document.getElementById("listBdiv").innerHTML = "";
rlm@0:     document.getElementById("resultdiv").innerHTML = "";
rlm@0:   }
rlm@0: }
rlm@0: 
rlm@0: </SCRIPT>
rlm@0: 
rlm@0: </HEAD>
rlm@0: <BODY onload="resetdiv(); SetA([],['listAdiv']); return true;" >
rlm@0: <form>
rlm@0:         <div id="listAdiv"></div>
rlm@0:         <div id="listBdiv"></div>
rlm@0:         <div id="resultdiv" style="border: 1px solid black; width: 240px; height: 80px; overflow: auto">
rlm@0:         </div>
rlm@0:   <input type="text" name="textfield">
rlm@0:   <input type="submit" name="Submit" value="Submit" 
rlm@0: 
rlm@0:   </form>
rlm@0: </BODY>
rlm@0: </HTML>
rlm@0: EOT
rlm@0: 
rlm@0:   return($html);
rlm@0: }
rlm@0: 
rlm@0: # these are my exported functions - note that set_listA and set_listB
rlm@0: # are just returning html to be inserted into their respective div
rlm@0: # elements.
rlm@0: sub set_listA {
rlm@0:   # this is the returned text... html to be displayed in the div
rlm@0:   # defined in the javascript call
rlm@0:   my $txt = qq!<select id="listA" name="listA_name" size=3!;
rlm@0:   $txt .= qq! onclick="resetdiv('resultdiv'); SetB( ['listA'], ['listBdiv'] ); return true;">!;
rlm@0:   # get values from $data, could also be a db lookup
rlm@0:   foreach my $topval ( keys %$data ) {
rlm@0:     $txt .= '<option value='. $topval . '>'.  $topval .' </option>';
rlm@0:   }
rlm@0:   $txt .= "</select>";
rlm@0:   print STDERR "set_listA:\n";
rlm@0:   print STDERR "returning $txt\n";
rlm@0:   return($txt);
rlm@0: }
rlm@0: 
rlm@0: sub set_listB {
rlm@0:   my $listA_selection = shift;
rlm@0:   print STDERR "set_listB: received $listA_selection .\n";
rlm@0: 
rlm@0:   # this is the returned text... html to be displayed in the div
rlm@0:   # defined in the javascript call
rlm@0:   my $txt = qq!<select multiple id="listB" name="listB_name" size=3 style="width: 140px"!; 
rlm@0:   $txt .= qq! onclick="ShowResult( ['listA','listB'], ['resultdiv'] ); return true;">!;
rlm@0: 
rlm@0:   # get values from $data, could also be a db lookup
rlm@0:   foreach my $midval ( keys %{ $data->{ $listA_selection } } ) {
rlm@0:     $txt .= '<option value=' . $midval . '>' . $midval . "</option>";
rlm@0:   }
rlm@0:   $txt .= "</select>";
rlm@0:   print STDERR "set_listB:\n";
rlm@0:   print STDERR "returning $txt\n";
rlm@0:   return($txt);
rlm@0: }
rlm@0: 
rlm@0: sub show_result {
rlm@0:   my $listA_selection = shift;
rlm@0:   my $txt = "";
rlm@0:   # this loop is needed in case the user selected multiple elements in
rlm@0:   # the second select box, listB
rlm@0:   while ( @_ ) {
rlm@0:     my $in = shift;
rlm@0:     $txt .= $data->{ $listA_selection }->{ $in } . "<br>";
rlm@0:   }
rlm@0: 
rlm@0:   print STDERR "show_result - returning txt with value: $txt\n";
rlm@0:   return( $txt );
rlm@0: }
rlm@0: