--- loncom/interface/lonhelper.pm 2003/04/30 15:18:36 1.13 +++ loncom/interface/lonhelper.pm 2003/05/05 18:05:21 1.19 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # .helper XML handler to implement the LON-CAPA helper # -# $Id: lonhelper.pm,v 1.13 2003/04/30 15:18:36 bowersj2 Exp $ +# $Id: lonhelper.pm,v 1.19 2003/05/05 18:05:21 bowersj2 Exp $ # # Copyright Michigan State University Board of Trustees # @@ -149,7 +149,11 @@ of the information used is persistent be 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. +lonxml; again, see lonprintout.pm for an example. In that case it is +imperative that you call B +before parsing XML fragments and B +when you are done. See lonprintout.pm for examples of this usage in the +printHelper subroutine. =cut @@ -202,8 +206,6 @@ sub handler { my $file; read $fh, $file, 100000000; - Apache::loncommon::get_unprocessed_cgi($ENV{QUERY_STRING}); - # Send header, don't cache this page if ($r->header_only) { if ($ENV{'browser.mathml'}) { @@ -324,6 +326,8 @@ sub new { $self->{STATE} = "START"; } + Apache::loncommon::get_unprocessed_cgi($ENV{QUERY_STRING}); + $self->{TOKEN} = $ENV{'form.TOKEN'}; # If a token was passed, we load that in. Otherwise, we need to create a # new storage file @@ -462,7 +466,7 @@ sub process { # Phase 2: Preprocess current state my $startState = $self->{STATE}; - my $state = $self->{STATES}{$startState}; + my $state = $self->{STATES}->{$startState}; # For debugging, print something here to determine if you're going # to an undefined state. @@ -473,10 +477,11 @@ sub process { # Phase 3: While the current state is different from the previous state, # keep processing. - while ( $startState ne $self->{STATE} ) + while ( $startState ne $self->{STATE} && + defined($self->{STATES}->{$self->{STATE}}) ) { $startState = $self->{STATE}; - $state = $self->{STATES}{$startState}; + $state = $self->{STATES}->{$startState}; $state->preprocess(); } @@ -495,6 +500,11 @@ sub display { my $result = ""; + if (!defined($state)) { + $result = "Error: state '$state' not defined!"; + return $result; + } + # Phase 4: Display. my $stateTitle = $state->title(); my $bodytag = &Apache::loncommon::bodytag("$self->{TITLE}",'',''); @@ -506,7 +516,7 @@ sub display { $bodytag HEADER - if (!$state->overrideForm()) { $result.="
"; } + if (!$state->overrideForm()) { $result.=""; } $result .= <

$stateTitle

@@ -740,22 +750,19 @@ sub process_multiple_choices { my $formname = shift; my $var = shift; - my $formvalue = $ENV{'form.' . $formname}; - if ($formvalue) { - # Must extract values from querystring 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; + # 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; } - $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; } @@ -990,17 +997,20 @@ sub render { if ($self->{'multichoice'}) { $result .= < - function checkall(value) { - for (i=0; i SCRIPT $buttons = < - - + +
  BUTTONS } @@ -1298,7 +1308,10 @@ the user can manipulate the folders. takes the standard variable attribute to control what helper 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 @@ -1358,6 +1371,8 @@ sub start_resource { $paramHash->{'variable'} = $token->[2]{'variable'}; $helper->declareVar($paramHash->{'variable'}); + $paramHash->{'multichoice'} = $token->[2]{'multichoice'}; + $paramHash->{'toponly'} = $token->[2]{'toponly'}; return ''; } @@ -1434,7 +1449,7 @@ sub start_mapurl { my $contents = Apache::lonxml::get_all_text('/mapurl', $parser); - $paramHash->{MAP_URL} = eval $contents; + $paramHash->{MAP_URL} = $contents; } sub end_mapurl { return ''; } @@ -1457,14 +1472,40 @@ sub render { my $var = $self->{'variable'}; my $curVal = $helper->{VARS}->{$var}; + my $buttons = ''; + + if ($self->{'multichoice'}) { + $result = < + function checkall(value, checkName) { + for (i=0; i +SCRIPT + $buttons = <   + + +
  +BUTTONS + } + if (defined $self->{ERROR_MSG}) { - $result .= '' . $self->{ERROR_MSG} . '

'; + $result .= '
' . $self->{ERROR_MSG} . '

'; } + $result .= $buttons; + my $filterFunc = $self->{FILTER_FUNC}; my $choiceFunc = $self->{CHOICE_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 # have to admit any language that lets me do this can't be all bad @@ -1472,12 +1513,16 @@ sub render { my $checked = 0; my $renderColFunc = sub { my ($resource, $part, $params) = @_; - + + my $inputType; + if ($multichoice) { $inputType = 'checkbox'; } + else {$inputType = 'radio'; } + if (!&$choiceFunc($resource)) { return ' '; } else { - my $col = "{'toponly'}; $result .= &Apache::lonnavmaps::render( { 'cols' => [$renderColFunc, Apache::lonnavmaps::resource()], @@ -1497,12 +1542,25 @@ sub render { 'resource_no_folder_link' => 1, 'iterator_map' => $mapUrl } ); + + $result .= $buttons; return $result; } 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; + } + if (defined($self->{NEXTSTATE})) { $helper->changeState($self->{NEXTSTATE}); } @@ -1572,21 +1630,25 @@ sub render { my $self = shift; my $result = ''; my $buttons = ''; + my $var = $self->{'variable'}; if ($self->{'multichoice'}) { $result = < - function checkall(value) { - for (i=0; i SCRIPT $buttons = < - - + +
BUTTONS } @@ -1627,7 +1689,7 @@ BUTTONS $checked = 1; } $result .= - " value='" . HTML::Entities::encode($_) + " value='" . HTML::Entities::encode($_ . ':' . $choices->{$_}->[$section]) . "' />" . HTML::Entities::encode($choices->{$_}->[$fullname]) . "" @@ -1777,20 +1839,20 @@ sub render { if ($self->{'multichoice'}) { $result = < - function checkall(value) { - for (i=0; i SCRIPT - my $buttons = <   - - + +
  BUTTONS } @@ -2130,7 +2192,7 @@ sub render { 'due_date' => "0_duedate", 'answer_date' => "0_answerdate"); - my $result = "\n"; + 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}};