Diff for /loncom/interface/lonmenu.pm between versions 1.140 and 1.503

version 1.140, 2004/12/07 23:59:52 version 1.503, 2020/10/06 21:28:33
Line 26 Line 26
 # http://www.lon-capa.org/  # http://www.lon-capa.org/
 #  #
 #  #
 # There are two parameters controlling the action of this module:  
 #  =head1 NAME
 # browser.interface - if this is 'textual', it overrides the second parameter  
 # and goes to screen reader PDA mode  Apache::lonmenu
 #  
 # environment.remote - if this is 'on', the routines controll the remote  =head1 SYNOPSIS
 # control, otherwise they render the main window controls; ignored it  
 # browser.interface is 'textual'  Loads contents of /home/httpd/lonTabs/mydesk.tab, 
 #  used to generate inline menu, and Main Menu page. 
   
   This is part of the LearningOnline Network with CAPA project
   described at http://www.lon-capa.org.
   
   =head1 GLOBAL VARIABLES
   
   =over
   
   =item @desklines
   
   Each element of this array contains a line of mydesk.tab that doesn't start with
   cat, prim or scnd. 
   It gets filled in the BEGIN block of this module.
   
   =item %category_names
   
   The keys of this hash are the abbreviations used in mydesk.tab in those lines that 
   start with cat, the values are strings representing titles. 
   It gets filled in the BEGIN block of this module.
   
   =item %category_members
   
   TODO 
   
   =item %category_positions
   
   The keys of this hash are the abbreviations used in mydesk.tab in those lines that
   start with cat, its values are position vectors (column, row). 
   It gets filled in the BEGIN block of this module.
   
   =item $readdesk
   
   Indicates that mydesk.tab has been read. 
   It is set to 'done' in the BEGIN block of this module.
   
   =item @primary_menu
   
   The elements of this array reference arrays that are made up of the components
   of those lines of mydesk.tab that start with prim:.
   It is used by primary_menu() to generate the corresponding menu.
   It gets filled in the BEGIN block of this module.
   
   =item %primary_sub_menu
   
   The keys of this hash reference are the names of items in the primary_menu array 
   which have sub-menus.  For each key, the corresponding value is a reference to
   an array containing components extracted from lines in mydesk.tab which begin
   with primsub:.
   This hash, which is used by primary_menu to generate sub-menus, is populated in
   the BEGIN block.
   
   =item @secondary_menu
   
   The elements of this array reference arrays that are made up of the components
   of those lines of mydesk.tab that start with scnd.
   It is used by secondary_menu() to generate the corresponding menu.
   It gets filled in the BEGIN block of this module.
   
   =back
   
   =head1 SUBROUTINES
   
   =over
   
   =item prep_menuitems(\@menuitem,$ltitarget)
   
   This routine wraps a menuitem in proper HTML. It is used by primary_menu() and 
   secondary_menu().
   
   =item primary_menu()
   
   This routine evaluates @primary_menu and returns a two item array, 
   with the array elements containing XHTML for the left and right sides of 
   the menu that contains the following links: About, Message, Roles, Help, Logout 
   @primary_menu is filled within the BEGIN block of this module with 
   entries from mydesk.tab
   
   =item secondary_menu()
   
   Same as primary_menu() but operates on @secondary_menu.
   
   =item create_submenu()
   
   Creates XHTML for unordered list of sub-menu items which belong to a 
   particular top-level menu item. Uses hover pseudo class in css to display
   dropdown list when mouse hovers over top-level item. Support for IE6 
   (no hover psuedo class) via LC_hoverable class for <li> tag for top-
   level item, which employs jQuery to handle behavior on mouseover.
   
   Inputs: 6 - (a) link and (b) target for anchor href in top level item,
               (c) title for text wrapped by anchor tag in top level item,
               (d) reference to array of arrays of sub-menu items,
               (e) boolean to indicate whether to call &mt() to translate 
                   name of menu item,
               (f) optional class for <li> element in primary menu, for which
                   sub menu is being generated.
   
    The underlying datastructure used in (d) contains data from mydesk.tab.
    It consists of an array which has an array for each item appearing in
    the menu (e.g. [["link", "title", "condition"]] for a single-item menu).
    create_submenu() supports also the creation of XHTML for nested dropdown
    menus represented by unordered lists. This is done by replacing the
    scalar used for the link with an arrayreference containing the menuitems
    for the nested menu. This can be done recursively so that the next menu
    may also contain nested submenus.
   
    Example:
    [ # begin of datastructure
    ["/home/", "Home", "condition1"], # 1st item of the 1st layer menu
    [ # 2nd item of the 1st layer menu
    [ # anon. array for nested menu
    ["/path1", "Path1", undef], # 1st item of the 2nd layer menu
    ["/path2", "Path2", undef], # 2nd item of the 2nd layer menu
    [ # 3rd item of the 2nd layer menu
    [[...], [...], ..., [...]], # containing another menu layer
    "Sub-Sub-Menu", # title for this container
    undef
    ]
    ], # end of array/nested menu
    "Sub-Menu", # title for the container item
    undef
    ] # end of 2nd item of the 1st layer menu
   ]
   
   =item innerregister()
   
   This gets called in order to register a URL in the body of the document
   
   =item clear()
   
   =item switch()
   
   Switch a button or create a link
   Switch acts on the javascript that is executed when a button is clicked.  
   The javascript is usually similar to "go('/adm/roles')" or "cstrgo(..)".
   
   =item secondlevel()
   
   =item openmenu()
   
   =item inlinemenu()
   
   =item rawconfig()
   
   =item utilityfunctions()
   
   Output from this routine is a number of javascript functions called by
   items in the inline menu, and in some cases items in the Main Menu page. 
   
   =item serverform()
   
   =item constspaceform()
   
   =item get_nav_status()
   
   =item hidden_button_check()
   
   =item roles_selector()
   
   =item jump_to_role()
   
   =back
   
   =cut
   
 package Apache::lonmenu;  package Apache::lonmenu;
   
 use strict;  use strict;
 use Apache::lonnet();  use Apache::lonnet;
 use Apache::Constants qw(:common);  
 use Apache::lonhtmlcommon();  use Apache::lonhtmlcommon();
 use Apache::loncommon();  use Apache::loncommon();
 use Apache::lonenc();  use Apache::lonenc();
 use Apache::lonlocal;  use Apache::lonlocal;
   use Apache::lonmsg();
   use LONCAPA qw(:DEFAULT :match);
   use LONCAPA::ltiutils;
   use HTML::Entities();
   use Apache::lonwishlist();
   
 use vars qw(@desklines $readdesk);  use vars qw(@desklines %category_names %category_members %category_positions 
               $readdesk @primary_menu %primary_submenu @secondary_menu %secondary_submenu);
   
 my @inlineremote;  my @inlineremote;
 my $font;  
 my $tabbg;  sub prep_menuitem {
 my $pgbg;      my ($menuitem,$ltitarget) = @_;
       return '' unless(ref($menuitem) eq 'ARRAY');
 # ================================================================ Little texts      my $link;
       if ($$menuitem[1]) { # graphical Link
 sub initlittle {          $link = "<img class=\"LC_noBorder\""
     return &Apache::lonlocal::texthash('ret' => 'Return to Last Location',                . " src=\"" . &Apache::loncommon::lonhttpdurl($$menuitem[1]) . "\"" 
        'nav' => 'Navigate Contents',                . " alt=\"" . &mt($$menuitem[2]) . "\" />";
        'main' => 'Main Menu',      } else {             # textual Link
        'launch' => 'Launch Remote Control');          $link = &mt($$menuitem[3]);
 }      }
       my $target = ' target="_top"';
 # ============================= This gets called at the top of the body section      if ($ltitarget eq 'iframe') {
           $target ='';
 sub menubuttons {      }
     my $forcereg=shift;      return '<li><a' 
     my $target  =shift;             # highlighting for new messages
     my $registration=shift;             . ( $$menuitem[4] eq 'newmsg' ? ' class="LC_new_message"' : '') 
     my $titletable=shift;             . qq| href="$$menuitem[0]"$target>$link</a></li>|;
     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},  }
     ['inhibitmenu']);  
     if ($ENV{'form.inhibitmenu'} eq 'yes') { return ''; }  # primary_menu() evaluates @primary_menu and returns a two item array,
   # with the array elements containing XHTML for the left and right sides of 
     my $navmaps='';  # the menu that contains the following links:
     my $reloadlink='';  # Personal, About, Message, Roles, Help, Logout
     my $escurl=&Apache::lonnet::escape(&Apache::lonenc::check_encrypt($ENV{'request.noversionuri'}));  # @primary_menu is filled within the BEGIN block of this module with 
     my $escsymb=&Apache::lonnet::escape(&Apache::lonenc::check_encrypt($ENV{'request.symb'}));  # entries from mydesk.tab
     if ($ENV{'request.state'} eq 'construct') {  sub primary_menu {
         if (($ENV{'request.noversionuri'} eq '') || (!defined($ENV{'request.noversionuri'}))) {      my ($crstype,$ltimenu) = @_;
             my $returnurl = $ENV{'request.filename'};      my (%menu,%ltiexc);
             $returnurl =~ s:^/home/([^/]+)/public_html/(.*)$:/priv/$1/$2:;      # each element of @primary contains following array:
             $escurl = &Apache::lonnet::escape($returnurl);      # (link url, icon path, alt text, link text, condition, position)
         }      my $public;
     }      if ((($env{'user.name'} eq 'public') && ($env{'user.domain'} eq 'public'))
     if ($ENV{'browser.interface'} eq 'textual') {          || (($env{'user.name'} eq '') && ($env{'user.domain'} eq ''))) {
 # Textual display only          $public = 1;
  my %lt=&initlittle();      }
         $pgbg='#FFFFFF';      my $rolecount;
         $tabbg='#FFFFFF';      if (($crstype eq 'Placement') && (!$env{'request.role.adv'})) {
  $font='#000000';          my $update=$env{'user.update.time'};
         if ($ENV{'request.course.id'}) {          if (!$update) {
     $navmaps=(<<ENDNAV);              $update = $env{'user.login.time'};
 <a href="/adm/navmaps?postdata=$escurl&postsymb=$escsymb" target="_top">$lt{'nav'}</a>          }
 ENDNAV          my %roles_in_env;
             if (($ENV{'request.noversionuri'}=~/^\/adm\//) &&          $rolecount = &Apache::lonroles::roles_from_env(\%roles_in_env,$update);
          ($ENV{'request.noversionuri'}!~/^\/adm\/wrapper\//) &&      }
          ($ENV{'request.noversionuri'}!~/^\/adm\/.*\/(smppg|bulletinboard|aboutme)(\?|$)/)) {      my ($lti,$ltitarget);
                 my $escreload=&Apache::lonnet::escape('return:');      if ($env{'request.lti.login'}) {
                 $reloadlink=(<<ENDRELOAD);          $lti = 1;
 <a href="/adm/flip?postdata=$escreload" target="_top"><font color="$font">$lt{'ret'}</font></a>          $ltitarget = $env{'request.lti.target'};
 ENDRELOAD          if (ref($ltimenu) eq 'HASH') {
             }              foreach my $item ('fullname','logout') {
         }                  unless ($ltimenu->{$item}) {
         my $form=&serverform();                      $ltiexc{$item} = 1;
         my $utility=&utilityfunctions();                  }
  my $output=(<<ENDMAINMENU);              }
 <script type="text/javascript">          }
 // BEGIN LON-CAPA Internal      }
 $utility      foreach my $menuitem (@primary_menu) {
 </script>          # evaluate conditions 
 <a href="/adm/menu" target="_top">$lt{'main'}</a>          next if    ref($menuitem)       ne 'ARRAY';    #
 $reloadlink $navmaps<br />          next if    $$menuitem[4]        eq 'nonewmsg'  # show links depending on
 <script type="text/javascript">                  && &Apache::lonmsg::mynewmail();       # whether a new msg 
 // END LON-CAPA Internal          next if    $$menuitem[4]        eq 'newmsg'    # arrived or not
 </script>                  && !&Apache::lonmsg::mynewmail();      # 
 $form          next if    $$menuitem[4]        !~ /public/    ##we've a public user,
 ENDMAINMENU                  && $public;                            ##who should not see all
         if ($registration) { $output.=&innerregister($forcereg,$target); }                                                         ##links
  return $output."<hr />";          next if    $$menuitem[4]        eq 'onlypublic'# hide links which are 
     } elsif ($ENV{'environment.remote'} eq 'off') {                  && !$public;                           # only visible to public
 # Remote Control is switched off                                                         # users
 # figure out colors          next if    $$menuitem[4]        eq 'roles'     ##show links depending on
  my %lt=&initlittle();                  && (&Apache::loncommon::show_course()  ##term 'Courses' or
  my $function='student';                  || $env{'request.lti.login'});         ##'Roles' wanted
         if ($ENV{'request.role'}=~/^(cc|in|ta|ep)/) {          next if    $$menuitem[4]        eq 'courses'   ##and not LTI access
     $function='coordinator';                  && (!&Apache::loncommon::show_course()
         }                  || !$env{'request.lti.login'});
  if ($ENV{'request.role'}=~/^(su|dc|ad|li)/) {          next if    $$menuitem[4]        eq 'notlti'
             $function='admin';                  && $lti;
         }          next if    $$menuitem[4]        eq 'ltiexc'
         if (($ENV{'request.role'}=~/^(au|ca)/) ||                  && exists($ltiexc{lc($menuitem->[3])});
             ($ENV{'request.noversionuri'}=~/^(\/priv|\~)/)) {          my $title = $menuitem->[3];
             $function='author';          if (($crstype eq 'Placement') && (!$env{'request.role.adv'})) {
         }              if ($menuitem->[4] eq 'courses') {
         my $domain=&Apache::loncommon::determinedomain();                  next unless ($rolecount>1);
         $pgbg=&Apache::loncommon::designparm($function.'.pgbg',$domain);              } else {
         $tabbg=&Apache::loncommon::designparm($function.'.tabbg',$domain);                  next unless (($title eq 'Personal') || ($title eq 'Logout'));
         $font=&Apache::loncommon::designparm($function.'.font',$domain);              }
         my $link=&Apache::loncommon::designparm($function.'.link',$domain);          }
         my $alink=&Apache::loncommon::designparm($function.'.alink',$domain);          my $position = $menuitem->[5];
         my $vlink=&Apache::loncommon::designparm($function.'.vlink',$domain);          if ($position eq '') {
         my $sidebg=&Apache::loncommon::designparm($function.'.sidebg',$domain);              $position = 'right';
 # Do we have a NAV link?          }
         if ($ENV{'request.course.id'}) {          if (defined($primary_submenu{$title})) {
            $navmaps=(<<ENDNAV);              my ($link,$target);
 <td bgcolor="$tabbg">              if ($menuitem->[0] ne '') {
 <a href="javascript:gonav('/adm/navmaps?postdata=$escurl&amp;postsymb=$escsymb')"><font color="$font">$lt{'nav'}</font></a></td>                  $link = $menuitem->[0];
 ENDNAV                  unless ($ltitarget eq 'iframe') {
     if (($ENV{'request.noversionuri'}=~/^\/adm\//) &&                      $target = '_top';
                 ($ENV{'request.noversionuri'}!~/^\/adm\/wrapper\//) &&                  }
          ($ENV{'request.noversionuri'}!~/^\/adm\/.*\/(smppg|bulletinboard|aboutme)(\?|$)/)) {              } else {
                 my $escreload=&Apache::lonnet::escape('return:');                  $link = '#';
                 $reloadlink=(<<ENDRELOAD);              }
 <td bgcolor="$tabbg">              my @primsub;
 <a href="/adm/flip?postdata=$escreload" target="_top"><font color="$font">$lt{'ret'}</font></a></td>              if (ref($primary_submenu{$title}) eq 'ARRAY') {
 ENDRELOAD                  foreach my $item (@{$primary_submenu{$title}}) {
             }                      next if (($crstype eq 'Placement') && (!$env{'request.role.adv'}));
         }                      next if (($item->[2] eq 'wishlist') && (!$env{'user.adv'}));
         my $reg='';                      next if ((($item->[2] eq 'portfolio') ||
         if ($registration) {                               ($item->[2] eq 'blog')) &&
            $reg=&innerregister($forcereg,$target,$titletable);                               (!&Apache::lonnet::usertools_access('','',$item->[2],
         }                                                             undef,'tools')));
         my $form=&serverform();                      push(@primsub,$item);
  my $utility=&utilityfunctions();                  }
  return (<<ENDINLINEMENU);                  if ($title eq 'Personal' && $env{'user.name'} && $env{'user.domain'} ) {
 <script type="text/javascript">                      unless ($ltiexc{'fullname'}) {
 // BEGIN LON-CAPA Internal                          $title = &Apache::loncommon::plainname($env{'user.name'},$env{'user.domain'});
 $utility                      }
 </script>                  } else {
 <font face="Arial,Helvetica,sans-serif"><table bgcolor="$pgbg" width="100%" border="0" cellpadding="1" cellspacing="1">                      $title = &mt($title);
 <tr>                  }
 <td bgcolor="$tabbg">                  if (@primsub > 0) {
 <a href="/adm/menu" target="_top"><font color="$font">$lt{'main'}</font></a>                      $menu{$position} .= &create_submenu($link,$target,$title,\@primsub,1);
 </td>                  } elsif ($link) {
 $reloadlink                      $menu{$position} .= '<li><a href="'.$link.'" target="'.$target.'">'.$title.'</a></li>';
 $navmaps                  }
 <td bgcolor="$tabbg">              }
 <a href="/adm/remote?action=launch&amp;url=$escurl" target="_top">          } elsif ($$menuitem[3] eq 'Help') { # special treatment for helplink
 <font color="$font">$lt{'launch'}</font></a></td>              next if ($crstype eq 'Placement'); 
 <td bgcolor="$tabbg">              if ($public) {
 <img align="right" src="/adm/lonIcons/minilogo.gif" />                  my $origmail = $Apache::lonnet::perlvar{'lonSupportEMail'};
 <b>LON-CAPA</b></td>                  my $defdom = &Apache::lonnet::default_login_domain();
 $form                  my $to = &Apache::loncommon::build_recipient_list(undef,
 </tr>                                                                    'helpdeskmail',
 </table>                                                                    $defdom,$origmail);
 </font>                  if ($to ne '') {
 <script type="text/javascript">                      $menu{$position} .= &prep_menuitem($menuitem,$ltitarget); 
 // END LON-CAPA Internal                  }
 </script>              } else {
 $reg                  $menu{$position} .= '<li>'.&Apache::loncommon::top_nav_help('Help').'</li>';
 ENDINLINEMENU              }
     } else {          } else {
  return '';              $menu{$position} .= prep_menuitem($menuitem,$ltitarget);
           }
       }
       my @output = ('','');
       if ($menu{'left'} ne '') {
           $output[0] = "<ol class=\"LC_primary_menu LC_floatleft\">$menu{'left'}</ol>";
       }
       if ($menu{'right'} ne '') {
           $output[1] = "<ol class=\"LC_primary_menu LC_floatright LC_right\">$menu{'right'}</ol>";
     }      }
       return @output;
 }  }
   
 # ====================================== This gets called in the header section  #returns hashref {user=>'',dom=>''} containing:
   #   own name, domain if user is au
   #   name, domain of parent author if user is ca or aa
   #empty return if user is not an author or not on homeserver
   #
   #TODO this should probably be moved somewhere more central
   #since it can be used by different parts of the system
   sub getauthor{
       return unless $env{'request.role'}=~/^(ca|aa|au)/; #nothing to do if user isn't some kind of author
   
                           #co- or assistent author?
       my ($dom, $user) = ($env{'request.role'} =~ /^(?:ca|aa)\.\/($match_domain)\/($match_username)$/)
                          ? ($1, $2) #domain, username of the parent author
                          : @env{ ('request.role.domain', 'user.name') }; #own domain, username
   
       # current server == home server?
       my $home =  &Apache::lonnet::homeserver($user,$dom);
       foreach (&Apache::lonnet::current_machine_ids()){
           return {user => $user, dom => $dom} if $_ eq $home;
       }
   
       # if wrong server
       return;
   }
   
   sub secondary_menu {
       my ($httphost,$ltiscope,$ltimenu,$noprimary) = @_;
       my $menu;
   
       my $crstype = &Apache::loncommon::course_type();
       my $crs_sec = $env{'request.course.id'} . ($env{'request.course.sec'} 
                                                  ? "/$env{'request.course.sec'}"
                                                  : '');
       my $canedit       = &Apache::lonnet::allowed('mdc', $env{'request.course.id'});
       my $canvieweditor = &Apache::lonnet::allowed('cev', $env{'request.course.id'});
       my $canviewroster = $env{'course.'.$env{'request.course.id'}.'.student_classlist_view'};
       if ($canviewroster eq 'disabled') {
           undef($canviewroster);
       }
       my $canviewgrps   = &Apache::lonnet::allowed('vcg', $crs_sec); 
       my $canmodifyuser = &Apache::lonnet::allowed('cst', $crs_sec);
       my $canviewusers  = &Apache::lonnet::allowed('vcl', $crs_sec); 
       my $canviewwnew   = &Apache::lonnet::allowed('whn', $crs_sec); 
       my $canviewpara   = &Apache::lonnet::allowed('vpa', $crs_sec);
       my $canmodpara    = &Apache::lonnet::allowed('opa', $crs_sec);
       my $canvgr        = &Apache::lonnet::allowed('vgr', $crs_sec);
       my $canmgr        = &Apache::lonnet::allowed('mgr', $crs_sec); 
       my $canplc        = &Apache::lonnet::allowed('plc', $crs_sec);
       my $author        = &getauthor();
   
       my ($cdom,$cnum,$showsyllabus,$showfeeds,$showresv,$grouptools,$lti,$ltimapres,%ltiexc);
       $grouptools = 0;
       if ($env{'request.course.id'}) {
           $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
           $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
           unless ($canedit || $canvieweditor)  {
               unless (&Apache::lonnet::is_on_map("public/$cdom/$cnum/syllabus")) {
                   if (($env{'course.'.$env{'request.course.id'}.'.externalsyllabus'}) ||
                       ($env{'course.'.$env{'request.course.id'}.'.uploadedsyllabus'}) ||
                       ($env{'course.'.$env{'request.course.id'}.'.updatedsyllabus'}) ||
                       ($env{'request.course.syllabustime'})) {
                       $showsyllabus = 1;
                   }
               }
               if ($env{'request.course.feeds'}) {
                   $showfeeds = 1;
               }
           }
           unless ($canmgr || $canvgr) {
               my %slots = &Apache::lonnet::get_course_slots($cnum,$cdom);
               if (keys(%slots) > 0) {
                   $showresv = 1;
               }
           }
           if ($env{'request.course.groups'} ne '') {
               foreach my $group (split(/:/,$env{'request.course.groups'})) {
                   next unless ($group =~ /^\w+$/);
                   my @privs = split(/:/,$env{"user.priv.$env{'request.role'}./$cdom/$cnum/$group"});
                   shift(@privs);
                   if (@privs) {
                       $grouptools ++;
                   }
               }
           }
           if ($env{'request.lti.login'}) {
               $lti = 1;
               if (ref($ltimenu) eq 'HASH') {
                   foreach my $item ('fullname','coursetitle','role','logout','grades') {
                       unless ($ltimenu->{$item}) {
                           $ltiexc{$item} = 1;
                       }
                   }
               }
               if (($ltiscope eq 'map') || ($ltiscope eq 'resource')) {
                   $ltimapres = 1;
               }
           }
       }
   
 sub registerurl {      my ($canmodifycoauthor); 
     my $forcereg=shift;      if ($env{'request.role'} eq "au./$env{'user.domain'}/") {
     my $target = shift;          my $extent = "$env{'user.domain'}/$env{'user.name'}";
     my $result = '';          if ((&Apache::lonnet::allowed('cca',$extent)) ||
     if ($ENV{'request.noversionuri'} eq '/res/adm/pages/menu.html') { return ''; }              (&Apache::lonnet::allowed('caa',$extent))) {
     my $force_title='';              $canmodifycoauthor = 1;
     if ($ENV{'request.state'} eq 'construct') {          }
  $force_title=&Apache::lonxml::display_title();  
     }  
     if ($target eq 'edit') {  
         $result .="<script type=\"text/javascript\">\n".  
             "if (typeof swmenu != 'undefined') {swmenu.currentURL=null;}\n".  
             &Apache::loncommon::browser_and_searcher_javascript().  
                 "\n</script>\n";  
     }  
     if (($ENV{'browser.interface'} eq 'textual') ||  
         ($ENV{'environment.remote'} eq 'off') ||  
         ((($ENV{'request.publicaccess'}) ||   
          (!&Apache::lonnet::is_on_map(  
    &Apache::lonnet::unescape($ENV{'request.noversionuri'})))) &&  
         (!$forcereg))) {  
   return $result.  
           '<script type="text/javascript">function LONCAPAreg(){;} function LONCAPAstale(){}</script>'.$force_title;  
     }  
 # Graphical display after login only  
     if ($Apache::lonxml::registered && !$forcereg) { return ''; }  
     if ($target ne 'edit') {  
  $result.=&innerregister($forcereg,$target);  
     }      }
     return $result.$force_title;  
 }  
   
 # =========== This gets called in order to register a URL, both with the Remote      my ($roleswitcher_js,$roleswitcher_form,$ltitarget);
 # =========== and in the body of the document      if ($env{'request.lti.login'}) {
           $ltitarget = $env{'request.lti.target'};
       }
   
       foreach my $menuitem (@secondary_menu) {
           # evaluate conditions 
           next if    ref($menuitem)  ne 'ARRAY';
           next if (($crstype eq 'Placement') && ($$menuitem[3] ne 'Roles') && (!$env{'request.role.adv'}));
           next if    $$menuitem[4]   ne 'always'
                   && ($$menuitem[4]   ne 'author' && $$menuitem[4] ne 'cca')
                   && !$env{'request.course.id'};
           next if    $$menuitem[4]   =~ /^crsedit/
                   && (!$canedit && !$canvieweditor);
           next if    $$menuitem[4]  eq 'nvgr'
                   && ($canvgr || $ltiexc{'grades'});
           next if    $$menuitem[4]  eq 'vgr'
                   && !$canvgr;
           next if    $$menuitem[4]   eq 'viewusers'
                   && !$canmodifyuser && !$canviewusers;
           next if    $$menuitem[4]   eq 'noviewusers'
                   && ($canmodifyuser || $canviewusers || !$canviewroster);
           next if    $$menuitem[4]   eq 'mgr'
                   && !$canmgr;
           next if    $$menuitem[4]   eq 'showresv'
                   && !$showresv;
           next if    $$menuitem[4]   eq 'whn'
                   && !$canviewwnew;
           next if    $$menuitem[4]   eq 'params'
                   && (!$canmodpara && !$canviewpara);
           next if    $$menuitem[4]   eq 'showgroups'
                   && ($canviewgrps || !$grouptools);
           next if    $$menuitem[4]   eq 'showsyllabus'
                   && !$showsyllabus;
           next if    $$menuitem[4]   eq 'showfeeds'
                   && !$showfeeds;
           next if     $$menuitem[4]  eq 'plc'
                   && !$canplc;
           next if    $$menuitem[4]    eq 'author'
                   && !$author;
           next if    $$menuitem[4]    eq 'cca'
                   && !$canmodifycoauthor;
           next if    $$menuitem[4]    eq 'notltimapres'
                   && $ltimapres;
           next if    $$menuitem[4]    eq 'notlti'
                   && $lti;
           next if    $$menuitem[4]    eq 'lti'
                   && (!$lti || !$noprimary);
           next if    $$menuitem[3]    eq 'Logout'
                   && $ltiexc{'logout'};
   
           my $title = $menuitem->[3];
           if (defined($secondary_submenu{$title})) {
               my ($link,$target);
               if ($menuitem->[0] ne '') {
                   $link = $menuitem->[0];
                   unless ($ltitarget eq 'iframe') {   
                       $target = '_top';
                   }
               } else {
                   $link = '#';
               }
               my @scndsub;
               if (ref($secondary_submenu{$title}) eq 'ARRAY') {
                   foreach my $item (@{$secondary_submenu{$title}}) {
                       if (ref($item) eq 'ARRAY') {
                           next if ($item->[2] eq 'vgr' && !$canvgr);
                           next if ($item->[2] eq 'opa' && !$canmodpara);
                           next if ($item->[2] eq 'vpa' && !$canviewpara);
                           next if ($item->[2] eq 'viewusers' && !($canmodifyuser || $canviewusers));
                           next if ($item->[2] eq 'mgr' && !$canmgr);
                           next if ($item->[2] eq 'vcg' && !$canviewgrps);
                           next if ($item->[2] eq 'crsedit' && !$canedit && !$canvieweditor);
                           next if ($item->[2] eq 'params' && !$canmodpara && !$canviewpara);
                           next if ($item->[2] eq 'author' && !$author);
                           next if ($item->[2] eq 'cca' && !$canmodifycoauthor);
                           next if ($item->[2] eq 'lti' && !$lti);
                           if ($item->[2] =~ /^lti(portfolio|wishlist|blog)$/) {
                               my $tool = $1;
                               next if !$lti;
                               next if (!&Apache::lonnet::usertools_access('','',$tool,
                                                                           undef,'tools'));
                           }
                           push(@scndsub,$item);
                       }
                   }
                   if ($title eq 'Personal' && $env{'user.name'} && $env{'user.domain'} ) {
                       unless ($ltiexc{'fullname'}) {
                           $title = &Apache::loncommon::plainname($env{'user.name'},$env{'user.domain'});
                       }
                   }
                   if (@scndsub > 0) {
                       $menu .= &create_submenu($link,$target,$title,\@scndsub,1);
                   } elsif ($link ne '#') {
                       $menu .= '<li><a href="'.$link.'" target="'.$target.'">'.&mt($title).'</a></li>';
                   }
               }
           } elsif ($$menuitem[3] eq 'Roles' && $env{'request.course.id'}) {
               # special treatment for role selector
               ($roleswitcher_js,$roleswitcher_form,my $switcher) =
                   &roles_selector(
                       $env{'course.' . $env{'request.course.id'} . '.domain'},
                       $env{'course.' . $env{'request.course.id'} . '.num'},
                       $httphost,$ltitarget
                   );
               $menu .= $switcher;
           } elsif ($$menuitem[3] eq 'Help') { # special treatment for helplink
               next if ($crstype eq 'Placement');
               $menu .= '<li>'.&Apache::loncommon::top_nav_help('Help').'</li>';
           } else {
               if ($$menuitem[3] eq 'Syllabus' && $env{'request.course.id'}) {
                   my $url = $$menuitem[0];
                   $url =~ s{\[cdom\]/\[cnum\]}{$cdom/$cnum};
                   if (&Apache::lonnet::is_on_map($url)) {
                       unless ($$menuitem[0] =~ /(\?|\&)register=1/) {
                           $$menuitem[0] .= (($$menuitem[0]=~/\?/)? '&' : '?').'register=1';
                       }
                   } else {
                       $$menuitem[0] =~ s{\&?register=1}{};
                   }
                   if ($env{'course.'.$env{'request.course.id'}.'.externalsyllabus'} =~ m{^http://}) {
                       if (($ENV{'SERVER_PORT'} == 443) || ($env{'request.use_absolute'} =~ m{^https://})) {
                           unless (&Apache::lonnet::uses_sts()) {
                               unless ($$menuitem[0] =~ m{^https?://}) {
                                   $$menuitem[0] = 'http://'.$ENV{'SERVER_NAME'}.$$menuitem[0];
                               }
                               unless ($$menuitem[0] =~ /(\&|\?)usehttp=1/) {
                                   $$menuitem[0] .= (($$menuitem[0]=~/\?/) ? '&' : '?').'usehttp=1';
                               }
                           }
                       }
                   }
                   $$menuitem[0] = &HTML::Entities::encode($$menuitem[0],'&<>"');
               }
               $menu .= &prep_menuitem(\@$menuitem,$ltitarget);
           }
       }
       if ($menu =~ /\[url\].*\[symb\]/) {
           my $escurl  = &escape( &Apache::lonenc::check_encrypt(
                                $env{'request.noversionuri'}));
   
           my $escsymb = &escape( &Apache::lonenc::check_encrypt(
                                $env{'request.symb'})); 
   
           if (    $env{'request.state'} eq 'construct'
               and (   $env{'request.noversionuri'} eq '' 
                    || !defined($env{'request.noversionuri'}))) 
           {
               my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'};
               ($escurl = $env{'request.filename'}) =~ s{^\Q$londocroot\E}{};
               $escurl  = &escape($escurl);
           }
           $menu =~ s/\[url\]/$escurl/g;
           $menu =~ s/\[symb\]/$escsymb/g;
       }
       $menu =~ s/\[uname\]/$$author{user}/g;
       $menu =~ s/\[udom\]/$$author{dom}/g;
       $menu =~ s/\[javascript\]/javascript:/g;
       if ($env{'request.course.id'}) {
           $menu =~ s/\[cnum\]/$cnum/g;
           $menu =~ s/\[cdom\]/$cdom/g;
       }
       if ($menu) {
           $menu = "<ul id=\"LC_secondary_menu\">$menu</ul>";
       }
       if ($roleswitcher_form) {
           $menu .= "\n$roleswitcher_js\n$roleswitcher_form";
       }
       return $menu;
   }
   
   sub create_submenu {
       my ($link,$target,$title,$submenu,$translate,$addclass) = @_;
       return unless (ref($submenu) eq 'ARRAY');
       my $disptarget;
       if ($target ne '') {
           $disptarget = ' target="'.$target.'"';
       }
       my $menu = '<li class="LC_hoverable '.$addclass.'">'.
                  '<a href="'.$link.'"'.$disptarget.'>'.
                  '<span class="LC_nobreak">'.$title.
                  '<span class="LC_fontsize_small" style="font-weight:normal;">'.
                  ' &#9660;</span></span></a>'.
                  '<ul>';
   
       # $link and $title are only used in the initial string written in $menu
       # as seen above, not needed for nested submenus
       $menu .= &build_submenu($target, $submenu, $translate, '1');
       $menu .= '</ul></li>';
   
       return $menu;
   }
   
   # helper routine for create_submenu
   # build the dropdown (and nested submenus) recursively
   # see perldoc create_submenu documentation for further information
   sub build_submenu {
       my ($target, $submenu, $translate, $first_level) = @_; 
       unless (@{$submenu}) {
           return '';
       }
   
       my $menu = '';
       my $count = 0;
       my $numsub = scalar(@{$submenu});
       foreach my $item (@{$submenu}) {
           $count ++;
           if (ref($item) eq 'ARRAY') {
               my $href = $item->[0];
               my $bordertop;
               my $borderbot;
               my $title;
   
               if ($translate) {
                    $title = &mt($item->[1]);
               } else {
                   $title = $item->[1];
               }
   
               if ($count == 1 && !$first_level) {
                   $bordertop = 'border-top: 1px solid black;';
               }
               if ($count == $numsub) {
                   $borderbot = 'border-bottom: 1px solid black;';
               }
   
               # href is a reference to another submenu
               if (ref($href) eq 'ARRAY') {
                   $menu .= '<li style="margin:0;padding:0;'.$bordertop . $borderbot . '">';
                   $menu .= '<p><span class="LC_primary_menu_innertitle">'
    . $title . '</span><span class="LC_primary_menu_innerarrow">&#9654;</span></p>';
                   $menu .= '<ul>';
                   $menu .= &build_submenu($target, $href, $translate);
                   $menu .= '</ul>';
                   $menu .= '</li>';    
               } else {    # href is the actual hyperlink and does not represent another submenu
                           # for the current menu title
                   if ($href =~ /(aboutme|rss\.html)$/) {
                       next unless (($env{'user.name'} ne '') && ($env{'user.domain'} ne ''));
                       $href =~ s/\[domain\]/$env{'user.domain'}/g;
                       $href =~ s/\[user\]/$env{'user.name'}/g;
                   } elsif (($href =~ m{^/adm/preferences\?}) && ($href =~ /\[returnurl\]/)) {
                       my $returnurl = $ENV{'REQUEST_URI'};
                       if ($ENV{'REQUEST_URI'} =~ m{/adm/preferences\?action=(?:changedomcoord|authorsettings)\&returnurl=([^\&]+)$}) {
                           $returnurl = $1;
                       }
                       if (($returnurl =~ m{^/adm/createuser($|\?action=)}) ||
                           ($returnurl =~ m{^/priv/$match_domain/$match_username}) ||
                           ($returnurl =~ m{^/res(/?$|/$match_domain/$match_username)})) {
                           $returnurl =~ s{\?.*$}{};
                           $returnurl = '&amp;returnurl='.&HTML::Entities::encode($returnurl,'"<>&\'');
                       } else {
                           undef($returnurl);
                       }
                       $href =~ s/\[returnurl\]/$returnurl/;
                   }
                   unless (($href eq '') || ($href =~ /^\#/)) {
                       if ($target eq '_top') {
                           $target = ' target="_top"';
                       }
                   }
   
                   $menu .= '<li style="margin:0;padding:0;'. $bordertop . $borderbot .'">';
                   $menu .= '<a href="'.$href.'"'.$target.'>' .  $title . '</a>';
                   $menu .= '</li>';
               }
           }
       }
       return $menu;
   }
   
 sub innerregister {  sub innerregister {
     my $forcereg=shift;      my ($forcereg,$bread_crumbs,$group,$pagebuttonshide,$hostname,$ltiscope,$ltiuri) = @_;
     my $target = shift;      my $const_space = ($env{'request.state'} eq 'construct');
     my $titletable = shift;  
     my $result = '';  
     my ($uname,$thisdisfn);  
     my $const_space = ($ENV{'request.state'} eq 'construct');  
     my $is_const_dir = 0;      my $is_const_dir = 0;
   
     if ($ENV{'request.noversionuri'} eq '/res/adm/pages/menu.html') { return ''; }      if ($env{'request.noversionuri'} =~ m{^/res/adm/pages/}) { return ''; }
   
     $Apache::lonxml::registered=1;      $env{'request.registered'} = 1;
   
     my $textinter=($ENV{'browser.interface'} eq 'textual');      undef(@inlineremote);
     my $noremote=($ENV{'environment.remote'} eq 'off');  
       
     my $textual=($textinter || $noremote);  
   
     @inlineremote=();      my ($mapurl,$resurl,$crstype,$navmap);
     undef @inlineremote;  
   
     my $reopen=&Apache::lonmenu::reopenmenu();      if ($env{'request.course.id'}) {
   #
   #course_type:  Course, Community, or Placement
   #
           $crstype = &Apache::loncommon::course_type();
           if ($env{'request.symb'}) {
               my $ignorenull;
               unless ($env{'request.noversionuri'} eq '/adm/navmaps') {
                   $ignorenull = 1;
               }
               my $symb = &Apache::lonnet::symbread('','',$ignorenull);
               ($mapurl, my $rid, $resurl) = &Apache::lonnet::decode_symb($symb);
               my $coursetitle = $env{'course.'.$env{'request.course.id'}.'.description'};
   
               my $maptitle = &Apache::lonnet::gettitle($mapurl);
               my $restitle = &Apache::lonnet::gettitle($symb);
               my (@crumbs,@mapcrumbs);
               if (($env{'request.noversionuri'} ne '/adm/navmaps') && ($mapurl ne '') &&
                   (!(($crstype eq 'Placement') && !$env{'request.role.adv'}))) {
                   unless ($ltiscope eq 'resource') {
                       if (($mapurl ne $env{'course.'.$env{'request.course.id'}.'.url'}) &&
                           !(($ltiscope eq 'map') && (&Apache::lonnet::clutter($resurl) eq $ltiuri))) {
                           $navmap = Apache::lonnavmaps::navmap->new();
                           if (ref($navmap)) {
                               @mapcrumbs = $navmap->recursed_crumbs($mapurl,$restitle);
                           }
                       }
                   }
               }
               unless (($forcereg) &&
                       ($env{'request.noversionuri'} eq '/adm/navmaps') &&
                       ($mapurl eq $env{'course.'.$env{'request.course.id'}.'.url'}) ||
                       (($crstype eq 'Placement') && (!$env{'request.role.adv'})) ||
                       ($ltiscope eq 'map') || ($ltiscope eq 'resource')) {
                   @crumbs = ({text  => $crstype.' Contents', 
                               href  => "Javascript:gopost('/adm/navmaps','')"});
               }
               if ($mapurl ne $env{'course.'.$env{'request.course.id'}.'.url'}) { 
                   if (@mapcrumbs) {
                       push(@crumbs,@mapcrumbs);
                   } elsif (!(($crstype eq 'Placement') && (!$env{'request.role.adv'})) &&
                            ($ltiscope ne 'map') && ($ltiscope ne 'resource')) {
                       push(@crumbs, {text  => '...',
                                      no_mt => 1});
                   }
               }
   
     my $newmail='';              unless ((($crstype eq 'Placement') && (!$env{'request.role.adv'})) || (@mapcrumbs) ||
     if ($noremote) {                      (!$maptitle) || ($maptitle eq 'default.sequence') ||
  $newmail='<font face="Arial,Helvetica,sans-serif"><table bgcolor="'.$pgbg.'" border="0" cellspacing="1" cellpadding="1" width="100%"><tr><td bgcolor="'.$tabbg.'">';                      ($mapurl eq $env{'course.'.$env{'request.course.id'}.'.url'}) ||
     }                      ($ltiscope eq 'resource')) {
     if (($textual) && ($ENV{'request.symb'}) && ($ENV{'request.course.id'})) {                  push @crumbs, {text => $maptitle, no_mt => 1, 
  my ($mapurl,$rid,$resurl)=&Apache::lonnet::decode_symb($ENV{'request.symb'});                                 href => &Apache::lonnet::clutter($mapurl).'?navmap=1'};
         $newmail.=$ENV{'course.'.$ENV{'request.course.id'}.'.description'};              }
         my $maptitle=&Apache::lonnet::gettitle($mapurl);              if ($restitle && !@mapcrumbs) {
  my $restitle=&Apache::lonnet::gettitle($resurl);                  push(@crumbs,{text => $restitle, no_mt => 1});
         if ($maptitle && $maptitle ne 'default.sequence') {              }
     $newmail.=', '.$maptitle;              my @tools;
               if ($env{'request.filename'} =~ /\.page$/) {
                   my %breadcrumb_tools = &Apache::lonhtmlcommon::current_breadcrumb_tools();
                   if (ref($breadcrumb_tools{'tools'}) eq 'ARRAY') {
                       @tools = @{$breadcrumb_tools{'tools'}};
                   }
               }
               &Apache::lonhtmlcommon::clear_breadcrumbs();
               &Apache::lonhtmlcommon::add_breadcrumb(@crumbs);
               if (@tools) {
                   &Apache::lonhtmlcommon::add_breadcrumb_tool('tools',@tools);
               }
           } else {
               $resurl = $env{'request.noversionuri'};
               my $courseurl = &Apache::lonnet::courseid_to_courseurl($env{'request.course.id'});
               my $title = &mt('View Resource');
               if ($resurl =~ m{^\Q/uploaded$courseurl/supplemental/\E(default|\d+)/}) {
                   &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['folderpath','title']);
                   &Apache::lonhtmlcommon::clear_breadcrumbs();
                   if ($env{'form.title'}) {
                       $title = $env{'form.title'};
                   }
                   my $trail;
                   if ($env{'form.folderpath'}) {
                       &prepare_functions($resurl,$forcereg,$group,undef,undef,1,$hostname);
                       ($trail) =
                           &Apache::lonhtmlcommon::docs_breadcrumbs(undef,$crstype,undef,$title,1);
                   } else {
                       &Apache::lonhtmlcommon::add_breadcrumb(
                       {text  => "Supplemental $crstype Content",
                        href  => "javascript:gopost('/adm/supplemental','')"});
                       $title = &mt('View Resource');
                       ($trail) = 
                           &Apache::lonhtmlcommon::docs_breadcrumbs(undef,$crstype,undef,$title,1);
                   }
                   return $trail;
               } elsif ($resurl =~ m{^\Q/uploaded$courseurl/portfolio/syllabus/}) {
                   &Apache::lonhtmlcommon::clear_breadcrumbs();
                   &prepare_functions('/public'.$courseurl."/syllabus",
                                      $forcereg,$group,undef,undef,1,$hostname);
                   $title = &mt('Syllabus File');
                   my ($trail) =
                       &Apache::lonhtmlcommon::docs_breadcrumbs(undef,$crstype,undef,$title,1,$hostname);
                   return $trail;
               }
               unless ($env{'request.state'} eq 'construct') {
                   &Apache::lonhtmlcommon::clear_breadcrumbs();
                   &Apache::lonhtmlcommon::add_breadcrumb({text => 'View Resource'});
               }
         }          }
         if ($restitle) {      } elsif (! $const_space){
     $newmail.=': '.$restitle;          #a situation when we're looking at a resource outside of context of a 
           #course or construction space (e.g. with cumulative rights)
           &Apache::lonhtmlcommon::clear_breadcrumbs();
           unless ($env{'request.noversionuri'} =~ m{^/adm/$match_domain/$match_username/aboutme$}) {
               &Apache::lonhtmlcommon::add_breadcrumb({text => 'View Resource'});
         }          }
         $newmail.='&nbsp;&nbsp;&nbsp;';  
     }      }
     if (&Apache::lonmsg::newmail()) {   
        $newmail=($textual?  
  '<b><a href="/adm/communicate" target="_top">You have new messages</a></b><br />':  
                           'swmenu.setstatus("you have","messages");');  
     }  
     if ($ENV{'request.state'} eq 'construct') {  
         $newmail = $titletable;  
     }  
     if ($noremote) {  
  $newmail.='</td></tr></table></font>';  
     }  
     my $timesync=($textual?'':'swmenu.syncclock(1000*'.time.');');  
     my $tablestart=($noremote?'<font face="Arial,Helvetica,sans-serif"><table bgcolor="'.$pgbg.'" border="0" cellspacing="1" cellpadding="1" width="100%">':'').($textinter?'<br /><a href="#content">'.&mt('Skip to Content').'</a><br />':'');  
     my $tableend=($noremote?'</table></font>':'').($textinter?'<a name="content" />':'');  
 # =============================================================================  # =============================================================================
 # ============================ This is for URLs that actually can be registered  # ============================ This is for URLs that actually can be registered
     if (($ENV{'request.noversionuri'}!~/^\/(res\/)*adm\//) || ($forcereg)) {      return '' unless ( ($env{'request.noversionuri'}!~m{^/(res/)*adm/}) 
 # -- This applies to homework problems for users with grading privileges                         || $forcereg );
  my $crs='/'.$ENV{'request.course.id'};      my ($cdom,$cnum,%perms,$cfile,$switchserver,$home,$forceedit,
  if ($ENV{'request.course.sec'}) {          $forceview,$editbutton);
     $crs.='_'.$ENV{'request.course.sec'};      if (($resurl =~ m{^/?adm/($match_domain)/($match_username)/aboutme$}) ||
  }          ($env{'request.role'} !~/^(aa|ca|au)/)) {
  $crs=~s/\_/\//g;          $editbutton = &prepare_functions($resurl,$forcereg,$group,'','','',$hostname);
       }
       if ($editbutton eq '') {
           $editbutton = &clear(6,1);
       }
   
         my $hwkadd='';  #
         if ($ENV{'request.filename'}=~/\.(problem|exam|quiz|assess|survey|form)$/) {  # This applies in course context
     if (&Apache::lonnet::allowed('vgr',$crs)) {  #
  $hwkadd.=&switch('','',7,1,'subm.gif','view sub-[_1]','missions[_1]',      if ($env{'request.course.id'}) {
                        "gocmd('/adm/grades','submission')",          $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
        'View user submissions for this assessment resource');          $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
             }          $perms{'mdc'} = &Apache::lonnet::allowed('mdc',$env{'request.course.id'});
     if (&Apache::lonnet::allowed('mgr',$crs)) {          $perms{'cev'} = &Apache::lonnet::allowed('cev',$env{'request.course.id'});
  $hwkadd.=&switch('','',7,2,'pgrd.gif','problem[_1]','grades[_3]',          my @privs;
                        "gocmd('/adm/grades','gradingmenu')",          my $gradable_exttool;
                        'Modify user grades for this assessment resource');          if ($env{'request.symb'} ne '') {
                if ($env{'request.noversionuri'} =~ m{^/adm/$cdom/$cnum/(\d+)/ext\.tool$}) {
                    if (&Apache::lonnet::EXT('resource.0.gradable') =~ /^yes$/i) {
                        $gradable_exttool = 1;
                        push(@privs,('mgr','vgr'));
                    }
                } elsif ($env{'request.filename'}=~/$LONCAPA::assess_re/) {
                    push(@privs,('mgr','vgr'));
                }
                push(@privs,('opa','vpa'));
           }
           foreach my $priv (@privs) {
               $perms{$priv} = &Apache::lonnet::allowed($priv,$env{'request.course.id'});
               if (!$perms{$priv} && $env{'request.course.sec'} ne '') {
                   $perms{$priv} = 
                       &Apache::lonnet::allowed($priv,"$env{'request.course.id'}/$env{'request.course.sec'}");
             }              }
           }
   #
   # Determine whether or not to show Grades and Submissions buttons
   #
           if (($env{'request.symb'} ne '') &&
               (($env{'request.filename'}=~/$LONCAPA::assess_re/) || ($gradable_exttool))) {
               if ($perms{'mgr'}) {
                   &switch('','',7,2,'pgrd.png','Content Grades','grades[_4]',
                           "gocmd('/adm/grades','gradingmenu')",
                           'Content Grades');
               } elsif ($perms{'vgr'}) {
                   &switch('','',7,2,'subm.png','Content Submissions','missions[_1]',
                           "gocmd('/adm/grades','submission')",
                           'Content Submissions');
                }
           }
           if (($env{'request.symb'} ne '') && (($perms{'opa'}) || ($perms{'vpa'}))) {
               &switch('','',7,3,'pparm.png','Content Settings','parms[_2]',
                       "gocmd('/adm/parmset','set')",
                       'Content Settings');
  }   }
  if (&Apache::lonnet::allowed('opa',$crs)) {  # End grades/submissions check
     $hwkadd.=&switch('','',7,3,'pparm.gif','problem[_2]','parms[_2]',  
      "gocmd('/adm/parmset','set')",  #
      'Modify deadlines, etc, for this resource');  # This applies to items inside a folder/page modifiable in the course.
  }  #
 # -- End Homework          if (($env{'request.symb'}=~/^uploaded/) && (($perms{'mdc'}) || ($perms{'cev'}))) {
         ###              my $text = 'Edit Folder';
         ### Determine whether or not to display the 'cstr' button for this              if (($mapurl =~ /\.page$/) ||
         ### resource                  ($env{'request.symb'}=~
         ###                       m{uploaded/$cdom/$cnum/default_\d+\.page$}))  {
         my $editbutton = '';                  $text = 'Edit Page';
         if ($ENV{'user.author'}) {  
             if ($ENV{'request.role'}=~/^(ca|au)/) {  
                 # Set defaults for authors  
                 my ($top,$bottom) = ('con-','struct');  
                 my $action = "go('/priv/".$ENV{'user.name'}."');";  
                 my $cadom  = $ENV{'request.role.domain'};  
                 my $caname = $ENV{'user.name'};  
                 my $desc = "Enter my resource construction space";  
                 # Set defaults for co-authors  
                 if ($ENV{'request.role'} =~ /^ca/) {   
                     ($cadom,$caname)=($ENV{'request.role'}=~/(\w+)\/(\w+)$/);  
                     ($top,$bottom) = ('co con-','struct');  
                     $action = "go('/priv/".$caname."');";  
                     $desc = "Enter construction space as co-author";  
                 }  
                 # Check that we are on the correct machine  
                 my $home = &Apache::lonnet::homeserver($caname,$cadom);  
  my $allowed=0;  
  my @ids=&Apache::lonnet::current_machine_ids();  
  foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } }  
  if (!$allowed) {  
     $editbutton=&switch('','',6,1,$top,,$bottom,$action,$desc);  
                 }  
             }  
             ##  
             ## Determine if user can edit url.  
             ##  
             my $cfile='';  
             my $cfuname='';  
             my $cfudom='';  
             if ($ENV{'request.filename'}) {  
                 my $file=&Apache::lonnet::declutter($ENV{'request.filename'});  
                 $file=~s/^(\w+)\/(\w+)/\/priv\/$2/;  
                 # Check that the user has permission to edit this resource  
                 ($cfuname,$cfudom)=&Apache::loncacc::constructaccess($file,$1);  
                 if (defined($cfudom)) {  
     my $home=&Apache::lonnet::homeserver($cfuname,$cfudom);  
     my $allowed=0;  
     my @ids=&Apache::lonnet::current_machine_ids();  
     foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } }  
     if ($allowed) {  
                         $cfile=$file;  
                     }  
                 }  
             }          
             # Finally, turn the button on or off  
             if ($cfile && !$const_space) {  
                 $editbutton=&switch  
                     ('','',6,1,'cstr.gif','edit[_1]','resource[_2]',  
                      "go('".$cfile."');","Edit this resource");  
             } elsif ($editbutton eq '') {  
                 $editbutton=&clear(6,1);  
             }              }
               &switch('','',7,4,'docs-22x22.png',$text,'parms[_2]',
                       "gocmd('/adm/coursedocs','direct')",
                       'Folder/Page Content');
         }          }
         ###  # End modifiable folder/page container check
         ###      }
   # End course context
   
 # Prepare the rest of the buttons  # Prepare the rest of the buttons
         my $menuitems;          my ($menuitems,$got_prt,$got_wishlist);
         if ($const_space) {          if ($const_space) {
     my ($uname,$thisdisfn) =  #
  ($ENV{'request.filename'}=~m|^/home/([^/]+)/public_html/(.*)|);  # We are in construction space
             my $currdir = '/priv/'.$uname.'/'.$thisdisfn;  #
   
               my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'};
       my ($udom,$uname,$thisdisfn) =
    ($env{'request.filename'}=~m{^\Q$londocroot/priv/\E([^/]+)/([^/]+)/(.*)$});
               my $currdir = '/priv/'.$udom.'/'.$uname.'/'.$thisdisfn;
             if ($currdir =~ m-/$-) {              if ($currdir =~ m-/$-) {
                 $is_const_dir = 1;                  $is_const_dir = 1;
                   if ($thisdisfn eq '') {
                       unless (($env{'request.course.id'}) && 
                               ($env{'course.'.$env{'request.course.id'}.'.num'} eq $uname) &&
                               ($env{'course.'.$env{'request.course.id'}.'.domain'} eq $udom)) { 
                           $is_const_dir = 2;
                       }
                   }
             } else {              } else {
                 $currdir =~ s#[^/]+$##;                  $currdir =~ s|[^/]+$||;
    my $cleandisfn = &Apache::loncommon::escape_single($thisdisfn);
    my $esc_currdir = &Apache::loncommon::escape_single($currdir);
   #
   # Probably should be in mydesk.tab
   #
                 $menuitems=(<<ENDMENUITEMS);                  $menuitems=(<<ENDMENUITEMS);
 s&6&1&list.gif&list[_1]&dir[_1]&golist('$currdir')&List current directory  s&6&1&list.png&Directory&dir[_1]&golist('$esc_currdir')&List current directory
 s&6&2&rtrv.gif&retrieve[_1]&version[_1]&gocstr('/adm/retrieve','/~$uname/$thisdisfn')&Retrieve old version  s&6&2&rtrv.png&Retrieve&version[_1]&gocstr('/adm/retrieve','/priv/$udom/$uname/$cleandisfn')&Retrieve old version
 s&6&3&pub.gif&publish[_1]&resource[_1]&gocstr('/adm/publish','/~$uname/$thisdisfn')&Publish this resource  s&6&3&pub.png&Publish&resource[_3]&gocstr('/adm/publish','/priv/$udom/$uname/$cleandisfn')&Publish this resource
 s&7&1&del.gif&delete[_1]&resource[_2]&gocstr('/adm/cfile?action=delete','/~$uname/$thisdisfn')&Delete this resource  s&7&1&del.png&Delete&resource[_2]&gocstr('/adm/cfile?action=delete','/priv/$udom/$uname/$cleandisfn')&Delete this resource
 s&7&2&prt.gif&prepare[_1]&printout[_1]&gocstr('/adm/printout','/~$uname/$thisdisfn')&Prepare a printable document  s&7&2&prt.png&Print&printout[_1]&gocstr('/adm/printout','/priv/$udom/$uname/$cleandisfn')&Prepare a printable document
 ENDMENUITEMS  ENDMENUITEMS
             }              }
         } elsif (defined($ENV{'request.course.id'})) {                  if (ref($bread_crumbs) eq 'ARRAY') {
     $menuitems=(<<ENDMENUITEMS);                      &Apache::lonhtmlcommon::clear_breadcrumbs();
 c&3&1                      foreach my $crumb (@{$bread_crumbs}){
 s&2&1&back.gif&backward[_1]&&gopost('/adm/flip','back:'+currentURL)&Go to the previous resource in the course sequence&1                          &Apache::lonhtmlcommon::add_breadcrumb($crumb);
 s&2&3&forw.gif&forward[_1]&&gopost('/adm/flip','forward:'+currentURL)&Go to the next resource in the course sequence&3                      }
                   }
           } elsif ( defined($env{'request.course.id'}) && 
    $env{'request.symb'} ne '' ) {
   #
   # We are in a course and looking at a registered URL
   # Should probably be in mydesk.tab
   #
               $menuitems = "c&3&1";
               if ($ltiscope eq 'resource') {
   # Suppress display of backward arrow for LTI Provider if scope is resource.
   # Suppress display of forward arrow for LTI Provider if scope is resource.
               } elsif ($ltiscope eq 'map') {
   # Suppress display of backward arrow for LTI Provider if scope is map and this is first resource.
   # Suppress display of forward arrow for LTI Provider if scope is map and this is the last resource.
                   my $showforw = 1;
                   my $showback = 1;
                   my $navmap = Apache::lonnavmaps::navmap->new();
                   if (ref($navmap)) {
                       my $mapres = $navmap->getResourceByUrl($ltiuri);
                       if (ref($mapres)) {
                           if ($navmap->isLastResource($mapres,$env{'request.symb'})) {
                               $showforw = 0;
                           }
                           if ($navmap->isFirstResource($mapres,$env{'request.symb'})) {
                               $showback = 0;
                           }
                       }
                   }
                   if ($showback) {
                       $menuitems.="
   s&2&1&back.png&&&gopost('/adm/flip','back:'+currentURL)&Previous content resource&&1";
                   }
                   if ($showforw) {
                       $menuitems.="
   s&2&3&forw.png&&&gopost('/adm/flip','forward:'+currentURL)&Next content resource&&3";
                   }
               } elsif (($crstype ne 'Placement') || ($env{'request.role.adv'})) {
                   $menuitems.="
   s&2&1&back.png&&&gopost('/adm/flip','back:'+currentURL)&Previous content resource&&1
   s&2&3&forw.png&&&gopost('/adm/flip','forward:'+currentURL)&Next content resource&&3";
               } else {
   # Suppress display of backward arrow for Placement Tests
   # Suppress display of forward arrow for Placement Tests if this is the last resource.
                   my $showforw = 1;
                   if ($env{'request.symb'}) {
                       my $navmap = Apache::lonnavmaps::navmap->new();
                       if (ref($navmap)) {
                           if (&Apache::lonplacementtest::is_lastres($env{'request.symb'},$navmap)) {
                               $showforw = 0;
                           }
                       }
                   }
                   if ($showforw) {
                       $menuitems.="
   s&2&3&forw.png&&&gopost('/adm/flip','forward:'+currentURL)&Next content resource&&3";
                   }
               }
       $menuitems .= (<<ENDMENUITEMS);
   
 c&6&3  c&6&3
 c&8&1  c&8&1
 c&8&2  c&8&2
 s&8&3&prt.gif&prepare[_1]&printout[_1]&gopost('/adm/printout',currentURL)&Prepare a printable document  s&8&3&prt.png&Print&printout[_1]&gopost('/adm/printout',currentURL)&Prepare a printable document
 s&9&1&sbkm.gif&set[_1]&bookmark[_2]&set_bookmark()&Set a bookmark for this resource&2  ENDMENUITEMS
 s&9&3&anot.gif&anno-[_1]&tations[_1]&annotate()&Make notes and annotations about this resource&2              $got_prt = 1;
               if (($env{'user.adv'}) && ($env{'request.uri'} =~ /^\/res/)
                   && (!$env{'request.enc'})) {
                   my ($cnum,$cdom) = &Apache::loncommon::crsauthor_url($env{'request.uri'});
                   unless ($cnum) {
                       # wishlist is only available for users with access to resource-pool
                       # and links can only be set for resources within the resource-pool
                       $menuitems .= (<<ENDMENUITEMS);
   s&9&1&wishlist-link.png&Stored Links&wishlistlink[_2]&set_wishlistlink()&Save a link for this resource in my personal Stored Links repository&&1
 ENDMENUITEMS  ENDMENUITEMS
             unless ($ENV{'request.noversionuri'}=~/\/(bulletinboard|smppg|navmaps|syllabus|aboutme)(\?|$)/) {                      $got_wishlist = 1;
         $menuitems.=(<<ENDREALRES);                  }
 s&6&3&catalog.gif&catalog[_1]&info[_1]&catalog_info()&Show catalog information              }
 s&8&1&eval.gif&evaluate[_1]&this[_1]&gopost('/adm/evaluate',currentURL,1)&Provide my evaluation of this resource  
 s&8&2&fdbk.gif&feedback[_1]&discuss[_1]&gopost('/adm/feedback',currentURL,1)&Provide feedback messages or contribute to the course discussion about this resource  my $currentURL = &Apache::loncommon::get_symb();
   my ($symb_old,$symb_old_enc) = &Apache::loncommon::clean_symb($currentURL);
   my $annotation = &Apache::loncommon::get_annotation($symb_old,$symb_old_enc);
   $menuitems.="s&9&3&";
   if(length($annotation) > 0){
    $menuitems.="anot2.png";
   }else{
    $menuitems.="anot.png";
   }
   $menuitems.="&Notes&&annotate()&";
   $menuitems.="Make notes and annotations about this resource&&1\n";
   my $is_mobile;
   if ($env{'browser.mobile'}) {
       $is_mobile = 1;
   }
   
               unless ($env{'request.noversionuri'}=~/\/(bulletinboard|smppg|navmaps|syllabus|aboutme|viewclasslist|portfolio)(\?|$)/) {
    if ((!$env{'request.enc'}) && ($env{'request.noversionuri'} !~ m{^/adm/wrapper/ext/}) &&
                       ($env{'request.noversionuri'} !~ m{^/uploaded/$match_domain/$match_courseid/(docs/|default_\d+\.page$)}) &&
                       ($env{'request.noversionuri'} !~ m{^/adm/.+/ext\.tool$})) {
       $menuitems.=(<<ENDREALRES);
   s&6&3&catalog.png&Info&info[_1]&catalog_info(currentURL,'$is_mobile')&Show Metadata
   ENDREALRES
                   }
                   unless (($env{'request.noversionuri'} =~ m{^/uploaded/$match_domain/$match_courseid/(docs/|default_\d+\.page$)}) ||
                           ($env{'request.noversionuri'} =~ m{^\Q/adm/wrapper/\E(ext|uploaded)/}) ||
                           ($env{'request.noversionuri'} =~ m{^/adm/.+/ext\.tool$})) {
                       $menuitems.=(<<ENDREALRES);
   s&8&1&eval.png&Evaluate&this[_1]&gopost('/adm/evaluate',currentURL,1)&Provide my evaluation of this resource
 ENDREALRES  ENDREALRES
                   }
                   unless ($env{'request.noversionuri'} =~ m{^\Q/adm/wrapper/\E(ext|uploaded)/}) {
                       $menuitems.=(<<ENDREALRES);
   s&8&2&fdbk.png&Communicate&discuss[_1]&gopost('/adm/feedback',currentURL,1)&Provide feedback messages or contribute to the course discussion about this resource
   ENDREALRES
                   }
       }
           }
    if ($env{'request.uri'} =~ /^\/res/) {
               unless ($got_prt) {
           $menuitems .= (<<ENDMENUITEMS);
   s&8&3&prt.png&Print&printout[_1]&gopost('/adm/printout',currentURL)&Prepare a printable document
   ENDMENUITEMS
                   $got_prt = 1;
               }
               unless ($got_wishlist) {
                   if (($env{'user.adv'}) && (!$env{'request.enc'})) {
                       # wishlist is only available for users with access to resource-pool
                       $menuitems .= (<<ENDMENUITEMS);
   s&9&1&wishlist-link.png&Stored Links&wishlistlink[_2]&set_wishlistlink()&Save a link for this resource in your personal Stored Links repository&&1
   ENDMENUITEMS
                       $got_wishlist = 1;
                   }
     }      }
         }          }
         my $buttons='';          my $buttons='';
         foreach (split(/\n/,$menuitems)) {          foreach (split(/\n/,$menuitems)) {
     my ($command,@rest)=split(/\&/,$_);      my ($command,@rest)=split(/\&/,$_);
             if ($command eq 's') {              my $idx=10*$rest[0]+$rest[1];
  $buttons.=&switch('','',@rest);              if (&hidden_button_check() eq 'yes') {
             } else {                  if ($idx == 21 ||$idx == 23) {
                 $buttons.=&clear(@rest);                      $buttons.=&switch('','',@rest);
                   } else {
                       $buttons.=&clear(@rest);
                   }
               } else {  
                   if ($command eq 's') {
               $buttons.=&switch('','',@rest);
                   } else {
                       $buttons.=&clear(@rest);
                   }
             }              }
         }          }
         if ($textual) {          my $showprogress;
 # Registered, textual output          if (($crstype eq 'Placement') && (!$env{'request.role.adv'})) {
     my $inlinebuttons='';              $showprogress = &placement_progress();
           }
     if ($ENV{'browser.interface'} eq 'textual') {  
  $inlinebuttons=  
                         join('',map { (defined($_)?$_:'') } @inlineremote);  
     } else {  
  $inlinebuttons=(<<ENDINLINE);  
 <tr><td>$inlineremote[21]</td><td>&nbsp;</td><td>$inlineremote[23]</td></tr>  
 <tr><td>$inlineremote[61]</td><td>$inlineremote[62]</td><td>$inlineremote[63]</td></tr>  
 <tr><td>$inlineremote[71]</td><td>$inlineremote[72]</td><td>$inlineremote[73]</td></tr>  
 <tr><td>$inlineremote[81]</td><td>$inlineremote[82]</td><td>$inlineremote[83]</td></tr>  
 <tr><td>$inlineremote[91]</td><td>$inlineremote[92]</td><td>$inlineremote[93]</td></tr>  
 ENDINLINE  
     }  
             if ($const_space && $is_const_dir) {  
                 $inlinebuttons = '';  
             }  
     $result =(<<ENDREGTEXT);  
 <script type="text/javascript">  
 // BEGIN LON-CAPA Internal  
 </script>  
 $timesync  
 $newmail  
 $tablestart  
 $inlinebuttons  
 $tableend  
 <script type="text/javascript">  
 // END LON-CAPA Internal  
 </script>  
   
 ENDREGTEXT  
 # Registered, graphical output  
         } else {  
     my $requri=&Apache::lonnet::clutter(&Apache::lonnet::fixversion((split(/\?/,$ENV{'request.noversionuri'}))[0]));  
     $requri=&Apache::lonenc::check_encrypt(&Apache::lonnet::unescape($requri));  
     my $cursymb=&Apache::lonenc::check_encrypt($ENV{'request.symb'});  
     my $navstatus=&get_nav_status();  
     my $clearcstr;  
     if ($ENV{'user.adv'}) { $clearcstr='clearbut(6,1)'; }  
     $result = (<<ENDREGTHIS);  
        
 <script type="text/javascript">  
 // BEGIN LON-CAPA Internal  
 var swmenu=null;  
   
     function LONCAPAreg() {   my $addremote=0;
   swmenu=$reopen;   foreach (@inlineremote) { if ($_ ne '') { $addremote=1; last;} }
           swmenu.clearTimeout(swmenu.menucltim);  
           $timesync  
           $newmail  
           $buttons  
   swmenu.currentURL="$requri";  
           swmenu.reloadURL=swmenu.currentURL+window.location.search;  
           swmenu.currentSymb="$cursymb";  
           swmenu.reloadSymb="$cursymb";  
           swmenu.currentStale=0;  
   $navstatus  
           $hwkadd  
           $editbutton  
     }  
   
     function LONCAPAstale() {  
   swmenu=$reopen  
           swmenu.currentStale=1;  
           if (swmenu.reloadURL!='' && swmenu.reloadURL!= null) {   
              swmenu.switchbutton  
              (3,1,'reload.gif','return','location','go(reloadURL)','Return to the last known location in the course sequence');  
   }  
           swmenu.clearbut(7,1);  
           swmenu.clearbut(7,2);  
           swmenu.clearbut(7,3);  
           swmenu.menucltim=swmenu.setTimeout(  
  'clearbut(2,1);clearbut(2,3);clearbut(8,1);clearbut(8,2);clearbut(8,3);'+  
  'clearbut(9,1);clearbut(9,3);clearbut(6,3);$clearcstr',  
   2000);  
       }  
   
 // END LON-CAPA Internal      if ($addremote) {
 </script>          my ($countdown,$buttonshide);
 ENDREGTHIS          if ($env{'request.filename'} =~ /\.page$/) {
         }              my %breadcrumb_tools = &Apache::lonhtmlcommon::current_breadcrumb_tools();
 # =============================================================================              if (ref($breadcrumb_tools{'tools'}) eq 'ARRAY') {
     } else {                  $countdown = $breadcrumb_tools{'tools'}->[0];
 # ========================================== This can or will not be registered              }
         if ($textual) {              $buttonshide = $pagebuttonshide;
 # Not registered, textual  
     $result= (<<ENDDONOTREGTEXT);  
 ENDDONOTREGTEXT  
         } else {          } else {
 # Not registered, graphical              $countdown = &countdown_timer();
            $result = (<<ENDDONOTREGTHIS);              $buttonshide = &hidden_button_check();
           }
           &Apache::lonhtmlcommon::clear_breadcrumb_tools();
   
 <script type="text/javascript">              &Apache::lonhtmlcommon::add_breadcrumb_tool(
 // BEGIN LON-CAPA Internal                  'navigation', @inlineremote[21,23]);
 var swmenu=null;  
   
     function LONCAPAreg() {          if ($buttonshide eq 'yes') {
   swmenu=$reopen              if ($countdown) {
           $timesync                  &Apache::lonhtmlcommon::add_breadcrumb_tool('tools',$countdown);
           swmenu.currentStale=1;              }
           swmenu.clearbut(2,1);              if ($showprogress) {
           swmenu.clearbut(2,3);                  &Apache::lonhtmlcommon::add_breadcrumb_tool('tools',$showprogress);
           swmenu.clearbut(8,1);              }
           swmenu.clearbut(8,2);          } else {
           swmenu.clearbut(8,3);              my @tools = @inlineremote[93,91,81,82,83];
           if (swmenu.currentURL) {              if ($countdown) {
              swmenu.switchbutton                  unshift(@tools,$countdown);
               (3,1,'reload.gif','return','location','go(currentURL)');              }
    } else {              &Apache::lonhtmlcommon::add_breadcrumb_tool(
       swmenu.clearbut(3,1);                  'tools',@tools);
           }  
     }  
   
     function LONCAPAstale() {              #publish button in construction space
               if ($env{'request.state'} eq 'construct'){
                   &Apache::lonhtmlcommon::add_breadcrumb_tool(
                        'advtools', $inlineremote[63]);
               } else {
                   &Apache::lonhtmlcommon::add_breadcrumb_tool(
                        'tools', $inlineremote[63]);
               }
               &advtools_crumbs(@inlineremote);
           }
       } else {
           if ($showprogress) {
               &Apache::lonhtmlcommon::add_breadcrumb_tool('tools',$showprogress);
           }
     }      }
       my ($topic_help,$topic_help_text);
 // END LON-CAPA Internal      if ($is_const_dir == 2) {
 </script>          if ((($ENV{'SERVER_PORT'} == 443) || 
 ENDDONOTREGTHIS               ($Apache::lonnet::protocol{$Apache::lonnet::perlvar{'lonHostID'}} eq 'https')) && 
        }              (&Apache::lonnet::usertools_access($env{'user.name'},$env{'user.domain'},'webdav'))) {
 # =============================================================================              $topic_help = 'Authoring_WebDAV,Authoring_WebDAV_Mac_10v6,Authoring_WebDAV_Mac_10v10,'.
                             'Authoring_WebDAV_Windows_v7,Authoring_WebDAV_Linux_Centos';
               $topic_help_text = 'About WebDAV access';
           }
     }      }
     return $result;      return   &Apache::lonhtmlcommon::scripttag('', 'start')
              . &Apache::lonhtmlcommon::breadcrumbs(undef,undef,0,'','','','',$topic_help,$topic_help_text)
              . &Apache::lonhtmlcommon::scripttag('', 'end');
 }  }
   
 sub loadevents() {  sub get_editbutton {
     if ($ENV{'request.state'} eq 'construct' ||      my ($cfile,$home,$switchserver,$forceedit,$forceview,$forcereg,$hostname) = @_;
  $ENV{'request.noversionuri'} eq '/res/adm/pages/menu.html') { return ''; }      my $jscall;
     return 'LONCAPAreg();';      if (($forceview) && ($env{'form.todocs'})) {
 }          my ($folderpath,$command,$navmap);
           if ($env{'request.symb'}) {
 sub unloadevents() {              $folderpath = &Apache::loncommon::symb_to_docspath($env{'request.symb'},\$navmap);
     if ($ENV{'request.state'} eq 'construct' ||          } elsif ($env{'form.folderpath'} =~ /^supplemental/) {
  $ENV{'request.noversionuri'} eq '/res/adm/pages/menu.html') { return ''; }              $folderpath = $env{'form.folderpath'};
     return 'LONCAPAstale();';              $command = '&forcesupplement=1';
           }
           $folderpath = &escape(&HTML::Entities::encode(&escape($folderpath),'<>&"'));
           $jscall = "go('/adm/coursedocs?folderpath=$folderpath$command')";
       } else {
           my $suppanchor;
           if ($env{'form.folderpath'}) {
               $suppanchor = $env{'form.anchor'};
           }
           $jscall = &Apache::lonhtmlcommon::jump_to_editres($cfile,$home,$switchserver,
                                                   $forceedit,$forcereg,$env{'request.symb'},
                                                   &escape($env{'form.folderpath'}),
                                                   &escape($env{'form.title'}),$hostname,
                                                   $env{'form.idx'},&escape($env{'form.suppurl'}),
                                                   $env{'form.todocs'},$suppanchor);
       }
       if ($jscall) {
           my $icon = 'pcstr.png';
           my $label = 'Edit';
           if ($forceview) {
               $icon = 'tolastloc.png';
               $label = 'Exit Editing';
           }
           &switch('','',6,1,$icon,$label,'resource[_2]',
                   $jscall,"Edit this resource");
           return 1;
       }
       return;
 }  }
   
 # ============================================================= Start up remote  sub prepare_functions {
       my ($resurl,$forcereg,$group,$bread_crumbs,$advtools,$docscrumbs,$hostname) = @_;
       unless ($env{'request.registered'}) {
           undef(@inlineremote);
       }
       my ($cdom,$cnum,%perms,$cfile,$switchserver,$home,$forceedit,
           $forceview);
   
 sub startupremote {      if ($env{'request.course.id'}) {
     my ($lowerurl)=@_;          $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
     if (($ENV{'browser.interface'} eq 'textual') ||          $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
         ($ENV{'environment.remote'} eq 'off')) {          $perms{'mdc'} = &Apache::lonnet::allowed('mdc',$env{'request.course.id'});
      return ('<meta HTTP-EQUIV="Refresh" CONTENT="0.5; url='.$lowerurl.'" />');  
     }      }
   
       my $editbutton = '';
       my $viewsrcbutton = '';
 #  #
 # The Remote actually gets launched!  # Determine whether or not to display 'Edit' or 'View Source' icon/button
 #  #
     my $configmenu=&rawconfig();      if ($resurl =~ m{^/?adm/($match_domain)/($match_username)/aboutme$}) {
     my $esclowerurl=&Apache::lonnet::escape($lowerurl);          my $file=&Apache::lonnet::declutter($env{'request.filename'});
     my $message=&mt('"Waiting for Remote Control window to load: "+[_1]','waited');          ($cfile,$home,$switchserver,$forceedit,$forceview) =
     return(<<ENDREMOTESTARTUP);              &Apache::lonnet::can_edit_resource($file,$cnum,$cdom,
 <script type="text/javascript">                  &Apache::lonnet::clutter($resurl),$env{'request.symb'},$group);
 var timestart;          if (($cfile) && ($home ne '') && ($home ne 'no_host')) {
 function wheelswitch() {              $editbutton = &get_editbutton($cfile,$home,$switchserver,
     if (typeof(document.wheel) != 'undefined') {                                            $forceedit,$forceview,$forcereg);
  if (typeof(document.wheel.spin) != 'undefined') {          }
     var date=new Date();      } elsif ((!$env{'request.course.id'}) &&
     var waited=Math.round(30-((date.getTime()-timestart)/1000));               ($env{'user.author'}) && ($env{'request.filename'}) &&
     document.wheel.spin.value=$message;               ($env{'request.role'} !~/^(aa|ca|au)/)) {
  }  #
   # Currently do not have the role of author or co-author.
   # Do we have authoring privileges for the resource?
   #
           my $file=&Apache::lonnet::declutter($env{'request.filename'});
           ($cfile,$home,$switchserver,$forceedit,$forceview) =
               &Apache::lonnet::can_edit_resource($file,$cnum,$cdom,
                   &Apache::lonnet::clutter($resurl),$env{'request.symb'},$group);
           if (($cfile) && ($home ne '') && ($home ne 'no_host')) {
               $editbutton = &get_editbutton($cfile,$home,$switchserver,
                                             $forceedit,$forceview,$forcereg);
           }
       } elsif ($env{'request.course.id'}) {
   #
   # This applies in course context
   #
           if (($perms{'mdc'}) &&
               (($resurl =~ m{^/?public/$cdom/$cnum/syllabus}) ||
                ($resurl =~ m{^/?uploaded/$cdom/$cnum/portfolio/syllabus/}) ||
                (($resurl =~ m{^/?uploaded/$cdom/$cnum/default_\d+\.sequence$}) && ($env{'form.navmap'})))) {
               if ($resurl =~ m{^/}) {
                   $cfile = $resurl;
               } else {
                   $cfile = "/$resurl";
               }
               $home = &Apache::lonnet::homeserver($cnum,$cdom);
               if ($env{'form.forceedit'}) {
                   $forceview = 1;
               } else {
                   $forceedit = 1;
               }
               if ($cfile =~ m{^/uploaded/$cdom/$cnum/default_\d+\.sequence$}) {
                   my $text = 'Edit Folder';
                   &switch('','',7,4,'docs-22x22.png','Edit Folder','parms[_2]',
                           "gocmd('/adm/coursedocs','direct')",
                           'Folder/Page Content');
                   $editbutton = 1;
               } else {
                   $editbutton = &get_editbutton($cfile,$home,$switchserver,
                                                 $forceedit,$forceview,$forcereg,
                                                 $hostname);
               }
           } elsif (($resurl eq '/adm/extresedit') &&
                    (($env{'form.symb'}) || ($env{'form.folderpath'}))) {
               ($cfile,$home,$switchserver,$forceedit,$forceview) =
               &Apache::lonnet::can_edit_resource($resurl,$cnum,$cdom,$resurl,
                                                  $env{'form.symb'});
               if ($cfile ne '') {
                   $editbutton = &get_editbutton($cfile,$home,$switchserver,
                                                 $forceedit,$forceview,$forcereg);
               }
           } elsif (($resurl =~ m{^/?adm/viewclasslist$}) &&
                    (&Apache::lonnet::allowed('opa',$env{'request.course.id'}))) {
               ($cfile,$home,$switchserver,$forceedit,$forceview) =
               &Apache::lonnet::can_edit_resource($resurl,$cnum,$cdom,$resurl,
                                                  $env{'form.symb'});
               $editbutton = &get_editbutton($cfile,$home,$switchserver,
                                             $forceedit,$forceview,$forcereg);
           } elsif (($resurl !~ m{^/?adm/($match_domain)/($match_username)/aboutme$}) &&
                    ($resurl ne '/cgi-bin/printout.pl')) {
               if ($env{'request.filename'}) {
                   my $file=&Apache::lonnet::declutter($env{'request.filename'});
                   ($cfile,$home,$switchserver,$forceedit,$forceview) =
                       &Apache::lonnet::can_edit_resource($file,$cnum,$cdom,
                           &Apache::lonnet::clutter($resurl),$env{'request.symb'},$group);
                   if ($cfile ne '') {
                       $editbutton = &get_editbutton($cfile,$home,$switchserver,
                                                     $forceedit,$forceview,$forcereg,
                                                     $hostname);
                   }
                   if ((($cfile eq '') || (!$editbutton)) &&
                       ($resurl =~ /$LONCAPA::assess_re/)) {
                       my $showurl = &Apache::lonnet::clutter($resurl);
                       my $crs_sec = $env{'request.course.id'} . (($env{'request.course.sec'} ne '')
                                                                 ? "/$env{'request.course.sec'}"
                                                                 : '');
                       if ((&Apache::lonnet::allowed('cre','/')) &&
                           (&Apache::lonnet::metadata($resurl,'sourceavail') eq 'open')) {
                           $viewsrcbutton = 1;
                       } elsif (&Apache::lonnet::allowed('vxc',$crs_sec)) {
                           if ($showurl =~ m{^\Q/res/$cdom/\E($match_username)/}) {
                               my $auname = $1;
                               if (($env{'request.course.adhocsrcaccess'} ne '') &&
                                   (grep(/^\Q$auname\E$/,split(/,/,$env{'request.course.adhocsrcaccess'})))) {
                                   $viewsrcbutton = 1;
                               } elsif ((&Apache::lonnet::metadata($resurl,'sourceavail') eq 'open') &&
                                        (&Apache::lonnet::allowed('bre',$crs_sec))) {
                                   $viewsrcbutton = 1;
                               }
                           }
                       }
                       if ($viewsrcbutton) {
                           &switch('','',6,1,'pcstr.png','View Source','resource[_2]','open_source()',
                                   'View source code');
                       }
                   }
               }
           }
     }      }
    if (window.status=='|') {   # End determination of 'Edit' icon/button display
       window.status='/';   
    } else {  
       if (window.status=='/') {  
          window.status='-';  
       } else {  
          if (window.status=='-') {   
             window.status='\\\\';   
          } else {  
             if (window.status=='\\\\') { window.status='|'; }  
          }  
       }  
    }   
 }  
   
 // ---------------------------------------------------------- The wait function  
 var canceltim;  
 function wait() {  
    if ((menuloaded==1) || (tim==1)) {  
       window.status='Done.';  
       if (tim==0) {  
          clearTimeout(canceltim);  
          $configmenu  
          window.location='$lowerurl';    
       } else {  
   window.location='/adm/remote?action=collapse&url=$esclowerurl';  
       }  
    } else {  
       wheelswitch();  
       setTimeout('wait();',200);  
    }  
 }  
   
 function main() {  
    canceltim=setTimeout('tim=1;',30000);  
    window.status='-';  
    var date=new Date();  
    timestart=date.getTime();  
    wait();  
 }  
   
 </script>      if ($env{'request.course.id'}) {
 ENDREMOTESTARTUP  # This applies to about me page for users in a course
 }          if ($resurl =~ m{^/?adm/($match_domain)/($match_username)/aboutme$}) {
               my ($sdom,$sname) = ($1,$2);
 sub setflags() {              unless (&Apache::lonnet::is_course($sdom,$sname)) {
     return(<<ENDSETFLAGS);                  &switch('','',6,4,'mail-message-new-22x22.png','Message to user',
 <script type="text/javascript">                          '',
     menuloaded=0;                          "go('/adm/email?compose=individual&amp;recname=$sname&amp;recdom=$sdom')",
     tim=0;                              'Send message to specific user');
 </script>              }
 ENDSETFLAGS              my $hideprivileged = 1;
 }              if (&Apache::lonnet::in_course($sdom,$sname,$cdom,$cnum,undef,
                                              $hideprivileged)) {
                   foreach my $priv ('vsa','vgr','srm') {
                       $perms{$priv} = &Apache::lonnet::allowed($priv,$env{'request.course.id'});
                       if (!$perms{$priv} && $env{'request.course.sec'} ne '') {
                           $perms{$priv} =
                               &Apache::lonnet::allowed($priv,"$env{'request.course.id'}/$env{'request.course.sec'}");
                       }
                   }
                   if ($perms{'vsa'}) {
                       &switch('','',6,5,'trck-22x22.png','Activity',
                               '',
                               "go('/adm/trackstudent?selected_student=$sname:$sdom')",
                               'View recent activity by this person');
                   }
                   if ($perms{'vgr'}) {
                       &switch('','',6,6,'rsrv-22x22.png','Reservations',
                               '',
                               "go('/adm/slotrequest?command=showresv&amp;origin=aboutme&amp;uname=$sname&amp;udom=$sdom')",
                               'Slot reservation history');
                   }
                   if ($perms{'srm'}) {
                       &switch('','',6,7,'contact-new-22x22.png','Records',
                               '',
                               "go('/adm/email?recordftf=retrieve&amp;recname=$sname&amp;recdom=$sdom')",
                               'Add records');
                   }
               }
           }
           if (($env{'form.folderpath'} =~ /^supplemental/) &&
               (&Apache::lonnet::allowed('mdc',$env{'request.course.id'})) &&
               (($resurl =~ m{^/adm/wrapper/ext/}) ||
                ($resurl =~ m{^/adm/$cdom/$cnum/\d+/ext\.tool$}) ||
                ($resurl =~ m{^/uploaded/$cdom/$cnum/supplemental/}) ||
                ($resurl eq '/adm/supplemental') ||
                ($resurl =~ m{^/public/$cdom/$cnum/syllabus$}) ||
                ($resurl =~ m{^/adm/$match_domain/$match_username/aboutme$}))) {
               my @folders=split('&',$env{'form.folderpath'});
               if ((@folders > 2) || ($resurl ne '/adm/supplemental')) {
                   my $suppanchor;
                   if ($resurl =~ m{^/adm/wrapper/ext/}) {
                       $suppanchor = $env{'form.anchor'};
                   }
                   my $esc_path=&escape(&HTML::Entities::encode(&escape($env{'form.folderpath'}),'<>&"'));
                   my $link = '/adm/coursedocs?command=direct&amp;forcesupplement=1&amp;supppath='.
                              "$esc_path&amp;anchor=$suppanchor";
                   if ($env{'request.use_absolute'} ne '') {
                       $link = $env{'request.use_absolute'}.$link;
                   }
                   &switch('','',7,4,'docs-22x22.png','Edit Folder','parms[_2]',
                           "location.href='$link'",'Folder/Page Content');
               }
           }
       }
   
 sub maincall() {  # End checking for items for about me page for users in a course
     if (($ENV{'browser.interface'} eq 'textual') ||      if ($docscrumbs) {
         ($ENV{'environment.remote'} eq 'off')) { return ''; }          &Apache::lonhtmlcommon::clear_breadcrumb_tools();
     return(<<ENDMAINCALL);          &advtools_crumbs(@inlineremote);
 <script type="text/javascript">          return $editbutton;
     main();      } elsif ($env{'request.registered'}) {
 </script>          return $editbutton || $viewsrcbutton;
 ENDMAINCALL      } else {
           if (ref($bread_crumbs) eq 'ARRAY') {
               if (@inlineremote > 0) {
                   if (ref($advtools) eq 'ARRAY') {
                       @{$advtools} = @inlineremote;
                   }
               }
               return;
           } elsif (@inlineremote > 0) {
               &Apache::lonhtmlcommon::clear_breadcrumb_tools();
               &advtools_crumbs(@inlineremote);
               return   &Apache::lonhtmlcommon::scripttag('', 'start')
                      . &Apache::lonhtmlcommon::breadcrumbs(undef,undef,0)
                      . &Apache::lonhtmlcommon::scripttag('', 'end');
           }
       }
 }  }
   
 sub load_remote_msg {  sub advtools_crumbs {
     my ($lowerurl)=@_;      my @funcs = @_;
       if ($env{'request.noversionuri'} =~ m{^/adm/$match_domain/$match_username/aboutme$}) {
     if (($ENV{'browser.interface'} eq 'textual') ||          &Apache::lonhtmlcommon::add_breadcrumb_tool(
         ($ENV{'environment.remote'} eq 'off')) { return ''; }              'advtools', @funcs[61,64,65,66,67,74]);
       } elsif ($env{'request.noversionuri'} !~ m{^/adm/(navmaps|viewclasslist)(\?|$)}) {
     my $esclowerurl=&Apache::lonnet::escape($lowerurl);          &Apache::lonhtmlcommon::add_breadcrumb_tool(
     my $link=&mt('<a href="[_1]">Continue</a> on in Inline Menu mode',              'advtools', @funcs[61,71,72,73,74,92]);
     "/adm/remote?action=collapse?url=$esclowerurl");      } elsif ($env{'request.noversionuri'} eq '/adm/viewclasslist') {
     return(<<ENDREMOTEFORM);          &Apache::lonhtmlcommon::add_breadcrumb_tool(
 <p>              'advtools', $funcs[61]);
 <form name="wheel">      }
 <input name="spin" type="text" size="60" />      return;
 </form>  
 </p>  
 <p>$link</p>  
 ENDREMOTEFORM  
 }  
 # ================================================================= Reopen menu  
   
 sub reopenmenu {  
    if (($ENV{'browser.interface'} eq 'textual') ||  
        ($ENV{'environment.remote'} eq 'off')) { return ''; }  
    my $menuname='LCmenu'.$Apache::lonnet::perlvar{'lonHostID'};  
    my $nothing = &Apache::lonhtmlcommon::javascript_nothing();  
    return('window.open('.$nothing.',"'.$menuname.'","",false);');  
 }   
   
 # =============================================================== Open the menu  
   
 sub open {  
     my $returnval='';  
     if (($ENV{'browser.interface'} eq 'textual') ||  
         ($ENV{'environment.remote'} eq 'off')) {   
  return '<script type="text/javascript">self.name="loncapaclient";</script>';  
     }  
     my $menuname='LCmenu'.$Apache::lonnet::perlvar{'lonHostID'};  
     unless (shift eq 'unix') {  
 # resizing does not work on linux because of virtual desktop sizes  
        $returnval.=(<<ENDRESIZE);  
 if (window.screen) {  
     self.resizeTo(screen.availWidth-215,screen.availHeight-55);  
     self.moveTo(190,15);  
 }  
 ENDRESIZE  
     }  
     $returnval.=(<<ENDOPEN);  
 window.status='Opening LON-CAPA Remote Control';  
 var menu=window.open("/res/adm/pages/menu.html","$menuname",  
 "height=350,width=150,scrollbars=no,menubar=no,top=5,left=5,screenX=5,screenY=5");  
 self.name='loncapaclient';  
 ENDOPEN  
     return '<script type="text/javascript">'.$returnval.'</script>';  
 }  }
   
   
 # ================================================================== Raw Config  # ================================================================== Raw Config
   
 sub clear {  sub clear {
     my ($row,$col)=@_;      my ($row,$col)=@_;
     unless (($ENV{'browser.interface'} eq 'textual') ||      $inlineremote[10*$row+$col]='';
             ($ENV{'environment.remote'} eq 'off')) {      return ''; 
        return "\n".qq(window.status+='.';swmenu.clearbut($row,$col););  
    } else {   
        $inlineremote[10*$row+$col]='';  
        return '';   
    }  
 }  }
   
 # ============================================ Switch a button or create a link  # ============================================ Switch a button or create a link
Line 727  sub clear { Line 1514  sub clear {
 # The javascript is usually similar to "go('/adm/roles')" or "cstrgo(..)".  # The javascript is usually similar to "go('/adm/roles')" or "cstrgo(..)".
   
 sub switch {  sub switch {
     my ($uname,$udom,$row,$col,$img,$top,$bot,$act,$desc,$nobreak)=@_;      my ($uname,$udom,$row,$col,$img,$top,$bot,$act,$desc,$cat,$nobreak)=@_;
     $act=~s/\$uname/$uname/g;      $act=~s/\$uname/$uname/g;
     $act=~s/\$udom/$udom/g;      $act=~s/\$udom/$udom/g;
     $top=&mt($top);      $top=&mt($top);
     $bot=&mt($bot);      $bot=&mt($bot);
     $desc=&mt($desc);      $desc=&mt($desc);
     $img=&mt($img);      my $idx=10*$row+$col;
     unless (($ENV{'browser.interface'} eq 'textual')  ||      $category_members{$cat}.=':'.$idx;
             ($ENV{'environment.remote'} eq 'off')) {  
 # Remote  # Inline Menu
        return "\n".      if ($nobreak==2) { return ''; }
  qq(window.status+='.';swmenu.switchbutton($row,$col,"$img","$top","$bot","$act","$desc"););      my $text=$top.' '.$bot;
    } elsif ($ENV{'browser.interface'} eq 'textual') {      $text=~s/\s*\-\s*//gs;
 # Accessibility  
        if ($nobreak==2) { return ''; }      my $pic=
        my $text=$top.' '.$bot;     '<img alt="'.$text.'" src="'.
        $text=~s/\s*\-\s*//gs;     &Apache::loncommon::lonhttpdurl('/res/adm/pages/'.$img).
        if ($nobreak) {     '" align="'.($nobreak==3?'right':'left').'" class="LC_icon" />';
    $inlineremote[10*$row+$col]=      if ($env{'browser.interface'} eq 'faketextual') {
        '<a href="javascript:'.$act.';">'.$text.'</a>';  # Main Menu
        } else {  
    $inlineremote[10*$row+$col]="\n<br />".  
        $desc.' <a href="javascript:'.$act.';">'.$text.'</a>';  
        }  
    } else {  
 # Inline Remote  
        if ($nobreak==2) { return ''; }  
        my $text=$top.' '.$bot;  
        $text=~s/\s*\-\s*//gs;  
   
        my $lonhttpdPort=$Apache::lonnet::perlvar{'lonhttpdPort'};  
        if (!defined($lonhttpdPort)) { $lonhttpdPort='8080'; }  
        my $pic=  
    '<img border="0" alt="'.$text.'" src="http://'.$ENV{'HTTP_HOST'}.  
    ':'.$lonhttpdPort.'/res/adm/pages/'.$img.'" align="'.  
    ($nobreak==3?'right':'left').'" />';  
        if (($ENV{'browser.interface'} eq 'textual') || ($ENV{'browser.interface'} eq 'faketextual')) {  
 # Accessibility  
    if ($nobreak==3) {     if ($nobreak==3) {
        $inlineremote[10*$row+$col]="\n".         $inlineremote[$idx]="\n".
    '<td width="40%" align="right"><font color="'.$font.'" size="+1">'.$text.     '<td class="LC_menubuttons_text" align="right">'.$text.
    '</font></td><td width="10%" align="right" bgcolor="'.$tabbg.'">'.     '</td><td align="left">'.
    '<a href="javascript:'.$act.';">'.$pic.'</a></td></tr>';     '<a href="javascript:'.$act.';">'.$pic.'</a></td></tr>';
    } elsif ($nobreak) {     } elsif ($nobreak) {
        $inlineremote[10*$row+$col]="\n<tr>".         $inlineremote[$idx]="\n<tr>".
    '<td width="10%" align="left" bgcolor="'.$tabbg.'">'.     '<td align="left">'.
    '<a href="javascript:'.$act.';">'.$pic.     '<a href="javascript:'.$act.';">'.$pic.'</a></td>
    '</a></td><td width="40%" align="left"><font color="'.$font.'" size="+1">'.$text.'</font></td>';                      <td class="LC_menubuttons_text" align="left"><a class="LC_menubuttons_link" href="javascript:'.$act.';"><span class="LC_menubuttons_inline_text">'.$text.'</span></a></td>';
    } else {     } else {
        $inlineremote[10*$row+$col]="\n<tr>".         $inlineremote[$idx]="\n<tr>".
    '<td width="10%" align="left" bgcolor="'.$tabbg.'">'.     '<td align="left">'.
    '<a href="javascript:'.$act.';">'.$pic.     '<a href="javascript:'.$act.';">'.$pic.
    '</a></td><td colspan="3"><font color="'.$font.'">'.$desc.     '</a></td><td class="LC_menubuttons_text" colspan="3">'.
    '</font></td></tr>';            '<a class="LC_menubuttons_link" href="javascript:'.$act.';"><span class="LC_menubuttons_inline_text">'.$desc.'</span></a></td></tr>';
    }     }
        } else {      } else {
 # Inline Menu  # Inline Menu
    $inlineremote[10*$row+$col]=          my @tools = (93,91,81,82,83);
    '<a href="javascript:'.$act.';">'.$pic.          unless ($env{'request.state'} eq 'construct') {
    '</a><font color="'.$font.'" size="2">'.$desc.              push(@tools,63);
    '</font>';          }
        }          if ((($env{'environment.icons'} eq 'iconsonly') ||
    }               ($env{'environment.icons'} eq '') && ($env{'request.lti.login'})) &&
               (grep(/^$idx$/,@tools))) {
               $inlineremote[$idx] =
           '<a title="'.$desc.'" class="LC_menubuttons_link" href="javascript:'.$act.';">'.$pic.'</a>';
           } else {
               $inlineremote[$idx] =
          '<a title="'.$desc.'" class="LC_menubuttons_link" href="javascript:'.$act.';">'.$pic.
          '<span class="LC_menubuttons_inline_text">'.$top.'&nbsp;</span></a>';
           }
       }
     return '';      return '';
 }  }
   
 sub secondlevel {  sub secondlevel {
     my $output='';      my $output='';
     my       my 
     ($uname,$udom,$rol,$crs,$pub,$con,$row,$col,$prt,$img,$top,$bot,$act,$desc)=@_;      ($uname,$udom,$rol,$crs,$pub,$con,$row,$col,$prt,$img,$top,$bot,$act,$desc,$cat)=@_;
     if ($prt eq 'any') {      if ($prt eq 'any') {
    $output.=switch($uname,$udom,$row,$col,$img,$top,$bot,$act,$desc);     $output.=&switch($uname,$udom,$row,$col,$img,$top,$bot,$act,$desc,$cat);
     } elsif ($prt=~/^r(\w+)/) {      } elsif ($prt=~/^r(\w+)/) {
         if ($rol eq $1) {          if ($rol eq $1) {
            $output.=switch($uname,$udom,$row,$col,$img,$top,$bot,$act,$desc);             $output.=&switch($uname,$udom,$row,$col,$img,$top,$bot,$act,$desc,$cat);
         }          }
     }      }
     return $output;      return $output;
 }  }
   
 sub openmenu {  
     my $menuname='LCmenu'.$Apache::lonnet::perlvar{'lonHostID'};  
     if (($ENV{'browser.interface'} eq 'textual') ||  
         ($ENV{'environment.remote'} eq 'off')) { return ''; }  
     my $nothing = &Apache::lonhtmlcommon::javascript_nothing();  
     return "window.open(".$nothing.",'".$menuname."');";  
 }  
   
 sub inlinemenu {  sub inlinemenu {
     @inlineremote=();      undef(@inlineremote);
     undef @inlineremote;      undef(%category_members);
   # calling rawconfig with "1" will evaluate mydesk.tab, even if there is no active remote control
     &rawconfig(1);      &rawconfig(1);
     return join('',map { (defined($_)?$_:'') } @inlineremote);      my $output='<table><tr>';
       for (my $col=1; $col<=2; $col++) {
           $output.='<td class="LC_mainmenu_col_fieldset">';
           for (my $row=1; $row<=8; $row++) {
               foreach my $cat (keys(%category_members)) {
                  if ($category_positions{$cat} ne "$col,$row") { next; }
                  #$output.='<table><tr><td colspan="4" class="LC_menubuttons_category">'.&mt($category_names{$cat}).'</td></tr>';
                  $output.='<div class="LC_Box LC_400Box">';
          $output.='<h3 class="LC_hcell">'.&mt($category_names{$cat}).'</h3>';
                  $output.='<table>';
                  my %active=();
                  foreach my $menu_item (split(/\:/,$category_members{$cat})) {
                     if ($inlineremote[$menu_item]) {
                        $active{$menu_item}=1;
                     }
                  }  
                  foreach my $item (sort(keys(%active))) {
                     $output.=$inlineremote[$item];
                  }
                  $output.='</table>';
                  $output.='</div>';
               }
            }
            $output.="</td>";
       }
       $output.="</tr></table>";
       return $output;
 }  }
   
 sub rawconfig {  sub rawconfig {
   #
   # This evaluates mydesk.tab
   # Need to add more positions and more privileges to deal with all
   # menu items.
   #
     my $textualoverride=shift;      my $textualoverride=shift;
     my $output='';      my $output='';
     unless (($ENV{'browser.interface'} eq 'textual') ||      return '' unless $textualoverride;
             ($ENV{'environment.remote'} eq 'off')) {      my $uname=$env{'user.name'};
        $output.=      my $udom=$env{'user.domain'};
  "window.status='Opening Remote Control';var swmenu=".&openmenu().      my $adv=$env{'user.adv'};
 "\nwindow.status='Configuring Remote Control ';";      my $show_course=&Apache::loncommon::show_course();
     } else {      my $author=$env{'user.author'};
        unless ($textualoverride) { return ''; }  
     }  
     my $uname=$ENV{'user.name'};  
     my $udom=$ENV{'user.domain'};  
     my $adv=$ENV{'user.adv'};  
     my $author=$ENV{'user.author'};  
     my $crs='';      my $crs='';
     if ($ENV{'request.course.id'}) {      my $crstype='';
        $crs='/'.$ENV{'request.course.id'};      if ($env{'request.course.id'}) {
        if ($ENV{'request.course.sec'}) {         $crs='/'.$env{'request.course.id'};
    $crs.='_'.$ENV{'request.course.sec'};         if ($env{'request.course.sec'}) {
      $crs.='_'.$env{'request.course.sec'};
        }         }
        $crs=~s/\_/\//g;         $crs=~s/\_/\//g;
          $crstype = &Apache::loncommon::course_type();
     }      }
     my $pub=($ENV{'request.state'} eq 'published');      my $pub=($env{'request.state'} eq 'published');
     my $con=($ENV{'request.state'} eq 'construct');      my $con=($env{'request.state'} eq 'construct');
     my $rol=$ENV{'request.role'};      my $rol=$env{'request.role'};
     my $requested_domain = $ENV{'request.role.domain'};      my $requested_domain;
     foreach (@desklines) {      if ($rol) {
         my ($row,$col,$pro,$prt,$img,$top,$bot,$act,$desc)=split(/\:/,$_);         $requested_domain = $env{'request.role.domain'};
       }
       foreach my $line (@desklines) {
           my ($row,$col,$pro,$prt,$img,$top,$bot,$act,$desc,$cat)=split(/\:/,$line);
         $prt=~s/\$uname/$uname/g;          $prt=~s/\$uname/$uname/g;
         $prt=~s/\$udom/$udom/g;          $prt=~s/\$udom/$udom/g;
         $prt=~s/\$crs/$crs/g;           if ($prt =~ /\$crs/) {
         $prt=~s/\$requested_domain/$requested_domain/g;              next unless ($env{'request.course.id'});
               next if ($crstype eq 'Community');
               $prt=~s/\$crs/$crs/g;
           } elsif ($prt =~ /\$cmty/) {
               next unless ($env{'request.course.id'});
               next if ($crstype ne 'Community');
               $prt=~s/\$cmty/$crs/g;
           }
           if ($prt =~ m/\$requested_domain/) {
               if ((!$requested_domain) && ($pro eq 'pbre') && ($env{'user.adv'})) {
                   $prt=~s/\$requested_domain/$env{'user.domain'}/g;
               } else {
                   $prt=~s/\$requested_domain/$requested_domain/g;
               }
           }
           if ($category_names{$cat}!~/\w/) { $cat='oth'; }
         if ($pro eq 'clear') {          if ($pro eq 'clear') {
     $output.=&clear($row,$col);      $output.=&clear($row,$col);
         } elsif ($pro eq 'any') {          } elsif ($pro eq 'any') {
                $output.=&secondlevel(                 $output.=&secondlevel(
   $uname,$udom,$rol,$crs,$pub,$con,$row,$col,$prt,$img,$top,$bot,$act,$desc);    $uname,$udom,$rol,$crs,$pub,$con,$row,$col,$prt,$img,$top,$bot,$act,$desc,$cat);
  } elsif ($pro eq 'smp') {   } elsif ($pro eq 'smp') {
             unless ($adv) {              unless ($adv) {
                $output.=&secondlevel(                 $output.=&secondlevel(
           $uname,$udom,$rol,$crs,$pub,$con,$row,$col,$prt,$img,$top,$bot,$act,$desc);            $uname,$udom,$rol,$crs,$pub,$con,$row,$col,$prt,$img,$top,$bot,$act,$desc,$cat);
             }              }
         } elsif ($pro eq 'adv') {          } elsif ($pro eq 'adv') {
             if ($adv) {              if ($adv) {
                $output.=&secondlevel(                 $output.=&secondlevel(
   $uname,$udom,$rol,$crs,$pub,$con,$row,$col,$prt,$img,$top,$bot,$act,$desc);    $uname,$udom,$rol,$crs,$pub,$con,$row,$col,$prt,$img,$top,$bot,$act,$desc,$cat);
               }
    } elsif ($pro eq 'shc') {
               if ($show_course) {
                  $output.=&secondlevel(
             $uname,$udom,$rol,$crs,$pub,$con,$row,$col,$prt,$img,$top,$bot,$act,$desc,$cat);
               }
           } elsif ($pro eq 'nsc') {
               if (!$show_course) {
                  $output.=&secondlevel(
     $uname,$udom,$rol,$crs,$pub,$con,$row,$col,$prt,$img,$top,$bot,$act,$desc,$cat);
             }              }
         } elsif (($pro=~/^p(\w+)/) && ($prt)) {          } elsif (($pro=~/^p(\w+)/) && ($prt)) {
     if (&Apache::lonnet::allowed($1,$prt)) {              my $priv = $1;
                $output.=switch($uname,$udom,$row,$col,$img,$top,$bot,$act,$desc);              if ($priv =~ /^mdc(Course|Community)/) {
                   if ($crstype eq $1) {
                       $priv = 'mdc';
                   } else {
                       next;
                   }
             }              }
         } elsif ($pro eq 'course') {              if ((($priv eq 'bre') && (&Apache::lonnet::allowed($priv,$prt) eq 'F')) ||
             if ($ENV{'request.course.fn'}) {                  (($priv ne 'bre') && (&Apache::lonnet::allowed($priv,$prt)))) {
                $output.=switch($uname,$udom,$row,$col,$img,$top,$bot,$act,$desc);                  $output.=&switch($uname,$udom,$row,$col,$img,$top,$bot,$act,$desc,$cat);
               }
           } elsif ($pro eq 'course')  {
               if (($env{'request.course.fn'}) && ($crstype ne 'Community')) {
                  $output.=&switch($uname,$udom,$row,$col,$img,$top,$bot,$act,$desc,$cat);
     }      }
           } elsif ($pro eq 'community')  {
               if (($env{'request.course.fn'}) && ($crstype eq 'Community')) {
                  $output.=&switch($uname,$udom,$row,$col,$img,$top,$bot,$act,$desc,$cat);
               }
         } elsif ($pro =~ /^courseenv_(.*)$/) {          } elsif ($pro =~ /^courseenv_(.*)$/) {
             my $key = $1;              my $key = $1;
             if ($ENV{'course.'.$ENV{'request.course.id'}.'.'.$key}) {              if ($crstype ne 'Community') {
                 $output.=switch($uname,$udom,$row,$col,$img,$top,$bot,$act,$desc);                  my $coursepref = $env{'course.'.$env{'request.course.id'}.'.'.$key};
                   if ($key eq 'canuse_pdfforms') {
                       if ($env{'request.course.id'} && $coursepref eq '') {
                           my %domdefs = &Apache::lonnet::get_domain_defaults($env{'course.'.$env{'request.course.id'}.'.domain'});
                           $coursepref = $domdefs{'canuse_pdfforms'};
                       }
                   }
                   if ($coursepref) { 
                       $output.=&switch($uname,$udom,$row,$col,$img,$top,$bot,$act,$desc,$cat);
                   }
               }
           } elsif ($pro =~ /^communityenv_(.*)$/) {
               my $key = $1;
               if ($crstype eq 'Community') {
                   my $coursepref = $env{'course.'.$env{'request.course.id'}.'.'.$key};
                   if ($key eq 'canuse_pdfforms') {
                       if ($env{'request.course.id'} && $coursepref eq '') {
                           my %domdefs = &Apache::lonnet::get_domain_defaults($env{'course.'.$env{'request.course.id'}.'.domain'});
                           $coursepref = $domdefs{'canuse_pdfforms'};
                       }
                   }
                   if ($coursepref) { 
                       $output.=&switch($uname,$udom,$row,$col,$img,$top,$bot,$act,$desc,$cat);
                   }
             }              }
         } elsif ($pro =~ /^course_(.*)$/) {          } elsif ($pro =~ /^course_(.*)$/) {
             # Check for permissions inside of a course              # Check for permissions inside of a course
             if (($ENV{'request.course.id'}) &&              if (($env{'request.course.id'}) && ($crstype ne 'Community') && 
                 (&Apache::lonnet::allowed($1,$ENV{'request.course.id'}.                  (&Apache::lonnet::allowed($1,$env{'request.course.id'}.
             ($ENV{'request.course.sec'}?'/'.$ENV{'request.course.sec'}:''))              ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''))
                  )) {                   )) {
                 $output.=switch($uname,$udom,$row,$col,$img,$top,$bot,$act,$desc);                  $output.=&switch($uname,$udom,$row,$col,$img,$top,$bot,$act,$desc,$cat);
     }      }
           } elsif ($pro =~ /^community_(.*)$/) {
               # Check for permissions inside of a community
               if (($env{'request.course.id'}) && ($crstype eq 'Community') &&   
                   (&Apache::lonnet::allowed($1,$env{'request.course.id'}.
               ($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''))
                    )) {
                   $output.=&switch($uname,$udom,$row,$col,$img,$top,$bot,$act,$desc,$cat);
               }
         } elsif ($pro eq 'author') {          } elsif ($pro eq 'author') {
             if ($author) {              if ($author) {
                 if ((($prt eq 'rca') && ($ENV{'request.role'}=~/^ca/)) ||                  if ((($prt eq 'rca') && ($env{'request.role'}=~/^ca/)) ||
                     (($prt eq 'rau') && ($ENV{'request.role'}=~/^au/))) {                      (($prt eq 'raa') && ($env{'request.role'}=~/^aa/)) || 
                       (($prt eq 'rau') && ($env{'request.role'}=~/^au/))) {
                     # Check that we are on the correct machine                      # Check that we are on the correct machine
                     my $cadom=$requested_domain;                      my $cadom=$requested_domain;
                     my $caname=$ENV{'user.name'};                      my $caname=$env{'user.name'};
                     if ($prt eq 'rca') {                      if (($prt eq 'rca') || ($prt eq 'raa')) {
        ($cadom,$caname)=         ($cadom,$caname)=
                                ($ENV{'request.role'}=~/(\w+)\/(\w+)$/);                                 ($env{'request.role'}=~/($match_domain)\/($match_username)$/);
                     }                                             }                       
                     $act =~ s/\$caname/$caname/g;                      $act =~ s/\$caname/$caname/g;
                       $act =~ s/\$cadom/$cadom/g;
                     my $home = &Apache::lonnet::homeserver($caname,$cadom);                      my $home = &Apache::lonnet::homeserver($caname,$cadom);
     my $allowed=0;      my $allowed=0;
     my @ids=&Apache::lonnet::current_machine_ids();      my @ids=&Apache::lonnet::current_machine_ids();
     foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } }      foreach my $id (@ids) { if ($id eq $home) { $allowed=1; } }
     if ($allowed) {      if ($allowed) {
                         $output.=switch($caname,$cadom,                          $output.=&switch($caname,$cadom,
                                         $row,$col,$img,$top,$bot,$act,$desc);                                          $row,$col,$img,$top,$bot,$act,$desc,$cat);
                     }                      }
                 }                  }
             }              }
           } elsif ($pro eq 'tools') {
               my @tools = ('aboutme','blog','portfolio');
               if (grep(/^\Q$prt\E$/,@tools)) {
                   if (!&Apache::lonnet::usertools_access($env{'user.name'},
                                                          $env{'user.domain'},
                                                          $prt,undef,'tools')) {
                       $output.=&clear($row,$col);
                       next;
                   }
               } elsif (($prt eq 'reqcrsnsc') || ($prt eq 'reqcrsshc')) {
                   if (($prt eq 'reqcrsnsc') && ($show_course))   {
                       next;
                   }
                   if (($prt eq 'reqcrsshc') && (!$show_course)) {
                       next;
                   }
                   my $showreqcrs = &check_for_rcrs();
                   if (!$showreqcrs) {
                       $output.=&clear($row,$col);
                       next;
                   }
               }
               $prt='any';
               $output.=&secondlevel(
             $uname,$udom,$rol,$crs,$pub,$con,$row,$col,$prt,$img,$top,$bot,$act,$desc,$cat);
         }          }
     }      }
     unless (($ENV{'browser.interface'} eq 'textual') ||  
             ($ENV{'environment.remote'} eq 'off')) {  
        $output.="\nwindow.status='Synchronizing Time';swmenu.syncclock(1000*".time.");\nwindow.status='Remote Control Configured.';";  
        if (&Apache::lonmsg::newmail()) {   
    $output.='swmenu.setstatus("you have","messages");';  
        }  
     }  
   
     return $output;      return $output;
 }  }
   
 # ======================================================================= Close  sub check_for_rcrs {
       my $showreqcrs = 0;
       my @reqtypes = ('official','unofficial','community','textbook','placement');
       foreach my $type (@reqtypes) {
           if (&Apache::lonnet::usertools_access($env{'user.name'},
                                                 $env{'user.domain'},
                                                 $type,undef,'requestcourses')) {
               $showreqcrs = 1;
               last;
           }
       }
       if (!$showreqcrs) {
           foreach my $type (@reqtypes) {
               if ($env{'environment.reqcrsotherdom.'.$type} ne '') {
                   $showreqcrs = 1;
                   last;
               }
           }
       }
       return $showreqcrs;
   }
   
   sub dc_popup_js {
       my %lt = &Apache::lonlocal::texthash(
                                             more => '(More ...)',
                                             less => '(Less ...)',
                                           );
       return <<"END";
   
 sub close {  function showCourseID() {
     if (($ENV{'browser.interface'} eq 'textual') ||      document.getElementById('dccid').style.display='block';
         ($ENV{'environment.remote'} eq 'off')) { return ''; }      document.getElementById('dccid').style.textAlign='left';
     my $menuname='LCmenu'.$Apache::lonnet::perlvar{'lonHostID'};      document.getElementById('dccid').style.textFace='normal';
     return(<<ENDCLOSE);      document.getElementById('dccidtext').innerHTML ='<a href="javascript:hideCourseID();" class="LC_menubuttons_link">$lt{'less'}</a>';
 <script type="text/javascript">      return;
 window.status='Accessing Remote Control';  
 menu=window.open("/adm/rat/empty.html","$menuname",  
                  "height=350,width=150,scrollbars=no,menubar=no");  
 window.status='Disabling Remote Control';  
 menu.active=0;  
 menu.autologout=0;  
 window.status='Closing Remote Control';  
 menu.close();  
 window.status='Done.';  
 </script>  
 ENDCLOSE  
 }  }
   
 # ====================================================================== Footer  function hideCourseID() {
       document.getElementById('dccid').style.display='none';
       document.getElementById('dccidtext').innerHTML ='<a href="javascript:showCourseID()" class="LC_menubuttons_link">$lt{'more'}</a>';
       return;
   }
   
 sub footer {  END
   
 }  }
   
 sub nav_control_js {  sub countdown_toggle_js {
     my $nav=($ENV{'environment.remotenavmap'} eq 'on');      return <<"END";
     return (<<NAVCONTROL);  
     var w_loncapanav_flag="$nav";  
   
   function toggleCountdown() {
       var countdownid = document.getElementById('duedatecountdown');
       var currstyle = countdownid.style.display;
       if (currstyle == 'inline') {
           countdownid.style.display = 'none';
           document.getElementById('ddcountcollapse').innerHTML='';
           document.getElementById('ddcountexpand').innerHTML='&#9668;&nbsp;';
       } else {
           countdownid.style.display = 'inline';
           document.getElementById('ddcountcollapse').innerHTML='&#9658;&nbsp;';
           document.getElementById('ddcountexpand').innerHTML='';
       }
       return;
   }
   
 function gonav(url) {  END
    if (w_loncapanav_flag != 1) {  
       gopost(url,'');  
    }  else {  
       navwindow=window.open(url,  
                   "loncapanav","height=600,width=400,scrollbars=1");   
    }  
 }  }
 NAVCONTROL  
   # This creates a "done button" for timed events.  The confirmation box is a jQuery
   # dialog widget. If the interval parameter requires a proctor key for the timed 
   # event to be marked done, there will also be a textbox where that can be entered. 
   # Clicking OK will set the value of LC_interval_done to 'true', and, if needed will 
   # set the value of LC_interval_done_proctorpass to the text entered in that box, 
   # and submit the corresponding form.
   # 
   # The &zero_time() routine in lonhomework.pm is called when a page is rendered if
   # LC_interval_done is true.
   #
   sub done_button_js {
       my ($type,$width,$height,$proctor,$donebuttontext) = @_;
       return unless (($type eq 'map') || ($type eq 'resource'));
       my %lt = &Apache::lonlocal::texthash(
                    title    => 'WARNING!',
                    preamble => 'You are trying to end this timed event early.',
                    map      => 'Confirming that you are done will cause the time to expire and prevent you from changing any answers in the current folder.',
                    resource => 'Confirming that you are done will cause the time to expire for this question, and prevent you from changing your answer(s).', 
                    okdone   => 'Click "OK" if you are completely finished.',
                    cancel   => 'Click "Cancel" to continue working.',
                    proctor  => 'Ask a proctor to enter the key, then click "OK" if you are completely finished.',
                    ok       => 'OK',
                    exit     => 'Cancel',
                    key      => 'Key:',
                    nokey    => 'A proctor key is required', 
       );
       my $shownsymb = &HTML::Entities::encode(&Apache::lonenc::check_encrypt($env{'request.symb'}));
       my $navmap = Apache::lonnavmaps::navmap->new(); 
       my ($missing,$tried) = (0,0);
       if (ref($navmap)) {
           my @resources=();
           if ($type eq 'map') {
               my ($mapurl,$rid,$resurl)=&Apache::lonnet::decode_symb($env{'request.symb'});
               if ($env{'request.symb'} =~ /\.page$/) {
                   @resources=$navmap->retrieveResources($resurl,sub { $_[0]->is_problem() });
               } else {
                   @resources=$navmap->retrieveResources($mapurl,sub { $_[0]->is_problem() });
               }
           } else {
               my $res = $navmap->getBySymb($env{'request.symb'});
               if (ref($res)) {
                   if ($res->is_problem()) {
                       push(@resources,$res);
                   }
               }
           }
           foreach my $res (@resources) {
               if (ref($res->parts()) eq 'ARRAY') {
                   foreach my $part (@{$res->parts()}) {
                       if (!$res->tries($part)) {
                           $missing++;
                       } else {
                           $tried++;
                       }
                   }
               }
           }
       }
       if ($missing) {
           $lt{'miss'} .= '<p class="LC_error">';
           if ($type eq 'map') {
               $lt{'miss'} .= &mt('Submissions are missing for [quant,_1,question part,question parts] in this folder.',$missing);
           } else {
               $lt{'miss'} .= &mt('Submissions are missing for [quant,_1,part] in this question.',$missing);
           }
           if ($missing > 1) {
               $lt{'miss'} .= ' '.&mt('If you confirm you are done you will be unable to submit answers for them.').'</span>';
           } else {
               $lt{'miss'} .= ' '.&mt('If you confirm you are done you will be unable to submit an answer for it.').'</p>';
           }
       }
       $donebuttontext = &HTML::Entities::encode($donebuttontext,'<>&"');
       if ($proctor) {
           if ($height !~ /^\d+$/) {
               $height = 400;
               if ($missing) {
                   $height += 60; 
               }
           }
           if ($width !~ /^\d+$/) {
               $width = 400;
               if ($missing) {
                   $width += 60;
               }
           }
           return <<END;
   <form method="post" name="LCdoneButton" action="">
       <input type="hidden" name="LC_interval_done" value="" />
       <input type="hidden" name="LC_interval_done_proctorpass" value="" />
       <input type="hidden" name="symb" value="$shownsymb" />
       <button id="LC_done-confirm-opener" type="button">$donebuttontext</button>
   </form>
   
   <div id="LC_done-confirm" title="$lt{'title'}">
     <p>$lt{'preamble'} $lt{$type}</p>
     $lt{'miss'}
     <p>$lt{'proctor'}</p>
     <form name="LCdoneButtonProctor" action="">
       <label>$lt{'key'}<input type="password" name="LC_interval_done_proctorkey" value="" /></label>
       <input type="submit" tabindex="-1" style="position:absolute; top:-1000px" />
     </form>
     <p>$lt{'cancel'}</p>
   </div>
   
   <script type="text/javascript">
   // <![CDATA[
       \$( "#LC_done-confirm" ).dialog({ autoOpen: false });
       \$( "#LC_done-confirm-opener" ).on("click", function() {
           \$( "#LC_done-confirm" ).dialog("open");
           \$( "#LC_done-confirm" ).dialog({
               height: $height,
               width: $width,
               modal: true,
               resizable: false,
               buttons: [
                   {
                       text: "$lt{'ok'}",
                       click: function() {
                           var proctorkey = \$( '[name="LC_interval_done_proctorkey"]' )[0].value;
                           if ((proctorkey == '') || (proctorkey == null)) {
                               alert("$lt{'nokey'}"); 
                           } else { 
                               \$( '[name="LC_interval_done"]' )[0].value = 'true';
                               \$( '[name="LC_interval_done_proctorpass"]' )[0].value = proctorkey;
                               \$( '[name="LCdoneButton"]' )[0].submit();
                           }
                       },
                   },
                   {
                       text: "$lt{'exit'}",
                       click: function() {
                           \$("#LC_done-confirm").dialog( "close" );
                       }
                   }
               ],
               close: function() {
                   \$( '[name="LC_interval_done_proctorkey"]' )[0].value = '';
               }
           });
           \$( "#LC_done-confirm" ).find( "form" ).on( "submit", function( event ) {
               event.preventDefault();
               \$( '[name="LC_interval_done"]' )[0].value = 'true';
               \$( '[name="LC_interval_done_proctorpass"]' )[0].value = \$( '[name="LC_interval_done_proctorkey"]' )[0].value;
               \$( '[name="LCdoneButton"]' )[0].submit();
           });
   });
   
   // ]]>
   </script>
   
   END
       } else {
           if ($height !~ /^\d+$/) {
               $height = 320;
               if ($missing) {
                   $height += 60;
               }
           }
           if ($width !~ /^\d+$/) {
               $width = 320;
               if ($missing) {
                   $width += 60;
               }
           }
           if ($missing) {
               $lt{'miss'} = '</p>'.$lt{'miss'}.'<p>';
           }
           return <<END;
   
   <form method="post" name="LCdoneButton" action="">
       <input type="hidden" name="LC_interval_done" value="" />
       <input type="hidden" name="symb" value="$shownsymb" />
       <button id="LC_done-confirm-opener" type="button">$donebuttontext</button>
   </form>
   
   <div id="LC_done-confirm" title="$lt{'title'}">
       <p>$lt{'preamble'} $lt{$type} $lt{'miss'} $lt{'okdone'} $lt{'cancel'}</p>
   </div>
   
   <script type="text/javascript">
   // <![CDATA[
   \$( "#LC_done-confirm" ).dialog({ autoOpen: false });
   \$( "#LC_done-confirm-opener" ).click(function() {
       \$( "#LC_done-confirm" ).dialog( "open" );
       \$( "#LC_done-confirm" ).dialog({
         resizable: false,
         height: $height,
         width: $width,
         modal: true,
         buttons: [
                    {
                       text: "$lt{'ok'}",
                       click: function() {
                           \$( this ).dialog( "close" );
                           \$( '[name="LC_interval_done"]' )[0].value = 'true';
                           \$( '[name="LCdoneButton"]' )[0].submit();
                       },
                    },
                    {
                        text: "$lt{'exit'}",
                        click: function() {
                            \$( this ).dialog( "close" );
                        },
                     },
                  ],
          });
   });
   // ]]>
   </script>
   
   END
       }
 }  }
   
 sub utilityfunctions {  sub utilityfunctions {
     my $caller = shift;      my ($httphost) = @_;
     unless (($ENV{'browser.interface'} eq 'textual')  ||      my $currenturl=&Apache::lonnet::clutter(&Apache::lonnet::fixversion((split(/\?/,$env{'request.noversionuri'}))[0]));
         ($ENV{'environment.remote'} eq 'off') || ($caller eq '/adm/menu')) { return ''; }      my $currentsymb=&Apache::lonenc::check_encrypt($env{'request.symb'});
     my $currenturl=&Apache::lonenc::check_encrypt($ENV{'request.noversionuri'});      if ($currenturl =~ m{^/adm/wrapper/ext/}) {
           if ($env{'request.external.querystring'}) {
               $currenturl .= ($currenturl=~/\?/)?'&':'?'.$env{'request.external.querystring'};
           }
           my ($anchor) = ($env{'request.symb'} =~ /(\#[^\#]+)$/);
           if (($anchor) && ($currenturl !~ /\Q$anchor\E$/)) {
               $currenturl .= $1;
           }
       }
       $currenturl=&Apache::lonenc::check_encrypt(&unescape($currenturl));
   
       my $dc_popup_cid;
       if ($env{'user.adv'} && exists($env{'user.role.dc./'.
                           $env{'course.'.$env{'request.course.id'}.
                                    '.domain'}.'/'})) {
           $dc_popup_cid = &dc_popup_js();
       }
   
       my $start_page_annotate = 
           &Apache::loncommon::start_page('Annotator',undef,
          {'only_body' => 1,
    'js_ready'  => 1,
    'bgcolor'   => '#BBBBBB',
    'add_entries' => {
       'onload' => 'javascript:document.goannotate.submit();'}});
   
       my $end_page_annotate = 
           &Apache::loncommon::end_page({'js_ready' => 1});
   
       my $jumptores = &Apache::lonhtmlcommon::javascript_jumpto_resource();
   
       my $esc_url=&escape($currenturl);
       my $esc_symb=&escape($currentsymb);
   
       my $countdown = &countdown_toggle_js();
   
       my $ltitarget;
       if ($env{'request.lti.login'}) {
           $ltitarget = $env{'request.lti.target'};
       }
   
       my $annotateurl = '/adm/annotation';
       if ($httphost) {
           $annotateurl = '/adm/annotations';
       }
       my $hostvar = '
   function setLCHost() {
       var lcHostname="";
   ';
       if ($httphost =~ m{^https?\://}) {
           $hostvar .= '    var lcServer="'.$httphost.'";'."\n".
                       '    var hostReg = /^https?:\/\/([^\/]+)$/i;'."\n".
                       '    var match = hostReg.exec(lcServer);'."\n".
                       '    if (match.length) {'."\n".
                       '        if (match[1] == location.hostname) {'."\n".
                       '            lcHostname=lcServer;'."\n".
                       '        }'."\n".
                       '    }'."\n";
       }
           
     my $currentsymb=&Apache::lonenc::check_encrypt($ENV{'request.symb'});      $hostvar .= '    return lcHostname;'."\n".
     my $nav_control=&nav_control_js();  '}'."\n";
 return (<<ENDUTILITY)  
   
     var currentURL="$currenturl";  return (<<ENDUTILITY)
     var reloadURL="$currenturl";      $hostvar
     var currentSymb="$currentsymb";      var currentURL=unescape("$esc_url");
       var reloadURL=unescape("$esc_url");
       var currentSymb=unescape("$esc_symb");
   
 $nav_control  $dc_popup_cid
   
 function go(url) {  $jumptores
    if (url!='' && url!= null) {  
        currentURL = null;  
        currentSymb= null;  
        window.location.href=url;  
    }  
 }  
   
 function gopost(url,postdata) {  function gopost(url,postdata) {
    if (url!='') {     if (url!='') {
       this.document.server.action=url;        var lcHostname = setLCHost();
         this.document.server.action=lcHostname+url;
       this.document.server.postdata.value=postdata;        this.document.server.postdata.value=postdata;
       this.document.server.command.value='';        this.document.server.command.value='';
       this.document.server.url.value='';        this.document.server.url.value='';
Line 1007  function gopost(url,postdata) { Line 2188  function gopost(url,postdata) {
   
 function gocmd(url,cmd) {  function gocmd(url,cmd) {
    if (url!='') {     if (url!='') {
       this.document.server.action=url;        var lcHostname = setLCHost();
         this.document.server.action=lcHostname+url;
       this.document.server.postdata.value='';        this.document.server.postdata.value='';
       this.document.server.command.value=cmd;        this.document.server.command.value=cmd;
       this.document.server.url.value=currentURL;        this.document.server.url.value=currentURL;
Line 1031  function gocstr(url,filename) { Line 2213  function gocstr(url,filename) {
                 this.document.cstrprint.curseed.value = this.document.lonhomework.rndseed.value                  this.document.cstrprint.curseed.value = this.document.lonhomework.rndseed.value
             }              }
             if (this.document.lonhomework.problemtype) {              if (this.document.lonhomework.problemtype) {
                 for (var i=0; i<this.document.lonhomework.problemtype.options.length; i++) {   if (this.document.lonhomework.problemtype.value) {
                     if (this.document.lonhomework.problemtype.options[i].selected) {      this.document.cstrprint.problemtype.value = 
                         if (this.document.lonhomework.problemtype.options[i].value != null && this.document.lonhomework.problemtype.options[i].value != '') {    this.document.lonhomework.problemtype.value;
                             this.document.cstrprint.problemtype.value = this.document.lonhomework.problemtype.options[i].value   } else if (this.document.lonhomework.problemtype.options) {
                         }      for (var i=0; i<this.document.lonhomework.problemtype.options.length; i++) {
                     }   if (this.document.lonhomework.problemtype.options[i].selected) {
                 }      if (this.document.lonhomework.problemtype.options[i].value != null && this.document.lonhomework.problemtype.options[i].value != '') { 
             }   this.document.cstrprint.problemtype.value = this.document.lonhomework.problemtype.options[i].value
         }   }
    }
       }
    }
       }
    }
         this.document.cstrprint.submit();          this.document.cstrprint.submit();
         return;          return;
     }      }
Line 1054  function golist(url) { Line 2241  function golist(url) {
    if (url!='' && url!= null) {     if (url!='' && url!= null) {
        currentURL = null;         currentURL = null;
        currentSymb= null;         currentSymb= null;
        top.location.href=url;         var lcHostname = setLCHost();
          var ltitarget = '$ltitarget';
          if (ltitarget == 'iframe') {
              document.location.href=lcHostname+url;
          } else {
              top.location.href=lcHostname+url;
          }
    }     }
 }  }
   
   
   
 function catalog_info() {  function catalog_info(url,isMobile) {
    loncatinfo=window.open(window.location.pathname+'.meta',"LONcatInfo",'height=320,width=280,resizable=yes,scrollbars=yes,location=no,menubar=no,toolbar=no');      if (isMobile == 1) {
           openMyModal(url+'.meta?modal=1',500,400,'yes');
       } else {
           loncatinfo=window.open(url+'.meta',"LONcatInfo",'height=500,width=400,resizable=yes,scrollbars=yes,location=no,menubar=no,toolbar=no');
       }
 }  }
   
 function chat_win() {  function chat_win() {
    lonchat=window.open('/res/adm/pages/chatroom.html',"LONchat",'height=320,width=280,resizable=yes,location=no,menubar=no,toolbar=no');     var lcHostname = setLCHost();
      lonchat=window.open(lcHostname+'/res/adm/pages/chatroom.html',"LONchat",'height=320,width=480,resizable=yes,location=no,menubar=no,toolbar=no');
 }  }
   
   function group_chat(group) {
      var lcHostname = setLCHost();
      var url = lcHostname+'/adm/groupchat?group='+group;
      var winName = 'LONchat_'+group;
      grpchat=window.open(url,winName,'height=320,width=280,resizable=yes,location=no,menubar=no,toolbar=no');
   }
   
   function annotate() {
      w_Annotator_flag=1;
      annotator=window.open('','Annotator','width=365,height=265,scrollbars=0');
      annotator.document.write(
      '$start_page_annotate'
     +"<form name='goannotate' target='Annotator' method='post' "
     +"action='$annotateurl'>"
     +"<input type='hidden' name='symbnew' value='"+currentSymb+"' />"
     +"<\\/form>"
     +'$end_page_annotate');
      annotator.document.close();
   }
   
   function open_StoredLinks_Import(rat) {
      var newWin;
      var lcHostname = setLCHost();
      if (rat) {
          newWin = window.open(lcHostname+'/adm/wishlist?inhibitmenu=yes&mode=import&rat='+rat,
                               'wishlistImport','scrollbars=1,resizable=1,menubar=0');
      }
      else {
          newWin = window.open(lcHostname+'/adm/wishlist?inhibitmenu=yes&mode=import',
                               'wishlistImport','scrollbars=1,resizable=1,menubar=0');
      }
      newWin.focus();
   }
   
   function open_source() {
      sourcewin=window.open('/adm/source?inhibitmenu=yes&viewonly=1&filename='+currentURL,'LONsource',
                            'height=500,width=600,resizable=yes,location=no,menubar=no,toolbar=no,scrollbars=yes');
   }
   
   function open_aboutLC() {
       var isMobile = "$env{'browser.mobile'}";
       var url = '/adm/about.html';
       if (isMobile == 1) {
           openMyModal(url,600,400,'yes');
       } else {
           window.open(url,"aboutLONCAPA","height=400,width=600,scrollbars=1,resizable=1,menubar=0,location=1");
       }
       return;
   }
   
   
   (function (\$) {
     \$(document).ready(function () {
       \$.single=function(a){return function(b){a[0]=b;return a}}(\$([1]));
       /*\@cc_on
         if (!window.XMLHttpRequest) {
           \$('.LC_hoverable').each(function () {
             this.attachEvent('onmouseenter', function (evt) { \$.single(evt.srcElement).addClass('hover'); });
             this.attachEvent('onmouseleave', function (evt) { \$.single(evt.srcElement).removeClass('hover'); });
           });
         }
       \@*/
     });
   }(jQuery));
   
   $countdown
   
 ENDUTILITY  ENDUTILITY
 }  }
   
 sub serverform {  sub serverform {
       my $target;
       unless (($env{'request.lti.login'}) && ($env{'request.lti.target'} eq 'iframe')) {
           $target = ' target="_top"';
       }
     return(<<ENDSERVERFORM);      return(<<ENDSERVERFORM);
   <form name="server" action="/adm/logout" method="post"$target>
 <form name="server" action="/adm/logout" method="post" target="_top">  
 <input type="hidden" name="postdata" value="none" />  <input type="hidden" name="postdata" value="none" />
 <input type="hidden" name="command" value="none" />  <input type="hidden" name="command" value="none" />
 <input type="hidden" name="url" value="none" />  <input type="hidden" name="url" value="none" />
Line 1083  ENDSERVERFORM Line 2352  ENDSERVERFORM
 }  }
   
 sub constspaceform {  sub constspaceform {
       my ($target,$printtarget);
       unless (($env{'request.lti.login'}) && ($env{'request.lti.target'} eq 'iframe')) {
           $target = ' target="_top"';
           $printtarget = ' target="_parent"';
       }
     return(<<ENDCONSTSPACEFORM);      return(<<ENDCONSTSPACEFORM);
 <form name="constspace" action="/adm/logout" method="post" target="_top">  <form name="constspace" action="/adm/logout" method="post"$target>
 <input type="hidden" name="filename" value="" />  <input type="hidden" name="filename" value="" />
 </form>  </form>
 <form name="cstrdelete" action="/adm/cfile" method="post" target="_top">  <form name="cstrdelete" action="/adm/cfile" method="post"$target>
 <input type="hidden" name="action" value="delete" />   <input type="hidden" name="action" value="delete" /> 
 <input type="hidden" name="filename" value="" />  <input type="hidden" name="filename" value="" />
 </form>  </form>
 <form name="cstrprint" action="/adm/printout" target="_parent" method="post">  <form name="cstrprint" action="/adm/printout" method="post"$printtarget>
 <input type="hidden" name="postdata" value="" />  <input type="hidden" name="postdata" value="" />
 <input type="hidden" name="curseed" value="" />  <input type="hidden" name="curseed" value="" />
 <input type="hidden" name="problemtype" value="" />  <input type="hidden" name="problemtype" value="" />
Line 1100  sub constspaceform { Line 2374  sub constspaceform {
 ENDCONSTSPACEFORM  ENDCONSTSPACEFORM
 }  }
   
   sub hidden_button_check {
       if ( $env{'request.course.id'} eq ''
            || $env{'request.role.adv'} ) {
   
 sub get_nav_status {          return;
     my $navstatus="swmenu.w_loncapanav_flag=";  
     if ($ENV{'environment.remotenavmap'} eq 'on') {  
  $navstatus.="1";  
     } else {  
  $navstatus.="-1";  
     }      }
     return $navstatus;      my $buttonshide = &Apache::lonnet::EXT('resource.0.buttonshide');
       return $buttonshide; 
 }  }
   
 # ================================================ Handler when called directly  sub roles_selector {
       my ($cdom,$cnum,$httphost,$ltitarget) = @_;
       my $crstype = &Apache::loncommon::course_type();
 sub handler {      my $now = time;
     my $r = shift;      my (%courseroles,%seccount,%courseprivs,%roledesc);
     &Apache::loncommon::content_type($r,'text/html');      my $is_cc;
     $r->send_http_header;      my ($js,$form,$switcher);
     return OK if $r->header_only;      my $ccrole;
       if ($crstype eq 'Community') {
           $ccrole = 'co';
       } else {
           $ccrole = 'cc';
       }
       my ($privref,$gotsymb,$destsymb);
       my $destinationurl = $ENV{'REQUEST_URI'};
       if ($destinationurl =~ /(\?|\&)symb=/) {
           $gotsymb = 1;
       } elsif ($destinationurl =~ m{^/enc/}) {
           my $plainurl = &Apache::lonenc::unencrypted($destinationurl);
           if ($plainurl =~ /(\?|\&)symb=/) {
               $gotsymb = 1;
           }
       }
       unless ($gotsymb) {
           $destsymb = &Apache::lonnet::symbread();
           if ($destsymb ne '') {
               $destsymb = &Apache::lonenc::check_encrypt($destsymb);
           }
       }
       my $reqprivs = &required_privs();
       if (ref($reqprivs) eq 'HASH') {
           my $destination = $destinationurl;
           $destination =~ s/(\?.*)$//;
           if (exists($reqprivs->{$destination})) {
               if ($reqprivs->{$destination} =~ /,/) {
                   @{$privref} = split(/,/,$reqprivs->{$destination});
               } else { 
                   $privref = [$reqprivs->{$destination}];
               }
           }
       }
       if ($env{'user.role.'.$ccrole.'./'.$cdom.'/'.$cnum}) {
           my ($start,$end) = split(/\./,$env{'user.role.'.$ccrole.'./'.$cdom.'/'.$cnum});
           if ((($start) && ($start<0)) || 
               (($end) && ($end<$now))  ||
               (($start) && ($now<$start))) {
               $is_cc = 0;
           } else {
               $is_cc = 1;
           }
       }
       if ($is_cc) {
           &get_all_courseroles($cdom,$cnum,\%courseroles,\%seccount,\%courseprivs);
       } elsif ($env{'request.role'} =~ m{^\Qcr/$cdom/$cdom-domainconfig/\E(\w+)\.\Q/$cdom/$cnum\E}) {
           &get_customadhoc_roles($cdom,$cnum,\%courseroles,\%seccount,\%courseprivs,\%roledesc,$privref);
       } else {
           my %gotnosection;
           foreach my $item (keys(%env)) {
               if ($item =~ m-^user\.role\.([^.]+)\./\Q$cdom\E/\Q$cnum\E/?(\w*)$-) {
                   my $role = $1;
                   my $sec = $2;
                   next if ($role eq 'gr');
                   my ($start,$end) = split(/\./,$env{$item});
                   next if (($start && $start > $now) || ($end && $end < $now));
                   if ($sec eq '') {
                       if (!$gotnosection{$role}) {
                           $seccount{$role} ++;
                           $gotnosection{$role} = 1;
                       }
                   }
                   if ((ref($privref) eq 'ARRAY') && (@{$privref} > 0)) {
                       my $cnumsec = $cnum;
                       if ($sec ne '') {
                           $cnumsec .= "/$sec";
                       }
                       $courseprivs{"$role./$cdom/$cnumsec./"} =
                           $env{"user.priv.$role./$cdom/$cnumsec./"};
                       $courseprivs{"$role./$cdom/$cnumsec./$cdom/"} =
                           $env{"user.priv.$role./$cdom/$cnumsec./$cdom/"};
                       $courseprivs{"$role./$cdom/$cnumsec./$cdom/$cnumsec"} =
                           $env{"user.priv.$role./$cdom/$cnumsec./$cdom/$cnumsec"};
                   }
                   if (ref($courseroles{$role}) eq 'ARRAY') {
                       if ($sec ne '') {
                           if (!grep(/^\Q$sec\E$/,@{$courseroles{$role}})) {
                               push(@{$courseroles{$role}},$sec);
                               $seccount{$role} ++;
                           }
                       }
                   } else {
                       @{$courseroles{$role}} = ();
                       if ($sec ne '') {
                           $seccount{$role} ++;
                           push(@{$courseroles{$role}},$sec);
                       }
                   }
               }
           }
       }
       my @roles_order = ($ccrole,'in','ta','ep','ad','st');
       my $numdiffsec;
       if (keys(%seccount) == 1) {
           foreach my $key (keys(%seccount)) {
               $numdiffsec = $seccount{$key};
           }
       }
       if ((keys(%seccount) > 1) || ($numdiffsec > 1)) {
           my @submenu;
           $js = &jump_to_role($cdom,$cnum,\%seccount,\%courseroles,\%courseprivs,\%roledesc,$privref);
           $form = 
               '<form name="rolechooser" method="post" action="'.$httphost.'/adm/roles">'."\n".
               '  <input type="hidden" name="destinationurl" value="'.
               &HTML::Entities::encode($destinationurl).'" />'."\n".
               '  <input type="hidden" name="gotorole" value="1" />'."\n".
               '  <input type="hidden" name="selectrole" value="" />'."\n".
               '  <input type="hidden" name="switchrole" value="" />'."\n";
           if ($destsymb ne '') {
               $form .= '  <input type="hidden" name="destsymb" value="'.
                           &HTML::Entities::encode($destsymb).'" />'."\n";
           }
           $form .= '</form>'."\n";
           foreach my $role (@roles_order) {
               my $include;
               if (defined($courseroles{$role})) {
                   if ($env{'request.role'} =~ m{^\Q$role\E}) {
                       if ($seccount{$role} > 1) {
                           $include = 1;
                       }
                   } else {
                       $include = 1;
                   }
               }
               if ($include) {
                   push(@submenu,['javascript:adhocRole('."'$role'".')',
                                  &Apache::lonnet::plaintext($role,$crstype)]);
               }
           }
           foreach my $role (sort(keys(%courseroles))) {
               if ($role =~ /^cr/) {
                   my $include;
                   if ($env{'request.role'} =~ m{^\Q$role\E}) {
                       if ($seccount{$role} > 1) {
                           $include = 1;
                       }
                   } else {
                       $include = 1; 
                   }
                   if ($include) {
                       my $rolename;
                       if ($role =~ m{^cr/$cdom/$cdom\-domainconfig/(\w+)(?:/\w+|$)}) {
                           $rolename = $roledesc{$role};
                           if ($rolename eq '') {
                               $rolename = &mt('Helpdesk [_1]',$1);
                           }
                       } else {
                           $rolename = &Apache::lonnet::plaintext($role);
                       }
                       push(@submenu,['javascript:adhocRole('."'$role'".')',
                                      $rolename]);
                   }
               }
           }
           if (@submenu > 0) {
               $switcher = &create_submenu('','',&mt('Switch role'),\@submenu,'','',$ltitarget);
           }
       }
       return ($js,$form,$switcher);
   }
   
     my $form;  sub get_all_courseroles {
     if ($ENV{'environment.remote'} ne 'off' &&      my ($cdom,$cnum,$courseroles,$seccount,$courseprivs) = @_;
  $ENV{'browser.interface'} ne 'textual') {      unless ((ref($courseroles) eq 'HASH') && (ref($seccount) eq 'HASH') &&
  $form=&serverform();              (ref($courseprivs) eq 'HASH')) {
           return;
       }
       my ($result,$cached) = 
           &Apache::lonnet::is_cached_new('getcourseroles',$cdom.'_'.$cnum);
       if (defined($cached)) {
           if (ref($result) eq 'HASH') {
               if ((ref($result->{'roles'}) eq 'HASH') && 
                   (ref($result->{'seccount'}) eq 'HASH') && 
                   (ref($result->{'privs'}) eq 'HASH')) {
                   %{$courseroles} = %{$result->{'roles'}};
                   %{$seccount} = %{$result->{'seccount'}};
                   %{$courseprivs} = %{$result->{'privs'}};
                   return;
               }
           }
     }      }
     my $bodytag=&Apache::loncommon::bodytag('Main Menu');      my %gotnosection;
     my $function='student';      my %adv_roles =
     if ($ENV{'request.role'}=~/^(cc|in|ta|ep)/) {           &Apache::lonnet::get_course_adv_roles($env{'request.course.id'},1);
  $function='coordinator';      foreach my $role (keys(%adv_roles)) {
           my ($urole,$usec) = split(/:/,$role);
           if (!$gotnosection{$urole}) {
               $seccount->{$urole} ++;
               $gotnosection{$urole} = 1;
           }
           if (ref($courseroles->{$urole}) eq 'ARRAY') {
               if ($usec ne '') {
                   if (!grep(/^Q$usec\E$/,@{$courseroles->{$urole}})) {
                       push(@{$courseroles->{$urole}},$usec);
                       $seccount->{$urole} ++;
                   }
               }
           } else {
               @{$courseroles->{$urole}} = ();
               if ($usec ne '') {
                   $seccount->{$urole} ++;
                   push(@{$courseroles->{$urole}},$usec);
               }
           }
           my $area = '/'.$cdom.'/'.$cnum;
           if ($usec ne '') {
               $area .= '/'.$usec;
           }
           if ($role =~ /^cr\//) {
               &Apache::lonnet::custom_roleprivs($courseprivs,$urole,$cdom,$cnum,$urole.'.'.$area,$area);
           } else {
               &Apache::lonnet::standard_roleprivs($courseprivs,$urole,$cdom,$urole.'.'.$area,$cnum,$area);
           }
     }      }
     if ($ENV{'request.role'}=~/^(su|dc|ad|li)/) {      my %sections_count = &Apache::loncommon::get_sections($cdom,$cnum,['st']);
  $function='admin';      @{$courseroles->{'st'}} = ();
       &Apache::lonnet::standard_roleprivs($courseprivs,'st',$cdom,"st./$cdom/$cnum",$cnum,"/$cdom/$cnum");
       if (keys(%sections_count) > 0) {
           push(@{$courseroles->{'st'}},keys(%sections_count));
           $seccount->{'st'} = scalar(keys(%sections_count));
       }
       $seccount->{'st'} ++; # Increment for a section-less student role.  
       my $rolehash = {
                        'roles'    => $courseroles,
                        'seccount' => $seccount,
                        'privs'    => $courseprivs,
                      };
       &Apache::lonnet::do_cache_new('getcourseroles',$cdom.'_'.$cnum,$rolehash);
       return;
   }
   
   sub get_customadhoc_roles {
       my ($cdom,$cnum,$courseroles,$seccount,$courseprivs,$roledesc,$privref) = @_;
       unless ((ref($courseroles) eq 'HASH') && (ref($seccount) eq 'HASH') &&
               (ref($courseprivs) eq 'HASH') && (ref($roledesc) eq 'HASH')) {
           return;
     }      }
     if (($ENV{'request.role'}=~/^(au|ca)/) ||      my $is_helpdesk = 0;
  ($ENV{'request.noversionuri'}=~/^(\/priv|\~)/)) {      my $now = time;
  $function='author';      foreach my $role ('dh','da') {
           if ($env{"user.role.$role./$cdom/"}) {
               my ($start,$end)=split(/\./,$env{"user.role.$role./$cdom/"});
               if (!($start && ($now<$start)) && !($end && ($now>$end))) {
                   $is_helpdesk = 1;
                   last;
               }
           }
     }      }
     my $domain=&Apache::loncommon::determinedomain();      if ($is_helpdesk) {
     $pgbg=&Apache::loncommon::designparm($function.'.pgbg',$domain);          my ($possroles,$description) = &Apache::lonnet::get_my_adhocroles($cdom.'_'.$cnum);
     $tabbg=&Apache::loncommon::designparm($function.'.tabbg',$domain);          my %available;
     $font=&Apache::loncommon::designparm($function.'.font',$domain);          if (ref($possroles) eq 'ARRAY') {
     my $script_tag;              map { $available{$_} = 1; } @{$possroles};
     if ($ENV{'environment.remote'} eq 'on') {          }
         my $utility=&utilityfunctions('/adm/menu');          my %domdefaults = &Apache::lonnet::get_domain_defaults($cdom);
         $script_tag=(<<ENDSCRIPT);          if (ref($domdefaults{'adhocroles'}) eq 'HASH') {
               if (keys(%{$domdefaults{'adhocroles'}})) {
                   my $numsec = 1;
                   my @sections;
                   my ($allseclist,$cached) =
                       &Apache::lonnet::is_cached_new('courseseclist',$cdom.'_'.$cnum);
                   if (defined($cached)) {
                       if ($allseclist ne '') {
                           @sections = split(/,/,$allseclist);
                           $numsec += scalar(@sections);
                       }
                   } else {
                       my %sections_count = &Apache::loncommon::get_sections($cdom,$cnum);
                       @sections = sort(keys(%sections_count));
                       $numsec += scalar(@sections);
                       $allseclist = join(',',@sections);
                       &Apache::lonnet::do_cache_new('courseseclist',$cdom.'_'.$cnum,$allseclist);
                   }
                   my (%adhoc,$gotprivs);
                   my $prefix = "cr/$cdom/$cdom".'-domainconfig';
                   foreach my $role (keys(%{$domdefaults{'adhocroles'}})) {
                       next if (($role eq '') || ($role =~ /\W/));
                       $seccount->{"$prefix/$role"} = $numsec;
                       $roledesc->{"$prefix/$role"} = $description->{$role};
                       if ((ref($privref) eq 'ARRAY') && (@{$privref} > 0)) {
                           if (exists($env{"user.priv.$prefix/$role./$cdom/$cnum./"})) {
                               $courseprivs->{"$prefix/$role./$cdom/$cnum./"} =
                                   $env{"user.priv.$prefix/$role./$cdom/$cnum./"};
                               $courseprivs->{"$prefix/$role./$cdom/$cnum./$cdom/"} =
                                   $env{"user.priv.$prefix/$role./$cdom/$cnum./$cdom/"};
                               $courseprivs->{"$prefix/$role./$cdom/$cnum./$cdom/$cnum"} =
                                   $env{"user.priv.$prefix/$role./$cdom/$cnum./$cdom/$cnum"};
                           } else {
                               unless ($gotprivs) {
                                   my ($adhocroles,$privscached) =
                                       &Apache::lonnet::is_cached_new('adhocroles',$cdom);
                                   if ((defined($privscached)) && (ref($adhocroles) eq 'HASH')) {
                                       %adhoc = %{$adhocroles};
                                   } else {
                                       my $confname = &Apache::lonnet::get_domainconfiguser($cdom);
                                       my %roledefs = &Apache::lonnet::dump('roles',$cdom,$confname,'rolesdef_');
                                       foreach my $key (keys(%roledefs)) {
                                           (undef,my $rolename) = split(/_/,$key);
                                           if ($rolename ne '') {
                                               my ($systempriv,$domainpriv,$coursepriv) = split(/\_/,$roledefs{$key});
                                               $coursepriv = &Apache::lonnet::course_adhocrole_privs($rolename,$cdom,$cnum,$coursepriv);
                                               $adhoc{$rolename} = join('_',($systempriv,$domainpriv,$coursepriv));
                                           }
                                       }
                                       &Apache::lonnet::do_cache_new('adhocroles',$cdom,\%adhoc);
                                   }
                                   $gotprivs = 1;
                               }
                               ($courseprivs->{"$prefix/$role./$cdom/$cnum./"},
                                $courseprivs->{"$prefix/$role./$cdom/$cnum./$cdom/"},
                                $courseprivs->{"$prefix/$role./$cdom/$cnum./$cdom/$cnum"}) =
                                    split(/\_/,$adhoc{$role});
                           }
                       }
                       if ($available{$role}) {
                           $courseroles->{"$prefix/$role"} = \@sections;
                       }
                   }
               }
           }
       }
       return;
   }
   
   sub jump_to_role {
       my ($cdom,$cnum,$seccount,$courseroles,$courseprivs,$roledesc,$privref) = @_;
       my %lt = &Apache::lonlocal::texthash(
                   this => 'This role has section(s) associated with it.',
                   ente => 'Enter a specific section.',
                   orlb => 'Enter a specific section, or leave blank for no section.',
                   avai => 'Available sections are:',
                   youe => 'You entered an invalid section choice:',
                   plst => 'Please try again.',
                   role => 'The role you selected is not permitted to view the current page.',
                   swit => 'Switch role, but display Main Menu page instead?',
       );
       my $js;
       if (ref($courseroles) eq 'HASH') {
           $js = '    var secpick = new Array("'.$lt{'ente'}.'","'.$lt{'orlb'}.'");'."\n". 
                 '    var numsec = new Array();'."\n".
                 '    var rolesections = new Array();'."\n".
                 '    var rolenames = new Array();'."\n".
                 '    var roleseclist = new Array();'."\n";
           my @items = keys(%{$courseroles});
           for (my $i=0; $i<@items; $i++) {
               $js .= '    rolenames['.$i.'] = "'.$items[$i].'";'."\n";
               my ($secs,$secstr);
               if (ref($courseroles->{$items[$i]}) eq 'ARRAY') {
                   my @sections = sort { $a <=> $b } @{$courseroles->{$items[$i]}};
                   $secs = join('","',@sections);
                   $secstr = join(', ',@sections);
               }
               $js .= '    rolesections['.$i.'] = new Array("'.$secs.'");'."\n".
                      '    roleseclist['.$i.'] = "'.$secstr.'";'."\n".
                      '    numsec['.$i.'] = "'.$seccount->{$items[$i]}.'";'."\n";
           }
       }
       my $checkroles = 0;
       if ((ref($privref) eq 'ARRAY') && (@{$privref} > 0) && (ref($courseprivs) eq 'HASH')) {
           my %disallowed;
           foreach my $role (sort(keys(%{$courseprivs}))) {
               my $trole;
               if ($role =~ m{^(.+?)\Q./$cdom/$cnum\E}) {
                   $trole = $1;
               }
               if (($trole ne '') && ($trole ne 'cm')) {
                   $disallowed{$trole} = 1;
                   foreach my $priv (@{$privref}) { 
                       if ($courseprivs->{$role} =~ /\Q:$priv\E($|:|\&\w+)/) {
                           delete($disallowed{$trole});
                           last;
                       }
                   }
               }
           }
           if (keys(%disallowed) > 0) {
               $checkroles = 1;
               $js .= "    var disallow = new Array('".join("','",keys(%disallowed))."');\n".
                      "    var rolecheck = 1;\n";
           }
       }
       if (!$checkroles) {
           $js .=  "    var disallow = new Array();\n".
                   "    rolecheck = 0;\n";
       }
       return <<"END";
 <script type="text/javascript">  <script type="text/javascript">
 $utility  //<![CDATA[
   function adhocRole(newrole) {
       $js
       if (newrole == '') {
           return;
       } 
       var fullrole = newrole+'./$cdom/$cnum';
       var selidx = '';
       for (var i=0; i<rolenames.length; i++) {
           if (rolenames[i] == newrole) {
               selidx = i;
           }
       }
       if (rolecheck > 0) {
           for (var i=0; i<disallow.length; i++) {
               if (disallow[i] == newrole) {
                   if (confirm("$lt{'role'}\\n$lt{'swit'}")) {
                       document.rolechooser.destinationurl.value = '/adm/menu';
                   } else {
                       return;
                   }
               }
           }
       }
       var secok = 1;
       var secchoice = '';
       if (selidx >= 0) {
           if (numsec[selidx] > 1) {
               secok = 0;
               var numrolesec = rolesections[selidx].length;
               var msgidx = numsec[selidx] - numrolesec;
               secchoice = prompt("$lt{'this'} "+secpick[msgidx]+"\\n$lt{'avai'} "+roleseclist[selidx],"");
               if (secchoice == '') {
                   if (msgidx > 0) {
                       secok = 1;
                   }
               } else {
                   for (var j=0; j<rolesections[selidx].length; j++) {
                       if (rolesections[selidx][j] == secchoice) {
                           secok = 1;
                       }
                   }
               }
           } else {
               if (rolesections[selidx].length == 1) {
                   secchoice = rolesections[selidx][0];
               }
           }
       }
       if (secok == 1) {
           if (secchoice != '') {
               fullrole += '/'+secchoice;
           }
       } else {
           if (secchoice != null) {
               alert("$lt{'youe'} \\""+secchoice+"\\".\\n $lt{'plst'}");
           }
           return;
       }
       if (fullrole == "$env{'request.role'}") {
           return;
       }
       itemid = retrieveIndex('gotorole');
       if (itemid != -1) {
           document.rolechooser.elements[itemid].name = fullrole;
       }
       document.rolechooser.switchrole.value = fullrole;
       document.rolechooser.selectrole.value = '1';
       document.rolechooser.submit();
       return;
   }
   
   function retrieveIndex(item) {
       for (var i=0;i<document.rolechooser.elements.length;i++) {
           if (document.rolechooser.elements[i].name == item) {
               return i;
           }
       }
       return -1;
   }
   // ]]>
 </script>  </script>
 ENDSCRIPT  END
   }
   
   sub required_privs {
       my $privs =  {
                '/adm/parmset'      => 'opa,vpa',
                '/adm/courseprefs'  => 'opa,vpa',
                '/adm/whatsnew'     => 'whn',
                '/adm/populate'     => 'cst,vpa,vcl',
                '/adm/trackstudent' => 'vsa',
                '/adm/statistics'   => 'mgr,vgr',
                '/adm/setblock'     => 'dcm,vcb',
                '/adm/coursedocs'   => 'mdc',
              };
       unless ($env{'course.'.$env{'request.course.id'}.'.grading'} eq 'spreadsheet') {
           $privs->{'/adm/classcalc'}   = 'vgr',
           $privs->{'/adm/assesscalc'}  = 'vgr',
           $privs->{'/adm/studentcalc'} = 'vgr';
       }
       return $privs;
   }
   
   sub countdown_timer {
       if (($env{'request.course.id'}) && ($env{'request.symb'} ne '') &&
           (($env{'request.filename'}=~/$LONCAPA::assess_re/) ||
            (($env{'request.symb'} =~ /ext\.tool$/) &&
            (&Apache::lonnet::EXT('resource.0.gradable',$env{'request.symb'}) =~ /^yes$/i)))) {
           my ($type,$hastimeleft,$slothastime);
           my $now = time;
           if ($env{'request.filename'} =~ /\.task$/) {
               $type = 'Task';
           } elsif ($env{'request.symb'} =~ /ext\.tool$/) {
               $type = 'tool';
           } else {
               $type = 'problem';
           }
           my ($status,$accessmsg,$slot_name,$slot);
           if ($type eq 'tool') {
               ($status,$accessmsg,$slot_name,$slot) =
                   &Apache::lonhomework::check_slot_access('0',$type,$env{'request.symb'},['0']);
           } else {
               ($status,$accessmsg,$slot_name,$slot) =
                   &Apache::lonhomework::check_slot_access('0',$type);
           }
           if ($slot_name ne '') {
               if (ref($slot) eq 'HASH') {
                   if (($slot->{'starttime'} < $now) &&
                       ($slot->{'endtime'} > $now)) {
                       $slothastime = 1;
                   }
               }
           }
           if ($status ne 'CAN_ANSWER') {
               return;
           }
           my $duedate = &Apache::lonnet::EXT("resource.0.duedate");
           my @interval=&Apache::lonnet::EXT("resource.0.interval");
           my ($timelimit,$usesdone,$donebuttontext,$proctor,$secret);
           if (@interval > 1) {
               ($timelimit,my $donesuffix) = split(/_/,$interval[0],2);
               if ($donesuffix =~ /^done\:([^\:]+)\:(.*)$/) {
                   $usesdone = 'done';
                   $donebuttontext = $1;
                   (undef,$proctor,$secret) = split(/_/,$2);
               } elsif ($donesuffix =~ /^done(|_.+)$/) {
                   $donebuttontext = &mt('Done');
                   ($usesdone,$proctor,$secret) = split(/_/,$donesuffix);
               }
               my $first_access=&Apache::lonnet::get_first_access($interval[1]);
               if ($first_access > 0) {
                   if ($first_access+$timelimit > time) {
                       $hastimeleft = 1;
                   }
               }
           }
           if (($duedate && $duedate > time) ||
               (!$duedate && $hastimeleft) ||
               ($slot_name ne '' && $slothastime)) {
               my ($collapse,$expand,$alttxt,$title,$currdisp,$donebutton);
               if ((@interval > 1 && $hastimeleft) ||
                   ($type eq 'Task' && $slothastime)) {
                   $currdisp = 'inline';
                   $collapse = '&#9658;&nbsp;';
                   if ((@interval > 1) && ($hastimeleft)) {
                       if ($usesdone eq 'done') {
                           $donebutton = &done_button_js($interval[1],'','',$proctor,$donebuttontext);
                       }
                   }
               } else {
                   $currdisp = 'none';
                   $expand = '&#9668;&nbsp;';
               }
               unless ($env{'environment.icons'} eq 'iconsonly') {
                   $alttxt = &mt('Timer');
                   $title = $alttxt.'&nbsp;';
               }
               my $desc = &mt('Countdown to due date/time');
   
               return <<END;
   $donebutton
   <a href="javascript:toggleCountdown();" class="LC_menubuttons_link">
   <span id="ddcountcollapse" class="LC_menubuttons_inline_text">
   $collapse
   </span></a>
   <span id="duedatecountdown" class="LC_menubuttons_inline_text" style="display: $currdisp;"></span>
   <a href="javascript:toggleCountdown();" class="LC_menubuttons_link">
   <span id="ddcountexpand" class="LC_menubuttons_inline_text" >$expand</span>
   <img src="/res/adm/pages/timer.png" title="$desc" class="LC_icon" alt="$alttxt" /><span class="LC_menubuttons_inline_text">$title</span></a>
   END
           }
     }      }
 # ---- Print the screen, pretend to be in text mode to generate text-based menu      return;
     unless ($ENV{'browser.interface'} eq 'textual') {  }
  $ENV{'browser.interface'}='faketextual';  
  $ENV{'environment.remote'}='off';  sub placement_progress {
     }      my ($totalpoints,$incomplete) = &Apache::lonplacementtest::check_completion(undef,undef,1);
     $r->print(<<ENDHEADER);      my $complete = 100 - $incomplete;
 <html><head>      return '<span class="LC_placement_prog">'.
 <title>LON-CAPA Main Menu</title>             &mt('Test is [_1]% complete',$complete).'</span>';
 $script_tag  
 </head>  
 $bodytag  
 ENDHEADER  
     $r->print('<table>'.&inlinemenu().'</table>'.$form);  
     $r->print('</body></html>');  
     return OK;  
 }  }
   
 # ================================================================ Main Program  # ================================================================ Main Program
   
 BEGIN {  BEGIN {
   if (! defined($readdesk)) {      if (! defined($readdesk)) {
    {          {
     my $tabfile = $Apache::lonnet::perlvar{'lonTabDir'}.'/mydesk.tab';              my $tabfile = $Apache::lonnet::perlvar{'lonTabDir'}.'/mydesk.tab';
     if ( CORE::open( my $config,"<$tabfile") ) {              if ( CORE::open( my $config,"<$tabfile") ) {
         while (my $configline=<$config>) {                  while (my $configline=<$config>) {
             $configline=(split(/\#/,$configline))[0];                      $configline=(split(/\#/,$configline))[0];
             $configline=~s/^\s+//;                      $configline=~s/^\s+//;
             chomp($configline);                      chomp($configline);
             if ($configline) {                      if ($configline=~/^cat\:/) {
                 $desklines[$#desklines+1]=$configline;                          my @entries=split(/\:/,$configline);
                           $category_positions{$entries[2]}=$entries[1];
                           $category_names{$entries[2]}=$entries[3];
                       } elsif ($configline=~/^prim\:/) {
                           my @entries = (split(/\:/, $configline))[1..6];
                           push(@primary_menu,\@entries);
                       } elsif ($configline=~/^primsub\:/) {
                           my ($parent,@entries) = (split(/\:/, $configline))[1..4];
                           push(@{$primary_submenu{$parent}},\@entries);
                       } elsif ($configline=~/^scnd\:/) {
                           my @entries = (split(/\:/, $configline))[1..5];
                           push(@secondary_menu,\@entries);
                       } elsif ($configline=~/^scndsub\:/) {
                           my ($parent,@entries) = (split(/\:/, $configline))[1..4];
                           push(@{$secondary_submenu{$parent}},\@entries);
                       } elsif ($configline) {
                           push(@desklines,$configline);
                       }
                   }
                   CORE::close($config);
             }              }
         }          }
         CORE::close($config);          $readdesk='done';
     }      }
    }  
    $readdesk='done';  
   }  
 }  }
   
 1;  1;
 __END__  __END__
   
   
   
   
   
   
   

Removed from v.1.140  
changed lines
  Added in v.1.503


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