--- loncom/interface/Attic/lonwizard.pm 2003/01/30 19:34:24 1.3 +++ loncom/interface/Attic/lonwizard.pm 2003/02/07 19:30:43 1.4 @@ -5,6 +5,7 @@ package Apache::lonwizard; use Apache::Constants qw(:common :http); use Apache::loncommon; +use Apache::lonnet; =head1 lonwizard - HTML "Wizard" framework for LON-CAPA @@ -253,6 +254,8 @@ HEADER } else { + $result .= '(): Returns a string representing the current state of the wizard, suitable for use directly as part of a query string. (See resource_state for an example.) + +=cut + +sub queryStringVars { + my $self = shift; + + my @queryString = (); + + for my $varname (keys %{$self->{VARS}}) { + push @queryString, Apache::lonnet::escape($varname) . "=" . + Apache::lonnet::escape($self->{VARS}{$varname}); + } + push @queryString, 'CURRENT_STATE=' . Apache::lonnet::escape($self->{STATE}); + push @queryString, 'RETURN_PAGE=' . Apache::lonnet::escape($self->{RETURN_PAGE}); + + return join '&', @queryString; +} + +=pod + =item B(): If a state calls this, the wizard will consider itself completed. The state should display a friendly "Done" message, and the wizard will display a link returning the user to the invoking page, rather then a "Next" button. =cut @@ -1081,10 +1105,12 @@ Note this state will not automatically a =over 4 -=item overriddent method B(parentLonWizReference, stateName, stateTitle, messageBefore, messageAfter, nextState, varName, filterFunction, choiceFunction): messageBefore and messageAfter appear before and after the state choice, respectively. nextState is the state to proceed to after the choice. varName is the wizard variable to store the choice in. +=item overriddent method B(parentLonWizReference, stateName, stateTitle, messageBefore, messageAfter, nextState, varName, filterFunction, choiceFunction, multichoice): messageBefore and messageAfter appear before and after the state choice, respectively. nextState is the state to proceed to after the choice. varName is the wizard variable to store the choice in. filterFunction is a function reference that receives the current resource as an argument, and returns 1 if it should be displayed, and 0 if it should not be displayed. By default, the class will use sub {return 1;}, which will show all resources. choiceFunction is a reference to a function that receives the resource object as a parameter and returns 1 if it should be a *selectable choice*, and 0 if not. By default, this is the same as the filterFunction, which means all displayed choices will be choosable. See parm wizard for an example of this in the resource selection routines. +multichoice specifies whether the state should provide radio buttons, allowing the user one choice, or checkboxes, allowing the user multiple choices, and automatically including some convenience buttons the user can choose (like "Check All" and "Uncheck All"), implemented with Javascript. Defaults to false, allow just one choice. + =back =cut @@ -1110,11 +1136,22 @@ sub new { if (!defined($self->{CHOICE_FUNC})) { $self->{CHOICE_FUNC} = $self->{FILTER_FUNC}; } + $self->{MULTICHOICE} = shift; + if (!defined($self->{MULTICHOICE})) { + $self->{MULTICHOICE} = 0; + } } sub postprocess { my $self = shift; my $wizard = $self->{WIZARD}; + + # If we were just manipulating a folder, do not proceed to the + # next state + if ($ENV{'form.folderManip'}) { + return; + } + my $chosenValue = $ENV{"form." . $self->{VAR_NAME} . ".forminput"}; $wizard->setVar($self->{VAR_NAME}, $chosenValue) if (defined($self->{VAR_NAME})); @@ -1124,9 +1161,18 @@ sub postprocess { sub render { my $self = shift; + my $wizard = $self->{WIZARD}; my $result = ""; my $var = $self->{VAR_NAME}; my $curVal = $self->{WIZARD}->{VARS}->{$var}; + my $vals = {}; + if ($curVal =~ /,/) { # multiple choices + foreach (split /,/, $curVal) { + $vals->{$_} = 1; + } + } else { + $vals->{$curVal} = 1; + } $result .= $self->{MESSAGE_BEFORE} if (defined $self->{MESSAGE_BEFORE}); @@ -1139,64 +1185,36 @@ sub render { return "Something has gone wrong with the map selection feature. Please contact your administrator."; } - my $iterator = $navmap->getIterator(undef, undef, undef, 1, 0); - my $depth = 1; - $iterator->next(); # discard first BEGIN_MAP - my $curRes = $iterator->next(); - my $i; - my $padding = "  "; - my $isChoosable = 0; + my $iterator = $navmap->getIterator(undef, undef, undef, 0, 0); my $filterFunc = $self->{FILTER_FUNC}; my $choiceFunc = $self->{CHOICE_FUNC}; - $result .= "\n"; - - while ($depth > 0) { - if ($curRes == $iterator->BEGIN_MAP()) { $depth++; } - if ($curRes == $iterator->END_MAP()) { $depth--; } - - if (ref($curRes) && &$filterFunc($curRes)) { - $result .= "'; + } else { + my $col = "\n"; + $col .= "value='" . $resource->{ID} . "' />"; + return $col; } + }; - $curRes = $iterator->next(); - } - - $result .= "
"; - - if (&$choiceFunc($curRes)) { - if (!$curVal) { - # Set this to the first one if they have no previous - # selection. - $curVal = $curRes->{ID}; - } - - $isChoosable = 1; - $result .= "{ID} eq $curVal) { - $result .= " checked"; - } - $result .= ' value="' . $curRes->{ID} . '" />'; - } - - $result .= ""; - - for ($i = 0; $i < $depth; $i++) { - $result .= $padding; + # Create the composite function that renders the column on the nav map + my $renderColFunc = sub { + my ($resource, $part, $params) = @_; + + if (!&$choiceFunc($resource)) { + return ' {$resource->{ID}}) { + $col .= "checked "; } - - #$result .= ""; - $result .= $curRes->compTitle . "
\n"; - + $result .= + &Apache::lonnavmaps::render( { "iterator" => $iterator, + 'cols' => [$renderColFunc, + Apache::lonnavmaps::resource()], + 'showParts' => 0, + 'queryString' => $wizard->queryStringVars() . '&folderManip=1', + 'url' => '/adm/wizard'} ); + $navmap->untieHashes(); - if (!$isChoosable) { - # FIXME: Check all the wiz vars for this. - $result .= "

There are no valid resources to select in this course. The entire course will be selected by default (as if 1you selected "Set for Whole Course" on the previous screen).

"; - $result .= "\n"; - } - - $result .= "

(Note: I need to add the icons in.)

"; $result .= $self->{MESSAGE_AFTER} if (defined $self->{MESSAGE_AFTER}); return $result;