version 1.136, 2003/02/04 16:37:51
|
version 1.139, 2003/02/06 22:58:12
|
Line 252 sub real_handler {
|
Line 252 sub real_handler {
|
return OK; |
return OK; |
} |
} |
|
|
# Grab a resource object so we have access to the constants; this |
my $res = "Apache::lonnavmaps::resource"; |
# is technically not proper, but should be harmless |
|
my $res = $navmap->firstResource(); |
|
|
|
# These are some data tables, which make it easy to change some of |
|
# of the specific visualization parameters if desired. |
|
|
|
my %condenseStatuses = |
|
( $res->NETWORK_FAILURE => 1, |
|
$res->NOTHING_SET => 1, |
|
$res->CORRECT => 1 ); |
|
|
|
my %filterHash; |
my %filterHash; |
# Figure out what we're not displaying |
# Figure out what we're not displaying |
Line 272 sub real_handler {
|
Line 262 sub real_handler {
|
} |
} |
} |
} |
|
|
# Is this a new-style course? If so, we want to suppress showing the top-level |
|
# maps in their own folders, in favor of "inlining" them. |
|
my $topResource = $navmap->getById("0.0"); |
|
|
|
# Begin the HTML table |
# Begin the HTML table |
# four cols: resource + indent, chat+feedback, icon, text string |
# four cols: resource + indent, chat+feedback, icon, text string |
$r->print('<table cellspacing="0" cellpadding="3" border="0" bgcolor="#FFFFFF">' ."\n"); |
$r->print('<table cellspacing="0" cellpadding="3" border="0" bgcolor="#FFFFFF">' ."\n"); |
Line 284 sub real_handler {
|
Line 270 sub real_handler {
|
# instead of uris. The changes to this and the main rendering |
# instead of uris. The changes to this and the main rendering |
# loop should be obvious. |
# loop should be obvious. |
# Here's a simple example of the iterator. |
# Here's a simple example of the iterator. |
# Preprocess the map: Look for current URL, force inlined maps to display |
# Preprocess the map: Look for current URL, open necessary maps |
|
|
my $mapIterator = $navmap->getIterator(undef, undef, undef, 1); |
my $mapIterator = $navmap->getIterator(undef, undef, undef, 1); |
my $found = 0; |
my $found = 0; |
Line 354 sub real_handler {
|
Line 340 sub real_handler {
|
$curRes = $mapIterator->next(); |
$curRes = $mapIterator->next(); |
} |
} |
|
|
undef $res; # so we don't accidentally use it later |
|
my $indentLevel = 0; |
|
my $indentString = "<img src='/adm/lonIcons/whitespace1.gif' width='25' height='1' alt='' border='0' />"; |
|
|
|
my $isNewBranch = 0; |
|
my $now = time(); |
|
my $in24Hours = $now + 24 * 60 * 60; |
|
my $displayedHereMarker = 0; |
|
my $displayedJumpMarker = 0; |
|
|
|
# We know the first thing is a BEGIN_MAP (see "$self->{STARTED}" |
|
# code in iterator->next), so ignore the first one |
|
$mapIterator = $navmap->getIterator(undef, undef, \%filterHash, |
|
$condition); |
|
$mapIterator->next(); |
|
$curRes = $mapIterator->next(); |
|
$depth = 1; |
|
|
|
my @backgroundColors = ("#FFFFFF", "#F6F6F6"); |
|
my $rowNum = 0; |
|
|
|
$counter = 0; |
|
|
|
while ($depth > 0) { |
|
if ($curRes == $mapIterator->BEGIN_MAP() || |
|
$curRes == $mapIterator->BEGIN_BRANCH()) { |
|
$indentLevel++; |
|
} |
|
if ($curRes == $mapIterator->END_MAP() || |
|
$curRes == $mapIterator->END_BRANCH()) { |
|
$indentLevel--; |
|
} |
|
if ($curRes == $mapIterator->BEGIN_BRANCH()) { |
|
$isNewBranch = 1; |
|
} |
|
if ($curRes == $mapIterator->BEGIN_MAP()) { $depth++; } |
|
if ($curRes == $mapIterator->END_MAP()) { $depth--; } |
|
|
|
if (ref($curRes)) { $counter++; } |
|
|
|
if (ref($curRes)) { |
|
|
|
my $deltalevel = $isNewBranch? 1 : 0; # reserves space for branch icon |
|
|
|
if ($indentLevel - $deltalevel < 0) { |
|
# If this would be at a negative depth (top-level maps in |
|
# new-style courses, we want to suppress their title display) |
|
# then ignore it. |
|
$curRes = $mapIterator->next(); |
|
next; |
|
} |
|
|
|
# Step one: Decide which parts to show |
|
my @parts = @{$curRes->parts()}; |
|
my $multipart = scalar(@parts) > 1; |
|
my $condensed = 0; |
|
|
|
if ($curRes->is_problem()) { |
|
|
|
# Is it multipart? |
|
if ($multipart) { |
|
# If it's multipart, see if part 0 is "open" |
|
# if it is, display all parts, if it isn't, |
|
# just display first |
|
if (!$curRes->opendate("0")) { |
|
# no parts are open, display as one part |
|
@parts = ("0"); |
|
$condensed = 1; |
|
} else { |
|
# Otherwise, only display part 0 if we want to |
|
# attach feedback or email information to it |
|
if ($curRes->hasDiscussion() || $curRes->getFeedback()) { |
|
# Is this right? I think this will toss it |
|
# if it DOES have discussion, not if it doesn't? |
|
# - Jeremy (yes, commenting on his own code) |
|
shift @parts; |
|
} else { |
|
# Now, we decide whether to condense the |
|
# parts due to similarity |
|
my $status = $curRes->status($parts[1]); |
|
my $due = $curRes->duedate($parts[1]); |
|
my $open = $curRes->opendate($parts[1]); |
|
my $statusAllSame = 1; |
|
my $dueAllSame = 1; |
|
my $openAllSame = 1; |
|
for (my $i = 2; $i < scalar(@parts); $i++) { |
|
if ($curRes->status($parts[$i]) != $status){ |
|
$statusAllSame = 0; |
|
} |
|
if ($curRes->duedate($parts[$i]) != $due ) { |
|
$dueAllSame = 0; |
|
} |
|
if ($curRes->opendate($parts[$i]) != $open) { |
|
$openAllSame = 0; |
|
} |
|
} |
|
|
|
# $*allSame is true if all the statuses were |
|
# the same. Now, if they are all the same and |
|
# match one of the statuses to condense, or they |
|
# are all open with the same due date, or they are |
|
# all OPEN_LATER with the same open date, display the |
|
# status of the first non-zero part (to get the 'correct' |
|
# status right, since 0 is never 'correct' or 'open'). |
|
if (($statusAllSame && defined($condenseStatuses{$status})) || |
|
($dueAllSame && $status == $curRes->OPEN && $statusAllSame)|| |
|
($openAllSame && $status == $curRes->OPEN_LATER && $statusAllSame) ){ |
|
@parts = ($parts[1]); |
|
$condensed = 1; |
|
} |
|
} |
|
} |
|
} |
|
|
|
} else { |
|
$parts[0] = "0"; # this is to get past foreach loop below |
|
# you can consider a non-problem resource as a resource |
|
# with only one part without loss, and it simplifies the looping |
|
} |
|
|
|
# Is it a multipart problem with a single part, now in |
|
# @parts with "0" filtered out? If so, 'forget' it's a multi-part |
|
# problem and treat it like a single-part problem. |
|
if ( scalar(@parts) == 1 ) { |
|
$multipart = 0; |
|
} |
|
|
|
# Display one part, in event of network error. |
|
# If this is a single part, we can at least show the correct |
|
# status, but if it's multipart, we're lost, since we can't |
|
# retreive the metadata to count the parts |
|
if ($curRes->{RESOURCE_ERROR}) { |
|
@parts = ("0"); |
|
} |
|
|
|
# Step Two: Print the actual data. |
|
|
|
# For each part we intend to display... |
|
foreach my $part (@parts) { |
|
|
|
my $nonLinkedText = ""; # unlinked stuff after title |
|
|
|
my $stack = $mapIterator->getStack(); |
|
my $src = getLinkForResource($stack); |
|
|
|
# Pass the correct symb on the querystring, so the |
|
# remote will figure out where we are if we click a link |
|
my $srcHasQuestion = $src =~ /\?/; |
|
my $link = $src. |
|
($srcHasQuestion?'&':'?') . |
|
'symb='.&Apache::lonnet::escape($curRes->symb()). |
|
'"'; |
|
|
|
my $title = $curRes->compTitle(); |
|
if ($src=~/^\/uploaded\//) { |
|
$nonLinkedText=$title; |
|
$title=''; |
|
} |
|
my $partLabel = ""; |
|
my $newBranchText = ""; |
|
|
|
# If this is a new branch, label it so |
|
if ($isNewBranch) { |
|
$newBranchText = "<img src=\"/adm/lonIcons/branch.gif\" border=\"0\">"; |
|
$isNewBranch = 0; |
|
} |
|
|
|
# links to open and close the folders |
|
my $linkopen = "<a href=\"$link\">"; |
|
my $linkclose = "</a>"; |
|
|
|
my $icon = "<img src=\"/adm/lonIcons/html.gif\" alt=\"\" border=\"0\" />"; |
|
if ($curRes->is_problem()) { |
|
if ($part eq "0" || $condensed) { |
|
$icon = '<img src="/adm/lonIcons/problem.gif" alt="" border=\"0\" />'; |
|
} else { |
|
$icon = $indentString; |
|
} |
|
} |
|
|
|
# Display the correct icon, link to open or shut map |
|
if ($curRes->is_map()) { |
|
my $mapId = $curRes->map_pc(); |
|
my $nowOpen = (!defined($filterHash{$mapId})); |
|
if ($condition) {$nowOpen = !$nowOpen;} |
|
$icon = $nowOpen ? |
|
"navmap.folder.closed.gif" : "navmap.folder.open.gif"; |
|
$icon = "<img src=\"/adm/lonIcons/$icon\" alt=\"\" border=\"0\" />"; |
|
$linkopen = "<a href=\"/adm/navmaps?filter="; |
|
$linkopen .= ($nowOpen xor $condition) ? |
|
addToFilter(\%filterHash, $mapId) : |
|
removeFromFilter(\%filterHash, $mapId); |
|
$linkopen .= "&condition=$condition&$queryAdd" . |
|
"&hereType=$hereType&here=" . |
|
Apache::lonnet::escape($here) . "&jumpType=".SYMB()."&" . |
|
"jump=" . Apache::lonnet::escape($curRes->symb()) ."\">"; |
|
$linkclose = "</a>"; |
|
|
|
} |
|
|
|
my $color; |
|
if ($curRes->is_problem()) { |
|
$color = $colormap{$curRes->status}; |
|
|
|
if (dueInLessThen24Hours($curRes, $part) || |
|
lastTry($curRes, $part)) { |
|
$color = $hurryUpColor; |
|
} |
|
} |
|
|
|
if ($curRes->randomout()) { |
|
$nonLinkedText .= ' <i>(hidden)</i> '; |
|
} |
|
|
|
$rowNum++; |
|
my $backgroundColor = $backgroundColors[$rowNum % scalar(@backgroundColors)]; |
|
|
|
# FIRST COL: The resource indentation, branch icon, name, and anchor |
|
$r->print(" <tr bgcolor=\"$backgroundColor\"><td align=\"left\" valign=\"center\">\n"); |
|
|
|
# Print the anchor if necessary |
|
if ($counter == $currentJumpIndex - $currentJumpDelta ) { |
|
$r->print('<a name="curloc" />'); |
|
$displayedJumpMarker = 1; |
|
} |
|
|
|
# print indentation |
|
for (my $i = 0; $i < $indentLevel - $deltalevel; $i++) { |
|
$r->print($indentString); |
|
} |
|
|
|
$r->print(" ${newBranchText}${linkopen}$icon${linkclose}\n"); |
|
|
|
my $curMarkerBegin = ""; |
|
my $curMarkerEnd = ""; |
|
|
|
# Is this the current resource? |
|
if (!$displayedHereMarker && |
|
(($hereType == SYMB() && $curRes->symb eq $here) || |
|
($hereType == URL() && $curRes->src eq $here))) { |
|
$curMarkerBegin = '<font color="red" size="+2">> </font>'; |
|
$curMarkerEnd = '<font color="red" size="+2"> <</font>'; |
|
$displayedHereMarker = 1; |
|
} |
|
|
|
if ($curRes->is_problem() && $part ne "0" && !$condensed) { |
|
$partLabel = " (Part $part)"; |
|
$title = ""; |
|
} |
|
if ($multipart && $condensed) { |
|
$nonLinkedText .= ' (' . $curRes->countParts() . ' parts)'; |
|
} |
|
|
|
$r->print(" $curMarkerBegin<a href=\"$link\">$title$partLabel</a> $curMarkerEnd $nonLinkedText"); |
|
|
|
#if ($curRes->{RESOURCE_ERROR}) { |
|
# $r->print(&Apache::loncommon::help_open_topic ("Navmap_Host_Down", |
|
# '<font size="-1">Host down</font>')); |
|
# } |
|
|
|
$r->print("</td>\n"); |
|
|
|
# SECOND COL: Is there text, feedback, errors?? |
|
my $discussionHTML = ""; my $feedbackHTML = ""; my $errorHTML = ""; |
|
|
|
if ($curRes->hasDiscussion()) { |
|
$discussionHTML = $linkopen . |
|
'<img border="0" src="/adm/lonMisc/chat.gif" />' . |
|
$linkclose; |
|
} |
|
|
|
if ($curRes->getFeedback()) { |
|
my $feedback = $curRes->getFeedback(); |
|
foreach (split(/\,/, $feedback)) { |
|
if ($_) { |
|
$feedbackHTML .= ' <a href="/adm/email?display=' |
|
. &Apache::lonnet::escape($_) . '">' |
|
. '<img src="/adm/lonMisc/feedback.gif" ' |
|
. 'border="0" /></a>'; |
|
} |
|
} |
|
} |
|
|
|
if ($curRes->getErrors()) { |
|
my $errors = $curRes->getErrors(); |
|
foreach (split(/,/, $errors)) { |
|
if ($_) { |
|
$errorHTML .= ' <a href="/adm/email?display=' |
|
. &Apache::lonnet::escape($_) . '">' |
|
. '<img src="/adm/lonMisc/bomb.gif" ' |
|
. 'border="0" /></a>'; |
|
} |
|
} |
|
} |
|
|
|
$r->print("<td width=\"75\" align=\"left\" valign=\"center\">$discussionHTML$feedbackHTML$errorHTML </td>"); |
|
|
|
# Is this the first displayed part of a multi-part problem |
|
# that has not been condensed, so we should suppress these two |
|
# columns so we don't display useless status info about part |
|
# "0"? |
|
my $firstDisplayed = !$condensed && $multipart && $part eq "0"; |
|
|
|
# THIRD COL: Problem status icon |
|
if ($curRes->is_problem() && |
|
!$firstDisplayed) { |
|
my $icon = $statusIconMap{$curRes->status($part)}; |
|
my $alt = $iconAltTags{$icon}; |
|
if ($icon) { |
|
$r->print("<td width=\"30\" valign=\"center\" width=\"50\" align=\"right\">$linkopen<img width=\"25\" height=\"25\" src=\"/adm/lonIcons/$icon\" border=\"0\" alt=\"$alt\" />$linkclose</td>\n"); |
|
} else { |
|
$r->print("<td width=\"30\"> </td>\n"); |
|
} |
|
} else { # not problem, no icon |
|
$r->print("<td width=\"30\"> </td>\n"); |
|
} |
|
|
|
# FOURTH COL: Text description |
|
$r->print("<td align=\"right\" valign=\"center\">\n"); |
|
|
|
if ($curRes->kind() eq "res" && |
|
$curRes->is_problem() && |
|
!$firstDisplayed) { |
|
$r->print ("<font color=\"$color\"><b>") if ($color); |
|
$r->print (getDescription($curRes, $part)); |
|
$r->print ("</b></font>") if ($color); |
|
} |
|
if ($curRes->is_map() && advancedUser() && $curRes->randompick()) { |
|
$r->print('(randomly select ' . $curRes->randompick() .')'); |
|
} |
|
|
|
$r->print(" </td></tr>\n"); |
|
|
|
if (!($counter % 20)) { $r->rflush(); } |
|
if ($counter == 2) { $r->rflush(); } |
|
} |
|
} |
|
$curRes = $mapIterator->next(); |
|
} |
|
|
|
$r->print("</table>"); |
|
|
|
# Print out the part that jumps to #curloc if it exists |
|
if ($displayedJumpMarker) { |
|
$r->print('<script>location += "#curloc";</script>'); |
|
} |
|
|
|
# renderer call |
# renderer call |
$mapIterator = $navmap->getIterator(undef, undef, \%filterHash, 0); |
$mapIterator = $navmap->getIterator(undef, undef, \%filterHash, 0); |
my $render = render({ 'cols' => [0,1,2,3], 'iterator' => $mapIterator, |
my $render = render({ 'cols' => [0,1,2,3], 'iterator' => $mapIterator, |
'url' => '/adm/navmaps', |
'url' => '/adm/navmaps', |
'queryString' => 'alreadyHere=1' }); |
'queryString' => 'alreadyHere=1', |
$r->print('|' . $render . '|'); |
'currentJumpIndex' => $currentJumpIndex}); |
|
$r->print($render); |
|
|
$navmap->untieHashes(); |
$navmap->untieHashes(); |
|
|
Line 1036 Note these functions are responsible for
|
Line 676 Note these functions are responsible for
|
|
|
=item * B<url>: The url the folders will link to, which should be the current page. Required if the resource info column is shown. |
=item * B<url>: The url the folders will link to, which should be the current page. Required if the resource info column is shown. |
|
|
|
=item * B<currentJumpIndex>: Describes the currently-open row number to cause the browser to jump to, because the user just opened that folder. |
|
|
|
=item * B<r>: The standard Apache response object. If you pass this to the render, it will use it to flush the table every 20 rows and handle the rendering itself. |
|
|
=back |
=back |
|
|
=head2 Additional Info |
=head2 Additional Info |
Line 1113 sub render_resource {
|
Line 757 sub render_resource {
|
. $params->{'hereType'} . '&here=' . |
. $params->{'hereType'} . '&here=' . |
&Apache::lonnet::escape($params->{'here'}) . |
&Apache::lonnet::escape($params->{'here'}) . |
'&jumpType=' . SYMB() . '&jump=' . |
'&jumpType=' . SYMB() . '&jump=' . |
&Apache::lonnet::escape($params->{$resource->symb()}) . "'>"; |
&Apache::lonnet::escape($resource->symb()) . "'>"; |
} |
} |
|
|
if ($resource->randomout()) { |
if ($resource->randomout()) { |
Line 1288 sub render {
|
Line 932 sub render {
|
my $jumpToSymb = $args->{'jumpToSymb'}; |
my $jumpToSymb = $args->{'jumpToSymb'}; |
my $hereURL = $args->{'hereURL'}; |
my $hereURL = $args->{'hereURL'}; |
my $hereSymb = $args->{'hereSymb'}; |
my $hereSymb = $args->{'hereSymb'}; |
|
# 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 $currentJumpIndex = setDefault($args->{'currentJumpIndex'}, 0); |
|
my $currentJumpDelta = 2; # change this to change how many resources are displayed |
|
# before the current resource when using #current |
|
my $r = $args->{'r'}; |
|
|
|
|
#if (defined($jumpToURL)) { |
|
# $args->{'jumpType'} = |
|
|
|
# End parameter setting |
# End parameter setting |
|
|
Line 1302 sub render {
|
Line 952 sub render {
|
$res->NOTHING_SET => 1, |
$res->NOTHING_SET => 1, |
$res->CORRECT => 1 ); |
$res->CORRECT => 1 ); |
my @backgroundColors = ("#FFFFFF", "#F6F6F6"); |
my @backgroundColors = ("#FFFFFF", "#F6F6F6"); |
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 |
|
|
|
# Shared variables |
# Shared variables |
$args->{'counter'} = 0; # counts the rows |
$args->{'counter'} = 0; # counts the rows |
Line 1445 sub render {
|
Line 1090 sub render {
|
my $srcHasQuestion = $src =~ /\?/; |
my $srcHasQuestion = $src =~ /\?/; |
$args->{"resourceLink"} = $src. |
$args->{"resourceLink"} = $src. |
($srcHasQuestion?'&':'?') . |
($srcHasQuestion?'&':'?') . |
'symb=' . &Apache::lonnet::escape($curRes->symb()). |
'symb=' . &Apache::lonnet::escape($curRes->symb()); |
'"'; |
|
|
|
# Now, display each column. |
# Now, display each column. |
foreach my $col (@$cols) { |
foreach my $col (@$cols) { |
|
my $colHTML = ''; |
|
if (ref($col)) { |
|
$colHTML .= &$col($curRes, $part, $args); |
|
} else { |
|
$colHTML .= &{$preparedColumns[$col]}($curRes, $part, $args); |
|
} |
|
|
# If this is the first column and it's time to print |
# If this is the first column and it's time to print |
# the anchor, do so |
# the anchor, do so |
if ($col == $cols->[0] && |
if ($col == $cols->[0] && |
$args->{'counter'} == $args->{'currentJumpIndex'} - |
$args->{'counter'} == $args->{'currentJumpIndex'} - |
$args->{'currentJumpDelta'}) { |
$currentJumpDelta) { |
$result .= '<a name="curloc" />'; |
# Jam the anchor after the <td> tag; |
|
# necessary for valid HTML (which Mozilla requires) |
|
$colHTML =~ s/\>/\>\<a name="curloc" \/\>/; |
$displayedJumpMarker = 1; |
$displayedJumpMarker = 1; |
} |
} |
|
$result .= $colHTML . "\n"; |
|
|
if (ref($col)) { |
|
$result .= &$col($curRes, $part, $args); |
|
} else { |
|
$result .= &{$preparedColumns[$col]}($curRes, $part, $args); |
|
} |
|
|
|
} |
} |
|
$result .= " </tr>\n"; |
$result .= " </tr>\n"; |
} |
|
|
|
if ($r && $rownum % 20 == 0) { |
|
$r->print($result); |
|
$result = ""; |
|
$r->rflush(); |
} |
} |
|
|
|
|
$curRes = $it->next(); |
$curRes = $it->next(); |
} |
} |
|
|
# Print out the part that jumps to #curloc if it exists |
# Print out the part that jumps to #curloc if it exists |
if ($args->{"displayedJumpMarker"}) { |
if ($displayedJumpMarker) { |
$result .= "<script>location += "#curloc";</script>\n"; |
$result .= "<script>location += \"#curloc\";</script>\n"; |
} |
} |
|
|
$result .= "</table>"; |
$result .= "</table>"; |
Line 2229 sub next {
|
Line 1878 sub next {
|
# If this is a blank resource, don't actually return it. |
# If this is a blank resource, don't actually return it. |
# Should you ever find you need it, make sure to add an option to the code |
# Should you ever find you need it, make sure to add an option to the code |
# that you can use; other things depend on this behavior. |
# that you can use; other things depend on this behavior. |
if (!$self->{HERE}->src() || !$self->{HERE}->browsePriv()) { |
my $browsePriv = $self->{HERE}->browsePriv(); |
|
if (!$self->{HERE}->src() || |
|
(!($browsePriv eq 'F') && !($browsePriv eq '2')) ) { |
return $self->next(); |
return $self->next(); |
} |
} |
|
|