--- loncom/interface/lonmenu.pm 2010/09/14 03:16:04 1.315.2.4 +++ loncom/interface/lonmenu.pm 2012/08/03 17:35:32 1.369.2.17 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Routines to control the menu # -# $Id: lonmenu.pm,v 1.315.2.4 2010/09/14 03:16:04 raeburn Exp $ +# $Id: lonmenu.pm,v 1.369.2.17 2012/08/03 17:35:32 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -26,10 +26,6 @@ # http://www.lon-capa.org/ # # -# There is one parameter controlling the action of this module: -# -# environment.remote - if this is 'on', the routines controll the remote -# control, otherwise they render the main window controls; =head1 NAME @@ -37,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. @@ -76,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 @@ -109,16 +115,21 @@ entries from mydesk.tab Same as primary_menu() but operates on @secondary_menu. -=item show_return_link() - -=item registerurl() +=item create_submenu() -This gets called in the header section +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
  • 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, both with the Remote -and in the body of the document +This gets called in order to register a URL in the body of the document =item loadevents() @@ -156,12 +167,11 @@ The javascript is usually similar to "go =item rawconfig() -=item close() - -=item footer() - =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() @@ -186,11 +196,13 @@ use Apache::lonhtmlcommon(); use Apache::loncommon(); use Apache::lonenc(); use Apache::lonlocal; +use Apache::lonmsg(); use LONCAPA qw(:DEFAULT :match); 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 %secondary_submenu); my @inlineremote; @@ -205,15 +217,15 @@ sub prep_menuitem { } else { # textual Link $link = &mt($$menuitem[3]); } - if($$menuitem[4] eq 'newmsg'){ #special style for New Messages - return '
  • '.$link.'
  • '; - } - return '
  • '.$link.'
  • '; + return '
  • $link
  • |; } # 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 { @@ -235,23 +247,59 @@ sub primary_menu { next if $$menuitem[4] !~ /public/ ##we've a public user, && $public; ##who should not see all ##links - next if $$menuitem[4] eq 'onlypublic'# hide links which are + next if $$menuitem[4] eq 'onlypublic'# hide links which are && !$public; # only visible to public # users next if $$menuitem[4] eq 'roles' ##show links depending on - && &Apache::loncommon::show_course(); ##term 'Courses' or + && &Apache::loncommon::show_course(); ##term 'Courses' or next if $$menuitem[4] eq 'courses' ##'Roles' wanted && !&Apache::loncommon::show_course(); ## - - - if ($$menuitem[3] eq 'Help') { # special treatment for helplink - $menu .= '
  • '.&Apache::loncommon::top_nav_help('Help').'
  • '; + + 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') && (!$env{'user.adv'})); + 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 .= '
  • '.&mt($title).'
  • '; + } + } + } elsif ($$menuitem[3] eq 'Help') { # special treatment for helplink + if ($public) { + my $origmail = $Apache::lonnet::perlvar{'lonSupportEMail'}; + my $defdom = &Apache::lonnet::default_login_domain(); + my $to = &Apache::loncommon::build_recipient_list(undef, + 'helpdeskmail', + $defdom,$origmail); + if ($to ne '') { + $menu .= &prep_menuitem($menuitem); + } + } else { + $menu .= '
  • '.&Apache::loncommon::top_nav_help('Help').'
  • '; + } } else { - my @items = @{$menuitem}; - $items[0] = 'javascript:'.$menuitem->[0].';'; - $menu .= &prep_menuitem(\@items); + $menu .= prep_menuitem($menuitem); } } + $menu =~ s/\[domain\]/$env{'user.domain'}/g; + $menu =~ s/\[user\]/$env{'user.name'}/g; return "
      $menu
    "; } @@ -281,69 +329,96 @@ sub getauthor{ return; } - sub secondary_menu { my $menu; my $crstype = &Apache::loncommon::course_type(); - my $crs_sec = $env{'request.course.id'} . ($env{'request.course.sec'} + 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 $canviewroster = $env{'course.'.$env{'request.course.id'}.'.student_classlist_view'}; my $canviewgrps = &Apache::lonnet::allowed('vcg', $crs_sec); - my $author = getauthor(); + my $canmodifyuser = &Apache::lonnet::allowed('cst', $crs_sec); + my $canviewwnew = &Apache::lonnet::allowed('whn', $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 $author = &getauthor(); - my $showlink = &show_return_link(); my %groups = &Apache::lonnet::get_active_groups( $env{'user.domain'}, $env{'user.name'}, $env{'course.' . $env{'request.course.id'} . '.domain'}, $env{'course.' . $env{'request.course.id'} . '.num'}); + foreach my $menuitem (@secondary_menu) { # evaluate conditions next if ref($menuitem) ne 'ARRAY'; next if $$menuitem[4] ne 'always' && $$menuitem[4] ne 'author' && !$env{'request.course.id'}; - next if $$menuitem[4] eq 'showreturn' - && !$showlink - && !($env{'request.state'} eq 'construct'); next if $$menuitem[4] =~ /^mdc/ && !$canedit; next if $$menuitem[4] eq 'mdcCourse' - && $crstype eq 'Community'; + && ($crstype eq 'Community'); next if $$menuitem[4] eq 'mdcCommunity' - && $crstype ne 'Community'; - next if $$menuitem[4] =~ /^remotenav/ - && $env{'environment.remotenavmap'} ne 'on'; - next if $$menuitem[4] =~ /noremotenav/ - && $env{'environment.remotenavmap'} eq 'on'; - next if $$menuitem[4] =~ /^(no|)remotenav$/ - && $crstype eq 'Community'; - next if $$menuitem[4] =~ /^(no|)remotenavCommunity$/ - && $crstype ne 'Community'; - next if $$menuitem[4] =~ /showgroups$/ - && !$canviewgrps - && !%groups; + && ($crstype eq 'Course'); + next if $$menuitem[4] eq 'nvgr' + && $canvgr; + next if $$menuitem[4] eq 'vgr' + && !$canvgr; + next if $$menuitem[4] eq 'cst' + && !$canmodifyuser; + next if $$menuitem[4] eq 'ncst' + && ($canmodifyuser || !$canviewroster); + next if $$menuitem[4] eq 'mgr' + && !$canmgr; + next if $$menuitem[4] eq 'nmgr' + && $canmgr; + next if $$menuitem[4] eq 'whn' + && !$canviewwnew; + next if $$menuitem[4] eq 'opa' + && !$canmodpara; + next if $$menuitem[4] eq 'nvcg' + && ($canviewgrps || !%groups); next if $$menuitem[4] eq 'author' && !$author; - if ($$menuitem[3] eq 'Roles' && $env{'request.course.id'}) { + my $title = $menuitem->[3]; + if (defined($secondary_submenu{$title})) { + my ($link,$target); + if ($menuitem->[0] ne '') { + $link = $menuitem->[0]; + $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 'cst' && !$canmodifyuser); + next if ($item->[2] eq 'mgr' && !$canmgr); + next if ($item->[2] eq 'vcg' && !$canviewgrps); + push(@scndsub,$item); + } + } + if (@scndsub > 0) { + $menu .= &create_submenu($link,$target,$title,\@scndsub); + } elsif ($link) { + $menu .= '
  • '.&mt($title).'
  • '; + } + } + } elsif ($$menuitem[3] eq 'Roles' && $env{'request.course.id'}) { # special treatment for role selector my $roles_selector = &roles_selector( $env{'course.' . $env{'request.course.id'} . '.domain'}, $env{'course.' . $env{'request.course.id'} . '.num'} ); - $menu .= $roles_selector ? "
  • $roles_selector
  • " + $menu .= $roles_selector ? "
  • $roles_selector
  • " : ''; - } elsif ($env{'environment.remotenavmap'} eq 'on') { - # open link using javascript when remote navmap is activated - my @items = @{$menuitem}; - if ($menuitem->[4] eq 'remotenav') { - $items[0] = "javascript:gonav('$menuitem->[0]');"; - } else { - $items[0] = "javascript:go('$menuitem->[0]');"; - } - $menu .= &prep_menuitem(\@items); } else { $menu .= &prep_menuitem(\@$menuitem); } @@ -359,9 +434,8 @@ sub secondary_menu { and ( $env{'request.noversionuri'} eq '' || !defined($env{'request.noversionuri'}))) { - ($escurl = $env{'request.filename'}) =~ - s{^/home/([^/]+)/public_html/(.*)$}{/priv/$1/$2}; - + my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'}; + ($escurl = $env{'request.filename'}) =~ s{^\Q$londocroot\E}{}; $escurl = &escape($escurl); } $menu =~ s/\[url\]/$escurl/g; @@ -373,39 +447,51 @@ sub secondary_menu { return ""; } -sub show_return_link { - if (($env{'request.noversionuri'} =~ m{^/adm/(viewclasslist|navmaps)($|\?)}) - || ($env{'request.noversionuri'} =~ m{^/adm/.*/aboutme($|\?)})) { - - return if ($env{'form.register'}); - } - return (($env{'request.noversionuri'}=~m{^/(res|public)/} && - $env{'request.symb'} eq '') - || - ($env{'request.noversionuri'}=~ m{^/cgi-bin/printout.pl}) - || - (($env{'request.noversionuri'}=~/^\/adm\//) && - ($env{'request.noversionuri'}!~/^\/adm\/wrapper\//) && - ($env{'request.noversionuri'}!~ - m[^/adm/.*/(smppg|bulletinboard)($|\?)]) - )); +sub create_submenu { + my ($link,$target,$title,$submenu) = @_; + return unless (ref($submenu) eq 'ARRAY'); + my $disptarget; + if ($target ne '') { + $disptarget = ' target="'.$target.'"'; + } + my $menu = '
  • '. + ''. + ''.&mt($title). + ''. + ' ▼'. + '
  • '; + return $menu; } - sub registerurl { my ($forcereg) = @_; my $result = ''; if ($env{'request.noversionuri'} =~ m{^/res/adm/pages/}) { return ''; } my $force_title=''; if ($env{'request.state'} eq 'construct') { - $force_title=&Apache::lonxml::display_title(); + $force_title=&Apache::lonxml::display_title(); } if (($env{'environment.remote'} eq 'off') || - ((($env{'request.publicaccess'}) || + ((($env{'request.publicaccess'}) || (!&Apache::lonnet::is_on_map( - &unescape($env{'request.noversionuri'})))) && + &unescape($env{'request.noversionuri'})))) && (!$forcereg))) { - return + return $result .' +ENDDONOTREGTHIS + + } + return ''; + } + # -- This applies to homework problems for users with grading privileges my $crs='/'.$env{'request.course.id'}; if ($env{'request.course.sec'}) { @@ -511,23 +618,29 @@ sub innerregister { my $hwkadd=''; if ($env{'request.symb'} ne '' && - $env{'request.filename'}=~/\.(problem|exam|quiz|assess|survey|form|task)$/) { + $env{'request.filename'}=~/$LONCAPA::assess_re/) { if (&Apache::lonnet::allowed('mgr',$crs)) { - $hwkadd.=&switch('','',7,2,'pgrd.gif','problem[_1]','grades[_4]', + $hwkadd.=&switch('','',7,2,'pgrd.png','Content Grades','grades[_4]', "gocmd('/adm/grades','gradingmenu')", - 'Modify user grades for this assessment resource'); + 'Content Grades'); } elsif (&Apache::lonnet::allowed('vgr',$crs)) { - $hwkadd.=&switch('','',7,2,'subm.gif','view sub-[_1]','missions[_1]', + $hwkadd.=&switch('','',7,2,'subm.png','Content Submissions','missions[_1]', "gocmd('/adm/grades','submission')", - 'View user submissions for this assessment resource'); + 'Content Submissions'); } } if ($env{'request.symb'} ne '' && &Apache::lonnet::allowed('opa',$crs)) { - $hwkadd.=&switch('','',7,3,'pparm.gif','problem[_2]','parms[_2]', + $hwkadd.=&switch('','',7,3,'pparm.png','Content Settings','parms[_2]', "gocmd('/adm/parmset','set')", - 'Modify parameter settings for this resource'); + 'Content Settings'); } + 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')", + 'Folder/Page Content'); + } # -- End Homework ### ### Determine whether or not to display the 'cstr' button for this @@ -547,7 +660,7 @@ sub innerregister { # # Set defaults for authors my ($top,$bottom) = ('con-','struct'); - my $action = "go('/priv/".$env{'user.name'}."');"; + my $action = "go('/priv/".$env{'user.domain'}.'/'.$env{'user.name'}."');"; my $cadom = $env{'request.role.domain'}; my $caname = $env{'user.name'}; my $desc = "Enter my construction space"; @@ -555,12 +668,12 @@ sub innerregister { if ($env{'request.role'} =~ /^ca/) { ($cadom,$caname)=($env{'request.role'}=~/($match_domain)\/($match_username)$/); ($top,$bottom) = ('co con-','struct'); - $action = "go('/priv/".$caname."');"; + $action = "go('/priv/".$cadom.'/'.$caname."');"; $desc = "Enter construction space as co-author"; } elsif ($env{'request.role'} =~ /^aa/) { ($cadom,$caname)=($env{'request.role'}=~/($match_domain)\/($match_username)$/); ($top,$bottom) = ('co con-','struct'); - $action = "go('/priv/".$caname."');"; + $action = "go('/priv/".$cadom.'/'.$caname."');"; $desc = "Enter construction space as assistant co-author"; } # Check that we are on the correct machine @@ -593,9 +706,13 @@ sub innerregister { $uploaded = &is_course_upload($file,$cnum,$cdom); } if (!$uploaded) { - $file=~s/^($match_domain)\/($match_username)/\/priv\/$2/; + + $file=~s{^(priv/$match_domain/$match_username)}{/$1}; + $file=~s{^($match_domain/$match_username)}{/priv/$1}; + # Check that the user has permission to edit this resource - ($cfuname,$cfudom)=&Apache::loncacc::constructaccess($file,$1); + my $setpriv = 1; + ($cfuname,$cfudom)=&Apache::loncacc::constructaccess($file,$setpriv); if (defined($cfudom)) { $home=&Apache::lonnet::homeserver($cfuname,$cfudom); my $allowed=0; @@ -625,7 +742,6 @@ sub innerregister { my $bot = "go('$cfile')"; if ($switchserver) { if ( $env{'request.symb'} && $env{'request.course.id'} ) { - my ($mapurl,$rid,$resurl) = &Apache::lonnet::decode_symb(&Apache::lonnet::symbread()); $cfile = '/adm/switchserver?otherserver='.$home.'&role='. &HTML::Entities::encode($env{'request.role'},'"<>&').'&symb='. &HTML::Entities::encode($env{'request.symb'},'"<>&'); @@ -633,8 +749,8 @@ sub innerregister { } } $editbutton=&switch - ('','',6,1,'pcstr.gif','edit[_1]','resource[_2]', - $bot,"Edit this resource"); + ('','',6,1,'pcstr.png','Edit','resource[_2]', + $bot,"Edit this resource"); $noeditbutton = 0; } } elsif ($editbutton eq '') { @@ -649,7 +765,7 @@ sub innerregister { my $cfile = &edit_course_upload($file,$cnum,$cdom); if ($cfile) { $editbutton=&switch - ('','',6,1,'pcstr.gif','edit[_1]', + ('','',6,1,'pcstr.png','Edit', 'resource[_2]',"go('".$cfile."');", 'Edit this resource'); } @@ -657,17 +773,31 @@ sub innerregister { } } } + if ($env{'request.course.id'}) { + if ($resurl eq "public/$cdom/$cnum/syllabus") { + if ($env{'course.'.$env{'request.course.id'}.'.externalsyllabus'} =~ /\w/) { + if (&Apache::lonnet::allowed('mdc',$env{'request.course.id'})) { + $editbutton=&switch('','',6,1,'pcstr.png','Edit', + 'resource[_2]', + "go('/adm/courseprefs?phase=display&actions=courseinfo')", + 'Edit this resource'); + } + } + } + } ### ### # Prepare the rest of the buttons - my $menuitems; + my ($menuitems,$got_prt,$got_wishlist); if ($const_space) { # # We are in construction space # - my ($uname,$thisdisfn) = - ($env{'request.filename'}=~m|^/home/([^/]+)/public_html/(.*)|); - 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-/$-) { $is_const_dir = 1; } else { @@ -678,73 +808,89 @@ sub innerregister { # Probably should be in mydesk.tab # $menuitems=(< 0){ - $menuitems.="anot2.gif"; + $menuitems.="anot2.png"; }else{ - $menuitems.="anot.gif"; + $menuitems.="anot.png"; } -$menuitems.="&anno-[_1]&tations[_1]&annotate()&"; +$menuitems.="&Notes&&annotate()&"; $menuitems.="Make notes and annotations about this resource&&1\n"; - unless ($noremote) { - my $showreqcrs = &check_for_rcrs(); - if ($showreqcrs) { - $menuitems.="s&8&1&rcrs.gif&request[_1]&course[_16]". - "&go('/adm/requestcourse')&Course requests\n"; - } - } unless ($env{'request.noversionuri'}=~/\/(bulletinboard|smppg|navmaps|syllabus|aboutme|viewclasslist|portfolio)(\?|$)/) { - if ((!$env{'request.enc'}) && ($env{'request.noversionuri'} !~ m{^/adm/wrapper/ext/})) { + if ((!$env{'request.enc'}) && ($env{'request.noversionuri'} !~ m{^/adm/wrapper/ext/}) && ($env{'request.noversionuri'} !~ m{^/uploaded/$match_domain/$match_courseid/docs/})) { $menuitems.=(< -#$inlineremote[21] $inlineremote[23] -#ENDARROWSINLINE -# if ( &hidden_button_check() ne 'yes' ) { -# $inlinebuttons .= (< -#ENDINLINEICONS -# } -# } else { # not iconsonly -# if ( $inlineremote[21] ne '' || $inlineremote[23] ne '' ) { -# $inlinebuttons = (<$inlineremote[21] $inlineremote[23] -#ENDFIRSTLINE -# } -# if ( &hidden_button_check() ne 'yes' ) { -# foreach my $row ( 6 .. 9 ) { -# if ( $inlineremote[ ${row} . '1' ] ne '' -# || $inlineremote[ $row . '2' ] ne '' -# || $inlineremote[ $row . '3' ] ne '' ) -# { -# $inlinebuttons .= <<"ENDLINE"; -#$inlineremote["${row}1"]$inlineremote["${row}2"]$inlineremote["${row}3"] -#ENDLINE -# } -# } -# } -# } - } - $breadcrumb = &Apache::lonhtmlcommon::breadcrumbs(undef,undef,0); - $result =(< -// BEGIN LON-CAPA Internal - -$timesync -$breadcrumb - - - -$newmail - - + if ($env{'user.adv'}) { $clearcstr='clearbut(6,1)'; } + return < // ENDREGTHIS } -# ============================================================================= - } else { -# ========================================== This can or will not be registered - if ($noremote) { -# Not registered - $result= (< -// - -ENDDONOTREGTHIS - } -# ============================================================================= - } - return $result; + return &Apache::lonhtmlcommon::scripttag('', 'start') + . &Apache::lonhtmlcommon::breadcrumbs(undef,undef,0) + . &Apache::lonhtmlcommon::scripttag('', 'end'); } sub is_course_upload { @@ -982,21 +1042,20 @@ sub edit_course_upload { sub loadevents() { if ($env{'request.state'} eq 'construct' || - $env{'request.noversionuri'} =~ m{^/res/adm/pages/}) { return ''; } + $env{'request.noversionuri'} =~ m{^/res/adm/pages/}) { return ''; } return 'LONCAPAreg();'; } sub unloadevents() { if ($env{'request.state'} eq 'construct' || - $env{'request.noversionuri'} =~ m{^/res/adm/pages/}) { return ''; } + $env{'request.noversionuri'} =~ m{^/res/adm/pages/}) { return ''; } return 'LONCAPAstale();'; } - sub startupremote { my ($lowerurl)=@_; - if ($env{'environment.remote'} eq 'off') { - return (''); + unless ($env{'environment.remote'} eq 'on') { + return (''); } # # The Remote actually gets launched! @@ -1010,25 +1069,25 @@ sub startupremote { var timestart; function wheelswitch() { if (typeof(document.wheel) != 'undefined') { - if (typeof(document.wheel.spin) != 'undefined') { - var date=new Date(); - var waited=Math.round(30-((date.getTime()-timestart)/1000)); - document.wheel.spin.value=$message; - } + if (typeof(document.wheel.spin) != 'undefined') { + var date=new Date(); + var waited=Math.round(30-((date.getTime()-timestart)/1000)); + document.wheel.spin.value=$message; + } } - if (window.status=='|') { - window.status='/'; + if (window.status=='|') { + window.status='/'; } else { if (window.status=='/') { window.status='-'; } else { - if (window.status=='-') { - window.status='\\\\'; + if (window.status=='-') { + window.status='\\\\'; } else { if (window.status=='\\\\') { window.status='|'; } } } - } + } } // ---------------------------------------------------------- The wait function @@ -1039,9 +1098,9 @@ function wait() { if (tim==0) { clearTimeout(canceltim); $configmenu - window.location='$lowerurl'; + window.location='$lowerurl'; } else { - window.location='/adm/remote?action=collapse&url=$esclowerurl'; + window.location='/adm/remote?action=collapse&url=$esclowerurl'; } } else { wheelswitch(); @@ -1074,7 +1133,7 @@ ENDSETFLAGS } sub maincall() { - if ($env{'environment.remote'} eq 'off') { return ''; } + unless ($env{'environment.remote'} eq 'on') { return ''; } return(< // '."\n" .'// '; } my $menuname = &get_menu_name(); - + # unless (shift eq 'unix') { # resizing does not work on linux because of virtual desktop sizes # $returnval.=(<13)) { return ''; } return "\n".qq(window.status+='.';swmenu.clearbut($row,$col);); - } else { - $inlineremote[10*$row+$col]=''; - return ''; - } + } else { + $inlineremote[10*$row+$col]=''; + return ''; + } } # ============================================ Switch a button or create a link @@ -1175,31 +1234,27 @@ sub switch { $top=&mt($top); $bot=&mt($bot); $desc=&mt($desc); - if (($env{'environment.remote'} ne 'off') || ($env{'environment.icons'} eq 'classic')) { - $img=&mt($img); - } my $idx=10*$row+$col; $category_members{$cat}.=':'.$idx; - unless ($env{'environment.remote'} eq 'off') { - if (($row<1) || ($row>13)) { return ''; } + if ($env{'environment.remote'} eq 'on') { + if (($row<1) || ($row>13)) { return ''; } # Remote - return "\n". + $img=~s/\.png$/\.gif/; + return "\n". qq(window.status+='.';swmenu.switchbutton($row,$col,"$img","$top","$bot","$act","$desc");); - } else { -# Inline Remote - if ($env{'environment.icons'} ne 'classic') { - $img=~s/\.gif$/\.png/; - } - if ($nobreak==2) { return ''; } - my $text=$top.' '.$bot; - $text=~s/\s*\-\s*//gs; + } + +# Inline Menu + if ($nobreak==2) { return ''; } + my $text=$top.' '.$bot; + $text=~s/\s*\-\s*//gs; - my $pic= + my $pic= ''.$text.''; - if ($env{'browser.interface'} eq 'faketextual') { + if ($env{'browser.interface'} eq 'faketextual') { # Main Menu if ($nobreak==3) { $inlineremote[$idx]="\n". @@ -1218,17 +1273,22 @@ sub switch { ''. ''.$desc.''; } - } else { + } else { # Inline Menu - if ($env{'environment.icons'} eq 'iconsonly') { - $inlineremote[$idx]=''.$pic.''; - } else { - $inlineremote[$idx]= - ''.$pic. - ''.$desc.''; - } - } - } + my @tools = (93,91,81,82,83); + unless ($env{'request.state'} eq 'construct') { + push(@tools,63); + } + if (($env{'environment.icons'} eq 'iconsonly') && + (grep(/^$idx$/,@tools))) { + $inlineremote[$idx] = + ''.$pic.''; + } else { + $inlineremote[$idx] = + ''.$pic. + ''.$top.' '; + } + } return ''; } @@ -1248,7 +1308,7 @@ sub secondlevel { sub openmenu { my $menuname = &get_menu_name(); - if ($env{'environment.remote'} eq 'off') { return ''; } + unless ($env{'environment.remote'} eq 'on') { return ''; } my $nothing = &Apache::lonhtmlcommon::javascript_nothing(); return "window.open(".$nothing.",'".$menuname."');"; } @@ -1295,12 +1355,12 @@ sub rawconfig { # my $textualoverride=shift; my $output=''; - unless ($env{'environment.remote'} eq 'off') { + if ($env{'environment.remote'} eq 'on') { $output.= "window.status='Opening Remote Control';var swmenu=".&openmenu(). "\nwindow.status='Configuring Remote Control ';"; } else { - unless ($textualoverride) { return ''; } + unless ($textualoverride) { return ''; } } my $uname=$env{'user.name'}; my $udom=$env{'user.domain'}; @@ -1438,6 +1498,7 @@ sub rawconfig { ($env{'request.role'}=~/($match_domain)\/($match_username)$/); } $act =~ s/\$caname/$caname/g; + $act =~ s/\$cadom/$cadom/g; my $home = &Apache::lonnet::homeserver($caname,$cadom); my $allowed=0; my @ids=&Apache::lonnet::current_machine_ids(); @@ -1475,13 +1536,12 @@ sub rawconfig { $uname,$udom,$rol,$crs,$pub,$con,$row,$col,$prt,$img,$top,$bot,$act,$desc,$cat); } } - unless ($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");'; - } + if ($env{'environment.remote'} eq 'on') { + $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; } @@ -1510,7 +1570,7 @@ sub check_for_rcrs { # ======================================================================= Close sub close { - if ($env{'environment.remote'} eq 'off') { return ''; } + unless ($env{'environment.remote'} eq 'on') { return ''; } my $menuname = &get_menu_name(); return(< @@ -1529,29 +1589,6 @@ window.status='Done.'; ENDCLOSE } -# ====================================================================== Footer - -sub footer { - -} - -sub nav_control_js { - my $nav=($env{'environment.remotenavmap'} eq 'on'); - return (< '(More ...)', @@ -1563,13 +1600,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 ='$lt{'less'}'; + document.getElementById('dccidtext').innerHTML ='$lt{'less'}'; return; } function hideCourseID() { document.getElementById('dccid').style.display='none'; - document.getElementById('dccidtext').innerHTML ='$lt{'more'}'; + document.getElementById('dccidtext').innerHTML ='$lt{'more'}'; return; } @@ -1577,22 +1614,36 @@ END } +sub countdown_toggle_js { + return <<"END"; + +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='◄ '; + } else { + countdownid.style.display = 'inline'; + document.getElementById('ddcountcollapse').innerHTML='► '; + document.getElementById('ddcountexpand').innerHTML=''; + } + return; +} + +END +} + sub utilityfunctions { - my $caller = shift; - unless ($env{'environment.remote'} eq 'off' || - $caller eq '/adm/menu') { - return ''; } - my $currenturl=&Apache::lonnet::clutter(&Apache::lonnet::fixversion((split(/\?/,$env{'request.noversionuri'}))[0])); - if ($currenturl =~ m{^/adm/wrapper/ext/}) { - if ($env{'request.external.querystring'}) { + if ($currenturl =~ m{^/adm/wrapper/ext/} + && $env{'request.external.querystring'} ) { $currenturl .= ($currenturl=~/\?/)?'&':'?'.$env{'request.external.querystring'}; - } } $currenturl=&Apache::lonenc::check_encrypt(&unescape($currenturl)); my $currentsymb=&Apache::lonenc::check_encrypt($env{'request.symb'}); - my $nav_control=&nav_control_js(); my $dc_popup_cid; if ($env{'user.adv'} && exists($env{'user.role.dc./'. @@ -1612,25 +1663,20 @@ sub utilityfunctions { my $end_page_annotate = &Apache::loncommon::end_page({'js_ready' => 1}); - my $start_page_bookmark = - &Apache::loncommon::start_page('Bookmarks',undef, - {'only_body' => 1, - 'js_ready' => 1, - 'bgcolor' => '#BBBBBB',}); - - my $end_page_bookmark = - &Apache::loncommon::end_page({'js_ready' => 1}); - 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); + + my $countdown = &countdown_toggle_js(); + return (<
    ' - +'
    Link Name:
    ' - +'
    Address:

    ' - +'$end_page_bookmark' ); - bmquery.document.close(); +function open_StoredLinks_Import(rat) { + var newWin; + if (rat) { + newWin = window.open('/adm/wishlist?inhibitmenu=yes&mode=import&rat='+rat, + 'wishlistImport','scrollbars=1,resizable=1,menubar=0'); + } + else { + newWin = window.open('/adm/wishlist?inhibitmenu=yes&mode=import', + 'wishlistImport','scrollbars=1,resizable=1,menubar=0'); + } + 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)); + +$countdown + ENDUTILITY } @@ -1815,23 +1855,20 @@ sub constspaceform { ENDCONSTSPACEFORM } - sub get_nav_status { my $navstatus="swmenu.w_loncapanav_flag="; if ($env{'environment.remotenavmap'} eq 'on') { - $navstatus.="1"; + $navstatus.="1"; } else { - $navstatus.="-1"; + $navstatus.="-1"; } return $navstatus; } sub hidden_button_check { - my $hidden; - if ($env{'request.course.id'} eq '') { - return; - } - if ($env{'request.role.adv'}) { + if ( $env{'request.course.id'} eq '' + || $env{'request.role.adv'} ) { + return; } my $buttonshide = &Apache::lonnet::EXT('resource.0.buttonshide'); @@ -1842,7 +1879,7 @@ sub roles_selector { my ($cdom,$cnum) = @_; my $crstype = &Apache::loncommon::course_type(); my $now = time; - my (%courseroles,%seccount); + my (%courseroles,%seccount,%courseprivs); my $is_cc; my $role_selector; my $ccrole; @@ -1850,7 +1887,17 @@ sub roles_selector { $ccrole = 'co'; } else { $ccrole = 'cc'; - } + } + my $priv; + my $destinationurl = $ENV{'REQUEST_URI'}; + my $reqprivs = &required_privs(); + if (ref($reqprivs) eq 'HASH') { + my $destination = $destinationurl; + $destination =~ s/(\?.*)$//; + if (exists($reqprivs->{$destination})) { + $priv = $reqprivs->{$destination}; + } + } if ($env{'user.role.'.$ccrole.'./'.$cdom.'/'.$cnum}) { my ($start,$end) = split(/\./,$env{'user.role.'.$ccrole.'./'.$cdom.'/'.$cnum}); @@ -1863,7 +1910,7 @@ sub roles_selector { } } if ($is_cc) { - &get_all_courseroles($cdom,$cnum,\%courseroles,\%seccount); + &get_all_courseroles($cdom,$cnum,\%courseroles,\%seccount,\%courseprivs,$priv); } else { my %gotnosection; foreach my $item (keys(%env)) { @@ -1879,6 +1926,18 @@ sub roles_selector { $gotnosection{$role} = 1; } } + if ($priv ne '') { + 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}})) { @@ -1904,7 +1963,7 @@ sub roles_selector { } my @roles_order = ($ccrole,'in','ta','ep','ad','st'); if (keys(%courseroles) > 1) { - $role_selector = &jump_to_role($cdom,$cnum,\%seccount,\%courseroles); + $role_selector = &jump_to_role($cdom,$cnum,\%seccount,\%courseroles,\%courseprivs,$priv); $role_selector .= '
    '."\n". ''."\n". + &HTML::Entities::encode($destinationurl).'" />'."\n". ''."\n". ''."\n". ''."\n". @@ -1930,8 +1989,9 @@ sub roles_selector { } sub get_all_courseroles { - my ($cdom,$cnum,$courseroles,$seccount) = @_; - unless ((ref($courseroles) eq 'HASH') && (ref($seccount) eq 'HASH')) { + my ($cdom,$cnum,$courseroles,$seccount,$courseprivs) = @_; + unless ((ref($courseroles) eq 'HASH') && (ref($seccount) eq 'HASH') && + (ref($courseprivs) eq 'HASH')) { return; } my ($result,$cached) = @@ -1939,9 +1999,11 @@ sub get_all_courseroles { if (defined($cached)) { if (ref($result) eq 'HASH') { if ((ref($result->{'roles'}) eq 'HASH') && - (ref($result->{'seccount'}) eq 'HASH')) { + (ref($result->{'seccount'}) eq 'HASH') && + (ref($result->{'privs'}) eq 'HASH')) { %{$courseroles} = %{$result->{'roles'}}; %{$seccount} = %{$result->{'seccount'}}; + %{$courseprivs} = %{$result->{'privs'}}; return; } } @@ -1969,30 +2031,43 @@ sub get_all_courseroles { 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); + } } my %sections_count = &Apache::loncommon::get_sections($cdom,$cnum,['st']); @{$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'} = scalar(keys(%sections_count)); } my $rolehash = { 'roles' => $courseroles, 'seccount' => $seccount, + 'privs' => $courseprivs, }; &Apache::lonnet::do_cache_new('getcourseroles',$cdom.'_'.$cnum,$rolehash); return; } sub jump_to_role { - my ($cdom,$cnum,$seccount,$courseroles) = @_; + my ($cdom,$cnum,$seccount,$courseroles,$courseprivs,$priv) = @_; 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', + 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') { @@ -2015,6 +2090,37 @@ sub jump_to_role { ' numsec['.$i.'] = "'.$seccount->{$items[$i]}.'";'."\n"; } } + my $checkroles = 0; + if ($priv && ref($courseprivs) eq 'HASH') { + my (%disallowed,%allowed,@disallow); + foreach my $role (sort(keys(%{$courseprivs}))) { + my $trole; + if ($role =~ m{^(.+?)\Q./$cdom/$cnum\E}) { + $trole = $1; + } + if (($trole ne '') && ($trole ne 'cm')) { + if ($courseprivs->{$role} =~ /\Q:$priv\E($|:|\&\w+)/) { + $allowed{$trole} = 1; + } else { + $disallowed{$trole} = 1; + } + } + } + foreach my $trole (keys(%disallowed)) { + unless ($allowed{$trole}) { + push(@disallow,$trole); + } + } + if (@disallow > 0) { + $checkroles = 1; + $js .= " var disallow = new Array('".join("','",@disallow)."');\n". + " var rolecheck = 1;\n"; + } + } + if (!$checkroles) { + $js .= " var disallow = new Array();\n". + " rolecheck = 0;\n"; + } return <<"END";