--- loncom/interface/lonmenu.pm	2011/11/27 20:55:58	1.362
+++ loncom/interface/lonmenu.pm	2012/05/24 23:30:16	1.376
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Routines to control the menu
 #
-# $Id: lonmenu.pm,v 1.362 2011/11/27 20:55:58 www Exp $
+# $Id: lonmenu.pm,v 1.376 2012/05/24 23:30:16 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -26,8 +26,6 @@
 # http://www.lon-capa.org/
 #
 #
-# There is one parameter controlling the action of this module:
-#
 
 =head1 NAME
 
@@ -35,7 +33,8 @@ Apache::lonmenu
 
 =head1 SYNOPSIS
 
-Coordinates the response to clicking an image.
+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.
@@ -74,10 +73,19 @@ It is set to 'done' in the BEGIN block o
 =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.
+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
@@ -107,6 +115,18 @@ entries from mydesk.tab
 
 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: 4 - (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.
+
 =item innerregister()
 
 This gets called in order to register a URL in the body of the document
@@ -129,6 +149,9 @@ The javascript is usually similar to "go
 
 =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()
@@ -159,7 +182,7 @@ use HTML::Entities();
 use Apache::lonwishlist();
 
 use vars qw(@desklines %category_names %category_members %category_positions 
-            $readdesk @primary_menu @secondary_menu);
+            $readdesk @primary_menu %primary_submenu @secondary_menu);
 
 my @inlineremote;
 
@@ -182,7 +205,7 @@ sub prep_menuitem {
 
 # primary_menu() evaluates @primary_menu and returns XHTML for the menu
 # that contains following links:
-# About, Message, Roles, Help, Logout
+# About, Message, Personal, Roles, Help, Logout
 # @primary_menu is filled within the BEGIN block of this module with 
 # entries from mydesk.tab
 sub primary_menu {
@@ -212,8 +235,35 @@ sub primary_menu {
         next if    $$menuitem[4]        eq 'courses'   ##'Roles' wanted
                 && !&Apache::loncommon::show_course(); ##
         
-            
-        if ($$menuitem[3] eq 'Help') { # special treatment for helplink
+        my $title = $menuitem->[3];
+        if (defined($primary_submenu{$title})) {
+            my ($link,$target);
+            if ($menuitem->[0] ne '') {
+                $link = $menuitem->[0];
+                $target = '_top';
+            } else {
+                $link = '#';
+            }
+            my @primsub;
+            if (ref($primary_submenu{$title}) eq 'ARRAY') {
+                foreach my $item (@{$primary_submenu{$title}}) {
+                    next if (($item->[2] eq 'wishlist') &&
+                             ((!&Apache::lonnet::allowed('bre',"/res/$env{'user.domain'}/")) &&
+                              (!&Apache::lonnet::allowed('bro',"/res/$env{'user.domain'}/"))));
+                    next if (($item->[2] eq 'reqcrs') && (!&check_for_rcrs()));
+                    next if ((($item->[2] eq 'portfolio') ||
+                             ($item->[2] eq 'blog')) &&
+                             (!&Apache::lonnet::usertools_access('','',$item->[2],
+                                                           undef,'tools')));
+                    push(@primsub,$item);
+                }
+                if (@primsub > 0) {
+                    $menu .= &create_submenu($link,$target,$title,\@primsub);
+                } elsif ($link) {
+                    $menu .= '<li><a href="'.$link.'" target="'.$target.'">'.$title.'</a></li>';
+                }
+            }
+        } elsif ($$menuitem[3] eq 'Help') { # special treatment for helplink
             if ($public) {
                 my $origmail = $Apache::lonnet::perlvar{'lonSupportEMail'};
                 my $defdom = &Apache::lonnet::default_login_domain();
@@ -269,6 +319,7 @@ sub secondary_menu {
                                                ? "/$env{'request.course.sec'}"
                                                : '');
     my $canedit       = &Apache::lonnet::allowed('mdc', $env{'request.course.id'});
+    my $canviewroster = $env{'course.'.$env{'request.course.id'}.'.student_classlist_view'};
     my $canviewgrps   = &Apache::lonnet::allowed('vcg', $crs_sec); 
     my $canmodifyuser = &Apache::lonnet::allowed('cst', $crs_sec); 
     my $canviewwnew   = &Apache::lonnet::allowed('whn', $crs_sec); 
@@ -297,7 +348,7 @@ sub secondary_menu {
         next if    $$menuitem[4]   eq 'cst'
                 && !$canmodifyuser;
         next if    $$menuitem[4]   eq 'ncst'
-                && $canmodifyuser;
+                && ($canmodifyuser || !$canviewroster);
         next if    $$menuitem[4]   eq 'mgr'
                 && !$canmgr;
         next if    $$menuitem[4]   eq 'nmgr'
@@ -348,6 +399,33 @@ sub secondary_menu {
     return "<ul id=\"LC_secondary_menu\">$menu</ul>";
 }
 
+sub create_submenu {
+    my ($link,$target,$title,$submenu) = @_;
+    return unless (ref($submenu) eq 'ARRAY');
+    my $menu = '<li class="LC_hoverable">'.
+               '<a href="'.$link.'" target="'.$target.'">'.
+               '<span class="LC_nobreak">'.$title.
+               '<span class="LC_fontsize_small" style="font-weight:normal;">'.
+               ' &#9660;</span></span></a>'.
+               '<ul>';
+    my $count = 0;
+    my $numsub = scalar(@{$submenu});
+    foreach my $item (@{$submenu}) {
+        $count ++;
+        if (ref($item) eq 'ARRAY') {
+            my $borderbot;
+            if ($count == $numsub) {
+                $borderbot = 'border-bottom:1px solid black;';
+            }
+            $menu .= '<li style="margin:0;padding:0;'.
+                     $borderbot.'"><a href="'.$item->[0].'">'.
+                     $item->[1].'</a></li>';
+        }
+    }
+    $menu .= '</ul></li>';
+    return $menu;
+}
+
 sub innerregister {
     my ($forcereg,$bread_crumbs) = @_;
     my $const_space = ($env{'request.state'} eq 'construct');
@@ -428,7 +506,7 @@ sub innerregister {
 			     "gocmd('/adm/parmset','set')",
 			     'Content Settings');
 	}
-        if ($env{'request.symb'} ne '' &&
+        if ($env{'request.symb'}=~/^uploaded/ &&
             &Apache::lonnet::allowed('mdc',$crs)) {
             $hwkadd.=&switch('','',7,4,'docs.png','Folder/Page Content','parms[_2]',
                              "gocmd('/adm/coursedocs','direct')",
@@ -633,7 +711,7 @@ ENDMENUITEMS
                 # 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&Wishlist&wishlistlink[_2]&set_wishlistlink()&Set a link for this resource to wishlist&&1
+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
             }
 
@@ -668,7 +746,7 @@ ENDMENUITEMS
             if (&Apache::lonnet::allowed('bre', $env{'request.course.id'}) eq 'F') {
                 # wishlist is only available for users with access to resource-pool
                 $menuitems .= (<<ENDMENUITEMS);
-s&9&1&wishlist-link.png&Wishlist&wishlistlink[_2]&set_wishlistlink()&Set a link for this resource to wishlist&&1
+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
             }
 	}
@@ -1087,13 +1165,13 @@ function showCourseID() {
     document.getElementById('dccid').style.display='block';
     document.getElementById('dccid').style.textAlign='left';
     document.getElementById('dccid').style.textFace='normal';
-    document.getElementById('dccidtext').innerHTML ='<a href="javascript:hideCourseID();">$lt{'less'}</a>';
+    document.getElementById('dccidtext').innerHTML ='<a href="javascript:hideCourseID();" class="LC_menubuttons_link">$lt{'less'}</a>';
     return;
 }
 
 function hideCourseID() {
     document.getElementById('dccid').style.display='none';
-    document.getElementById('dccidtext').innerHTML ='<a href="javascript:showCourseID()">$lt{'more'}</a>';
+    document.getElementById('dccidtext').innerHTML ='<a href="javascript:showCourseID()" class="LC_menubuttons_link">$lt{'more'}</a>';
     return;
 }
 
@@ -1132,12 +1210,14 @@ sub utilityfunctions {
     my $confirm_switch = &mt("Editing requires switching to the resource's home server.").'\n'.
                          &mt('Switch server?');
 
+    my $esc_url=&escape($currenturl);
+    my $esc_symb=&escape($currentsymb);
 
 return (<<ENDUTILITY)
 
-    var currentURL="$currenturl";
-    var reloadURL="$currenturl";
-    var currentSymb="$currentsymb";
+    var currentURL=unescape("$esc_url");
+    var reloadURL=unescape("$esc_url");
+    var currentSymb=unescape("$esc_symb");
 
 $dc_popup_cid
 
@@ -1230,7 +1310,7 @@ function golist(url) {
 
 
 function catalog_info() {
-   loncatinfo=window.open(window.location.pathname+'.meta',"LONcatInfo",'height=320,width=280,resizable=yes,scrollbars=yes,location=no,menubar=no,toolbar=no');
+   openMyModal(window.location.pathname+'.meta',500,400,'yes');
 }
 
 function chat_win() {
@@ -1256,19 +1336,7 @@ function annotate() {
    annotator.document.close();
 }
 
-function set_wishlistlink(title, path) {
-    if (!title) {
-        title = document.title;
-        title = title.replace(/^LON-CAPA /,'');
-    }
-    if (!path) {
-        path = location.pathname;
-    }
-    Win = window.open('/adm/wishlist?mode=newLink&setTitle='+title+'&setPath='+path,
-                      'wishlistNewLink','width=560,height=350,scrollbars=0');
-}
-
-function open_Wishlist_Import(rat) {
+function open_StoredLinks_Import(rat) {
    var newWin;
    if (rat) {
        newWin = window.open('/adm/wishlist?inhibitmenu=yes&mode=import&rat='+rat,
@@ -1281,6 +1349,20 @@ function open_Wishlist_Import(rat) {
    newWin.focus();
 }
 
+(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));
+
 ENDUTILITY
 }
 
@@ -1668,11 +1750,13 @@ sub required_privs {
              '/adm/populate'     => 'cst',
              '/adm/trackstudent' => 'vsa',
              '/adm/statistics'   => 'vgr',
+             '/adm/setblock'     => 'dcm',
+             '/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';
+        $privs->{'/adm/classcalc'}   = 'vgr',
+        $privs->{'/adm/assesscalc'}  = 'vgr',
+        $privs->{'/adm/studentcalc'} = 'vgr';
     }
     return $privs;
 }
@@ -1695,6 +1779,9 @@ BEGIN {
                     } elsif ($configline=~/^prim\:/) {
                         my @entries = (split(/\:/, $configline))[1..5];
                         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;