Diff for /loncom/interface/lonnavmaps.pm between versions 1.267.2.5 and 1.300

version 1.267.2.5, 2004/09/20 15:26:04 version 1.300, 2004/10/07 22:12:47
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 83  my %colormap = Line 83  my %colormap =
 # is not yet done and due in less then 24 hours  # is not yet done and due in less then 24 hours
 my $hurryUpColor = "#FF0000";  my $hurryUpColor = "#FF0000";
   
   sub launch_win {
       my ($mode,$script,$toplinkitems)=@_;
       my $result;
       if ($script ne 'no') {
    $result.='<script type="text/javascript">';
       }
       $result.='function launch_navmapwin() {
                    newWindow=open(\'/adm/navmaps?launchExternal\',\'loncapanav\',\'width=400,height=600,scrollbars=1\');
                  }';
       if ($mode eq 'now') {
    $result.="\nlaunch_navmapwin();\n";
       }
       if ($script ne 'no') {
    $result.='</script>';
       }
       if ($mode eq 'link') {
    &add_linkitem($toplinkitems,'launchnav','launch_navmapwin()',
         "Launch navigation window");
       }
       return $result;
   }
   
   sub close {
       if ($ENV{'environment.remotenavmap'} ne 'on') { return ''; }
       return(<<ENDCLOSE);
   <script type="text/javascript">
   window.status='Accessing Nav Control';
   menu=window.open("/adm/rat/empty.html","loncapanav",
                    "height=600,width=400,scrollbars=1");
   window.status='Closing Nav Control';
   menu.close();
   window.status='Done.';
   </script>
   ENDCLOSE
   }
   
   sub nav_control_js {
       my $nav=($ENV{'environment.remotenavmap'} eq 'on');
       return (<<NAVCONTROL);
       var w_loncapanav_flag="$nav";
   
   
   function gonav(url) {
      if (w_loncapanav_flag != 1) {
         gopost(url,'');
      }  else {
         navwindow=window.open(url,
                     "loncapanav","height=600,width=400,scrollbars=1"); 
      }
   }
   NAVCONTROL
   }
   
   sub update {
       if ($ENV{'environment.remotenavmap'} ne 'on') { return ''; }
       if (!$ENV{'request.course.id'}) { return ''; }
       if ($ENV{'REQUEST_URI'}=~m|^/adm/navmaps|) { return ''; }
       return(<<ENDUPDATE);
   <form name="navform"></form>
   <script type="text/javascript">
   this.document.navform.action='/adm/navmaps#curloc';
   this.document.navform.target='loncapanav';
   this.document.navform.submit();
   </script>
   ENDUPDATE
   }
   
 sub handler {  sub handler {
     my $r = shift;      my $r = shift;
     real_handler($r);      real_handler($r);
Line 111  sub real_handler { Line 178  sub real_handler {
     &Apache::loncommon::no_cache($r);      &Apache::loncommon::no_cache($r);
     $r->send_http_header;      $r->send_http_header;
   
       my %toplinkitems=();
   
       if ($ENV{QUERY_STRING} eq 'collapseExternal') {
    &Apache::lonnet::put('environment',{'remotenavmap' => 'off'});
    &Apache::lonnet::appenv('environment.remotenavmap' => 'off');
    my $menu=&Apache::lonmenu::reopenmenu();
    my $navstatus=&Apache::lonmenu::get_nav_status();
    if ($menu) {
       $menu=(<<MENU)
                swmenu=$menu
                swmenu.clearTimeout(swmenu.menucltim);
        $navstatus
   MENU
           } else {
       my $nothing = &Apache::lonhtmlcommon::javascript_nothing();
       my $mainwindow='window.open('.$nothing.',"loncapaclient","",false);';
       $menu=(<<MENU)
                swmenu=$mainwindow
        $navstatus
   MENU
    }
    $r->print(<<"ENDSUBM");
    <html>
           <head>
     <script type="text/javascript">
        function submitthis() {
       $menu
       self.close();
       }
   
      </script>
           </head>
    <body bgcolor="#FFFFFF" onLoad="submitthis()"></body>
           </html>
   ENDSUBM
           return;
       }
       if ($ENV{QUERY_STRING} eq 'launchExternal') {
    &Apache::lonnet::put('environment',{'remotenavmap' => 'on'});
    &Apache::lonnet::appenv('environment.remotenavmap' => 'on');
       }
   
     # Create the nav map      # Create the nav map
     my $navmap = Apache::lonnavmaps::navmap->new();      my $navmap = Apache::lonnavmaps::navmap->new();
   
Line 123  sub real_handler { Line 232  sub real_handler {
     $r->print("<html><head>\n");      $r->print("<html><head>\n");
     $r->print("<title>".&mt('Navigate Course Contents')."</title>");      $r->print("<title>".&mt('Navigate Course Contents')."</title>");
 # ------------------------------------------------------------ Get query string  # ------------------------------------------------------------ Get query string
     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['register']);      &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['register','sort','showOnlyHomework']);
           
 # ----------------------------------------------------- Force menu registration  # ----------------------------------------------------- Force menu registration
     my $addentries='';      my $addentries='';
       my $more_unload;
       my $body_only='';
       if ($ENV{'environment.remotenavmap'} eq 'on') {
    $r->print('<script type="text/javascript">
                         function collapse() {
                            this.document.location="/adm/navmaps?collapseExternal";
                         }
                      </script>');
   # FIXME need to be smarter to only catch window close events
   # $more_unload="collapse()"
    $body_only=1;
       }
     if ($ENV{'form.register'}) {      if ($ENV{'form.register'}) {
        $addentries=' onLoad="'.&Apache::lonmenu::loadevents().   $addentries=' onLoad="'.&Apache::lonmenu::loadevents().
    '" onUnload="'.&Apache::lonmenu::unloadevents().'"';      '" onUnload="'.&Apache::lonmenu::unloadevents().';'.
        $r->print(&Apache::lonmenu::registerurl(1));      $more_unload.'"';
    $r->print(&Apache::lonmenu::registerurl(1));
       } else {
    $addentries=' onUnload="'.$more_unload.'"';
     }      }
   
     # Header      # Header
     $r->print('</head>'.      $r->print('</head>'.
               &Apache::loncommon::bodytag('Navigate Course Contents','',                &Apache::loncommon::bodytag('Navigate Course Contents','',
                                     $addentries,'','',$ENV{'form.register'}));    $addentries,$body_only,'',
     $r->print('<script>window.focus();</script>'.    $ENV{'form.register'}));
       &Apache::loncommon::help_open_menu('','Navigation Screen','Navigation_Screen','',undef,'RAT'));      $r->print('<script>window.focus();</script>');
             
     $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 173  sub real_handler { Line 298  sub real_handler {
         }          }
     }      }
   
       if ($ENV{QUERY_STRING} eq 'launchExternal') {
    $r->print('
             <form name="returnwin" action="/adm/flip?postdata=return%3a" 
                   method="post" target="loncapaclient">
             </form>');
    $r->print('
             <script type="text/javascript">
                 this.document.returnwin.submit();
             </script>');
       }
   
       if ($ENV{'environment.remotenavmap'} ne 'on') {
    $r->print(&launch_win('link','yes',\%toplinkitems));
       } 
       if ($ENV{'environment.remotenavmap'} eq 'on') {
    &add_linkitem(\%toplinkitems,'closenav','collapse()',
         "Close navigation window");
       } 
   
     my $jumpToFirstHomework = 0;      my $jumpToFirstHomework = 0;
     # Check to see if the student is jumping to next open, do-able problem      # Check to see if the student is jumping to next open, do-able problem
     if ($ENV{QUERY_STRING} eq 'jumpToFirstHomework') {      if ($ENV{QUERY_STRING} =~ /^jumpToFirstHomework/) {
         $jumpToFirstHomework = 1;          $jumpToFirstHomework = 1;
         # Find the next homework problem that they can do.          # Find the next homework problem that they can do.
         my $iterator = $navmap->getIterator(undef, undef, undef, 1);          my $iterator = $navmap->getIterator(undef, undef, undef, 1);
Line 208  sub real_handler { Line 352  sub real_handler {
             $r->print("<font size='+2'>All homework assignments have been completed.</font><br /><br />");              $r->print("<font size='+2'>All homework assignments have been completed.</font><br /><br />");
         }          }
     } else {      } else {
         $r->print("<a href='navmaps?jumpToFirstHomework'>" .   &add_linkitem(\%toplinkitems,'firsthomework',
        &mt("Go To My First Homework Problem")."</a>&nbsp;&nbsp;&nbsp;&nbsp;");        'location.href="navmaps?jumpToFirstHomework"',
         "Show Me My First Homework Problem");
     }      }
   
     my $suppressEmptySequences = 0;      my $suppressEmptySequences = 0;
Line 218  sub real_handler { Line 363  sub real_handler {
   
     # Display only due homework.      # Display only due homework.
     my $showOnlyHomework = 0;      my $showOnlyHomework = 0;
     if ($ENV{QUERY_STRING} eq 'showOnlyHomework') {      if ($ENV{'form.showOnlyHomework'} eq "1") {
         $showOnlyHomework = 1;          $showOnlyHomework = 1;
         $suppressEmptySequences = 1;          $suppressEmptySequences = 1;
         $filterFunc = sub { my $res = shift;           $filterFunc = sub { my $res = shift; 
                             return $res->completable() || $res->is_map();                              return $res->completable() || $res->is_map();
                         };                          };
    &add_linkitem(\%toplinkitems,'everything',
        'location.href="navmaps?sort='.$ENV{'form.sort'}.'"',
         "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'} = '';
         $ENV{'form.condition'} = 1;          $ENV{'form.condition'} = 1;
  $resource_no_folder_link = 1;   $resource_no_folder_link = 1;
     } else {      } else {
         $r->print("<a href='navmaps?showOnlyHomework'>" .   &add_linkitem(\%toplinkitems,'uncompleted',
        &mt("Show Only Uncompleted Homework")."</a>&nbsp;&nbsp;&nbsp;&nbsp;");        'location.href="navmaps?sort='.$ENV{'form.sort'}.
     }            '&showOnlyHomework=1"',
         "Show Only Uncompleted Homework");
       }
   
       my %selected=($ENV{'form.sort'} => 'selected=on');
       my $sort_html=("<form>
                    <nobr>
                       <input type=\"hidden\" name=\"showOnlyHomework\" value=\"".$ENV{'form.showOnlyHomework'}."\" />
                       <input type=\"submit\" value=\"".&mt('Sort by:')."\" />
                       <select name=\"sort\">
                          <option value=\"default\" $selected{'default'}>".&mt('Default')."</option>
                          <option value=\"title\"   $selected{'title'}  >".&mt('Title')."</option>
                          <option value=\"duedate\" $selected{'duedate'}>".&mt('Duedate')."</option>
                          <option value=\"discussion\" $selected{'discussion'}>".&mt('Has Discussion')."</option>
                       </select>
                    </nobr>
                  </form>");
     # renderer call      # renderer call
     my $renderArgs = { 'cols' => [0,1,2,3],      my $renderArgs = { 'cols' => [0,1,2,3],
          'sort' => $ENV{'form.sort'},
                        'url' => '/adm/navmaps',                         'url' => '/adm/navmaps',
                        'navmap' => $navmap,                         'navmap' => $navmap,
                        'suppressNavmap' => 1,                         'suppressNavmap' => 1,
                        'suppressEmptySequences' => $suppressEmptySequences,                         'suppressEmptySequences' => $suppressEmptySequences,
                        'filterFunc' => $filterFunc,                         'filterFunc' => $filterFunc,
        'resource_no_folder_link' => $resource_no_folder_link,         'resource_no_folder_link' => $resource_no_folder_link,
                        'r' => $r};         'sort_html'=> $sort_html,
                          'r' => $r,
                          'caller' => 'navmapsdisplay',
                          '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 868  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 879  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 904  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 921  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 959  sub render_resource { Line 1124  sub render_resource {
   
     if ($resource->is_problem() && $part ne '0' &&       if ($resource->is_problem() && $part ne '0' && 
         !$params->{'condensed'}) {          !$params->{'condensed'}) {
  my $displaypart=&Apache::lonnet::EXT('resource.'.$part.'.display',   my $displaypart=$resource->part_display($part);
      $resource->symb());  
  unless ($displaypart) { $displaypart=$part; }  
         $partLabel = " (Part: $displaypart)";          $partLabel = " (Part: $displaypart)";
  $link.='#'.&Apache::lonnet::escape($part);   $link.='#'.&Apache::lonnet::escape($part);
         $title = "";          $title = "";
Line 971  sub render_resource { Line 1134  sub render_resource {
         $nonLinkedText .= ' (' . $resource->countParts() . ' parts)';          $nonLinkedText .= ' (' . $resource->countParts() . ' parts)';
     }      }
   
       my $target;
       if ($ENV{'environment.remotenavmap'} eq 'on') {
    $target=' target="loncapaclient" ';
       }
     if (!$params->{'resource_nolink'} && !$resource->is_sequence() && !$resource->is_empty_sequence) {      if (!$params->{'resource_nolink'} && !$resource->is_sequence() && !$resource->is_empty_sequence) {
         $result .= "  $curMarkerBegin<a href='$link'>$title$partLabel</a>$curMarkerEnd $nonLinkedText</td>";          $result .= "  $curMarkerBegin<a $target href='$link'>$title$partLabel</a>$curMarkerEnd $nonLinkedText</td>";
     } else {      } else {
         $result .= "  $curMarkerBegin$title$partLabel$curMarkerEnd $nonLinkedText</td>";          $result .= "  $curMarkerBegin$title$partLabel$curMarkerEnd $nonLinkedText</td>";
     }      }
Line 987  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 1000  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 1015  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 1044  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 1175  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 1336  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 1360  sub render { Line 1536  sub render {
     }      }
   
     if ($printCloseAll && !$args->{'resource_no_folder_link'}) {      if ($printCloseAll && !$args->{'resource_no_folder_link'}) {
    my ($link,$text);
         if ($condition) {          if ($condition) {
             $result.="<a href=\"navmaps?condition=0&filter=&$queryString" .      $link='"navmaps?condition=0&filter=&'.$queryString.
                 "&here=" . Apache::lonnet::escape($here) .   '&here='.&Apache::lonnet::escape($here).'"';
                 "\">".&mt('Close All Folders')."</a>";      $text='Close All Folders';
         } else {          } else {
             $result.="<a href=\"navmaps?condition=1&filter=&$queryString" .      $link='"navmaps?condition=1&filter=&'.$queryString.
                 "&here=" . Apache::lonnet::escape($here) .    '&here='.&Apache::lonnet::escape($here).'"';
                 "\">".&mt('Open All Folders')."</a>";      $text='Open All Folders';
         }          }
    if ($args->{'caller'} eq 'navmapsdisplay') {
       &add_linkitem($args->{'linkitems'},'changefolder',
     'location.href='.$link,$text);
    } else {
       $result.='<a href='.$link.'>'.&mt($text).'</a>';
    }
         $result .= "\n";          $result .= "\n";
     }      }
   
     # Check for any unread discussions in all resources.      # Check for any unread discussions in all resources.
     if (!$args->{'resource_no_folder_link'}) {      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 %lt = &Apache::lonlocal::texthash(   <input type="hidden" name="navmaps" value="$haveDisc" />
  'mapr' => 'Mark all posts read',      </form>
  );  
     $result .= (<<END);  
         &nbsp;&nbsp;&nbsp;<a href="javascript:document.clearbubbles.submit()">$lt{'mapr'}</a>&nbsp;<a href="javascript:void(open('/adm/help/NavMaps_MarkPosts_Read.hlp', 'Help_for_NavMaps_MarkPosts', 'menubar=0,toolbar=1,scrollbars=1,width=350,height=400,resizable=yes'))" title="Online Help"><image src="/adm/help/gif/smallHelp.gif" border="0" alt="(Help: NavMaps_MarkPostsLink)" /></a>  
  <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') {
           $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 {          } else {
     $result .= '<br />';      $result .= '</tr><tr>'; 
           }
    $result.=&show_linkitems($args->{'linkitems'});
           if ($args->{'sort_html'}) {
       if ($ENV{'environment.remotenavmap'} ne 'on') {
    $result.='<td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>'.
       '<td align="right">'.$args->{'sort_html'}.'</td></tr>';
       } else {
    $result.='</tr><tr><td align="left"><br />'.
       $args->{'sort_html'}.'</td></tr>';
       }
  }   }
           $result .= '</table>';
       } elsif ($args->{'sort_html'}) { 
           $result.=$args->{'sort_html'}; 
     }      }
   
     $result .= "<br />\n";      $result .= "<br />\n";
     if ($r) {      if ($r) {
         $r->print($result);          $r->print($result);
Line 1427  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 1477  END Line 1690  END
     $args->{'here'} = $here;      $args->{'here'} = $here;
   
     $args->{'indentLevel'} = -1; # first BEGIN_MAP takes this to 0      $args->{'indentLevel'} = -1; # first BEGIN_MAP takes this to 0
     while ($curRes = $it->next($closeAllPages)) {      my @resources;
       my $code='';# sub { !(shift->is_map();) };
       if ($args->{'sort'} eq 'title') {
           my $oldFilterFunc = $filterFunc;
    my $filterFunc= 
       sub {
    my ($res)=@_;
    if ($res->is_map()) { return 0;}
    return &$oldFilterFunc($res);
       };
    @resources=$navmap->retrieveResources(undef,$filterFunc);
    @resources= sort { &cmp_title($a,$b) } @resources;
       } elsif ($args->{'sort'} eq 'duedate') {
    my $oldFilterFunc = $filterFunc;
    my $filterFunc= 
       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) {
           return $a->duedate cmp $b->duedate;
       }
       my $value=&cmp_title($a,$b);
       return $value;
    } @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 {
    #unknow sort mechanism or default
    undef($args->{'sort'});
       }
   
   
       while (1) {
    if ($args->{'sort'}) {
       $curRes = shift(@resources);
    } else {
       $curRes = $it->next($closeAllPages);
    }
    if (!$curRes) { last; }
   
         # Maintain indentation level.          # Maintain indentation level.
         if ($curRes == $it->BEGIN_MAP() ||          if ($curRes == $it->BEGIN_MAP() ||
             $curRes == $it->BEGIN_BRANCH() ) {              $curRes == $it->BEGIN_BRANCH() ) {
Line 1591  END Line 1857  END
   
             # Set up some data about the parts that the cols might want              # Set up some data about the parts that the cols might want
             my $filter = $it->{FILTER};              my $filter = $it->{FILTER};
             my $stack = $it->getStack();      my $src;
             my $src = getLinkForResource($stack);      if ($args->{'sort'}) {
    $src = $curRes->src(); # FIXME this is wrong for .pages
       } else {
    my $stack = $it->getStack();
    $src=getLinkForResource($stack);
       }
             my $anchor='';              my $anchor='';
             if ($src=~s/(\#.*$)//) {              if ($src=~s/(\#.*)$//) {
  $anchor=$1;   $anchor=$1;
     }      }
             my $srcHasQuestion = $src =~ /\?/;              my $srcHasQuestion = $src =~ /\?/;
Line 1602  END Line 1873  END
                 ($srcHasQuestion?'&':'?') .                  ($srcHasQuestion?'&':'?') .
                 'symb=' . &Apache::lonnet::escape($curRes->symb()).                  'symb=' . &Apache::lonnet::escape($curRes->symb()).
  $anchor;   $anchor;
               
             # Now, display each column.              # Now, display each column.
             foreach my $col (@$cols) {              foreach my $col (@$cols) {
                 my $colHTML = '';                  my $colHTML = '';
Line 1668  if (location.href.indexOf('#curloc')==-1 Line 1939  if (location.href.indexOf('#curloc')==-1
         $r->rflush();          $r->rflush();
     }      }
                   
     if ($mustCloseNavMap) { $navmap->untieHashes(); }       return $result;
   }
   
   sub add_linkitem {
       my ($linkitems,$name,$cmd,$text)=@_;
       $$linkitems{$name}{'cmd'}=$cmd;
       $$linkitems{$name}{'text'}=&mt($text);
   }
   
   sub show_linkitems {
       my ($linkitems)=@_;
       my @linkorder = ("launchnav","closenav","firsthomework","everything",
        "uncompleted","changefolder","clearbubbles");
       
       my $result .= (<<ENDBLOCK);
                 <td align="left">
   <script type="text/javascript">
       function changeNavDisplay () {
    var navchoice = document.linkitems.toplink[document.linkitems.toplink.selectedIndex].value;
   ENDBLOCK
       foreach my $link (@linkorder) {
    $result.= "if (navchoice == '$link') {".
       $linkitems->{$link}{'cmd'}."}\n";
       }
       $result.='}
                 </script>
                      <form name="linkitems" method="post">
                          <nobr><select name="toplink">'."\n";
       foreach my $link (@linkorder) {
    if (defined($linkitems->{$link})) {
       if ($linkitems->{$link}{'text'} ne '') {
    $result .= ' <option value="'.$link.'">'.
       $linkitems->{$link}{'text'}."</option>\n";
       }
    }
       }
       $result .= '</select>&nbsp;<input type="button" name="chgnav"
                      value="Go" onClick="javascript:changeNavDisplay()" />
                   </nobr></form></td>'."\n";
   
     return $result;      return $result;
 }  }
   
Line 1730  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 1879  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 1899  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 1954  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 2057  sub getById { Line 2351  sub getById {
 sub getBySymb {  sub getBySymb {
     my $self = shift;      my $self = shift;
     my $symb = shift;      my $symb = shift;
   
     my ($mapUrl, $id, $filename) = &Apache::lonnet::decode_symb($symb);      my ($mapUrl, $id, $filename) = &Apache::lonnet::decode_symb($symb);
     my $map = $self->getResourceByUrl($mapUrl);      my $map = $self->getResourceByUrl($mapUrl);
     return $self->getById($map->map_pc() . '.' . $id);      my $returnvalue = undef;
       if (ref($map)) {
           $returnvalue = $self->getById($map->map_pc() .'.'.$id);
       }
       return $returnvalue;
 }  }
   
 sub getByMapPc {  sub getByMapPc {
Line 2253  in the filter function. Line 2552  in the filter function.
   
 =cut  =cut
   
   
 sub getResourceByUrl {  sub getResourceByUrl {
     my $self = shift;      my $self = shift;
     my $resUrl = shift;      my $resUrl = shift;
Line 2335  sub hasResource { Line 2635  sub hasResource {
 1;  1;
   
 package Apache::lonnavmaps::iterator;  package Apache::lonnavmaps::iterator;
   use WeakRef;
 =pod  =pod
   
 =back  =back
Line 2475  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 2811  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 2839  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 2993  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 3075  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 3518  sub weight { Line 3818  sub weight {
  $self->symb(), $ENV{'user.domain'},   $self->symb(), $ENV{'user.domain'},
  $ENV{'user.name'},    $ENV{'user.name'}, 
  $ENV{'request.course.sec'});   $ENV{'request.course.sec'});
   }
   sub part_display {
       my $self= shift(); my $partID = shift();
       if (! defined($partID)) { $partID = '0'; }
       my $display=&Apache::lonnet::EXT('resource.'.$partID.'.display',
                                        $self->symb);
       if (! defined($display) || $display eq '') {
           $display = $partID;
       }
       return $display;
 }  }
   
 # Multiple things need this  # Multiple things need this
Line 3608  Returns the number of parts of the probl Line 3917  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 3654  sub countParts { Line 3973  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 3741  sub extractParts { Line 4080  sub extractParts {
         }          }
                   
   
           # These hashes probably do not need names that end with "Hash"....
         my %responseIdHash;          my %responseIdHash;
         my %responseTypeHash;          my %responseTypeHash;
   
Line 3776  sub extractParts { Line 4116  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;

Removed from v.1.267.2.5  
changed lines
  Added in v.1.300


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