--- loncom/interface/loncommon.pm 2014/06/16 05:41:23 1.1075.2.76
+++ loncom/interface/loncommon.pm 2016/08/06 20:15:00 1.1075.2.103
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# a pile of common routines
#
-# $Id: loncommon.pm,v 1.1075.2.76 2014/06/16 05:41:23 raeburn Exp $
+# $Id: loncommon.pm,v 1.1075.2.103 2016/08/06 20:15:00 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -72,7 +72,8 @@ use Apache::lonuserstate();
use Apache::courseclassifier();
use LONCAPA qw(:DEFAULT :match);
use DateTime::TimeZone;
-use DateTime::Locale::Catalog;
+use DateTime::Locale;
+use Encode();
use Authen::Captcha;
use Captcha::reCAPTCHA;
use Crypt::DES;
@@ -532,7 +533,7 @@ ENDAUTHORBRW
sub coursebrowser_javascript {
my ($domainfilter,$sec_element,$formname,$role_element,$crstype,
- $credits_element) = @_;
+ $credits_element,$instcode) = @_;
my $wintitle = 'Course_Browser';
if ($crstype eq 'Community') {
$wintitle = 'Community_Browser';
@@ -583,6 +584,12 @@ sub coursebrowser_javascript {
var ownername = document.forms[formid].ccuname.value;
var ownerdom = document.forms[formid].ccdomain.options[document.forms[formid].ccdomain.selectedIndex].value;
url += '&cloner='+ownername+':'+ownerdom;
+ if (type == 'Course') {
+ url += '&crscode='+document.forms[formid].crscode.value;
+ }
+ }
+ if (formname == 'requestcrs') {
+ url += '&crsdom=$domainfilter&crscode=$instcode';
}
if (multflag !=null && multflag != '') {
url += '&multiple='+multflag;
@@ -958,15 +965,16 @@ sub select_datelocale {
}
$output .= '> ';
}
+ my @languages = &Apache::lonlocal::preferred_languages();
my (@possibles,%locale_names);
- my @locales = DateTime::Locale::Catalog::Locales;
- foreach my $locale (@locales) {
- if (ref($locale) eq 'HASH') {
- my $id = $locale->{'id'};
- if ($id ne '') {
- my $en_terr = $locale->{'en_territory'};
- my $native_terr = $locale->{'native_territory'};
- my @languages = &Apache::lonlocal::preferred_languages();
+ my @locales = DateTime::Locale->ids();
+ foreach my $id (@locales) {
+ if ($id ne '') {
+ my ($en_terr,$native_terr);
+ my $loc = DateTime::Locale->load($id);
+ if (ref($loc)) {
+ $en_terr = $loc->name();
+ $native_terr = $loc->native_name();
if (grep(/^en$/,@languages) || !@languages) {
if ($en_terr ne '') {
$locale_names{$id} = '('.$en_terr.')';
@@ -980,7 +988,8 @@ sub select_datelocale {
$locale_names{$id} = '('.$en_terr.')';
}
}
- push (@possibles,$id);
+ $locale_names{$id} = Encode::encode('UTF-8',$locale_names{$id});
+ push(@possibles,$id);
}
}
}
@@ -991,7 +1000,7 @@ sub select_datelocale {
}
$output.=">$item";
if ($locale_names{$item} ne '') {
- $output.=" $locale_names{$item}\n";
+ $output.=' '.$locale_names{$item};
}
$output.="\n";
}
@@ -1293,7 +1302,7 @@ sub helpLatexCheatsheet {
$out .= ' '
.&help_open_topic('Authoring_Output_Tags',&mt('Output Tags'),$stayOnPage,undef,600)
.' '
- .&help_open_topic('Authoring_Multilingual_Problems',&mt('How to create problems in different languages'),$stayOnPage,undef,600)
+ .&help_open_topic('Authoring_Multilingual_Problems',&mt('Languages'),$stayOnPage,undef,600)
.'';
}
$out .= ''; # End cheatsheet
@@ -2341,6 +2350,8 @@ Outputs:
=item * $clientinfo
+=item * $clientosversion
+
=back
=back
@@ -2360,6 +2371,7 @@ sub decode_user_agent {
my $clientmathml='';
my $clientunicode='0';
my $clientmobile=0;
+ my $clientosversion='';
for (my $i=0;$i<=$#browsertype;$i++) {
my ($bname,$match,$notmatch,$vreg,$minv,$univ)=split(/\%/,$browsertype[$i]);
if (($httpbrowser=~/$match/i) && ($httpbrowser!~/$notmatch/i)) {
@@ -2381,7 +2393,12 @@ sub decode_user_agent {
if ($httpbrowser=~/next/i) { $clientos='next'; }
if (($httpbrowser=~/mac/i) ||
($httpbrowser=~/powerpc/i)) { $clientos='mac'; }
- if ($httpbrowser=~/win/i) { $clientos='win'; }
+ if ($httpbrowser=~/win/i) {
+ $clientos='win';
+ if ($httpbrowser =~/Windows\s+NT\s+(\d+\.\d+)/i) {
+ $clientosversion = $1;
+ }
+ }
if ($httpbrowser=~/embed/i) { $clientos='pda'; }
if ($httpbrowser=~/(Android|iPod|iPad|iPhone|webOS|Blackberry|Windows Phone|Opera m(?:ob|in)|Fennec)/i) {
$clientmobile=lc($1);
@@ -2392,7 +2409,8 @@ sub decode_user_agent {
$clientinfo = 'chromeframe-'.$1;
}
return ($httpbrowser,$clientbrowser,$clientversion,$clientmathml,
- $clientunicode,$clientos,$clientmobile,$clientinfo);
+ $clientunicode,$clientos,$clientmobile,$clientinfo,
+ $clientosversion);
}
###############################################################
@@ -3668,7 +3686,7 @@ sub user_lang {
=over 4
=item * &get_previous_attempt($symb, $username, $domain, $course,
- $getattempt, $regexp, $gradesub)
+ $getattempt, $regexp, $gradesub, $usec, $identifier)
Return string with previous attempt on problem. Arguments:
@@ -3690,6 +3708,11 @@ Return string with previous attempt on p
=item * $gradesub: routine that processes the string if it matches $regexp
+=item * $usec: section of the desired student
+
+=item * $identifier: counter for student (multiple students one problem) or
+ problem (one student; whole sequence).
+
=back
The output string is a table containing all desired attempts, if any.
@@ -3697,7 +3720,7 @@ The output string is a table containing
=cut
sub get_previous_attempt {
- my ($symb,$username,$domain,$course,$getattempt,$regexp,$gradesub)=@_;
+ my ($symb,$username,$domain,$course,$getattempt,$regexp,$gradesub,$usec,$identifier)=@_;
my $prevattempts='';
no strict 'refs';
if ($symb) {
@@ -3707,13 +3730,18 @@ sub get_previous_attempt {
my %lasthash=();
my $version;
for ($version=1;$version<=$returnhash{'version'};$version++) {
- foreach my $key (sort(split(/\:/,$returnhash{$version.':keys'}))) {
- $lasthash{$key}=$returnhash{$version.':'.$key};
+ foreach my $key (reverse(sort(split(/\:/,$returnhash{$version.':keys'})))) {
+ if ($key =~ /\.rawrndseed$/) {
+ my ($id) = ($key =~ /^(.+)\.rawrndseed$/);
+ $lasthash{$id.'.rndseed'} = $returnhash{$version.':'.$key};
+ } else {
+ $lasthash{$key}=$returnhash{$version.':'.$key};
+ }
}
}
$prevattempts=&start_data_table().&start_data_table_header_row();
$prevattempts.='
'.&mt('History').' | ';
- my (%typeparts,%lasthidden);
+ my (%typeparts,%lasthidden,%regraded,%hidestatus);
my $showsurv=&Apache::lonnet::allowed('vas',$env{'request.course.id'});
foreach my $key (sort(keys(%lasthash))) {
my ($ign,@parts) = split(/\./,$key);
@@ -3730,6 +3758,18 @@ sub get_previous_attempt {
$lasthidden{$ign.'.'.$id} = 1;
}
}
+ if ($identifier ne '') {
+ my $id = join(',',@parts);
+ if (&Apache::lonnet::EXT("resource.$id.problemstatus",$symb,
+ $domain,$username,$usec,undef,$course) =~ /^no/) {
+ $hidestatus{$ign.'.'.$id} = 1;
+ }
+ }
+ } elsif ($data eq 'regrader') {
+ if (($identifier ne '') && (@parts)) {
+ my $id = join(',',@parts);
+ $regraded{$ign.'.'.$id} = 1;
+ }
}
} else {
if ($#parts == 0) {
@@ -3741,17 +3781,60 @@ sub get_previous_attempt {
}
$prevattempts.=&end_data_table_header_row();
if ($getattempt eq '') {
+ my (%solved,%resets,%probstatus);
+ if (($identifier ne '') && (keys(%regraded) > 0)) {
+ for ($version=1;$version<=$returnhash{'version'};$version++) {
+ foreach my $id (keys(%regraded)) {
+ if (($returnhash{$version.':'.$id.'.regrader'}) &&
+ ($returnhash{$version.':'.$id.'.tries'} eq '') &&
+ ($returnhash{$version.':'.$id.'.award'} eq '')) {
+ push(@{$resets{$id}},$version);
+ }
+ }
+ }
+ }
for ($version=1;$version<=$returnhash{'version'};$version++) {
- my @hidden;
+ my (@hidden,@unsolved);
if (%typeparts) {
foreach my $id (keys(%typeparts)) {
- if (($returnhash{$version.':'.$id.'.type'} eq 'anonsurvey') || ($returnhash{$version.':'.$id.'.type'} eq 'anonsurveycred')) {
+ if (($returnhash{$version.':'.$id.'.type'} eq 'anonsurvey') ||
+ ($returnhash{$version.':'.$id.'.type'} eq 'anonsurveycred')) {
push(@hidden,$id);
+ } elsif ($identifier ne '') {
+ unless (($returnhash{$version.':'.$id.'.type'} eq 'survey') ||
+ ($returnhash{$version.':'.$id.'.type'} eq 'surveycred') ||
+ ($hidestatus{$id})) {
+ next if ((ref($resets{$id}) eq 'ARRAY') && grep(/^\Q$version\E$/,@{$resets{$id}}));
+ if ($returnhash{$version.':'.$id.'.solved'} eq 'correct_by_student') {
+ push(@{$solved{$id}},$version);
+ } elsif (($returnhash{$version.':'.$id.'.solved'} ne '') &&
+ (ref($solved{$id}) eq 'ARRAY')) {
+ my $skip;
+ if (ref($resets{$id}) eq 'ARRAY') {
+ foreach my $reset (@{$resets{$id}}) {
+ if ($reset > $solved{$id}[-1]) {
+ $skip=1;
+ last;
+ }
+ }
+ }
+ unless ($skip) {
+ my ($ign,$partslist) = split(/\./,$id,2);
+ push(@unsolved,$partslist);
+ }
+ }
+ }
}
}
}
$prevattempts.=&start_data_table_row().
- ''.&mt('Transaction [_1]',$version).' | ';
+ ''.&mt('Transaction [_1]',$version);
+ if (@unsolved) {
+ $prevattempts .= '';
+ }
+ $prevattempts .= ' | ';
if (@hidden) {
foreach my $key (sort(keys(%lasthash))) {
next if ($key =~ /\.foilorder$/);
@@ -3773,9 +3856,15 @@ sub get_previous_attempt {
}
} else {
if ($key =~ /\./) {
- my $value = &format_previous_attempt_value($key,
- $returnhash{$version.':'.$key});
- $prevattempts.=''.$value.' | ';
+ my $value = $returnhash{$version.':'.$key};
+ if ($key =~ /\.rndseed$/) {
+ my ($id) = ($key =~ /^(.+)\.rndseed$/);
+ if (exists($returnhash{$version.':'.$id.'.rawrndseed'})) {
+ $value = $returnhash{$version.':'.$id.'.rawrndseed'};
+ }
+ }
+ $prevattempts.=''.&format_previous_attempt_value($key,$value).
+ ' | ';
} else {
$prevattempts.=' | ';
}
@@ -3784,9 +3873,15 @@ sub get_previous_attempt {
} else {
foreach my $key (sort(keys(%lasthash))) {
next if ($key =~ /\.foilorder$/);
- my $value = &format_previous_attempt_value($key,
- $returnhash{$version.':'.$key});
- $prevattempts.=''.$value.' | ';
+ my $value = $returnhash{$version.':'.$key};
+ if ($key =~ /\.rndseed$/) {
+ my ($id) = ($key =~ /^(.+)\.rndseed$/);
+ if (exists($returnhash{$version.':'.$id.'.rawrndseed'})) {
+ $value = $returnhash{$version.':'.$id.'.rawrndseed'};
+ }
+ }
+ $prevattempts.=''.&format_previous_attempt_value($key,$value).
+ ' | ';
}
}
$prevattempts.=&end_data_table_row();
@@ -4541,9 +4636,9 @@ sub blocking_status {
# build a link to a popup window containing the details
my $querystring = "?activity=$activity";
# $uname and $udom decide whose portfolio the user is trying to look at
- if ($activity eq 'port') {
- $querystring .= "&udom=$udom" if $udom;
- $querystring .= "&uname=$uname" if $uname;
+ if (($activity eq 'port') || ($activity eq 'passwd')) {
+ $querystring .= "&udom=$udom" if ($udom =~ /^$match_domain$/);
+ $querystring .= "&uname=$uname" if ($uname =~ /^$match_username$/);
} elsif ($activity eq 'docs') {
$querystring .= '&url='.&HTML::Entities::encode($url,'&"');
}
@@ -4562,13 +4657,17 @@ END_MYBLOCK
my $popupUrl = "/adm/blockingstatus/$querystring";
my $text = &mt('Communication Blocked');
+ my $class = 'LC_comblock';
if ($activity eq 'docs') {
$text = &mt('Content Access Blocked');
+ $class = '';
} elsif ($activity eq 'printout') {
$text = &mt('Printing Blocked');
+ } elsif ($activity eq 'passwd') {
+ $text = &mt('Password Changing Blocked');
}
$output .= <<"END_BLOCK";
-
+
![$text $text](/res/adm/pages/comblock.png)
@@ -4686,23 +4785,28 @@ sub get_domainconf {
if (keys(%{$domconfig{'login'}})) {
foreach my $key (keys(%{$domconfig{'login'}})) {
if (ref($domconfig{'login'}{$key}) eq 'HASH') {
- if ($key eq 'loginvia') {
- if (ref($domconfig{'login'}{'loginvia'}) eq 'HASH') {
- foreach my $hostname (keys(%{$domconfig{'login'}{'loginvia'}})) {
- if (ref($domconfig{'login'}{'loginvia'}{$hostname}) eq 'HASH') {
- if ($domconfig{'login'}{'loginvia'}{$hostname}{'server'}) {
- my $server = $domconfig{'login'}{'loginvia'}{$hostname}{'server'};
- $designhash{$udom.'.login.loginvia'} = $server;
- if ($domconfig{'login'}{'loginvia'}{$hostname}{'serverpath'} eq 'custom') {
-
- $designhash{$udom.'.login.loginvia_'.$hostname} = $server.':'.$domconfig{'login'}{'loginvia'}{$hostname}{'custompath'};
- } else {
- $designhash{$udom.'.login.loginvia_'.$hostname} = $server.':'.$domconfig{'login'}{'loginvia'}{$hostname}{'serverpath'};
+ if (($key eq 'loginvia') || ($key eq 'headtag')) {
+ if (ref($domconfig{'login'}{$key}) eq 'HASH') {
+ foreach my $hostname (keys(%{$domconfig{'login'}{$key}})) {
+ if (ref($domconfig{'login'}{$key}{$hostname}) eq 'HASH') {
+ if ($key eq 'loginvia') {
+ if ($domconfig{'login'}{'loginvia'}{$hostname}{'server'}) {
+ my $server = $domconfig{'login'}{'loginvia'}{$hostname}{'server'};
+ $designhash{$udom.'.login.loginvia'} = $server;
+ if ($domconfig{'login'}{'loginvia'}{$hostname}{'serverpath'} eq 'custom') {
+ $designhash{$udom.'.login.loginvia_'.$hostname} = $server.':'.$domconfig{'login'}{'loginvia'}{$hostname}{'custompath'};
+ } else {
+ $designhash{$udom.'.login.loginvia_'.$hostname} = $server.':'.$domconfig{'login'}{'loginvia'}{$hostname}{'serverpath'};
+ }
}
- if ($domconfig{'login'}{'loginvia'}{$hostname}{'exempt'}) {
- $designhash{$udom.'.login.loginvia_exempt_'.$hostname} = $domconfig{'login'}{'loginvia'}{$hostname}{'exempt'};
+ } elsif ($key eq 'headtag') {
+ if ($domconfig{'login'}{'headtag'}{$hostname}{'url'}) {
+ $designhash{$udom.'.login.headtag_'.$hostname} = $domconfig{'login'}{'headtag'}{$hostname}{'url'};
}
}
+ if ($domconfig{'login'}{$key}{$hostname}{'exempt'}) {
+ $designhash{$udom.'.login.'.$key.'_exempt_'.$hostname} = $domconfig{'login'}{$key}{$hostname}{'exempt'};
+ }
}
}
}
@@ -5026,9 +5130,6 @@ Inputs:
=item * $args, optional argument valid values are
no_auto_mt_title -> prevents &mt()ing the title arg
- inherit_jsmath -> when creating popup window in a page,
- should it have jsmath forced on by the
- current page
=item * $advtoolsref, optional argument, ref to an array containing
inlineremote items to be added in "Functions" menu below
@@ -5096,7 +5197,7 @@ sub bodytag {
# construct main body tag
my $bodytag = "".
- &Apache::lontexconvert::init_math_support($args->{'inherit_jsmath'});
+ &Apache::lontexconvert::init_math_support();
&get_unprocessed_cgi($ENV{'QUERY_STRING'}, ['inhibitmenu']);
@@ -5323,7 +5424,6 @@ sub endbodytag {
unless ((ref($args) eq 'HASH') && ($args->{'notbody'})) {
$endbodytag='';
}
- $endbodytag=&Apache::lontexconvert::jsMath_process()."\n".$endbodytag;
if ( exists( $env{'internal.head.redirect'} ) ) {
if (!(ref($args) eq 'HASH' && $args->{'noredirectlink'})) {
$endbodytag=
@@ -6602,6 +6702,10 @@ fieldset {
/* overflow: hidden; */
}
+article.geogebraweb div {
+ margin: 0;
+}
+
fieldset > legend {
font-weight: bold;
padding: 0 5px 0 5px;
@@ -7337,6 +7441,82 @@ sub headtag {
ADDMETA
+ } else {
+ unless (($args->{'frameset'}) || ($args->{'js_ready'}) || ($args->{'only_body'}) || ($args->{'no_nav_bar'})) {
+ my $requrl = $env{'request.uri'};
+ if ($requrl eq '') {
+ $requrl = $ENV{'REQUEST_URI'};
+ $requrl =~ s/\?.+$//;
+ }
+ unless (($requrl =~ m{^/adm/(?:switchserver|login|authenticate|logout|groupsort|cleanup|helper|slotrequest|grades)(\?|$)}) ||
+ (($requrl =~ m{^/res/}) && (($env{'form.submitted'} eq 'scantron') ||
+ ($env{'form.grade_symb'}) || ($Apache::lonhomework::scantronmode)))) {
+ my $dom_in_use = $Apache::lonnet::perlvar{'lonDefDomain'};
+ unless (&Apache::lonnet::allowed('mau',$dom_in_use)) {
+ my %domdefs = &Apache::lonnet::get_domain_defaults($dom_in_use);
+ if (ref($domdefs{'offloadnow'}) eq 'HASH') {
+ my $lonhost = $Apache::lonnet::perlvar{'lonHostID'};
+ if ($domdefs{'offloadnow'}{$lonhost}) {
+ my $newserver = &Apache::lonnet::spareserver(30000,undef,1,$dom_in_use);
+ if (($newserver) && ($newserver ne $lonhost)) {
+ my $numsec = 5;
+ my $timeout = $numsec * 1000;
+ my ($newurl,$locknum,%locks,$msg);
+ if ($env{'request.role.adv'}) {
+ ($locknum,%locks) = &Apache::lonnet::get_locks();
+ }
+ my $disable_submit = 0;
+ if ($requrl =~ /$LONCAPA::assess_re/) {
+ $disable_submit = 1;
+ }
+ if ($locknum) {
+ my @lockinfo = sort(values(%locks));
+ $msg = &mt('Once the following tasks are complete: ')."\\n".
+ join(", ",sort(values(%locks)))."\\n".
+ &mt('your session will be transferred to a different server, after you click "Roles".');
+ } else {
+ if (($requrl =~ m{^/res/}) && ($env{'form.submitted'} =~ /^part_/)) {
+ $msg = &mt('Your LON-CAPA submission has been recorded')."\\n";
+ }
+ $msg .= &mt('Your current LON-CAPA session will be transferred to a different server in [quant,_1,second].',$numsec);
+ $newurl = '/adm/switchserver?otherserver='.$newserver;
+ if (($env{'request.role'}) && ($env{'request.role'} ne 'cm')) {
+ $newurl .= '&role='.$env{'request.role'};
+ }
+ if ($env{'request.symb'}) {
+ $newurl .= '&symb='.$env{'request.symb'};
+ } else {
+ $newurl .= '&origurl='.$requrl;
+ }
+ }
+ &js_escape(\$msg);
+ $result.=<
+
+OFFLOAD
+ }
+ }
+ }
+ }
+ }
+ }
}
if (!defined($title)) {
$title = 'The LearningOnline Network with CAPA';
@@ -7534,9 +7714,6 @@ $args - additional optional args support
no_inline_link -> if true and in remote mode, don't show the
'Switch To Inline Menu' link
no_auto_mt_title -> prevent &mt()ing the title arg
- inherit_jsmath -> when creating popup window in a page,
- should it have jsmath forced on by the
- current page
bread_crumbs -> Array containing breadcrumbs
bread_crumbs_component -> if exists show it as headline else show only the breadcrumbs
group -> includes the current group, if page is for a
@@ -7663,10 +7840,12 @@ function set_wishlistlink(title, path) {
title = title.replace(/^LON-CAPA /,'');
}
title = encodeURIComponent(title);
+ title = title.replace("'","\\\'");
if (!path) {
path = location.pathname;
}
path = encodeURIComponent(path);
+ path = path.replace("'","\\\'");
Win = window.open('/adm/wishlist?mode=newLink&setTitle='+title+'&setPath='+path,
'wishlistNewLink','width=560,height=350,scrollbars=0');
}
@@ -7709,12 +7888,13 @@ var modalWindow = {
};
var openMyModal = function(source,width,height,scrolling,transparency,style)
{
+ source = source.replace("'","'");
modalWindow.windowId = "myModal";
modalWindow.width = width;
modalWindow.height = height;
- modalWindow.content = "