Diff for /loncom/interface/lonnavmaps.pm between versions 1.282 and 1.301

version 1.282, 2004/08/29 04:09:27 version 1.301, 2004/10/27 18:15:31
Line 35  use Apache::loncommon(); Line 35  use Apache::loncommon();
 use Apache::lonmenu();  use Apache::lonmenu();
 use Apache::lonlocal;  use Apache::lonlocal;
 use POSIX qw (floor strftime);  use POSIX qw (floor strftime);
 use Data::Dumper; # for debugging, not always used  use Data::Dumper; # for debugging, not always 
   
 # symbolic constants  # symbolic constants
 sub SYMB { return 1; }  sub SYMB { return 1; }
Line 127  sub nav_control_js { Line 127  sub nav_control_js {
   
 function gonav(url) {  function gonav(url) {
    if (w_loncapanav_flag != 1) {     if (w_loncapanav_flag != 1) {
       go(url);        gopost(url,'');
    }  else {     }  else {
       navwindow=window.open(url,        navwindow=window.open(url,
                   "loncapanav","height=600,width=400,scrollbars=1");                     "loncapanav","height=600,width=400,scrollbars=1"); 
Line 262  ENDSUBM Line 262  ENDSUBM
               &Apache::loncommon::bodytag('Navigate Course Contents','',                &Apache::loncommon::bodytag('Navigate Course Contents','',
   $addentries,$body_only,'',    $addentries,$body_only,'',
   $ENV{'form.register'}));    $ENV{'form.register'}));
     $r->print('<script>window.focus();</script>'.      $r->print('<script>window.focus();</script>');
       &Apache::loncommon::help_open_menu('','Navigation Screen','Navigation_Screen','',undef,'RAT'));  
             
     $r->rflush();      $r->rflush();
   
     # Check that it's defined      # Check that it's defined
     if (!($navmap->courseMapDefined())) {      if (!($navmap->courseMapDefined())) {
    $r->print(&Apache::loncommon::help_open_menu('','Navigation Screen','Navigation_Screen','',undef,'RAT'));
         $r->print('<font size="+2" color="red">Coursemap undefined.</font>' .          $r->print('<font size="+2" color="red">Coursemap undefined.</font>' .
                   '</body></html>');                    '</body></html>');
         return OK;          return OK;
Line 354  ENDSUBM Line 354  ENDSUBM
     } else {      } else {
  &add_linkitem(\%toplinkitems,'firsthomework',   &add_linkitem(\%toplinkitems,'firsthomework',
       'location.href="navmaps?jumpToFirstHomework"',        'location.href="navmaps?jumpToFirstHomework"',
       "Go To My First Homework Problem");        "Show Me My First Homework Problem");
     }      }
   
     my $suppressEmptySequences = 0;      my $suppressEmptySequences = 0;
Line 370  ENDSUBM Line 370  ENDSUBM
                             return $res->completable() || $res->is_map();                              return $res->completable() || $res->is_map();
                         };                          };
  &add_linkitem(\%toplinkitems,'everything',   &add_linkitem(\%toplinkitems,'everything',
      'location.href="locatnavmaps?sort='.$ENV{'form.sort'}.'"',       'location.href="navmaps?sort='.$ENV{'form.sort'}.'"',
       "Show Everything");        "Show Everything");
         $r->print("<p><font size='+2'>".&mt("Uncompleted Homework")."</font></p>");          $r->print("<p><font size='+2'>".&mt("Uncompleted Homework")."</font></p>");
         $ENV{'form.filter'} = '';          $ENV{'form.filter'} = '';
Line 392  ENDSUBM Line 392  ENDSUBM
                        <option value=\"default\" $selected{'default'}>".&mt('Default')."</option>                         <option value=\"default\" $selected{'default'}>".&mt('Default')."</option>
                        <option value=\"title\"   $selected{'title'}  >".&mt('Title')."</option>                         <option value=\"title\"   $selected{'title'}  >".&mt('Title')."</option>
                        <option value=\"duedate\" $selected{'duedate'}>".&mt('Duedate')."</option>                         <option value=\"duedate\" $selected{'duedate'}>".&mt('Duedate')."</option>
                          <option value=\"discussion\" $selected{'discussion'}>".&mt('Has Discussion')."</option>
                     </select>                      </select>
                  </nobr>                   </nobr>
                </form>");                 </form>");
     # renderer call      # renderer call
     my $renderArgs = { 'cols' => [0,2,3],      my $renderArgs = { 'cols' => [0,1,2,3],
        'sort' => $ENV{'form.sort'},         'sort' => $ENV{'form.sort'},
                        'url' => '/adm/navmaps',                         'url' => '/adm/navmaps',
                        'navmap' => $navmap,                         'navmap' => $navmap,
Line 409  ENDSUBM Line 410  ENDSUBM
                        'caller' => 'navmapsdisplay',                         'caller' => 'navmapsdisplay',
                        'linkitems' => \%toplinkitems};                         'linkitems' => \%toplinkitems};
     my $render = render($renderArgs);      my $render = render($renderArgs);
     $navmap->untieHashes();  
   
     # If no resources were printed, print a reassuring message so the      # If no resources were printed, print a reassuring message so the
     # user knows there was no error.      # user knows there was no error.
Line 1034  sub render_resource { Line 1034  sub render_resource {
   
     my $partLabel = "";      my $partLabel = "";
     my $newBranchText = "";      my $newBranchText = "";
           my $location=&Apache::loncommon::lonhttpdurl("/adm/lonIcons");
     # If this is a new branch, label it so      # If this is a new branch, label it so
     if ($params->{'isNewBranch'}) {      if ($params->{'isNewBranch'}) {
         $newBranchText = "<img src='/adm/lonIcons/branch.gif' border='0' />";          $newBranchText = "<img src='$location/branch.gif' border='0' />";
     }      }
   
     # links to open and close the folder      # links to open and close the folder
Line 1045  sub render_resource { Line 1045  sub render_resource {
     my $linkclose = "</a>";      my $linkclose = "</a>";
   
     # Default icon: unknown page      # Default icon: unknown page
     my $icon = "<img src='/adm/lonIcons/unknown.gif' alt='' border='0' />";      my $icon = "<img src='$location/unknown.gif' alt='' border='0' />";
           
     if ($resource->is_problem()) {      if ($resource->is_problem()) {
         if ($part eq '0' || $params->{'condensed'}) {          if ($part eq '0' || $params->{'condensed'}) {
             $icon = '<img src="/adm/lonIcons/problem.gif" alt="" border="0" />';              $icon ='<img src="'.$location.'/problem.gif" alt="" border="0" />';
         } else {          } else {
             $icon = $params->{'indentString'};              $icon = $params->{'indentString'};
         }          }
     } else {      } else {
  $icon = "<img src='".&Apache::loncommon::icon($resource->src).   $icon = "<img src='".&Apache::loncommon::lonhttpdurl(&Apache::loncommon::icon($resource->src))."' alt='' border='0' />";
     "' alt='' border='0' />";  
     }      }
   
     # Display the correct map icon to open or shut map      # Display the correct map icon to open or shut map
Line 1070  sub render_resource { Line 1069  sub render_resource {
   
         if (!$params->{'resource_no_folder_link'}) {          if (!$params->{'resource_no_folder_link'}) {
             $icon = "navmap.$folderType." . ($nowOpen ? 'closed' : 'open') . '.gif';              $icon = "navmap.$folderType." . ($nowOpen ? 'closed' : 'open') . '.gif';
             $icon = "<img src='/adm/lonIcons/$icon' alt='' border='0' />";              $icon = "<img src='$location/$icon' alt='' border='0' />";
   
             $linkopen = "<a href='" . $params->{'url'} . '?' .               $linkopen = "<a href='" . $params->{'url'} . '?' . 
                 $params->{'queryString'} . '&filter=';                  $params->{'queryString'} . '&filter=';
Line 1087  sub render_resource { Line 1086  sub render_resource {
             # Don't allow users to manipulate folder              # Don't allow users to manipulate folder
             $icon = "navmap.$folderType." . ($nowOpen ? 'closed' : 'open') .              $icon = "navmap.$folderType." . ($nowOpen ? 'closed' : 'open') .
                 '.nomanip.gif';                  '.nomanip.gif';
             $icon = "<img src='/adm/lonIcons/$icon' alt='' border='0' />";              $icon = "<img src='$location/$icon' alt='' border='0' />";
   
             $linkopen = "";              $linkopen = "";
             $linkclose = "";              $linkclose = "";
Line 1155  sub render_communication_status { Line 1154  sub render_communication_status {
     my $link = $params->{"resourceLink"};      my $link = $params->{"resourceLink"};
     my $linkopen = "<a href='$link'>";      my $linkopen = "<a href='$link'>";
     my $linkclose = "</a>";      my $linkclose = "</a>";
       my $location=&Apache::loncommon::lonhttpdurl("/adm/lonMisc");
     if ($resource->hasDiscussion()) {      if ($resource->hasDiscussion()) {
         $discussionHTML = $linkopen .          $discussionHTML = $linkopen .
             '<img border="0" src="/adm/lonMisc/chat.gif" />' .              '<img border="0" src="'.$location.'/chat.gif" />' .
             $linkclose;              $linkclose;
     }      }
           
Line 1168  sub render_communication_status { Line 1167  sub render_communication_status {
             if ($_) {              if ($_) {
                 $feedbackHTML .= '&nbsp;<a href="/adm/email?display='                  $feedbackHTML .= '&nbsp;<a href="/adm/email?display='
                     . &Apache::lonnet::escape($_) . '">'                      . &Apache::lonnet::escape($_) . '">'
                     . '<img src="/adm/lonMisc/feedback.gif" '                      . '<img src="'.$location.'/feedback.gif" '
                     . 'border="0" /></a>';                      . 'border="0" /></a>';
             }              }
         }          }
Line 1183  sub render_communication_status { Line 1182  sub render_communication_status {
                 $errorcount++;                  $errorcount++;
                 $errorHTML .= '&nbsp;<a href="/adm/email?display='                  $errorHTML .= '&nbsp;<a href="/adm/email?display='
                     . &Apache::lonnet::escape($_) . '">'                      . &Apache::lonnet::escape($_) . '">'
                     . '<img src="/adm/lonMisc/bomb.gif" '                      . '<img src="'.$location.'/bomb.gif" '
                     . 'border="0" /></a>';                      . 'border="0" /></a>';
             }              }
         }          }
Line 1212  sub render_quick_status { Line 1211  sub render_quick_status {
         my $icon = $statusIconMap{$resource->simpleStatus($part)};          my $icon = $statusIconMap{$resource->simpleStatus($part)};
         my $alt = $iconAltTags{$icon};          my $alt = $iconAltTags{$icon};
         if ($icon) {          if ($icon) {
             $result .= "<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";      my $location=
    &Apache::loncommon::lonhttpdurl("/adm/lonIcons/$icon");
               $result .= "<td width='30' valign='center' width='50' align='right'>$linkopen<img width='25' height='25' src='$location' border='0' alt='$alt' />$linkclose</td>\n";
         } else {          } else {
             $result .= "<td width='30'>&nbsp;</td>\n";              $result .= "<td width='30'>&nbsp;</td>\n";
         }          }
Line 1343  sub setDefault { Line 1344  sub setDefault {
     return $val;      return $val;
 }  }
   
   sub cmp_title {
       my ($atitle,$btitle) = (lc($_[0]->compTitle),lc($_[1]->compTitle));
       $atitle=~s/^\s*//;
       $btitle=~s/^\s*//;
       return $atitle cmp $btitle;
   }
   
 sub render {  sub render {
     my $args = shift;      my $args = shift;
     &Apache::loncommon::get_unprocessed_cgi($ENV{QUERY_STRING});      &Apache::loncommon::get_unprocessed_cgi($ENV{QUERY_STRING});
     my $result = '';      my $result = '';
   
     # Configure the renderer.      # Configure the renderer.
     my $cols = $args->{'cols'};      my $cols = $args->{'cols'};
     if (!defined($cols)) {      if (!defined($cols)) {
Line 1428  sub render { Line 1435  sub render {
         # We only need to do this if we need to open the maps to show the          # 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          # current position. This will change the counter so we can't count
         # for the jump marker with this loop.          # for the jump marker with this loop.
         while (($curRes = $mapIterator->next()) && !$found) {          while ($here && ($curRes = $mapIterator->next()) && !$found) {
             if (ref($curRes) && $curRes->symb() eq $here) {              if (ref($curRes) && $curRes->symb() eq $here) {
                 my $mapStack = $mapIterator->getStack();                  my $mapStack = $mapIterator->getStack();
                                   
Line 1504  sub render { Line 1511  sub render {
     my $printKey = $args->{'printKey'};      my $printKey = $args->{'printKey'};
     my $printCloseAll = $args->{'printCloseAll'};      my $printCloseAll = $args->{'printCloseAll'};
     if (!defined($printCloseAll)) { $printCloseAll = 1; }      if (!defined($printCloseAll)) { $printCloseAll = 1; }
       
     # Print key?      # Print key?
     if ($printKey) {      if ($printKey) {
         $result .= '<table border="0" cellpadding="2" cellspacing="0">';          $result .= '<table border="0" cellpadding="2" cellspacing="0">';
         my $date=localtime;          my $date=localtime;
         $result.='<tr><td align="right" valign="bottom">Key:&nbsp;&nbsp;</td>';          $result.='<tr><td align="right" valign="bottom">Key:&nbsp;&nbsp;</td>';
    my $location=&Apache::loncommon::lonhttpdurl("/adm/lonMisc");
         if ($navmap->{LAST_CHECK}) {          if ($navmap->{LAST_CHECK}) {
             $result .=               $result .= 
                 '<img src="/adm/lonMisc/chat.gif"> '.&mt('New discussion since').' '.                  '<img src="'.$location.'/chat.gif"> '.&mt('New discussion since').' '.
                 strftime("%A, %b %e at %I:%M %P", localtime($navmap->{LAST_CHECK})).                  strftime("%A, %b %e at %I:%M %P", localtime($navmap->{LAST_CHECK})).
                 '</td><td align="center" valign="bottom">&nbsp;&nbsp;'.                  '</td><td align="center" valign="bottom">&nbsp;&nbsp;'.
                 '<img src="/adm/lonMisc/feedback.gif"> '.&mt('New message (click to open)').'<p>'.                  '<img src="'.$location.'/feedback.gif"> '.&mt('New message (click to open)').'<p>'.
                 '</td>';                   '</td>'; 
         } else {          } else {
             $result .= '<td align="center" valign="bottom">&nbsp;&nbsp;'.              $result .= '<td align="center" valign="bottom">&nbsp;&nbsp;'.
                 '<img src="/adm/lonMisc/chat.gif"> '.&mt('Discussions').'</td><td align="center" valign="bottom">'.                  '<img src="'.$location.'/chat.gif"> '.&mt('Discussions').'</td><td align="center" valign="bottom">'.
                 '&nbsp;&nbsp;<img src="/adm/lonMisc/feedback.gif"> '.&mt('New message (click to open)').                  '&nbsp;&nbsp;<img src="'.$location.'/feedback.gif"> '.&mt('New message (click to open)').
                 '</td>';                   '</td>'; 
         }          }
   
Line 1549  sub render { Line 1557  sub render {
   
     # Check for any unread discussions in all resources.      # Check for any unread discussions in all resources.
     if ($args->{'caller'} eq 'navmapsdisplay') {      if ($args->{'caller'} eq 'navmapsdisplay') {
  my $totdisc = 0;   &add_linkitem($args->{'linkitems'},'clearbubbles',
  my $haveDisc = '';        'document.clearbubbles.submit()',
  my @allres=$navmap->retrieveResources();        'Mark all posts read');
  foreach my $resource (@allres) {   my $time=time;
     if ($resource->hasDiscussion()) {   $result .= (<<END);
  my $ressymb;      <form name="clearbubbles" method="post" action="/adm/feedback">
  if ($resource->symb() =~ m-(___adm/\w+/\w+)/(\d+)/bulletinboard$-) {   <input type="hidden" name="navurl" value="$ENV{'QUERY_STRING'}" />
     $ressymb = 'bulletin___'.$2.$1.'/'.$2.'/bulletinboard';   <input type="hidden" name="navtime" value="$time" />
  } else {  END
     $ressymb = $resource->symb();          if ($args->{'sort'} eq 'discussion') { 
       my $totdisc = 0;
       my $haveDisc = '';
       my @allres=$navmap->retrieveResources();
       foreach my $resource (@allres) {
    if ($resource->hasDiscussion()) {
       my $ressymb;
       if ($resource->symb() =~ m-(___adm/\w+/\w+)/(\d+)/bulletinboard$-) {
    $ressymb = 'bulletin___'.$2.$1.'/'.$2.'/bulletinboard';
       } else {
    $ressymb = $resource->symb();
       }
       $haveDisc .= $ressymb.':';
       $totdisc ++;
  }   }
  $haveDisc .= $ressymb.':';  
  $totdisc ++;  
     }      }
  }      if ($totdisc > 0) {
  if ($totdisc > 0) {   $haveDisc =~ s/:$//;
     $haveDisc =~ s/:$//;   $result .= (<<END);
             my $navurl = $ENV{'QUERY_STRING'};   <input type="hidden" name="navmaps" value="$haveDisc" />
     &add_linkitem($args->{'linkitems'},'clearbubbles',      </form>
   'document.clearbubbles.submit()',  
   'Mark all posts read');  
             $result .= (<<END);  
  <form name="clearbubbles" method="post" action="/adm/feedback">  
  <input type="hidden" name="navurl" value="$ENV{'QUERY_STRING'}" />  
  <input type="hidden" name="navmaps" value="$haveDisc" />  
  </form>  
 END  END
               }
  }   }
    $result.='</form>';
     }      }
   
     if ($args->{'caller'} eq 'navmapsdisplay') {      if ($args->{'caller'} eq 'navmapsdisplay') {
           $result .= '<table><tr><td>'.
                      &Apache::loncommon::help_open_menu('','Navigation Screen','Navigation_Screen','',undef,'RAT').'</td>';
    if ($ENV{'environment.remotenavmap'} ne 'on') {
       $result .= '<td>&nbsp;</td>'; 
           } else {
       $result .= '</tr><tr>'; 
           }
  $result.=&show_linkitems($args->{'linkitems'});   $result.=&show_linkitems($args->{'linkitems'});
         if ($args->{'sort_html'}) {          if ($args->{'sort_html'}) {
     if ($ENV{'environment.remotenavmap'} ne 'on') {      if ($ENV{'environment.remotenavmap'} ne 'on') {
Line 1617  END Line 1638  END
     $args->{'indentLevel'} = 0;      $args->{'indentLevel'} = 0;
     $args->{'isNewBranch'} = 0;      $args->{'isNewBranch'} = 0;
     $args->{'condensed'} = 0;          $args->{'condensed'} = 0;    
     $args->{'indentString'} = setDefault($args->{'indentString'}, "<img src='/adm/lonIcons/whitespace1.gif' width='25' height='1' alt='' border='0' />");      my $location=
    &Apache::loncommon::lonhttpdurl("/adm/lonIcons/whitespace1.gif");
       $args->{'indentString'} = setDefault($args->{'indentString'}, "<img src='$location' width='25' height='1' alt='' border='0' />");
     $args->{'displayedHereMarker'} = 0;      $args->{'displayedHereMarker'} = 0;
   
     # If we're suppressing empty sequences, look for them here. Use DFS for speed,      # If we're suppressing empty sequences, look for them here. Use DFS for speed,
Line 1678  END Line 1701  END
  return &$oldFilterFunc($res);   return &$oldFilterFunc($res);
     };      };
  @resources=$navmap->retrieveResources(undef,$filterFunc);   @resources=$navmap->retrieveResources(undef,$filterFunc);
  @resources= sort {lc($a->compTitle) cmp lc($b->compTitle)} @resources;   @resources= sort { &cmp_title($a,$b) } @resources;
     } elsif ($args->{'sort'} eq 'duedate') {      } elsif ($args->{'sort'} eq 'duedate') {
  @resources=$navmap->retrieveResources(undef,   my $oldFilterFunc = $filterFunc;
        sub { shift->is_problem(); });   my $filterFunc= 
  @resources= sort      sub {
  {   my ($res)=@_;
    if (!$res->is_problem()) { return 0;}
    return &$oldFilterFunc($res);
       };
    @resources=$navmap->retrieveResources(undef,$filterFunc);
    @resources= sort {
     if ($a->duedate ne $b->duedate) {      if ($a->duedate ne $b->duedate) {
         return $a->duedate cmp $b->duedate;          return $a->duedate cmp $b->duedate;
     } else {  
  lc($a->compTitle) cmp lc($b->compTitle)  
     }      }
       my $value=&cmp_title($a,$b);
       return $value;
  } @resources;   } @resources;
       } elsif ($args->{'sort'} eq 'discussion') {
    my $oldFilterFunc = $filterFunc;
    my $filterFunc= 
       sub {
    my ($res)=@_;
    if (!$res->hasDiscussion() &&
       !$res->getFeedback() &&
       !$res->getErrors()) { return 0;}
    return &$oldFilterFunc($res);
       };
    @resources=$navmap->retrieveResources(undef,$filterFunc);
    @resources= sort { &cmp_title($a,$b) } @resources;
     } else {      } else {
  #unknow sort mechanism or default   #unknow sort mechanism or default
  undef($args->{'sort'});   undef($args->{'sort'});
Line 1899  if (location.href.indexOf('#curloc')==-1 Line 1939  if (location.href.indexOf('#curloc')==-1
         $r->rflush();          $r->rflush();
     }      }
                   
     if ($mustCloseNavMap) { $navmap->untieHashes(); }   
   
     return $result;      return $result;
 }  }
   
Line 1916  sub show_linkitems { Line 1954  sub show_linkitems {
      "uncompleted","changefolder","clearbubbles");       "uncompleted","changefolder","clearbubbles");
           
     my $result .= (<<ENDBLOCK);      my $result .= (<<ENDBLOCK);
                 <td align="left">
 <script type="text/javascript">  <script type="text/javascript">
     function changeNavDisplay () {      function changeNavDisplay () {
  var navchoice = document.linkitems.toplink[document.linkitems.toplink.selectedIndex].value;   var navchoice = document.linkitems.toplink[document.linkitems.toplink.selectedIndex].value;
Line 1926  ENDBLOCK Line 1965  ENDBLOCK
     }      }
     $result.='}      $result.='}
               </script>                </script>
               <table><tr><td align="left">  
                    <form name="linkitems" method="post">                     <form name="linkitems" method="post">
                        <nobr><select name="toplink">'."\n";                         <nobr><select name="toplink">'."\n";
     foreach my $link (@linkorder) {      foreach my $link (@linkorder) {
Line 1940  ENDBLOCK Line 1978  ENDBLOCK
     $result .= '</select>&nbsp;<input type="button" name="chgnav"      $result .= '</select>&nbsp;<input type="button" name="chgnav"
                    value="Go" onClick="javascript:changeNavDisplay()" />                     value="Go" onClick="javascript:changeNavDisplay()" />
                 </nobr></form></td>'."\n";                  </nobr></form></td>'."\n";
   
     return $result;      return $result;
 }  }
   
Line 2000  successful, or B<undef> if not. Line 2039  successful, or B<undef> if not.
   
 =back  =back
   
 When you are done with the $navmap object, you I<must> call   
 $navmap->untieHashes(), or you'll prevent the current user from using that   
 course until the web server is restarted. (!)  
   
 =head2 Methods  =head2 Methods
   
 =over 4  =over 4
Line 2149  sub generate_email_discuss_status { Line 2184  sub generate_email_discuss_status {
           
     foreach my $msgid (split(/\&/, $keys)) {      foreach my $msgid (split(/\&/, $keys)) {
  $msgid=&Apache::lonnet::unescape($msgid);   $msgid=&Apache::lonnet::unescape($msgid);
  my $plain=&Apache::lonnet::unescape(&Apache::lonnet::unescape($msgid));   if ((!$emailstatus{$msgid}) || ($emailstatus{$msgid} eq 'new')) {
  if ($plain=~/(Error|Feedback) \[([^\]]+)\]/) {      my $plain=
     my ($what,$url)=($1,$2);   &Apache::lonnet::unescape(&Apache::lonnet::unescape($msgid));
     my %status=      if ($plain=~/(Error|Feedback) \[([^\]]+)\]/) {
  &Apache::lonnet::get('email_status',[$msgid]);   my ($what,$url)=($1,$2);
     if ($status{$msgid}=~/^error\:/) {   
  $status{$msgid}='';   
     }  
       
     if (($status{$msgid} eq 'new') ||   
  (!$status{$msgid})) {   
  if ($what eq 'Error') {   if ($what eq 'Error') {
     $error{$url}.=','.$msgid;       $error{$url}.=','.$msgid; 
  } else {   } else {
Line 2169  sub generate_email_discuss_status { Line 2198  sub generate_email_discuss_status {
  }   }
     }      }
           
       #url's of resources that have feedbacks
     $self->{FEEDBACK} = \%feedback;      $self->{FEEDBACK} = \%feedback;
     $self->{ERROR_MSG} = \%error; # what is this? JB      #or errors
       $self->{ERROR_MSG} = \%error;
     $self->{DISCUSSION_TIME} = \%discussiontime;      $self->{DISCUSSION_TIME} = \%discussiontime;
     $self->{EMAIL_STATUS} = \%emailstatus;      $self->{EMAIL_STATUS} = \%emailstatus;
     $self->{LAST_READ} = \%lastreadtime;      $self->{LAST_READ} = \%lastreadtime;
Line 2224  sub getIterator { Line 2255  sub getIterator {
     return $iterator;      return $iterator;
 }  }
   
 # unties the hash when done  
 sub untieHashes {  
     my $self = shift;  
     untie %{$self->{NAV_HASH}};  
     untie %{$self->{PARM_HASH}};  
 }  
   
 # Private method: Does the given resource (as a symb string) have  # Private method: Does the given resource (as a symb string) have
 # current discussion? Returns 0 if chat/mail data not extracted.  # current discussion? Returns 0 if chat/mail data not extracted.
 sub hasDiscussion {  sub hasDiscussion {
Line 2611  sub hasResource { Line 2635  sub hasResource {
 1;  1;
   
 package Apache::lonnavmaps::iterator;  package Apache::lonnavmaps::iterator;
   use WeakRef;
 =pod  =pod
   
 =back  =back
Line 2751  sub new { Line 2775  sub new {
     my $class = ref($proto) || $proto;      my $class = ref($proto) || $proto;
     my $self = {};      my $self = {};
   
     $self->{NAV_MAP} = shift;      weaken($self->{NAV_MAP} = shift);
     return undef unless ($self->{NAV_MAP});      return undef unless ($self->{NAV_MAP});
   
     # Handle the parameters      # Handle the parameters
Line 3087  sub populateStack { Line 3111  sub populateStack {
 1;  1;
   
 package Apache::lonnavmaps::DFSiterator;  package Apache::lonnavmaps::DFSiterator;
   use WeakRef;
 # Not documented in the perldoc: This is a simple iterator that just walks  # Not documented in the perldoc: This is a simple iterator that just walks
 #  through the nav map and presents the resources in a depth-first search  #  through the nav map and presents the resources in a depth-first search
 #  fashion, ignorant of conditionals, randomized resources, etc. It presents  #  fashion, ignorant of conditionals, randomized resources, etc. It presents
Line 3115  sub new { Line 3139  sub new {
     my $class = ref($proto) || $proto;      my $class = ref($proto) || $proto;
     my $self = {};      my $self = {};
   
     $self->{NAV_MAP} = shift;      weaken($self->{NAV_MAP} = shift);
     return undef unless ($self->{NAV_MAP});      return undef unless ($self->{NAV_MAP});
   
     $self->{FIRST_RESOURCE} = shift || $self->{NAV_MAP}->firstResource();      $self->{FIRST_RESOURCE} = shift || $self->{NAV_MAP}->firstResource();
Line 3269  sub populateStack { Line 3293  sub populateStack {
 1;  1;
   
 package Apache::lonnavmaps::resource;  package Apache::lonnavmaps::resource;
   use WeakRef;
 use Apache::lonnet;  use Apache::lonnet;
   
 =pod  =pod
Line 3351  sub new { Line 3375  sub new {
     my $class = ref($proto) || $proto;      my $class = ref($proto) || $proto;
     my $self = {};      my $self = {};
   
     $self->{NAV_MAP} = shift;      weaken($self->{NAV_MAP} = shift);
     $self->{ID} = shift;      $self->{ID} = shift;
   
     # Store this new resource in the parent nav map's cache.      # Store this new resource in the parent nav map's cache.
Line 3472  sub title { Line 3496  sub title {
     return $self->navHash("title_", 1); }      return $self->navHash("title_", 1); }
 # considered private and undocumented  # considered private and undocumented
 sub to { my $self=shift; return $self->navHash("to_", 1); }  sub to { my $self=shift; return $self->navHash("to_", 1); }
   sub condition {
       my $self=shift;
       my $undercond=$self->navHash("undercond_", 1);
       if (!defined($undercond)) { return 1; };
       my $condid=$self->navHash("condid_$undercond");
       if (!defined($condid)) { return 1; };
       my $condition=&Apache::lonnet::directcondval($condid);
       return $condition;
   }
   
 sub compTitle {  sub compTitle {
     my $self = shift;      my $self = shift;
     my $title = $self->title();      my $title = $self->title();
Line 3893  Returns the number of parts of the probl Line 3927  Returns the number of parts of the probl
 for single part problems, returns 1. For multipart, it returns the  for single part problems, returns 1. For multipart, it returns the
 number of parts in the problem, not including psuedo-part 0.   number of parts in the problem, not including psuedo-part 0. 
   
   =item * B<countResponses>():
   
   Returns the total number of responses in the problem a student can answer.
   
   =item * B<responseTypes>():
   
   Returns a hash whose keys are the response types.  The values are the number 
   of times each response type is used.  This is for the I<entire> problem, not 
   just a single part.
   
 =item * B<multipart>():  =item * B<multipart>():
   
 Returns true if the problem is multipart, false otherwise. Use this instead  Returns true if the problem is multipart, false otherwise. Use this instead
Line 3939  sub countParts { Line 3983  sub countParts {
     return scalar(@{$parts}); # + $delta;      return scalar(@{$parts}); # + $delta;
 }  }
   
   sub countResponses {
       my $self = shift;
       my $count;
       foreach my $part (@{$self->parts()}) {
           $count+= scalar($self->responseIds($part));
       }
       return $count;
   }
   
   sub responseTypes {
       my $self = shift;
       my %responses;
       foreach my $part ($self->parts()) {
           foreach my $responsetype ($self->responseType($part)) {
               $responses{$responsetype}++ if (defined($responsetype));
           }
       }
       return %responses;
   }
   
 sub multipart {  sub multipart {
     my $self = shift;      my $self = shift;
     return $self->countParts() > 1;      return $self->countParts() > 1;
Line 4026  sub extractParts { Line 4090  sub extractParts {
         }          }
                   
   
           # These hashes probably do not need names that end with "Hash"....
         my %responseIdHash;          my %responseIdHash;
         my %responseTypeHash;          my %responseTypeHash;
   
Line 4061  sub extractParts { Line 4126  sub extractParts {
             }              }
         }          }
  my $resorder = &Apache::lonnet::metadata($self->src(),'responseorder');   my $resorder = &Apache::lonnet::metadata($self->src(),'responseorder');
           #
           # Reorder the arrays in the %responseIdHash and %responseTypeHash
  if ($resorder) {   if ($resorder) {
     my @resorder=split(/,/,$resorder);      my @resorder=split(/,/,$resorder);
     foreach my $part (keys(%responseIdHash)) {      foreach my $part (keys(%responseIdHash)) {
  my %resids = map { ($_,1) } @{ $responseIdHash{$part} };   my $i=0;
    my %resids = map { ($_,$i++) } @{ $responseIdHash{$part} };
  my @neworder;   my @neworder;
  foreach my $possibleid (@resorder) {   foreach my $possibleid (@resorder) {
     if (exists($resids{$possibleid})) {      if (exists($resids{$possibleid})) {
  push(@neworder,$possibleid);   push(@neworder,$resids{$possibleid});
     }      }
  }   }
  $responseIdHash{$part}=\@neworder;   my @ids;
    my @type;
    foreach my $element (@neworder) {
       push (@ids,$responseIdHash{$part}->[$element]);
       push (@type,$responseTypeHash{$part}->[$element]);
    }
    $responseIdHash{$part}=\@ids;
    $responseTypeHash{$part}=\@type;
     }      }
  }   }
         $self->{RESPONSE_IDS} = \%responseIdHash;          $self->{RESPONSE_IDS} = \%responseIdHash;
Line 4267  sub getCompletionStatus { Line 4342  sub getCompletionStatus {
   
     # Left as separate if statements in case we ever do more with this      # Left as separate if statements in case we ever do more with this
     if ($status eq 'correct_by_student') {return $self->CORRECT;}      if ($status eq 'correct_by_student') {return $self->CORRECT;}
       if ($status eq 'correct_by_scantron') {return $self->CORRECT;}
     if ($status eq 'correct_by_override') {return $self->CORRECT_BY_OVERRIDE; }      if ($status eq 'correct_by_override') {return $self->CORRECT_BY_OVERRIDE; }
     if ($status eq 'incorrect_attempted') {return $self->INCORRECT; }      if ($status eq 'incorrect_attempted') {return $self->INCORRECT; }
     if ($status eq 'incorrect_by_override') {return $self->INCORRECT_BY_OVERRIDE; }      if ($status eq 'incorrect_by_override') {return $self->INCORRECT_BY_OVERRIDE; }
Line 4603  sub getNext { Line 4679  sub getNext {
     my $to = $self->to();      my $to = $self->to();
     foreach my $branch ( split(/,/, $to) ) {      foreach my $branch ( split(/,/, $to) ) {
         my $choice = $self->{NAV_MAP}->getById($branch);          my $choice = $self->{NAV_MAP}->getById($branch);
           if (!$choice->condition()) { next; }
         my $next = $choice->goesto();          my $next = $choice->goesto();
         $next = $self->{NAV_MAP}->getById($next);          $next = $self->{NAV_MAP}->getById($next);
   

Removed from v.1.282  
changed lines
  Added in v.1.301


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>