--- loncom/interface/lonhelper.pm 2003/04/10 18:02:09 1.5 +++ loncom/interface/lonhelper.pm 2003/04/11 17:45:37 1.7 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # .helper XML handler to implement the LON-CAPA helper # -# $Id: lonhelper.pm,v 1.5 2003/04/10 18:02:09 bowersj2 Exp $ +# $Id: lonhelper.pm,v 1.7 2003/04/11 17:45:37 bowersj2 Exp $ # # Copyright Michigan State University Board of Trustees # @@ -62,8 +62,8 @@ of the helper itself, such as "Parameter =head2 State tags State tags are required to have an attribute "name", which is the symbolic -name of the state and will not be directly seen by the user. The wizard is -required to have one state named "START", which is the state the wizard +name of the state and will not be directly seen by the user. The helper is +required to have one state named "START", which is the state the helper will start with. By convention, this state should clearly describe what the helper will do for the user, and may also include the first information entry the user needs to do for the helper. @@ -95,12 +95,26 @@ use Apache::Constants qw(:common); use Apache::File; use Apache::lonxml; +# Register all the tags with the helper, so the helper can +# push and pop them + +my @helperTags; + +sub register { + my ($namespace, @tags) = @_; + + for my $tag (@tags) { + push @helperTags, [$namespace, $tag]; + } +} + BEGIN { - &Apache::lonxml::register('Apache::lonhelper', - ('helper', 'state')); + Apache::lonxml::register('Apache::lonhelper', + ('helper')); + register('Apache::lonhelper', ('state')); } -# Since all wizards are only three levels deep (wizard tag, state tag, +# Since all helpers are only three levels deep (helper tag, state tag, # substate type), it's easier and more readble to explicitly track # those three things directly, rather then futz with the tag stack # every time. @@ -145,7 +159,7 @@ sub handler { &Apache::lonxml::xmlparse($r, 'helper', $file); $r->print($helper->display()); - return OK; + return OK; } sub start_helper { @@ -154,6 +168,10 @@ sub start_helper { if ($target ne 'helper') { return ''; } + + for my $tagList (@helperTags) { + Apache::lonxml::register($tagList->[0], $tagList->[1]); + } $helper = Apache::lonhelper::helper->new($token->[2]{'title'}); return ''; @@ -165,7 +183,11 @@ sub end_helper { if ($target ne 'helper') { return ''; } - + + for my $tagList (@helperTags) { + Apache::lonxml::deregister($tagList->[0], $tagList->[1]); + } + return ''; } @@ -472,11 +494,26 @@ sub preprocess { } } +# FIXME: Document that all postprocesses must return a true value or +# the state transition will be overridden sub postprocess { my $self = shift; - + + # Save the state so we can roll it back if we need to. + my $originalState = $helper->{STATE}; + my $everythingSuccessful = 1; + for my $element (@{$self->{ELEMENTS}}) { - $element->postprocess(); + my $result = $element->postprocess(); + if (!$result) { $everythingSuccessful = 0; } + } + + # If not all the postprocesses were successful, override + # any state transitions that may have occurred. It is the + # responsibility of the states to make sure they have + # error handling in that case. + if (!$everythingSuccessful) { + $helper->{STATE} = $originalState; } } @@ -531,8 +568,8 @@ the helper variables, like this: =cut BEGIN { - &Apache::lonxml::register('Apache::lonhelper::element', - ('nextstate')); + &Apache::lonhelper::register('Apache::lonhelper::element', + ('nextstate')); } # Because we use the param hash, this is often a sufficent @@ -622,7 +659,7 @@ transition directly to the state in the This will display the HTML message and transition to the if -given. The HTML will be directly inserted into the wizard, so if you don't +given. The HTML will be directly inserted into the helper, so if you don't want text to run together, you'll need to manually wrap the in

tags, or whatever is appropriate for your HTML. @@ -642,7 +679,7 @@ no strict; use strict; BEGIN { - &Apache::lonxml::register('Apache::lonhelper::message', + &Apache::lonhelper::register('Apache::lonhelper::message', ('message', 'message_text')); } @@ -690,6 +727,8 @@ sub postprocess { if (defined($self->{NEXTSTATE})) { $helper->changeState($self->{NEXTSTATE}); } + + return 1; } 1; @@ -764,7 +803,7 @@ no strict; use strict; BEGIN { - &Apache::lonxml::register('Apache::lonhelper::choices', + &Apache::lonhelper::register('Apache::lonhelper::choices', ('choice', 'choices')); } @@ -826,7 +865,7 @@ sub render { my $result = ''; if ($self->{'multichoice'}) { - $result = < function checkall(value) { for (i=0; i -
+
  BUTTONS } if (defined $self->{ERROR_MSG}) { - $result .= '' . $self->{ERROR_MSG} . '

'; + $result .= '
' . $self->{ERROR_MSG} . '
'; } $result .= $buttons; - + $result .= "\n\n"; my $type = "radio"; @@ -878,6 +917,17 @@ sub postprocess { my $self = shift; my $chosenValue = $ENV{'form.' . $self->{'variable'} . '.forminput'}; + if (!$chosenValue) { + $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 (defined($self->{NEXTSTATE})) { $helper->changeState($self->{NEXTSTATE}); } @@ -889,6 +939,7 @@ sub postprocess { } } } + return 1; } 1; @@ -931,7 +982,7 @@ use strict; use Time::localtime; BEGIN { - &Apache::lonxml::register('Apache::lonhelper::date', + &Apache::lonhelper::register('Apache::lonhelper::date', ('date')); } @@ -1089,7 +1140,7 @@ sub postprocess { $checkDate->year + 1900 != $year) { $self->{ERROR_MSG} = "Can't use " . $months[$month] . " $day, $year as a " . "date because it doesn't exist. Please enter a valid date."; - return; + return 0; } $helper->{VARS}->{$var} = $chosenDate; @@ -1097,6 +1148,8 @@ sub postprocess { if (defined($self->{NEXTSTATE})) { $helper->changeState($self->{NEXTSTATE}); } + + return 1; } 1; @@ -1151,7 +1204,7 @@ no strict; use strict; BEGIN { - &Apache::lonxml::register('Apache::lonhelper::resource', + &Apache::lonhelper::register('Apache::lonhelper::resource', ('resource', 'filterfunc', 'choicefunc', 'valuefunc')); } @@ -1304,6 +1357,8 @@ sub postprocess { if (defined($self->{NEXTSTATE})) { $helper->changeState($self->{NEXTSTATE}); } + + return 1; } 1; @@ -1330,7 +1385,7 @@ use strict; BEGIN { - &Apache::lonxml::register('Apache::lonhelper::student', + &Apache::lonhelper::register('Apache::lonhelper::student', ('student')); } @@ -1434,6 +1489,27 @@ BUTTONS return $result; } +sub postprocess { + my $self = shift; + + my $result = $ENV{'form.' . $self->{'variable'} . '.forminput'}; + if (!$result) { + $self->{ERROR_MSG} = 'You must choose at least one student '. + 'to continue.'; + return 0; + } + + if ($self->{'multichoice'}) { + $self->process_multiple_choices($self->{'variable'}.'.forminput', + $self->{'variable'}); + } + if (defined($self->{NEXTSTATE})) { + $helper->changeState($self->{NEXTSTATE}); + } + + return 1; +} + 1; package Apache::lonhelper::files; @@ -1473,8 +1549,8 @@ no strict; use strict; BEGIN { - &Apache::lonxml::register('Apache::lonhelper::files', - ('files', 'filechoice', 'filefilter')); + &Apache::lonhelper::register('Apache::lonhelper::files', + ('files', 'filechoice', 'filefilter')); } sub new { @@ -1579,6 +1655,10 @@ BUTTONS $result .= $buttons; + if (defined $self->{ERROR_MSG}) { + $result .= '
' . $self->{ERROR_MSG} . '

'; + } + $result .= '
'; # Keeps track if there are no choices, prints appropriate error @@ -1621,6 +1701,13 @@ BUTTONS sub postprocess { my $self = shift; + my $result = $ENV{'form.' . $self->{'variable'} . '.forminput'}; + if (!$result) { + $self->{ERROR_MSG} = 'You must choose at least one file '. + 'to continue.'; + return 0; + } + if ($self->{'multichoice'}) { $self->process_multiple_choices($self->{'variable'}.'.forminput', $self->{'variable'}); @@ -1628,6 +1715,8 @@ sub postprocess { if (defined($self->{NEXTSTATE})) { $helper->changeState($self->{NEXTSTATE}); } + + return 1; } 1;