Diff for /loncom/interface/lonhelper.pm between versions 1.11 and 1.18

version 1.11, 2003/04/15 19:10:00 version 1.18, 2003/05/05 15:17:25
Line 84  Of course this does nothing. In order fo Line 84  Of course this does nothing. In order fo
 necessary to put actual elements into the wizard. Documentation for each  necessary to put actual elements into the wizard. Documentation for each
 of these elements follows.  of these elements follows.
   
   =head2 Creating a Helper With Code, Not XML
   
   In some situations, such as the printing wizard (see lonprintout.pm), 
   writing the helper in XML would be too complicated, because of scope 
   issues or the fact that the code actually outweighs the XML. It is
   possible to create a helper via code, though it is a little odd.
   
   Creating a helper via code is more like issuing commands to create
   a helper then normal code writing. For instance, elements will automatically
   be added to the last state created, so it's important to create the 
   states in the correct order.
   
   First, create a new helper:
   
    use Apache::lonhelper;
   
    my $helper = Apache::lonhelper::new->("Helper Title");
   
   Next you'll need to manually add states to the helper:
   
    Apache::lonhelper::state->new("STATE_NAME", "State's Human Title");
   
   You don't need to save a reference to it because all elements up until
   the next state creation will automatically be added to this state.
   
   Elements are created by populating the $paramHash in 
   Apache::lonhelper::paramhash. To prevent namespace issues, retrieve 
   a reference to that has with getParamHash:
   
    my $paramHash = Apache::lonhelper::getParamHash();
   
   You will need to do this for each state you create.
   
   Populate the $paramHash with the parameters for the element you wish
   to add next; the easiest way to find out what those entries are is
   to read the code. Some common ones are 'variable' to record the variable
   to store the results in, and NEXTSTATE to record a next state transition.
   
   Then create your element:
   
    $paramHash->{MESSAGETEXT} = "This is a message.";
    Apache::lonhelper::message->new();
   
   The creation will take the $paramHash and bless it into a
   Apache::lonhelper::message object. To create the next element, you need
   to get a reference to the new, empty $paramHash:
   
    $paramHash = Apache::lonhelper::getParamHash();
   
   and you can repeat creating elements that way. You can add states
   and elements as needed.
   
   See lonprintout.pm, subroutine printHelper for an example of this, where
   we dynamically add some states to prevent security problems, for instance.
   
   Normally the machinery in the XML format is sufficient; dynamically 
   adding states can easily be done by wrapping the state in a <condition>
   tag. This should only be used when the code dominates the XML content,
   the code is so complicated that it is difficult to get access to
   all of the information you need because of scoping issues, or so much
   of the information used is persistent because would-be <exec> or 
   <eval> blocks that using the {DATA} mechanism results in hard-to-read
   and -maintain code.
   
   It is possible to do some of the work with an XML fragment parsed by
   lonxml; again, see lonprintout.pm for an example. In that case it is 
   imperative that you call B<Apache::lonhelper::registerHelperTags()>
   before parsing XML fragments and B<Apache::lonhelper::unregisterHelperTags()>
   when you are done. See lonprintout.pm for examples of this usage in the
   printHelper subroutine.
   
 =cut  =cut
   
 package Apache::lonhelper;  package Apache::lonhelper;
Line 122  my $substate; Line 193  my $substate;
 # end of the element tag is located.  # end of the element tag is located.
 my $paramHash;   my $paramHash; 
   
   # For debugging purposes, one can send a second parameter into this
   # function, the 'uri' of the helper you wish to have rendered, and
   # call this from other handlers.
 sub handler {  sub handler {
     my $r = shift;      my $r = shift;
     $ENV{'request.uri'} = $r->uri();      my $uri = shift;
     my $filename = '/home/httpd/html' . $r->uri();      if (!defined($uri)) { $uri = $r->uri(); }
       $ENV{'request.uri'} = $uri;
       my $filename = '/home/httpd/html' . $uri;
     my $fh = Apache::File->new($filename);      my $fh = Apache::File->new($filename);
     my $file;      my $file;
     read $fh, $file, 100000000;      read $fh, $file, 100000000;
   
     Apache::loncommon::get_unprocessed_cgi($ENV{QUERY_STRING});  
   
     # Send header, don't cache this page      # Send header, don't cache this page
     if ($r->header_only) {      if ($r->header_only) {
         if ($ENV{'browser.mathml'}) {          if ($ENV{'browser.mathml'}) {
Line 154  sub handler { Line 228  sub handler {
     # xml parsing      # xml parsing
     &Apache::lonxml::xmlparse($r, 'helper', $file);      &Apache::lonxml::xmlparse($r, 'helper', $file);
   
       $helper->process();
   
     $r->print($helper->display());      $r->print($helper->display());
    return OK;     return OK;
 }  }
   
   sub registerHelperTags {
       for my $tagList (@helperTags) {
           Apache::lonxml::register($tagList->[0], $tagList->[1]);
       }
   }
   
   sub unregisterHelperTags {
       for my $tagList (@helperTags) {
           Apache::lonxml::deregister($tagList->[0], $tagList->[1]);
       }
   }
   
 sub start_helper {  sub start_helper {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
   
Line 165  sub start_helper { Line 253  sub start_helper {
         return '';          return '';
     }      }
   
     for my $tagList (@helperTags) {      registerHelperTags();
         Apache::lonxml::register($tagList->[0], $tagList->[1]);  
     }      Apache::lonhelper::helper->new($token->[2]{'title'});
       
     $helper = Apache::lonhelper::helper->new($token->[2]{'title'});  
     return '';      return '';
 }  }
   
Line 180  sub end_helper { Line 266  sub end_helper {
         return '';          return '';
     }      }
   
     for my $tagList (@helperTags) {      unregisterHelperTags();
         Apache::lonxml::deregister($tagList->[0], $tagList->[1]);  
     }  
   
     return '';      return '';
 }  }
Line 194  sub start_state { Line 278  sub start_state {
         return '';          return '';
     }      }
   
     $state = Apache::lonhelper::state->new($token->[2]{'name'},      Apache::lonhelper::state->new($token->[2]{'name'},
                                            $token->[2]{'title'});                                    $token->[2]{'title'});
     return '';      return '';
 }  }
   
   # Use this to get the param hash from other files.
   sub getParamHash {
       return $paramHash;
   }
   
   # Use this to get the helper, if implementing elements in other files
   # (like lonprintout.pm)
   sub getHelper {
       return $helper;
   }
   
 # don't need this, so ignore it  # don't need this, so ignore it
 sub end_state {  sub end_state {
     return '';      return '';
Line 231  sub new { Line 326  sub new {
  $self->{STATE} = "START";   $self->{STATE} = "START";
     }      }
   
       Apache::loncommon::get_unprocessed_cgi($ENV{QUERY_STRING});
   
     $self->{TOKEN} = $ENV{'form.TOKEN'};      $self->{TOKEN} = $ENV{'form.TOKEN'};
     # If a token was passed, we load that in. Otherwise, we need to create a       # If a token was passed, we load that in. Otherwise, we need to create a 
     # new storage file      # new storage file
Line 287  sub new { Line 384  sub new {
     # for an example.      # for an example.
     $self->{DATA} = {};      $self->{DATA} = {};
   
       $helper = $self;
   
       # Establish the $paramHash
       $paramHash = {};
   
     bless($self, $class);      bless($self, $class);
     return $self;      return $self;
 }  }
Line 347  sub registerState { Line 449  sub registerState {
     $self->{STATES}{$stateName} = $state;      $self->{STATES}{$stateName} = $state;
 }  }
   
 # Done in four phases  sub process {
 # 1: Do the post processing for the previous state.  
 # 2: Do the preprocessing for the current state.  
 # 3: Check to see if state changed, if so, postprocess current and move to next.  
 #    Repeat until state stays stable.  
 # 4: Render the current state to the screen as an HTML page.  
 sub display {  
     my $self = shift;      my $self = shift;
   
     my $result = "";  
   
     # Phase 1: Post processing for state of previous screen (which is actually      # Phase 1: Post processing for state of previous screen (which is actually
     # the "current state" in terms of the helper variables), if it wasn't the       # the "current state" in terms of the helper variables), if it wasn't the 
     # beginning state.      # beginning state.
     if ($self->{STATE} ne "START" || $ENV{"form.SUBMIT"} eq "Next ->") {      if ($self->{STATE} ne "START" || $ENV{"form.SUBMIT"} eq "Next ->") {
  my $prevState = $self->{STATES}{$self->{STATE}};   my $prevState = $self->{STATES}{$self->{STATE}};
             $prevState->postprocess();          $prevState->postprocess();
     }      }
           
     # Note, to handle errors in a state's input that a user must correct,      # Note, to handle errors in a state's input that a user must correct,
Line 372  sub display { Line 466  sub display {
   
     # Phase 2: Preprocess current state      # Phase 2: Preprocess current state
     my $startState = $self->{STATE};      my $startState = $self->{STATE};
     my $state = $self->{STATES}{$startState};      my $state = $self->{STATES}->{$startState};
           
     # Error checking; it is intended that the developer will have      # For debugging, print something here to determine if you're going
     # checked all paths and the user can't see this!      # to an undefined state.
     if (!defined($state)) {      if (!defined($state)) {
         $result .="Error! The state ". $startState ." is not defined.";          return;
         return $result;  
     }      }
     $state->preprocess();      $state->preprocess();
   
     # Phase 3: While the current state is different from the previous state,      # Phase 3: While the current state is different from the previous state,
     # keep processing.      # keep processing.
     while ( $startState ne $self->{STATE} )      while ( $startState ne $self->{STATE} && 
               defined($self->{STATES}->{$self->{STATE}}) )
     {      {
  $startState = $self->{STATE};   $startState = $self->{STATE};
  $state = $self->{STATES}{$startState};   $state = $self->{STATES}->{$startState};
  $state->preprocess();   $state->preprocess();
     }      }
   
       return;
   } 
   
   # 1: Do the post processing for the previous state.
   # 2: Do the preprocessing for the current state.
   # 3: Check to see if state changed, if so, postprocess current and move to next.
   #    Repeat until state stays stable.
   # 4: Render the current state to the screen as an HTML page.
   sub display {
       my $self = shift;
   
       my $state = $self->{STATES}{$self->{STATE}};
   
       my $result = "";
   
       if (!defined($state)) {
           $result = "<font color='#ff0000'>Error: state '$state' not defined!</font>";
           return $result;
       }
   
     # Phase 4: Display.      # Phase 4: Display.
     my $stateTitle = $state->title();      my $stateTitle = $state->title();
     my $bodytag = &Apache::loncommon::bodytag("$self->{TITLE}",'','');      my $bodytag = &Apache::loncommon::bodytag("$self->{TITLE}",'','');
Line 402  sub display { Line 516  sub display {
     </head>      </head>
     $bodytag      $bodytag
 HEADER  HEADER
     if (!$state->overrideForm()) { $result.="<form name='wizform' method='GET'>"; }      if (!$state->overrideForm()) { $result.="<form name='helpform' method='GET'>"; }
     $result .= <<HEADER;      $result .= <<HEADER;
         <table border="0"><tr><td>          <table border="0"><tr><td>
         <h2><i>$stateTitle</i></h2>          <h2><i>$stateTitle</i></h2>
Line 430  HEADER Line 544  HEADER
         $result .= "</center>\n";          $result .= "</center>\n";
     }      }
   
     foreach my $key (keys %{$self->{VARS}}) {      #foreach my $key (keys %{$self->{VARS}}) {
         $result .= "|$key| -> " . $self->{VARS}->{$key} . "<br />";      #    $result .= "|$key| -> " . $self->{VARS}->{$key} . "<br />";
     }      #}
   
     $result .= <<FOOTER;      $result .= <<FOOTER;
               </td>                </td>
Line 474  sub new { Line 588  sub new {
   
     $helper->registerState($self);      $helper->registerState($self);
   
       $state = $self;
   
     return $self;      return $self;
 }  }
   
Line 517  sub postprocess { Line 633  sub postprocess {
     }      }
 }  }
   
   # Override the form if any element wants to.
   # two elements overriding the form will make a mess, but that should
   # be considered helper author error ;-)
 sub overrideForm {  sub overrideForm {
       my $self = shift;
       for my $element (@{$self->{ELEMENTS}}) {
           if ($element->overrideForm()) {
               return 1;
           }
       }
     return 0;      return 0;
 }  }
   
Line 616  sub render { Line 741  sub render {
     return '';      return '';
 }  }
   
   sub overrideForm {
       return 0;
   }
   
 sub process_multiple_choices {  sub process_multiple_choices {
     my $self = shift;      my $self = shift;
     my $formname = shift;      my $formname = shift;
     my $var = shift;      my $var = shift;
   
     my $formvalue = $ENV{'form.' . $formname};      # Must extract values from data directly, as there
     if ($formvalue) {      # may be more then one.
         # Must extract values from querystring directly, as there      my @values;
         # may be more then one.      for my $formparam (split (/&/, $ENV{QUERY_STRING})) {
         my @values;          my ($name, $value) = split(/=/, $formparam);
         for my $formparam (split (/&/, $ENV{QUERY_STRING})) {          if ($name ne $formname) {
             my ($name, $value) = split(/=/, $formparam);              next;
             if ($name ne $formname) {  
                 next;  
             }  
             $value =~ tr/+/ /;  
             $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;  
             push @values, $value;  
         }          }
         $helper->{VARS}->{$var} = join('|||', @values);          $value =~ tr/+/ /;
           $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
           push @values, $value;
     }      }
       $helper->{VARS}->{$var} = join('|||', @values);
           
     return;      return;
 }  }
Line 766  B<SUB-TAGS> Line 892  B<SUB-TAGS>
       For example,          For example,  
       <choice computer='234-12-7312'>Bobby McDormik</choice>.        <choice computer='234-12-7312'>Bobby McDormik</choice>.
   
         <choice> can take a parameter "eval", which if set to
         a true value, will cause the contents of the tag to be
         evaluated as it would be in an <eval> tag; see <eval> tag
         below.
   
 <choice> may optionally contain a 'nextstate' attribute, which  <choice> may optionally contain a 'nextstate' attribute, which
 will be the state transisitoned to if the choice is made, if  will be the state transisitoned to if the choice is made, if
 the choice is not multichoice.  the choice is not multichoice.
Line 846  sub start_choice { Line 977  sub start_choice {
     my $human = &Apache::lonxml::get_all_text('/choice',      my $human = &Apache::lonxml::get_all_text('/choice',
                                               $parser);                                                $parser);
     my $nextstate = $token->[2]{'nextstate'};      my $nextstate = $token->[2]{'nextstate'};
     push @{$paramHash->{CHOICES}}, [$human, $computer, $nextstate];      my $evalFlag = $token->[2]{'eval'};
       push @{$paramHash->{CHOICES}}, [$human, $computer, $nextstate, 
                                       $evalFlag];
     return '';      return '';
 }  }
   
Line 864  sub render { Line 997  sub render {
     if ($self->{'multichoice'}) {      if ($self->{'multichoice'}) {
         $result .= <<SCRIPT;          $result .= <<SCRIPT;
 <script>  <script>
     function checkall(value) {      function checkall(value, checkName) {
  for (i=0; i<document.forms.wizform.elements.length; i++) {   for (i=0; i<document.forms.helpform.elements.length; i++) {
             document.forms.wizform.elements[i].checked=value;              ele = document.forms.helpform.elements[i];
               if (ele.name == checkName + '.forminput') {
                   document.forms.helpform.elements[i].checked=value;
               }
         }          }
     }      }
 </script>  </script>
 SCRIPT  SCRIPT
         $buttons = <<BUTTONS;          $buttons = <<BUTTONS;
 <br />  <br />
 <input type="button" onclick="checkall(true)" value="Select All" />  <input type="button" onclick="checkall(true, '$var')" value="Select All" />
 <input type="button" onclick="checkall(false)" value="Unselect All" />  <input type="button" onclick="checkall(false, '$var')" value="Unselect All" />
 <br />&nbsp;  <br />&nbsp;
 BUTTONS  BUTTONS
     }      }
Line 900  BUTTONS Line 1036  BUTTONS
             $result .= " checked ";              $result .= " checked ";
             $checked = 1;              $checked = 1;
         }          }
         $result .= "/></td><td> " . $choice->[0] . "</td></tr>\n";          my $choiceLabel = $choice->[0];
           if ($choice->[4]) {  # if we need to evaluate this choice
               $choiceLabel = "sub { my $helper = shift; my $state = shift;" .
                   $choiceLabel . "}";
               $choiceLabel = eval($choiceLabel);
               $choiceLabel = &$choiceLabel($helper, $self);
           }
           $result .= "/></td><td> " . $choiceLabel . "</td></tr>\n";
     }      }
     $result .= "</table>\n\n\n";      $result .= "</table>\n\n\n";
     $result .= $buttons;      $result .= $buttons;
Line 1165  the user can manipulate the folders. Line 1308  the user can manipulate the folders.
   
 <resource> takes the standard variable attribute to control what helper  <resource> takes the standard variable attribute to control what helper
 variable stores the results. It also takes a "multichoice" attribute,  variable stores the results. It also takes a "multichoice" attribute,
 which controls whether the user can select more then one resource.  which controls whether the user can select more then one resource. The 
   "toponly" attribute controls whether the resource display shows just the
   resources in that sequence, or recurses into all sub-sequences, defaulting
   to false.
   
 B<SUB-TAGS>  B<SUB-TAGS>
   
Line 1192  B<SUB-TAGS> Line 1338  B<SUB-TAGS>
   "}" returns a string representing what you want to have as the value. By    "}" returns a string representing what you want to have as the value. By
   default, the value will be the resource ID of the object ($res->{ID}).    default, the value will be the resource ID of the object ($res->{ID}).
   
   =item * <mapurl>: If the URL of a map is given here, only that map
     will be displayed, instead of the whole course.
   
 =back  =back
   
 =cut  =cut
Line 1203  use strict; Line 1352  use strict;
 BEGIN {  BEGIN {
     &Apache::lonhelper::register('Apache::lonhelper::resource',      &Apache::lonhelper::register('Apache::lonhelper::resource',
                               ('resource', 'filterfunc',                                 ('resource', 'filterfunc', 
                                'choicefunc', 'valuefunc'));                                 'choicefunc', 'valuefunc',
                                  'mapurl'));
 }  }
   
 sub new {  sub new {
Line 1221  sub start_resource { Line 1371  sub start_resource {
   
     $paramHash->{'variable'} = $token->[2]{'variable'};      $paramHash->{'variable'} = $token->[2]{'variable'};
     $helper->declareVar($paramHash->{'variable'});      $helper->declareVar($paramHash->{'variable'});
       $paramHash->{'multichoice'} = $token->[2]{'multichoice'};
       $paramHash->{'toponly'} = $token->[2]{'toponly'};
     return '';      return '';
 }  }
   
Line 1288  sub start_valuefunc { Line 1440  sub start_valuefunc {
   
 sub end_valuefunc { return ''; }  sub end_valuefunc { return ''; }
   
   sub start_mapurl {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
   
       if ($target ne 'helper') {
           return '';
       }
   
       my $contents = Apache::lonxml::get_all_text('/mapurl',
                                                   $parser);
       $paramHash->{MAP_URL} = $contents;
   }
   
   sub end_mapurl { return ''; }
   
 # A note, in case I don't get to this before I leave.  # A note, in case I don't get to this before I leave.
 # If someone complains about the "Back" button returning them  # If someone complains about the "Back" button returning them
 # to the previous folder state, instead of returning them to  # to the previous folder state, instead of returning them to
Line 1306  sub render { Line 1472  sub render {
     my $var = $self->{'variable'};      my $var = $self->{'variable'};
     my $curVal = $helper->{VARS}->{$var};      my $curVal = $helper->{VARS}->{$var};
   
       my $buttons = '';
   
       if ($self->{'multichoice'}) {
           $result = <<SCRIPT;
   <script>
       function checkall(value, checkName) {
    for (i=0; i<document.forms.helpform.elements.length; i++) {
               ele = document.forms.helpform.elements[i];
               if (ele.name == checkName + '.forminput') {
                   document.forms.helpform.elements[i].checked=value;
               }
           }
       }
   </script>
   SCRIPT
           $buttons = <<BUTTONS;
   <br /> &nbsp;
   <input type="button" onclick="checkall(true, '$var')" value="Select All Resources" />
   <input type="button" onclick="checkall(false, '$var')" value="Unselect All Resources" />
   <br /> &nbsp;
   BUTTONS
       }
   
     if (defined $self->{ERROR_MSG}) {      if (defined $self->{ERROR_MSG}) {
         $result .= '<font color="#FF0000">' . $self->{ERROR_MSG} . '</font><br /><br />';          $result .= '<br /><font color="#FF0000">' . $self->{ERROR_MSG} . '</font><br /><br />';
     }      }
   
       $result .= $buttons;
   
     my $filterFunc = $self->{FILTER_FUNC};      my $filterFunc = $self->{FILTER_FUNC};
     my $choiceFunc = $self->{CHOICE_FUNC};      my $choiceFunc = $self->{CHOICE_FUNC};
     my $valueFunc = $self->{VALUE_FUNC};      my $valueFunc = $self->{VALUE_FUNC};
       my $mapUrl = $self->{MAP_URL};
       my $multichoice = $self->{'multichoice'};
   
     # Create the composite function that renders the column on the nav map      # Create the composite function that renders the column on the nav map
     # have to admit any language that lets me do this can't be all bad      # have to admit any language that lets me do this can't be all bad
Line 1320  sub render { Line 1513  sub render {
     my $checked = 0;      my $checked = 0;
     my $renderColFunc = sub {      my $renderColFunc = sub {
         my ($resource, $part, $params) = @_;          my ($resource, $part, $params) = @_;
           
           my $inputType;
           if ($multichoice) { $inputType = 'checkbox'; }
           else {$inputType = 'radio'; }
   
         if (!&$choiceFunc($resource)) {          if (!&$choiceFunc($resource)) {
             return '<td>&nbsp;</td>';              return '<td>&nbsp;</td>';
         } else {          } else {
             my $col = "<td><input type='radio' name='${var}.forminput' ";              my $col = "<td><input type='$inputType' name='${var}.forminput' ";
             if (!$checked) {              if (!$checked && !$multichoice) {
                 $col .= "checked ";                  $col .= "checked ";
                 $checked = 1;                  $checked = 1;
             }              }
Line 1336  sub render { Line 1533  sub render {
         }          }
     };      };
   
     $ENV{'form.condition'} = 1;      $ENV{'form.condition'} = !$self->{'toponly'};
     $result .=       $result .= 
         &Apache::lonnavmaps::render( { 'cols' => [$renderColFunc,           &Apache::lonnavmaps::render( { 'cols' => [$renderColFunc, 
                                                   Apache::lonnavmaps::resource()],                                                    Apache::lonnavmaps::resource()],
                                        'showParts' => 0,                                         'showParts' => 0,
                                        'url' => $helper->{URL},  
                                        'filterFunc' => $filterFunc,                                         'filterFunc' => $filterFunc,
                                        'resource_no_folder_link' => 1 }                                         'resource_no_folder_link' => 1,
                                          'iterator_map' => $mapUrl }
                                        );                                         );
   
       $result .= $buttons;
                                                                                                   
     return $result;      return $result;
 }  }
           
 sub postprocess {  sub postprocess {
     my $self = shift;      my $self = shift;
   
       if ($self->{'multichoice'}) {
           $self->process_multiple_choices($self->{'variable'}.'.forminput',
                                           $self->{'variable'});
       }
   
       if ($self->{'multichoice'} && !$helper->{VARS}->{$self->{'variable'}}) {
           $self->{ERROR_MSG} = 'You must choose at least one resource to continue.';
           return 0;
       }
   
     if (defined($self->{NEXTSTATE})) {      if (defined($self->{NEXTSTATE})) {
         $helper->changeState($self->{NEXTSTATE});          $helper->changeState($self->{NEXTSTATE});
     }      }
Line 1401  sub start_student { Line 1611  sub start_student {
     $paramHash->{'variable'} = $token->[2]{'variable'};      $paramHash->{'variable'} = $token->[2]{'variable'};
     $helper->declareVar($paramHash->{'variable'});      $helper->declareVar($paramHash->{'variable'});
     $paramHash->{'multichoice'} = $token->[2]{'multichoice'};      $paramHash->{'multichoice'} = $token->[2]{'multichoice'};
       if (defined($token->[2]{'nextstate'})) {
           $paramHash->{NEXTSTATE} = $token->[2]{'nextstate'};
       }
       
 }      }    
   
 sub end_student {  sub end_student {
Line 1416  sub render { Line 1630  sub render {
     my $self = shift;      my $self = shift;
     my $result = '';      my $result = '';
     my $buttons = '';      my $buttons = '';
       my $var = $self->{'variable'};
   
     if ($self->{'multichoice'}) {      if ($self->{'multichoice'}) {
         $result = <<SCRIPT;          $result = <<SCRIPT;
 <script>  <script>
     function checkall(value) {      function checkall(value, checkName) {
  for (i=0; i<document.forms.wizform.elements.length; i++) {   for (i=0; i<document.forms.helpform.elements.length; i++) {
             document.forms.wizform.elements[i].checked=value;              ele = document.forms.helpform.elements[i];
               if (ele.name == checkName + '.forminput') {
                   document.forms.helpform.elements[i].checked=value;
               }
         }          }
     }      }
 </script>  </script>
 SCRIPT  SCRIPT
         $buttons = <<BUTTONS;          $buttons = <<BUTTONS;
 <br />  <br />
 <input type="button" onclick="checkall(true)" value="Select All" />  <input type="button" onclick="checkall(true, '$var')" value="Select All Students" />
 <input type="button" onclick="checkall(false)" value="Unselect All" />  <input type="button" onclick="checkall(false, '$var')" value="Unselect All Students" />
 <br />  <br />
 BUTTONS  BUTTONS
     }      }
Line 1441  BUTTONS Line 1659  BUTTONS
   
     # Load up the students      # Load up the students
     my $choices = &Apache::loncoursedata::get_classlist();      my $choices = &Apache::loncoursedata::get_classlist();
   
     my @keys = keys %{$choices};      my @keys = keys %{$choices};
   
     # Constants      # Constants
Line 1622  sub render { Line 1839  sub render {
     if ($self->{'multichoice'}) {      if ($self->{'multichoice'}) {
         $result = <<SCRIPT;          $result = <<SCRIPT;
 <script>  <script>
     function checkall(value) {      function checkall(value, checkName) {
  for (i=0; i<document.forms.wizform.elements.length; i++) {   for (i=0; i<document.forms.helpform.elements.length; i++) {
             ele = document.forms.wizform.elements[i];              ele = document.forms.helpform.elements[i];
             if (ele.type == "checkbox") {              if (ele.name == checkName + '.forminput') {
                 document.forms.wizform.elements[i].checked=value;                  document.forms.helpform.elements[i].checked=value;
             }              }
         }          }
     }      }
 </script>  </script>
 SCRIPT  SCRIPT
         my $buttons = <<BUTTONS;          $buttons = <<BUTTONS;
 <br /> &nbsp;  <br /> &nbsp;
 <input type="button" onclick="checkall(true)" value="Select All" />  <input type="button" onclick="checkall(true, '$var')" value="Select All Files" />
 <input type="button" onclick="checkall(false)" value="Unselect All" />  <input type="button" onclick="checkall(false, '$var')" value="Unselect All Files" />
 <br /> &nbsp;  <br /> &nbsp;
 BUTTONS  BUTTONS
     }      }
Line 1752  sub new { Line 1969  sub new {
 sub start_section {  sub start_section {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
   
     $paramHash->{CHOICES} = [];  
   
     if ($target ne 'helper') {      if ($target ne 'helper') {
         return '';          return '';
     }      }
   
       $paramHash->{CHOICES} = [];
   
     $paramHash->{'variable'} = $token->[2]{'variable'};      $paramHash->{'variable'} = $token->[2]{'variable'};
     $helper->declareVar($paramHash->{'variable'});      $helper->declareVar($paramHash->{'variable'});
     $paramHash->{'multichoice'} = $token->[2]{'multichoice'};      $paramHash->{'multichoice'} = $token->[2]{'multichoice'};
     if (defined($token->[2]{'nextstate'})) {      if (defined($token->[2]{'nextstate'})) {
         $paramHash->{'nextstate'} = $token->[2]{'nextstate'};          $paramHash->{NEXTSTATE} = $token->[2]{'nextstate'};
     }      }
   
     # Populate the CHOICES element      # Populate the CHOICES element
Line 1776  sub start_section { Line 1994  sub start_section {
         } else {          } else {
             $choices{$sectionName} = $sectionName;              $choices{$sectionName} = $sectionName;
         }          }
     }      } 
          
     for my $sectionName (sort(keys(%choices))) {      for my $sectionName (sort(keys(%choices))) {
           
         push @{$paramHash->{CHOICES}}, [$sectionName, $sectionName];          push @{$paramHash->{CHOICES}}, [$sectionName, $sectionName];
     }      }
   
 }      }    
   
 sub end_section { return ''; }  sub end_section {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
   
       if ($target ne 'helper') {
           return '';
       }
       Apache::lonhelper::section->new();
   }    
 1;  1;
   
 package Apache::lonhelper::general;  package Apache::lonhelper::general;
Line 1919  sub end_eval { Line 2143  sub end_eval {
     Apache::lonhelper::message->new();      Apache::lonhelper::message->new();
 }  }
   
   1;
   
   package Apache::lonhelper::parmwizfinal;
   
   # This is the final state for the parmwizard. It is not generally useful,
   # so it is not perldoc'ed. It does its own processing.
   # It is represented with <parmwizfinal />, and
   # should later be moved to lonparmset.pm .
   
   no strict;
   @ISA = ('Apache::lonhelper::element');
   use strict;
   
   BEGIN {
       &Apache::lonhelper::register('Apache::lonhelper::parmwizfinal',
                                    ('parmwizfinal'));
   }
   
   use Time::localtime;
   
   sub new {
       my $ref = Apache::lonhelper::choices->new();
       bless ($ref);
   }
   
   sub start_parmwizfinal { return ''; }
   
   sub end_parmwizfinal {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
   
       if ($target ne 'helper') {
           return '';
       }
       Apache::lonhelper::parmwizfinal->new();
   }
   
   # Renders a form that, when submitted, will form the input to lonparmset.pm
   sub render {
       my $self = shift;
       my $vars = $helper->{VARS};
   
       # FIXME: Unify my designators with the standard ones
       my %dateTypeHash = ('open_date' => "Opening Date",
                           'due_date' => "Due Date",
                           'answer_date' => "Answer Date");
       my %parmTypeHash = ('open_date' => "0_opendate",
                           'due_date' => "0_duedate",
                           'answer_date' => "0_answerdate");
       
       my $result = "<form name='helpform' method='get' action='/adm/parmset'>\n";
       $result .= '<p>Confirm that this information is correct, then click &quot;Finish Wizard&quot; to complete setting the parameter.<ul>';
       my $affectedResourceId = "";
       my $parm_name = $parmTypeHash{$vars->{ACTION_TYPE}};
       my $level = "";
       
       # Print the type of manipulation:
       $result .= '<li>Setting the <b>' . $dateTypeHash{$vars->{ACTION_TYPE}}
                  . "</b></li>\n";
       if ($vars->{ACTION_TYPE} eq 'due_date' || 
           $vars->{ACTION_TYPE} eq 'answer_date') {
           # for due dates, we default to "date end" type entries
           $result .= "<input type='hidden' name='recent_date_end' " .
               "value='" . $vars->{PARM_DATE} . "' />\n";
           $result .= "<input type='hidden' name='pres_value' " . 
               "value='" . $vars->{PARM_DATE} . "' />\n";
           $result .= "<input type='hidden' name='pres_type' " .
               "value='date_end' />\n";
       } elsif ($vars->{ACTION_TYPE} eq 'open_date') {
           $result .= "<input type='hidden' name='recent_date_start' ".
               "value='" . $vars->{PARM_DATE} . "' />\n";
           $result .= "<input type='hidden' name='pres_value' " .
               "value='" . $vars->{PARM_DATE} . "' />\n";
           $result .= "<input type='hidden' name='pres_type' " .
               "value='date_start' />\n";
       } 
       
       # Print the granularity, depending on the action
       if ($vars->{GRANULARITY} eq 'whole_course') {
           $result .= '<li>for <b>all resources in the course</b></li>';
           $level = 9; # general course, see lonparmset.pm perldoc
           $affectedResourceId = "0.0";
       } elsif ($vars->{GRANULARITY} eq 'map') {
           my $navmap = Apache::lonnavmaps::navmap->new(
                              $ENV{"request.course.fn"}.".db",
                              $ENV{"request.course.fn"}."_parms.db", 0, 0);
           my $res = $navmap->getById($vars->{RESOURCE_ID});
           my $title = $res->compTitle();
           $navmap->untieHashes();
           $result .= "<li>for the map named <b>$title</b></li>";
           $level = 8;
           $affectedResourceId = $vars->{RESOURCE_ID};
       } else {
           my $navmap = Apache::lonnavmaps::navmap->new(
                              $ENV{"request.course.fn"}.".db",
                              $ENV{"request.course.fn"}."_parms.db", 0, 0);
           my $res = $navmap->getById($vars->{RESOURCE_ID});
           my $title = $res->compTitle();
           $navmap->untieHashes();
           $result .= "<li>for the resource named <b>$title</b></li>";
           $level = 7;
           $affectedResourceId = $vars->{RESOURCE_ID};
       }
   
       # Print targets
       if ($vars->{TARGETS} eq 'course') {
           $result .= '<li>for <b>all students in course</b></li>';
       } elsif ($vars->{TARGETS} eq 'section') {
           my $section = $vars->{SECTION_NAME};
           $result .= "<li>for section <b>$section</b></li>";
           $level -= 3;
           $result .= "<input type='hidden' name='csec' value='" .
               HTML::Entities::encode($section) . "' />\n";
       } else {
           # FIXME: This is probably wasteful! Store the name!
           my $classlist = Apache::loncoursedata::get_classlist();
           my $name = $classlist->{$vars->{USER_NAME}}->[6];
           $result .= "<li>for <b>$name</b></li>";
           $level -= 6;
           my ($uname, $udom) = split /:/, $vars->{USER_NAME};
           $result .= "<input type='hidden' name='uname' value='".
               HTML::Entities::encode($uname) . "' />\n";
           $result .= "<input type='hidden' name='udom' value='".
               HTML::Entities::encode($udom) . "' />\n";
       }
   
       # Print value
       $result .= "<li>to <b>" . ctime($vars->{PARM_DATE}) . "</b> (" .
           Apache::lonnavmaps::timeToHumanString($vars->{PARM_DATE}) 
           . ")</li>\n";
   
       # print pres_marker
       $result .= "\n<input type='hidden' name='pres_marker'" .
           " value='$affectedResourceId&$parm_name&$level' />\n";
   
       $result .= "<br /><br /><center><input type='submit' value='Finish Helper' /></center></form>\n";
   
       return $result;
   }
       
   sub overrideForm {
       return 1;
   }
   
 1;  1;
   

Removed from v.1.11  
changed lines
  Added in v.1.18


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>