--- loncom/interface/lonhelper.pm 2003/05/08 19:52:43 1.25 +++ loncom/interface/lonhelper.pm 2003/05/15 16:14:52 1.30 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # .helper XML handler to implement the LON-CAPA helper # -# $Id: lonhelper.pm,v 1.25 2003/05/08 19:52:43 bowersj2 Exp $ +# $Id: lonhelper.pm,v 1.30 2003/05/15 16:14:52 bowersj2 Exp $ # # Copyright Michigan State University Board of Trustees # @@ -234,6 +234,7 @@ sub real_handler { my $file; read $fh, $file, 100000000; + # Send header, don't cache this page if ($r->header_only) { if ($ENV{'browser.mathml'}) { @@ -343,8 +344,6 @@ sub new { $self->{TITLE} = shift; - Apache::loncommon::get_unprocessed_cgi($ENV{QUERY_STRING}); - # If there is a state from the previous form, use that. If there is no # state, use the start state parameter. if (defined $ENV{"form.CURRENT_STATE"}) @@ -460,7 +459,11 @@ sub declareVar { my $envname = 'form.' . $var . '.forminput'; if (defined($ENV{$envname})) { - $self->{VARS}->{$var} = $ENV{$envname}; + if (ref($ENV{$envname})) { + $self->{VARS}->{$var} = join('|||', @{$ENV{$envname}}); + } else { + $self->{VARS}->{$var} = $ENV{$envname}; + } } } @@ -544,17 +547,44 @@ sub display { $bodytag HEADER - if (!$state->overrideForm()) { $result.="
"; } + if (!$state->overrideForm()) { $result.=""; } $result .= <

$stateTitle

HEADER + $result .= "
"; + if (!$state->overrideForm()) { $result .= $self->_saveVars(); } - $result .= $state->render() . "

 

"; + $result .= $state->render(); + + $result .= "
"; + + # Warning: Copy and pasted from below, because it's too much trouble to + # turn this into a subroutine + if (!$state->overrideForm()) { + $result .= '
'; + if ($self->{STATE} ne $self->{START_STATE}) { + #$result .= '  '; + } + if ($self->{DONE}) { + my $returnPage = $self->{RETURN_PAGE}; + $result .= "End Helper"; + } + else { + $result .= 'overrideForm()) { $result .= '
'; if ($self->{STATE} ne $self->{START_STATE}) { @@ -565,9 +595,9 @@ HEADER $result .= "End Helper"; } else { - $result .= '{VARS}->{$key} . "
"; #} + $result .= "
"; + $result .= < @@ -688,6 +720,7 @@ sub render { for my $element (@{$self->{ELEMENTS}}) { push @results, $element->render(); } + return join("\n", @results); } @@ -700,23 +733,8 @@ package Apache::lonhelper::element; =head2 Element Base Class -The Apache::lonhelper::element base class provides support methods for -the elements to use, such as a multiple value processer. - -B: - -=over 4 - -=item * process_multiple_choices(formName, varName): Process the form -element named "formName" and place the selected items into the helper -variable named varName. This is for things like checkboxes or -multiple-selection listboxes where the user can select more then -one entry. The selected entries are delimited by triple pipes in -the helper variables, like this: - - CHOICE_1|||CHOICE_2|||CHOICE_3 - -=back +The Apache::lonhelper::element base class provides support for elements +and defines some generally useful tags for use in elements. B @@ -830,28 +848,6 @@ sub overrideForm { return 0; } -sub process_multiple_choices { - my $self = shift; - my $formname = shift; - my $var = shift; - - # Must extract values from data directly, as there - # may be more then one. - my @values; - for my $formparam (split (/&/, $ENV{QUERY_STRING})) { - my ($name, $value) = split(/=/, $formparam); - 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); - - return; -} - 1; package Apache::lonhelper::message; @@ -960,6 +956,10 @@ the result is stored in. takes an attribute "multichoice" which, if set to a true value, will allow the user to select multiple choices. + takes an attribute "allowempty" which, if set to a true +value, will allow the user to select none of the choices without raising +an error message. + B can have the following subtags: @@ -1049,6 +1049,7 @@ sub start_choices { $paramHash->{'variable'} = $token->[2]{'variable'} if (!defined($paramHash->{'variable'})); $helper->declareVar($paramHash->{'variable'}); $paramHash->{'multichoice'} = $token->[2]{'multichoice'}; + $paramHash->{'allowempty'} = $token->[2]{'allowempty'}; $paramHash->{CHOICES} = []; return ''; } @@ -1193,15 +1194,14 @@ sub postprocess { my $self = shift; my $chosenValue = $ENV{'form.' . $self->{'variable'} . '.forminput'}; - if (!defined($chosenValue)) { + if (!defined($chosenValue) && !$self->{'allowempty'}) { $self->{ERROR_MSG} = "You must choose one or more choices to" . " continue."; return 0; } - if ($self->{'multichoice'}) { - $self->process_multiple_choices($self->{'variable'}.'.forminput', - $self->{'variable'}); + if (ref($chosenValue)) { + $helper->{VARS}->{$self->{'variable'}} = join('|||', @$chosenValue); } if (defined($self->{NEXTSTATE})) { @@ -1447,7 +1447,10 @@ variable stores the results. It also tak 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. +to false. The "suppressEmptySequences" attribute reflects the +suppressEmptySequences argument to the render routine, which will cause +folders that have all of their contained resources filtered out to also +be filtered out. B @@ -1508,6 +1511,7 @@ sub start_resource { $paramHash->{'variable'} = $token->[2]{'variable'}; $helper->declareVar($paramHash->{'variable'}); $paramHash->{'multichoice'} = $token->[2]{'multichoice'}; + $paramHash->{'suppressEmptySequences'} = $token->[2]{'suppressEmptySequences'}; $paramHash->{'toponly'} = $token->[2]{'toponly'}; return ''; } @@ -1676,6 +1680,7 @@ BUTTONS 'showParts' => 0, 'filterFunc' => $filterFunc, 'resource_no_folder_link' => 1, + 'suppressEmptySequences' => $self->{'suppressEmptySequences'}, 'iterator_map' => $mapUrl } ); @@ -1687,11 +1692,6 @@ BUTTONS sub postprocess { 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; @@ -1849,10 +1849,6 @@ sub postprocess { return 0; } - if ($self->{'multichoice'}) { - $self->process_multiple_choices($self->{'variable'}.'.forminput', - $self->{'variable'}); - } if (defined($self->{NEXTSTATE})) { $helper->changeState($self->{NEXTSTATE}); } @@ -2137,10 +2133,6 @@ sub postprocess { return 0; } - if ($self->{'multichoice'}) { - $self->process_multiple_choices($self->{'variable'}.'.forminput', - $self->{'variable'}); - } if (defined($self->{NEXTSTATE})) { $helper->changeState($self->{NEXTSTATE}); } @@ -2357,6 +2349,101 @@ sub end_eval { 1; +package Apache::lonhelper::final; + +=pod + +=head2 Element: final + + is a special element that works with helpers that use the +tag. It goes through all the states and elements, executing the +snippets and collecting the results. Finally, it takes the user out of the +helper, going to a provided page. + +=cut + +no strict; +@ISA = ("Apache::lonhelper::element"); +use strict; + +BEGIN { + &Apache::lonhelper::register('Apache::lonhelper::final', + ('final', 'exitpage')); +} + +sub new { + my $ref = Apache::lonhelper::element->new(); + bless($ref); +} + +sub start_final { return ''; } + +sub end_final { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; + + if ($target ne 'helper') { + return ''; + } + + Apache::lonhelper::final->new(); + + return ''; +} + +sub start_exitpage { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; + + if ($target ne 'helper') { + return ''; + } + + $paramHash->{EXIT_PAGE} = &Apache::lonxml::get_all_text('/exitpage', + $parser); + + return ''; +} + +sub end_exitpage { return ''; } + +sub render { + my $self = shift; + + my @results; + + # Collect all the results + for my $stateName (keys %{$helper->{STATES}}) { + my $state = $helper->{STATES}->{$stateName}; + + for my $element (@{$state->{ELEMENTS}}) { + if (defined($element->{FINAL_CODE})) { + # Compile the code. + my $code = 'sub { my $helper = shift; ' . $element->{FINAL_CODE} . + '}'; + $code = eval($code); + die 'Error while executing final code for element with var ' . + $element->{'variable'} . ', Perl said: ' . $@ if $@; + + my $result = &$code($helper); + if ($result) { + push @results, $result; + } + } + } + } + + if (scalar(@results) == 0) { + return ''; + } + + my $result = "
    \n"; + for my $re (@results) { + $result .= '
  • ' . $re . "
  • \n"; + } + return $result . '
'; +} + +1; + package Apache::lonhelper::parmwizfinal; # This is the final state for the parmwizard. It is not generally useful, @@ -2404,60 +2491,72 @@ sub render { 'due_date' => "0_duedate", 'answer_date' => "0_answerdate"); - my $result = "\n"; - $result .= '

Confirm that this information is correct, then click "Finish Wizard" to complete setting the parameter.

    '; my $affectedResourceId = ""; my $parm_name = $parmTypeHash{$vars->{ACTION_TYPE}}; my $level = ""; - - # Print the type of manipulation: - $result .= '
  • Setting the ' . $dateTypeHash{$vars->{ACTION_TYPE}} - . "
  • \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 .= "\n"; - $result .= "\n"; - $result .= "\n"; - } elsif ($vars->{ACTION_TYPE} eq 'open_date') { - $result .= "\n"; - $result .= "\n"; - $result .= "\n"; - } - + my $resourceString; + my $symb; + my $paramlevel; + # Print the granularity, depending on the action if ($vars->{GRANULARITY} eq 'whole_course') { - $result .= '
  • for all resources in the course
  • '; + $resourceString .= '
  • for all resources in the course
  • '; $level = 9; # general course, see lonparmset.pm perldoc $affectedResourceId = "0.0"; + $symb = 'a'; + $paramlevel = 'general'; } 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(); + $symb = $res->symb(); $navmap->untieHashes(); - $result .= "
  • for the map named $title
  • "; + $resourceString .= "
  • for the map named $title
  • "; $level = 8; $affectedResourceId = $vars->{RESOURCE_ID}; + $paramlevel = 'map'; } 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}); + $symb = $res->symb(); my $title = $res->compTitle(); $navmap->untieHashes(); - $result .= "
  • for the resource named $title
  • "; + $resourceString .= "
  • for the resource named $title
  • "; $level = 7; $affectedResourceId = $vars->{RESOURCE_ID}; + $paramlevel = 'full'; } + my $result = "\n"; + $result .= '

    Confirm that this information is correct, then click "Finish Wizard" to complete setting the parameter.

      '; + + # Print the type of manipulation: + $result .= '
    • Setting the ' . $dateTypeHash{$vars->{ACTION_TYPE}} + . "
    • \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 .= "\n"; + $result .= "\n"; + $result .= "\n"; + } elsif ($vars->{ACTION_TYPE} eq 'open_date') { + $result .= "\n"; + $result .= "\n"; + $result .= "\n"; + } + + $result .= $resourceString; + # Print targets if ($vars->{TARGETS} eq 'course') { $result .= '
    • for all students in course
    • '; @@ -2470,7 +2569,10 @@ sub render { } else { # FIXME: This is probably wasteful! Store the name! my $classlist = Apache::loncoursedata::get_classlist(); - my $name = $classlist->{$vars->{USER_NAME}}->[6]; + my $username = $vars->{USER_NAME}; + # Chop off everything after the last colon (section) + $username = substr($username, 0, rindex($username, ':')); + my $name = $classlist->{$username}->[6]; $result .= "
    • for $name
    • "; $level -= 6; my ($uname, $udom) = split /:/, $vars->{USER_NAME}; @@ -2488,6 +2590,12 @@ sub render { # print pres_marker $result .= "\n\n"; + + # Make the table appear + $result .= "\n"; + $result .= "\n"; + $result .= "\n"; + $result .= "\n"; $result .= "

      \n";