--- loncom/interface/lonnavmaps.pm 2003/02/06 22:58:12 1.139
+++ loncom/interface/lonnavmaps.pm 2003/03/25 22:35:58 1.167
@@ -2,7 +2,7 @@
# The LearningOnline Network with CAPA
# Navigate Maps Handler
#
-# $Id: lonnavmaps.pm,v 1.139 2003/02/06 22:58:12 bowersj2 Exp $
+# $Id: lonnavmaps.pm,v 1.167 2003/03/25 22:35:58 albertel Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -38,17 +38,18 @@
# YEAR=2002
# 1/1 Gerd Kortemeyer
# Oct-Nov Jeremy Bowers
+# YEAR=2003
+# Jeremy Bowers ... lots of days
package Apache::lonnavmaps;
+use vars qw($test @refsToUntie %navmaphash %parmhash);
use strict;
use Apache::Constants qw(:common :http);
use Apache::loncommon();
+use Apache::lonmenu();
use POSIX qw (floor strftime);
-my %navmaphash;
-my %parmhash;
-
# symbolic constants
sub SYMB { return 1; }
sub URL { return 2; }
@@ -56,21 +57,23 @@ sub NOTHING { return 3; }
# Some data
+my $resObj = "Apache::lonnavmaps::resource";
+
# Keep these mappings in sync with lonquickgrades, which uses the colors
# instead of the icons.
my %statusIconMap =
- ( Apache::lonnavmaps::resource->NETWORK_FAILURE => '',
- Apache::lonnavmaps::resource->NOTHING_SET => '',
- Apache::lonnavmaps::resource->CORRECT => 'navmap.correct.gif',
- Apache::lonnavmaps::resource->EXCUSED => 'navmap.correct.gif',
- Apache::lonnavmaps::resource->PAST_DUE_NO_ANSWER => 'navmap.wrong.gif',
- Apache::lonnavmaps::resource->PAST_DUE_ANSWER_LATER => 'navmap.wrong.gif',
- Apache::lonnavmaps::resource->ANSWER_OPEN => 'navmap.wrong.gif',
- Apache::lonnavmaps::resource->OPEN_LATER => '',
- Apache::lonnavmaps::resource->TRIES_LEFT => 'navmap.open.gif',
- Apache::lonnavmaps::resource->INCORRECT => 'navmap.wrong.gif',
- Apache::lonnavmaps::resource->OPEN => 'navmap.open.gif',
- Apache::lonnavmaps::resource->ATTEMPTED => 'navmap.open.gif' );
+ ( $resObj->NETWORK_FAILURE => '',
+ $resObj->NOTHING_SET => '',
+ $resObj->CORRECT => 'navmap.correct.gif',
+ $resObj->EXCUSED => 'navmap.correct.gif',
+ $resObj->PAST_DUE_NO_ANSWER => 'navmap.wrong.gif',
+ $resObj->PAST_DUE_ANSWER_LATER => 'navmap.wrong.gif',
+ $resObj->ANSWER_OPEN => 'navmap.wrong.gif',
+ $resObj->OPEN_LATER => '',
+ $resObj->TRIES_LEFT => 'navmap.open.gif',
+ $resObj->INCORRECT => 'navmap.wrong.gif',
+ $resObj->OPEN => 'navmap.open.gif',
+ $resObj->ATTEMPTED => 'navmap.open.gif' );
my %iconAltTags =
( 'navmap.correct.gif' => 'Correct',
@@ -79,22 +82,26 @@ my %iconAltTags =
# Defines a status->color mapping, null string means don't color
my %colormap =
- ( Apache::lonnavmaps::resource->NETWORK_FAILURE => '',
- Apache::lonnavmaps::resource->CORRECT => '',
- Apache::lonnavmaps::resource->EXCUSED => '#3333FF',
- Apache::lonnavmaps::resource->PAST_DUE_ANSWER_LATER => '',
- Apache::lonnavmaps::resource->PAST_DUE_NO_ANSWER => '',
- Apache::lonnavmaps::resource->ANSWER_OPEN => '#006600',
- Apache::lonnavmaps::resource->OPEN_LATER => '',
- Apache::lonnavmaps::resource->TRIES_LEFT => '',
- Apache::lonnavmaps::resource->INCORRECT => '',
- Apache::lonnavmaps::resource->OPEN => '',
- Apache::lonnavmaps::resource->NOTHING_SET => '' );
+ ( $resObj->NETWORK_FAILURE => '',
+ $resObj->CORRECT => '',
+ $resObj->EXCUSED => '#3333FF',
+ $resObj->PAST_DUE_ANSWER_LATER => '',
+ $resObj->PAST_DUE_NO_ANSWER => '',
+ $resObj->ANSWER_OPEN => '#006600',
+ $resObj->OPEN_LATER => '',
+ $resObj->TRIES_LEFT => '',
+ $resObj->INCORRECT => '',
+ $resObj->OPEN => '',
+ $resObj->NOTHING_SET => '' );
# And a special case in the nav map; what to do when the assignment
# is not yet done and due in less then 24 hours
my $hurryUpColor = "#FF0000";
-
+$test = 'abc';
sub cleanup {
+ &Apache::lonnet::logthis("Cleanup called.");
+ &Apache::lonnet::logthis("refs size".scalar(@refsToUntie));
+ &Apache::lonnet::logthis("test is ".$test);
+ $test = '467';
if (tied(%navmaphash)){
&Apache::lonnet::logthis('Cleanup navmaps: navmaphash');
unless (untie(%navmaphash)) {
@@ -107,6 +114,15 @@ sub cleanup {
&Apache::lonnet::logthis('Failed cleanup navmaps: parmhash');
}
}
+ # Apparently, if you take a reference to a tied hash, both the
+ # original hash and the tied hash must be untied. Bleh.
+ for my $ref (@refsToUntie) {
+ &Apache::lonnet::logthis('Cleanup navmaps: reference');
+ unless (untie(%$ref)) {
+ &Apache::lonnet::logthis('Failed cleanup navmaps: reference');
+ }
+ }
+ @refsToUntie = ();
}
sub handler {
@@ -117,8 +133,6 @@ sub handler {
sub real_handler {
my $r = shift;
- &Apache::loncommon::get_unprocessed_cgi($ENV{QUERY_STRING});
-
# Handle header-only request
if ($r->header_only) {
if ($ENV{'browser.mathml'}) {
@@ -140,7 +154,7 @@ sub real_handler {
$r->send_http_header;
# Create the nav map
- my $navmap = Apache::lonnavmaps::navmap->new(
+ my $navmap = Apache::lonnavmaps::navmap->new($r,
$ENV{"request.course.fn"}.".db",
$ENV{"request.course.fn"}."_parms.db", 1, 1);
@@ -152,11 +166,22 @@ sub real_handler {
}
$r->print("
\n");
- $r->print("Navigate Course Contents");
+ $r->print("Navigate Course Contents");
+# ------------------------------------------------------------ Get query string
+ &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['register']);
+
+# ----------------------------------------------------- Force menu registration
+ my $addentries='';
+ if ($ENV{'form.register'}) {
+ $addentries=' onLoad="'.&Apache::lonmenu::loadevents().
+ '" onUnload="'.&Apache::lonmenu::unloadevents().'"';
+ $r->print(&Apache::lonmenu::registerurl(1));
+ }
# Header
- $r->print(&Apache::loncommon::bodytag('Navigate Course Contents','',
- ''));
+ $r->print(''.
+ &Apache::loncommon::bodytag('Navigate Course Contents','',
+ $addentries,'','',$ENV{'form.register'}));
$r->print('');
$r->rflush();
@@ -164,84 +189,6 @@ sub real_handler {
# Now that we've displayed some stuff to the user, init the navmap
$navmap->init();
- $r->print('');
-
- my $condition = 0;
- if ($ENV{'form.condition'}) {
- $condition = 1;
- }
-
- # Determine where the "here" marker is and where the screen jumps to.
- my $hereType; # the type of marker, SYMB, URL, or NOTHING
- my $here; # the actual URL or SYMB for the here marker
- my $jumpType; # The type of the thing we have a jump for, SYMB or URL
- my $jump; # the SYMB/URL of the resource we need to jump to
-
- if ( $ENV{'form.alreadyHere'} ) { # we came from a user's manipulation of the nav page
- # If this is a click on a folder or something, we want to preserve the "here"
- # from the querystring, and get the new "jump" marker
- $hereType = $ENV{'form.hereType'};
- $here = $ENV{'form.here'};
- $jumpType = $ENV{'form.jumpType'} || NOTHING();
- $jump = $ENV{'form.jump'};
- } else { # the user is visiting the nav map from the remote
- # We're coming from the remote. We have either a url, a symb, or nothing,
- # and we need to figure out what.
- # Preference: Symb
-
- if ($ENV{'form.symb'}) {
- $hereType = $jumpType = SYMB();
- $here = $jump = $ENV{'form.symb'};
- } elsif ($ENV{'form.postdata'}) {
- # couldn't find a symb, is there a URL?
- my $currenturl = $ENV{'form.postdata'};
- $currenturl=~s/^http\:\/\///;
- $currenturl=~s/^[^\/]+//;
-
- $hereType = $jumpType = URL;
- $here = $jump = $currenturl;
- } else {
- # Nothing
- $hereType = $jumpType = NOTHING();
- }
- }
-
-
- # alreadyHere allows us to only open the maps necessary to view
- # the current location once, while at the same time remembering
- # the current location. Without that check, the user would never
- # be able to close those maps; the user would close it, and the
- # currenturl scan would re-open it.
- my $queryAdd = "&alreadyHere=1";
-
- if ($condition) {
- $r->print("Close All Folders");
- } else {
- $r->print("Open All Folders");
- }
-
$r->print('
');
$r->rflush();
@@ -252,103 +199,51 @@ sub real_handler {
return OK;
}
- my $res = "Apache::lonnavmaps::resource";
-
- my %filterHash;
- # Figure out what we're not displaying
- foreach (split(/\,/, $ENV{"form.filter"})) {
- if ($_) {
- $filterHash{$_} = "1";
- }
- }
-
- # Begin the HTML table
- # four cols: resource + indent, chat+feedback, icon, text string
- $r->print('' ."\n");
-
- # This needs to be updated to use symbs from the remote,
- # instead of uris. The changes to this and the main rendering
- # loop should be obvious.
- # Here's a simple example of the iterator.
- # Preprocess the map: Look for current URL, open necessary maps
-
- my $mapIterator = $navmap->getIterator(undef, undef, undef, 1);
- my $found = 0;
+ # See if there's only one map in the top-level... if so,
+ # automatically display it
+ my $iterator = $navmap->getIterator(undef, undef, undef, 0);
my $depth = 1;
- my $currentJumpIndex = 0; # keeps track of when the current resource is found,
- # so we can back up a few and put the anchor above the
- # current resource
- my $currentJumpDelta = 2; # change this to change how many resources are displayed
- # before the current resource when using #current
- $mapIterator->next(); # discard the first BEGIN_MAP
- my $curRes = $mapIterator->next();
- my $counter = 0;
- my $foundJump = ($jumpType == NOTHING()); # look for jump point if we have one
- my $looped = 0;
-
- # We only need to do this if we need to open the maps to show the
- # current position. This will change the counter so we can't count
- # for the jump marker with this loop.
- while ($depth > 0 && !$ENV{'form.alreadyHere'}) {
- if ($curRes == $mapIterator->BEGIN_MAP()) { $depth++; }
- if ($curRes == $mapIterator->END_MAP()) { $depth--; }
+ $iterator->next();
+ my $curRes = $iterator->next();
+ my $sequenceCount = 0;
+ my $sequenceId;
+ while ($depth > 0) {
+ if ($curRes == $iterator->BEGIN_MAP()) { $depth++; }
+ if ($curRes == $iterator->END_MAP()) { $depth--; }
- if (ref($curRes) && !$ENV{'form.alreadyHere'} &&
- ($hereType == SYMB() && $curRes->symb() eq $here) ||
- (ref($curRes) && $hereType == URL() && $curRes->src() eq $here)) {
- my $mapStack = $mapIterator->getStack();
-
- # Ensure the parent maps are open
- for my $map (@{$mapStack}) {
- if ($condition) {
- undef $filterHash{$map->map_pc()};
- } else {
- $filterHash{$map->map_pc()} = 1;
- }
- }
- $ENV{'form.alreadyHere'} = 1;
+ if (ref($curRes) && $curRes->is_sequence()) {
+ $sequenceCount++;
+ $sequenceId = $curRes->map_pc();
}
- $looped = 1;
- $curRes = $mapIterator->next();
- }
-
- $mapIterator = $navmap->getIterator(undef, undef, \%filterHash, 0);
- $depth = 1;
- $mapIterator->next();
- $curRes = $mapIterator->next();
+ $curRes = $iterator->next();
+ }
- while ($depth > 0 && !$foundJump) {
- if ($curRes == $mapIterator->BEGIN_MAP()) { $depth++; }
- if ($curRes == $mapIterator->END_MAP()) { $depth--; }
- if (ref($curRes)) { $counter++; }
+ if ($sequenceCount == 1) {
+ # The automatic iterator creation in the render call
+ # will pick this up.
+ $ENV{'form.filter'} = "$sequenceId";
+ }
- if (ref($curRes) &&
- (($jumpType == SYMB() && $curRes->symb() eq $jump) ||
- ($jumpType == URL() && $curRes->src() eq $jump))) {
- # If this is the correct resource, be sure to
- # show it by making sure the containing maps
- # are open.
+ # renderer call
+ my $render = render({ 'cols' => [0,1,2,3],
+ 'url' => '/adm/navmaps',
+ 'suppressNavmap' => 1,
+ 'r' => $r});
- # This is why we have to use the main iterator instead of the
- # potentially faster DFS: The count has to be the same, so
- # the order has to be the same, which DFS won't give us.
- $currentJumpIndex = $counter;
- $foundJump = 1;
- }
+ #$navmap->untieHashes();
- $curRes = $mapIterator->next();
+ if (tied(%navmaphash)) {
+ $r->print("Dang it.");
+ } else {
+ $r->print("It's out.");
}
-
- # renderer call
- $mapIterator = $navmap->getIterator(undef, undef, \%filterHash, 0);
- my $render = render({ 'cols' => [0,1,2,3], 'iterator' => $mapIterator,
- 'url' => '/adm/navmaps',
- 'queryString' => 'alreadyHere=1',
- 'currentJumpIndex' => $currentJumpIndex});
- $r->print($render);
- $navmap->untieHashes();
+ if (tied(%parmhash)) {
+ $r->print("Dang it.");
+ } else {
+ $r->print("It's out.");
+ }
$r->print("