--- loncom/interface/loncommon.pm 2011/07/26 17:14:56 1.1015
+++ loncom/interface/loncommon.pm 2012/12/27 00:00:23 1.1107
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# a pile of common routines
#
-# $Id: loncommon.pm,v 1.1015 2011/07/26 17:14:56 raeburn Exp $
+# $Id: loncommon.pm,v 1.1107 2012/12/27 00:00:23 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -70,6 +70,9 @@ use Apache::lonclonecourse();
use LONCAPA qw(:DEFAULT :match);
use DateTime::TimeZone;
use DateTime::Locale::Catalog;
+use Text::Aspell;
+use Authen::Captcha;
+use Captcha::reCAPTCHA;
# ---------------------------------------------- Designs
use vars qw(%defaultdesign);
@@ -154,6 +157,9 @@ sub ssi_with_retries {
# ----------------------------------------------- Filetypes/Languages/Copyright
my %language;
my %supported_language;
+my %supported_codes;
+my %latex_language; # For choosing hyphenation in
+my %latex_language_bykey; # for choosing hyphenation from metadata
my %cprtag;
my %scprtag;
my %fe; my %fd; my %fm;
@@ -186,11 +192,16 @@ BEGIN {
while (my $line = <$fh>) {
next if ($line=~/^\#/);
chomp($line);
- my ($key,$two,$country,$three,$enc,$val,$sup)=(split(/\t/,$line));
+ my ($key,$code,$country,$three,$enc,$val,$sup,$latex)=(split(/\t/,$line));
$language{$key}=$val.' - '.$enc;
if ($sup) {
$supported_language{$key}=$sup;
+ $supported_codes{$key} = $code;
}
+ if ($latex) {
+ $latex_language_bykey{$key} = $latex;
+ $latex_language{$code} = $latex;
+ }
}
close($fh);
}
@@ -632,6 +643,51 @@ ENDJS
}
+sub javascript_array_indexof {
+ return <
+// >> 0;
+ if (len === 0) {
+ return -1;
+ }
+ var n = 0;
+ if (arguments.length > 0) {
+ n = Number(arguments[1]);
+ if (n !== n) { // shortcut for verifying if it is NaN
+ n = 0;
+ } else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) {
+ n = (n > 0 || -1) * Math.floor(Math.abs(n));
+ }
+ }
+ if (n >= len) {
+ return -1;
+ }
+ var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
+ for (; k < len; k++) {
+ if (k in t && t[k] === searchElement) {
+ return k;
+ }
+ }
+ return -1;
+ }
+}
+
+// ]]>
+
+
+ENDJS
+
+}
+
sub userbrowser_javascript {
my $id_functions = &javascript_index_functions();
return <<"ENDUSERBRW";
@@ -802,6 +858,9 @@ sub selectcourse_link {
} elsif ($selecttype eq 'Course/Community') {
$linktext = &mt('Select Course/Community');
$type = '';
+ } elsif ($selecttype eq 'Select') {
+ $linktext = &mt('Select');
+ $type = '';
}
return ''
."'.&Apache::loncommon::help_open_topic($topic,&mt($text),
- undef, undef, 600).
- ' ';
+ $addOther = ''.&help_open_topic($topic,&mt($text),$stayOnPage, undef, 600).' ';
}
$out = '' # Start cheatsheet
.$addOther
.''
- .&Apache::loncommon::help_open_topic('Greek_Symbols',&mt('Greek Symbols'),
- undef,undef,600)
+ .&help_open_topic('Greek_Symbols',&mt('Greek Symbols'),$stayOnPage,undef,600)
.' '
- .&Apache::loncommon::help_open_topic('Other_Symbols',&mt('Other Symbols'),
- undef,undef,600)
+ .&help_open_topic('Other_Symbols',&mt('Other Symbols'),$stayOnPage,undef,600)
.' ';
unless ($not_author) {
$out .= ' '
- .&Apache::loncommon::help_open_topic('Authoring_Output_Tags',&mt('Output Tags'),
- undef,undef,600)
+ .&help_open_topic('Authoring_Output_Tags',&mt('Output Tags'),$stayOnPage,undef,600)
.' ';
}
$out .= ' '; # End cheatsheet
@@ -1323,7 +1410,7 @@ function helpMenu(target) {
return;
}
function writeHelp(caller) {
- caller.document.writeln('$start_page $end_page')
+ caller.document.writeln('$start_page\\n \\n \\n$end_page')
caller.document.close()
caller.focus()
}
@@ -1697,6 +1784,7 @@ Inputs: $workbook
Returns: $format, a hash reference.
+
=cut
###############################################################
@@ -1929,19 +2017,112 @@ sub select_form {
# For display filters
sub display_filter {
+ my ($context) = @_;
if (!$env{'form.show'}) { $env{'form.show'}=10; }
if (!$env{'form.displayfilter'}) { $env{'form.displayfilter'}='currentfolder'; }
- return ''.&mt('Records [_1]',
+ my $phraseinput = 'hidden';
+ my $includeinput = 'hidden';
+ my ($checked,$includetypestext);
+ if ($env{'form.displayfilter'} eq 'containing') {
+ $phraseinput = 'text';
+ if ($context eq 'parmslog') {
+ $includeinput = 'checkbox';
+ if ($env{'form.includetypes'}) {
+ $checked = ' checked="checked"';
+ }
+ $includetypestext = &mt('Include parameter types');
+ }
+ } else {
+ $includetypestext = ' ';
+ }
+ my ($additional,$secondid,$thirdid);
+ if ($context eq 'parmslog') {
+ $additional =
+ ' '.
+ ' '.$includetypestext.' '.
+ ' ';
+ $secondid = 'includetypes';
+ $thirdid = 'includetypestext';
+ }
+ my $onchange = "javascript:toggleHistoryOptions(this,'containingphrase','$context',
+ '$secondid','$thirdid')";
+ return ''.&mt('Records: [_1]',
&Apache::lonmeta::selectbox('show',$env{'form.show'},undef,
(&mt('all'),10,20,50,100,1000,10000))).
' '.
- &mt('Filter [_1]',
+ &mt('Filter: [_1]',
&select_form($env{'form.displayfilter'},
'displayfilter',
{'currentfolder' => 'Current folder/page',
'containing' => 'Containing phrase',
- 'none' => 'None'})).
- ' ';
+ 'none' => 'None'},$onchange)).' '.
+ ' '.$additional;
+}
+
+sub display_filter_js {
+ my $includetext = &mt('Include parameter types');
+ return <<"ENDJS";
+
+function toggleHistoryOptions(setter,firstid,context,secondid,thirdid) {
+ var firstType = 'hidden';
+ if (setter.options[setter.selectedIndex].value == 'containing') {
+ firstType = 'text';
+ }
+ firstObject = document.getElementById(firstid);
+ if (typeof(firstObject) == 'object') {
+ if (firstObject.type != firstType) {
+ changeInputType(firstObject,firstType);
+ }
+ }
+ if (context == 'parmslog') {
+ var secondType = 'hidden';
+ if (firstType == 'text') {
+ secondType = 'checkbox';
+ }
+ secondObject = document.getElementById(secondid);
+ if (typeof(secondObject) == 'object') {
+ if (secondObject.type != secondType) {
+ changeInputType(secondObject,secondType);
+ }
+ }
+ var textItem = document.getElementById(thirdid);
+ var currtext = textItem.innerHTML;
+ var newtext;
+ if (firstType == 'text') {
+ newtext = '$includetext';
+ } else {
+ newtext = ' ';
+ }
+ if (currtext != newtext) {
+ textItem.innerHTML = newtext;
+ }
+ }
+ return;
+}
+
+function changeInputType(oldObject,newType) {
+ var newObject = document.createElement('input');
+ newObject.type = newType;
+ if (oldObject.size) {
+ newObject.size = oldObject.size;
+ }
+ if (oldObject.value) {
+ newObject.value = oldObject.value;
+ }
+ if (oldObject.name) {
+ newObject.name = oldObject.name;
+ }
+ if (oldObject.id) {
+ newObject.id = oldObject.id;
+ }
+ oldObject.parentNode.replaceChild(newObject,oldObject);
+ return;
+}
+
+ENDJS
}
sub gradeleveldescription {
@@ -2330,7 +2511,7 @@ END
return $result;
}
-sub authform_authorwarning{
+sub authform_authorwarning {
my $result='';
$result=''.
&mt('As a general rule, only authors or co-authors should be '.
@@ -2339,16 +2520,16 @@ sub authform_authorwarning{
return $result;
}
-sub authform_nochange{
+sub authform_nochange {
my %in = (
formname => 'document.cu',
kerb_def_dom => 'MSU.EDU',
@_,
);
- my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'});
+ my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'});
my $result;
- if (keys(%can_assign) == 0) {
- $result = &mt('Under you current role you are not permitted to change login settings for this user');
+ if (!$authnum) {
+ $result = &mt('Under your current role you are not permitted to change login settings for this user');
} else {
$result = ''.&mt('[_1] Do not change login data',
' ';
+ $authtype = ' ';
}
}
}
@@ -2430,9 +2611,9 @@ sub authform_kerberos {
$krbcheck.' />';
}
if (($can_assign{'krb4'} && $can_assign{'krb5'}) ||
- ($can_assign{'krb4'} && !$can_assign{'krb5'} &&
+ ($can_assign{'krb4'} && !$can_assign{'krb5'} &&
$in{'curr_authtype'} eq 'krb5') ||
- (!$can_assign{'krb4'} && $can_assign{'krb5'} &&
+ (!$can_assign{'krb4'} && $can_assign{'krb5'} &&
$in{'curr_authtype'} eq 'krb4')) {
$result .= &mt
('[_1] Kerberos authenticated with domain [_2] '.
@@ -2468,14 +2649,14 @@ sub authform_kerberos {
return $result;
}
-sub authform_internal{
+sub authform_internal {
my %in = (
formname => 'document.cu',
kerb_def_dom => 'MSU.EDU',
@_,
);
my ($intcheck,$intarg,$result,$authtype,$autharg,$jscall);
- my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'});
+ my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'});
if (defined($in{'curr_authtype'})) {
if ($in{'curr_authtype'} eq 'int') {
if ($can_assign{'int'}) {
@@ -2504,7 +2685,7 @@ sub authform_internal{
if (defined($in{'mode'})) {
if ($in{'mode'} eq 'modifycourse') {
if ($authnum == 1) {
- $authtype = ' ';
+ $authtype = ' ';
}
}
}
@@ -2523,14 +2704,14 @@ sub authform_internal{
return $result;
}
-sub authform_local{
+sub authform_local {
my %in = (
formname => 'document.cu',
kerb_def_dom => 'MSU.EDU',
@_,
);
my ($loccheck,$locarg,$result,$authtype,$autharg,$jscall);
- my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'});
+ my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'});
if (defined($in{'curr_authtype'})) {
if ($in{'curr_authtype'} eq 'loc') {
if ($can_assign{'loc'}) {
@@ -2559,7 +2740,7 @@ sub authform_local{
if (defined($in{'mode'})) {
if ($in{'mode'} eq 'modifycourse') {
if ($authnum == 1) {
- $authtype = ' ';
+ $authtype = ' ';
}
}
}
@@ -2577,14 +2758,14 @@ sub authform_local{
return $result;
}
-sub authform_filesystem{
+sub authform_filesystem {
my %in = (
formname => 'document.cu',
kerb_def_dom => 'MSU.EDU',
@_,
);
my ($fsyscheck,$result,$authtype,$autharg,$jscall);
- my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'});
+ my ($authnum,%can_assign) = &get_assignable_auth($in{'domain'});
if (defined($in{'curr_authtype'})) {
if ($in{'curr_authtype'} eq 'fsys') {
if ($can_assign{'fsys'}) {
@@ -2610,7 +2791,7 @@ sub authform_filesystem{
if (defined($in{'mode'})) {
if ($in{'mode'} eq 'modifycourse') {
if ($authnum == 1) {
- $authtype = ' ';
+ $authtype = ' ';
}
}
}
@@ -2805,6 +2986,7 @@ database which holds them.
Uses global $thesaurus_db_file.
+
=cut
###############################################################
@@ -2840,13 +3022,77 @@ sub get_related_words {
untie %thesaurus_db;
return @Words;
}
+###############################################################
+#
+# Spell checking
+#
=pod
+=head1 Spell checking
+
+=over 4
+
+=item * &check_spelling($wordlist $language)
+
+Takes a string containing words and feeds it to an external
+spellcheck program via a pipeline. Returns a string containing
+them mis-spelled words.
+
+Parameters:
+
+=over 4
+
+=item - $wordlist
+
+String that will be fed into the spellcheck program.
+
+=item - $language
+
+Language string that specifies the language for which the spell
+check will be performed.
+
+=back
+
=back
+Note: This sub assumes that aspell is installed.
+
+
=cut
+
+=pod
+
+=back
+
+=cut
+
+sub check_spelling {
+ my ($wordlist, $language) = @_;
+ my @misspellings;
+
+ # Generate the speller and set the langauge.
+ # if explicitly selected:
+
+ my $speller = Text::Aspell->new;
+ if ($language) {
+ $speller->set_option('lang', $language);
+ }
+
+ # Turn the word list into an array of words by splittingon whitespace
+
+ my @words = split(/\s+/, $wordlist);
+
+ foreach my $word (@words) {
+ if(! $speller->check($word)) {
+ push(@misspellings, $word);
+ }
+ }
+ return join(' ', @misspellings);
+
+}
+
# -------------------------------------------------------------- Plaintext name
=pod
@@ -3076,12 +3322,12 @@ sub noteswrapper {
# ------------------------------------------------------------- Aboutme Wrapper
sub aboutmewrapper {
- my ($link,$username,$domain,$target)=@_;
+ my ($link,$username,$domain,$target,$class)=@_;
if (!defined($username) && !defined($domain)) {
return;
}
- return ''.$link.' ';
+ return ''.$link.' ';
}
# ------------------------------------------------------------ Syllabus Wrapper
@@ -3182,11 +3428,29 @@ sub languagedescription {
($supported_language{$code}?' ('.&mt('interface available').')':'');
}
+=pod
+
+=item * &plainlanguagedescription
+
+Returns both the plain language description (e.g. 'Creoles and Pidgins, English-based (Other)')
+and the language character encoding (e.g. ISO) separated by a ' - ' string.
+
+=cut
+
sub plainlanguagedescription {
my $code=shift;
return $language{$code};
}
+=pod
+
+=item * &supportedlanguagecode
+
+Returns the supported language code (e.g. sptutf maps to pt) given a language
+code.
+
+=cut
+
sub supportedlanguagecode {
my $code=shift;
return $supported_language{$code};
@@ -3194,6 +3458,35 @@ sub supportedlanguagecode {
=pod
+=item * &latexlanguage()
+
+Given a language key code returns the correspondnig language to use
+to select the correct hyphenation on LaTeX printouts. This is undef if there
+is no supported hyphenation for the language code.
+
+=cut
+
+sub latexlanguage {
+ my $code = shift;
+ return $latex_language{$code};
+}
+
+=pod
+
+=item * &latexhyphenation()
+
+Same as above but what's supplied is the language as it might be stored
+in the metadata.
+
+=cut
+
+sub latexhyphenation {
+ my $key = shift;
+ return $latex_language_bykey{$key};
+}
+
+=pod
+
=item * ©rightids()
returns list of all copyrights
@@ -3890,9 +4183,7 @@ sub findallcourses {
$udom = $env{'user.domain'};
}
if (($uname ne $env{'user.name'}) || ($udom ne $env{'user.domain'})) {
- my $extra = &Apache::lonnet::freeze_escape({'skipcheck' => 1});
- my %roleshash = &Apache::lonnet::dump('roles',$udom,$uname,'.',undef,
- $extra);
+ my %roleshash = &Apache::lonnet::dump('roles',$udom,$uname);
if (!%roles) {
%roles = (
cc => 1,
@@ -3917,18 +4208,25 @@ sub findallcourses {
if ($tstart) {
next if ($tstart > $now);
}
- my ($cdom,$cnum,$sec,$cnumpart,$secpart,$role,$realsec);
+ my ($cdom,$cnum,$sec,$cnumpart,$secpart,$role);
(undef,$cdom,$cnumpart,$secpart) = split(/\//,$entry);
+ my $value = $trole.'/'.$cdom.'/';
if ($secpart eq '') {
($cnum,$role) = split(/_/,$cnumpart);
$sec = 'none';
- $realsec = '';
+ $value .= $cnum.'/';
} else {
$cnum = $cnumpart;
($sec,$role) = split(/_/,$secpart);
- $realsec = $sec;
+ $value .= $cnum.'/'.$sec;
+ }
+ if (ref($courses{$cdom.'_'.$cnum}{$sec}) eq 'ARRAY') {
+ unless (grep(/^\Q$value\E$/,@{$courses{$cdom.'_'.$cnum}{$sec}})) {
+ push(@{$courses{$cdom.'_'.$cnum}{$sec}},$value);
+ }
+ } else {
+ @{$courses{$cdom.'_'.$cnum}{$sec}} = ($value);
}
- $courses{$cdom.'_'.$cnum}{$sec} = $trole.'/'.$cdom.'/'.$cnum.'/'.$realsec;
}
} else {
foreach my $key (keys(%env)) {
@@ -3946,11 +4244,19 @@ sub findallcourses {
if ($now>$endtime) { $active=0; }
}
if ($active) {
+ my $value = $role.'/'.$cdom.'/'.$cnum.'/';
if ($sec eq '') {
$sec = 'none';
+ } else {
+ $value .= $sec;
+ }
+ if (ref($courses{$cdom.'_'.$cnum}{$sec}) eq 'ARRAY') {
+ unless (grep(/^\Q$value\E$/,@{$courses{$cdom.'_'.$cnum}{$sec}})) {
+ push(@{$courses{$cdom.'_'.$cnum}{$sec}},$value);
+ }
+ } else {
+ @{$courses{$cdom.'_'.$cnum}{$sec}} = ($value);
}
- $courses{$cdom.'_'.$cnum}{$sec} =
- $role.'/'.$cdom.'/'.$cnum.'/'.$sec;
}
}
}
@@ -3961,7 +4267,7 @@ sub findallcourses {
###############################################
sub blockcheck {
- my ($setters,$activity,$uname,$udom) = @_;
+ my ($setters,$activity,$uname,$udom,$url) = @_;
if (!defined($udom)) {
$udom = $env{'user.domain'};
@@ -3973,13 +4279,14 @@ sub blockcheck {
# If uname and udom are for a course, check for blocks in the course.
if (&Apache::lonnet::is_course($udom,$uname)) {
- my %records = &Apache::lonnet::dump('comm_block',$udom,$uname);
- my ($startblock,$endblock)=&get_blocks($setters,$activity,$udom,$uname);
- return ($startblock,$endblock);
+ my ($startblock,$endblock,$triggerblock) =
+ &get_blocks($setters,$activity,$udom,$uname,$url);
+ return ($startblock,$endblock,$triggerblock);
}
my $startblock = 0;
my $endblock = 0;
+ my $triggerblock = '';
my %live_courses = &findallcourses(undef,$uname,$udom);
# If uname is for a user, and activity is course-specific, i.e.,
@@ -4043,34 +4350,38 @@ sub blockcheck {
if ($otheruser) {
# Resource belongs to user other than current user.
# Assemble privs for that user, and check for 'evb' priv.
- my ($trole,$tdom,$tnum,$tsec);
- my $entry = $live_courses{$course}{$sec};
- if ($entry =~ /^cr/) {
- ($trole,$tdom,$tnum,$tsec) =
- ($entry =~ m|^(cr/$match_domain/$match_username/\w+)\./($match_domain)/($match_username)/?(\w*)$|);
- } else {
- ($trole,$tdom,$tnum,$tsec) = split(/\//,$entry);
- }
- my ($spec,$area,$trest,%allroles,%userroles);
- $area = '/'.$tdom.'/'.$tnum;
- $trest = $tnum;
- if ($tsec ne '') {
- $area .= '/'.$tsec;
- $trest .= '/'.$tsec;
- }
- $spec = $trole.'.'.$area;
- if ($trole =~ /^cr/) {
- &Apache::lonnet::custom_roleprivs(\%allroles,$trole,
- $tdom,$spec,$trest,$area);
- } else {
- &Apache::lonnet::standard_roleprivs(\%allroles,$trole,
- $tdom,$spec,$trest,$area);
- }
- my ($author,$adv) = &Apache::lonnet::set_userprivs(\%userroles,\%allroles);
- if ($userroles{'user.priv.'.$checkrole} =~ /evb\&([^\:]*)/) {
- if ($1) {
- $no_userblock = 1;
- last;
+ my (%allroles,%userroles);
+ if (ref($live_courses{$course}{$sec}) eq 'ARRAY') {
+ foreach my $entry (@{$live_courses{$course}{$sec}}) {
+ my ($trole,$tdom,$tnum,$tsec);
+ if ($entry =~ /^cr/) {
+ ($trole,$tdom,$tnum,$tsec) =
+ ($entry =~ m|^(cr/$match_domain/$match_username/\w+)\./($match_domain)/($match_username)/?(\w*)$|);
+ } else {
+ ($trole,$tdom,$tnum,$tsec) = split(/\//,$entry);
+ }
+ my ($spec,$area,$trest);
+ $area = '/'.$tdom.'/'.$tnum;
+ $trest = $tnum;
+ if ($tsec ne '') {
+ $area .= '/'.$tsec;
+ $trest .= '/'.$tsec;
+ }
+ $spec = $trole.'.'.$area;
+ if ($trole =~ /^cr/) {
+ &Apache::lonnet::custom_roleprivs(\%allroles,$trole,
+ $tdom,$spec,$trest,$area);
+ } else {
+ &Apache::lonnet::standard_roleprivs(\%allroles,$trole,
+ $tdom,$spec,$trest,$area);
+ }
+ }
+ my ($author,$adv) = &Apache::lonnet::set_userprivs(\%userroles,\%allroles);
+ if ($userroles{'user.priv.'.$checkrole} =~ /evb\&([^\:]*)/) {
+ if ($1) {
+ $no_userblock = 1;
+ last;
+ }
}
}
} else {
@@ -4090,46 +4401,139 @@ sub blockcheck {
# Retrieve blocking times and identity of locker for course
# of specified user, unless user has 'evb' privilege.
- my ($start,$end)=&get_blocks($setters,$activity,$cdom,$cnum);
+ my ($start,$end,$trigger) =
+ &get_blocks($setters,$activity,$cdom,$cnum,$url);
if (($start != 0) &&
(($startblock == 0) || ($startblock > $start))) {
$startblock = $start;
+ if ($trigger ne '') {
+ $triggerblock = $trigger;
+ }
}
if (($end != 0) &&
(($endblock == 0) || ($endblock < $end))) {
$endblock = $end;
+ if ($trigger ne '') {
+ $triggerblock = $trigger;
+ }
}
}
- return ($startblock,$endblock);
+ return ($startblock,$endblock,$triggerblock);
}
sub get_blocks {
- my ($setters,$activity,$cdom,$cnum) = @_;
+ my ($setters,$activity,$cdom,$cnum,$url) = @_;
my $startblock = 0;
my $endblock = 0;
+ my $triggerblock = '';
my $course = $cdom.'_'.$cnum;
$setters->{$course} = {};
$setters->{$course}{'staff'} = [];
$setters->{$course}{'times'} = [];
- my %records = &Apache::lonnet::dump('comm_block',$cdom,$cnum);
- foreach my $record (keys(%records)) {
- my ($start,$end) = ($record =~ m/^(\d+)____(\d+)$/);
- if ($start <= time && $end >= time) {
- my ($staff_name,$staff_dom,$title,$blocks) =
- &parse_block_record($records{$record});
- if ($blocks->{$activity} eq 'on') {
- push(@{$$setters{$course}{'staff'}},[$staff_name,$staff_dom]);
- push(@{$$setters{$course}{'times'}}, [$start,$end]);
- if ( ($startblock == 0) || ($startblock > $start) ) {
- $startblock = $start;
+ $setters->{$course}{'triggers'} = [];
+ my (@blockers,%triggered);
+ my $now = time;
+ my %commblocks = &Apache::lonnet::get_comm_blocks($cdom,$cnum);
+ if ($activity eq 'docs') {
+ @blockers = &Apache::lonnet::has_comm_blocking('bre',undef,$url,\%commblocks);
+ foreach my $block (@blockers) {
+ if ($block =~ /^firstaccess____(.+)$/) {
+ my $item = $1;
+ my $type = 'map';
+ my $timersymb = $item;
+ if ($item eq 'course') {
+ $type = 'course';
+ } elsif ($item =~ /___\d+___/) {
+ $type = 'resource';
+ } else {
+ $timersymb = &Apache::lonnet::symbread($item);
}
- if ( ($endblock == 0) || ($endblock < $end) ) {
- $endblock = $end;
+ my $start = $env{'course.'.$cdom.'_'.$cnum.'.firstaccess.'.$timersymb};
+ my $end = $start + $env{'course.'.$cdom.'_'.$cnum.'.timerinterval.'.$timersymb};
+ $triggered{$block} = {
+ start => $start,
+ end => $end,
+ type => $type,
+ };
+ }
+ }
+ } else {
+ foreach my $block (keys(%commblocks)) {
+ if ($block =~ m/^(\d+)____(\d+)$/) {
+ my ($start,$end) = ($1,$2);
+ if ($start <= time && $end >= time) {
+ if (ref($commblocks{$block}) eq 'HASH') {
+ if (ref($commblocks{$block}{'blocks'}) eq 'HASH') {
+ if ($commblocks{$block}{'blocks'}{$activity} eq 'on') {
+ unless(grep(/^\Q$block\E$/,@blockers)) {
+ push(@blockers,$block);
+ }
+ }
+ }
+ }
+ }
+ } elsif ($block =~ /^firstaccess____(.+)$/) {
+ my $item = $1;
+ my $timersymb = $item;
+ my $type = 'map';
+ if ($item eq 'course') {
+ $type = 'course';
+ } elsif ($item =~ /___\d+___/) {
+ $type = 'resource';
+ } else {
+ $timersymb = &Apache::lonnet::symbread($item);
}
+ my $start = $env{'course.'.$cdom.'_'.$cnum.'.firstaccess.'.$timersymb};
+ my $end = $start + $env{'course.'.$cdom.'_'.$cnum.'.timerinterval.'.$timersymb};
+ if ($start && $end) {
+ if (($start <= time) && ($end >= time)) {
+ unless (grep(/^\Q$block\E$/,@blockers)) {
+ push(@blockers,$block);
+ $triggered{$block} = {
+ start => $start,
+ end => $end,
+ type => $type,
+ };
+ }
+ }
+ }
+ }
+ }
+ }
+ foreach my $blocker (@blockers) {
+ my ($staff_name,$staff_dom,$title,$blocks) =
+ &parse_block_record($commblocks{$blocker});
+ push(@{$$setters{$course}{'staff'}},[$staff_name,$staff_dom]);
+ my ($start,$end,$triggertype);
+ if ($blocker =~ m/^(\d+)____(\d+)$/) {
+ ($start,$end) = ($1,$2);
+ } elsif (ref($triggered{$blocker}) eq 'HASH') {
+ $start = $triggered{$blocker}{'start'};
+ $end = $triggered{$blocker}{'end'};
+ $triggertype = $triggered{$blocker}{'type'};
+ }
+ if ($start) {
+ push(@{$$setters{$course}{'times'}}, [$start,$end]);
+ if ($triggertype) {
+ push(@{$$setters{$course}{'triggers'}},$triggertype);
+ } else {
+ push(@{$$setters{$course}{'triggers'}},0);
+ }
+ if ( ($startblock == 0) || ($startblock > $start) ) {
+ $startblock = $start;
+ if ($triggertype) {
+ $triggerblock = $blocker;
+ }
+ }
+ if ( ($endblock == 0) || ($endblock < $end) ) {
+ $endblock = $end;
+ if ($triggertype) {
+ $triggerblock = $blocker;
+ }
}
}
}
- return ($startblock,$endblock);
+ return ($startblock,$endblock,$triggerblock);
}
sub parse_block_record {
@@ -4153,39 +4557,50 @@ sub parse_block_record {
}
sub blocking_status {
- my ($activity,$uname,$udom) = @_;
- my %setters;
+ my ($activity,$uname,$udom,$url) = @_;
+ my %setters;
- # check for active blocking
- my ($startblock,$endblock)=&blockcheck(\%setters,$activity,$uname,$udom);
-
- my $blocked = $startblock && $endblock ? 1 : 0;
-
- # caller just wants to know whether a block is active
- if (!wantarray) { return $blocked; }
-
- # 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
- $querystring .= "&udom=$udom" if $udom;
- $querystring .= "&uname=$uname" if $uname;
-
- my $output .= <<'END_MYBLOCK';
- function openWindow(url, wdwName, w, h, toolbar,scrollbar) {
- var options = "width=" + w + ",height=" + h + ",";
- options += "resizable=yes,scrollbars="+scrollbar+",status=no,";
- options += "menubar=no,toolbar="+toolbar+",location=no,directories=no";
- var newWin = window.open(url, wdwName, options);
- newWin.focus();
- }
+# check for active blocking
+ my ($startblock,$endblock,$triggerblock) =
+ &blockcheck(\%setters,$activity,$uname,$udom,$url);
+ my $blocked = 0;
+ if ($startblock && $endblock) {
+ $blocked = 1;
+ }
+
+# caller just wants to know whether a block is active
+ if (!wantarray) { return $blocked; }
+
+# 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;
+ } elsif ($activity eq 'docs') {
+ $querystring .= '&url='.&HTML::Entities::encode($url,'&"');
+ }
+
+ my $output .= <<'END_MYBLOCK';
+function openWindow(url, wdwName, w, h, toolbar,scrollbar) {
+ var options = "width=" + w + ",height=" + h + ",";
+ options += "resizable=yes,scrollbars="+scrollbar+",status=no,";
+ options += "menubar=no,toolbar="+toolbar+",location=no,directories=no";
+ var newWin = window.open(url, wdwName, options);
+ newWin.focus();
+}
END_MYBLOCK
- $output = Apache::lonhtmlcommon::scripttag($output);
+ $output = Apache::lonhtmlcommon::scripttag($output);
- my $popupUrl = "/adm/blockingstatus/$querystring";
- my $text = mt('Communication Blocked');
-
- $output .= <<"END_BLOCK";
+ my $popupUrl = "/adm/blockingstatus/$querystring";
+ my $text = &mt('Communication Blocked');
+ if ($activity eq 'docs') {
+ $text = &mt('Content Access Blocked');
+ } elsif ($activity eq 'printout') {
+ $text = &mt('Printing Blocked');
+ }
+ $output .= <<"END_BLOCK";
@@ -4196,7 +4611,7 @@ END_MYBLOCK
END_BLOCK
- return ($blocked, $output);
+ return ($blocked, $output);
}
###############################################
@@ -4398,7 +4813,7 @@ sub get_legacy_domconf {
close($fh);
}
}
- if (-e '/home/httpd/html/adm/lonDomLogos/'.$udom.'.gif') {
+ if (-e $Apache::lonnet::perlvar{'lonDocRoot'}.'/adm/lonDomLogos/'.$udom.'.gif') {
$legacyhash{$udom.'.login.domlogo'} = "/adm/lonDomLogos/$udom.gif";
}
return %legacyhash;
@@ -4456,7 +4871,10 @@ sub designparm {
return $env{'environment.color.'.$which};
}
$domain=&determinedomain($domain);
- my %domdesign = &get_domainconf($domain);
+ my %domdesign;
+ unless ($domain eq 'public') {
+ %domdesign = &get_domainconf($domain);
+ }
my $output;
if ($domdesign{$domain.'.'.$which} ne '') {
$output = $domdesign{$domain.'.'.$which};
@@ -4481,27 +4899,39 @@ sub designparm {
=item * &authorspace()
-Inputs: ./.
+Inputs: $url (usually will be undef).
-Returns: Path to the Construction Space of the current user's
- accessed author space
- The author space will be that of the current user
- when accessing the own author space
- and that of the co-author/assistent co-author
- when accessing the co-author's/assistent co-author's
- space
+Returns: Path to Construction Space containing the resource or
+ directory being viewed (or for which action is being taken).
+ If $url is provided, and begins /priv//
+ the path will be that portion of the $context argument.
+ Otherwise the path will be for the author space of the current
+ user when the current role is author, or for that of the
+ co-author/assistant co-author space when the current role
+ is co-author or assistant co-author.
=cut
sub authorspace {
+ my ($url) = @_;
+ if ($url ne '') {
+ if ($url =~ m{^(/priv/$match_domain/$match_username/)}) {
+ return $1;
+ }
+ }
my $caname = '';
- if ($env{'request.role'} =~ /^ca|^aa/) {
- (undef,$caname) =
+ my $cadom = '';
+ if ($env{'request.role'} =~ /^(?:ca|aa)/) {
+ ($cadom,$caname) =
($env{'request.role'}=~/($match_domain)\/($match_username)$/);
- } else {
+ } elsif ($env{'request.role'} =~ m{^au\./($match_domain)/}) {
$caname = $env{'user.name'};
+ $cadom = $env{'user.domain'};
+ }
+ if (($caname ne '') && ($cadom ne '')) {
+ return "/priv/$cadom/$caname/";
}
- return '/priv/'.$caname.'/';
+ return;
}
##############################################
@@ -4529,7 +4959,9 @@ sub head_subbox {
=item * &CSTR_pageheader()
-Inputs: ./.
+Input: (optional) filename from which breadcrumb trail is built.
+ In most cases no input as needed, as $env{'request.filename'}
+ is appropriate for use in building the breadcrumb trail.
Returns: HTML div with CSTR path and recent box
To be included on Construction Space pages
@@ -4537,12 +4969,19 @@ Returns: HTML div with CSTR path and rec
=cut
sub CSTR_pageheader {
- # this is for resources; directories have customtitle, and crumbs
- # and select recent are created in lonpubdir.pm
- my ($uname,$thisdisfn)=
- ($env{'request.filename'} =~ m|^/home/([^/]+)/public_html/(.*)|);
- my $formaction='/priv/'.$uname.'/'.$thisdisfn;
- $formaction=~s/\/+/\//g;
+ my ($trailfile) = @_;
+ if ($trailfile eq '') {
+ $trailfile = $env{'request.filename'};
+ }
+
+# this is for resources; directories have customtitle, and crumbs
+# and select recent are created in lonpubdir.pm
+
+ my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'};
+ my ($udom,$uname,$thisdisfn)=
+ ($trailfile =~ m{^\Q$londocroot\E/priv/([^/]+)/([^/]+)/(.*)$});
+ my $formaction = "/priv/$udom/$uname/$thisdisfn";
+ $formaction =~ s{/+}{/}g;
my $parentpath = '';
my $lastitem = '';
@@ -4559,7 +4998,7 @@ sub CSTR_pageheader {
.''.&mt('Construction Space:').' '
.'
';
+ my $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'})) {
@@ -4871,7 +5325,7 @@ sub standard_css {
my $mono = 'monospace';
my $data_table_head = $sidebg;
my $data_table_light = '#FAFAFA';
- my $data_table_dark = '#F0F0F0';
+ my $data_table_dark = '#E0E0E0';
my $data_table_darker = '#CCCCCC';
my $data_table_highlight = '#FFFF00';
my $mail_new = '#FFBB77';
@@ -4911,7 +5365,6 @@ body {
a:focus,
a:focus img {
color: red;
- background: yellow;
}
form, .inline {
@@ -4964,10 +5417,12 @@ form, .inline {
.LC_error {
color: red;
- font-size: larger;
}
-.LC_warning,
+.LC_warning {
+ color: darkorange;
+}
+
.LC_diff_removed {
color: red;
}
@@ -5006,35 +5461,36 @@ div.LC_confirm_box .LC_success img {
}
.LC_discussion {
- background: $tabbg;
+ background: $data_table_dark;
border: 1px solid black;
margin: 2px;
}
-.LC_disc_action_links_bar {
- background: $tabbg;
- border: none;
- margin: 4px;
-}
-
.LC_disc_action_left {
+ background: $sidebg;
text-align: left;
+ padding: 4px;
+ margin: 2px;
}
.LC_disc_action_right {
+ background: $sidebg;
text-align: right;
+ padding: 4px;
+ margin: 2px;
}
.LC_disc_new_item {
background: white;
border: 2px solid red;
- margin: 2px;
+ margin: 4px;
+ padding: 4px;
}
.LC_disc_old_item {
background: white;
- border: 1px solid black;
- margin: 2px;
+ margin: 4px;
+ padding: 4px;
}
table.LC_pastsubmission {
@@ -5129,11 +5585,11 @@ td.LC_table_cell_checkbox {
text-align: left;
}
-.LC_head_subbox {
+.LC_head_subbox, .LC_actionbox {
clear:both;
background: #F8F8F8; /* $sidebg; */
border: 1px solid $sidebg;
- margin: 0 0 10px 0;
+ margin: 0 0 10px 0;
padding: 3px;
text-align: left;
}
@@ -5156,7 +5612,7 @@ td.LC_table_cell_checkbox {
vertical-align: middle;
}
-li.LC_menubuttons_inline_text img,a {
+li.LC_menubuttons_inline_text img {
cursor:pointer;
text-decoration: none;
}
@@ -5452,6 +5908,11 @@ span.LC_current_location {
background: $pgbg;
}
+span.LC_current_nav_location {
+ font-weight:bold;
+ background: $sidebg;
+}
+
span.LC_parm_menu_item {
font-size: larger;
}
@@ -5823,7 +6284,6 @@ div.LC_docs_entry_move {
table.LC_data_table tr > td.LC_docs_entry_commands,
table.LC_data_table tr > td.LC_docs_entry_parameter {
- background: #DDDDDD;
font-size: x-small;
}
@@ -5953,6 +6413,7 @@ div.LC_edit_problem_footer {
font-weight: normal;
font-size: medium;
margin: 2px;
+ background-color: $sidebg;
}
div.LC_edit_problem_header,
@@ -5969,6 +6430,7 @@ div.LC_edit_problem_header_title {
font-size: larger;
background: $tabbg;
padding: 3px;
+ margin: 0 0 5px 0;
}
table.LC_edit_problem_header_title {
@@ -6006,7 +6468,6 @@ div.LC_createcourse {
display:none;
}
-a:hover,
ol.LC_primary_menu a:hover,
ol#LC_MenuBreadcrumbs a:hover,
ol#LC_PathBreadcrumbs a:hover,
@@ -6100,6 +6561,7 @@ fieldset > legend {
ol.LC_primary_menu {
float: right;
margin: 0;
+ padding: 0;
background-color: $pgbg_or_bgcolor;
}
@@ -6108,14 +6570,55 @@ ol#LC_PathBreadcrumbs {
}
ol.LC_primary_menu li {
- display: inline;
- padding: 5px 5px 0 10px;
+ color: RGB(80, 80, 80);
+ vertical-align: middle;
+ text-align: left;
+ list-style: none;
+ float: left;
+}
+
+ol.LC_primary_menu li a {
+ display: block;
+ margin: 0;
+ padding: 0 5px 0 10px;
+ text-decoration: none;
+}
+
+ol.LC_primary_menu li ul {
+ display: none;
+ width: 10em;
+ background-color: $data_table_light;
+}
+
+ol.LC_primary_menu li:hover ul, ol.LC_primary_menu li.hover ul {
+ display: block;
+ position: absolute;
+ margin: 0;
+ padding: 0;
+ z-index: 2;
+}
+
+ol.LC_primary_menu li:hover li, ol.LC_primary_menu li.hover li {
+ font-size: 90%;
vertical-align: top;
+ float: none;
+ border-left: 1px solid black;
+ border-right: 1px solid black;
+}
+
+ol.LC_primary_menu li:hover li a, ol.LC_primary_menu li.hover li a {
+ background-color:$data_table_light;
+}
+
+ol.LC_primary_menu li li a:hover {
+ color:$button_hover;
+ background-color:$data_table_dark;
}
ol.LC_primary_menu li img {
vertical-align: bottom;
height: 1.1em;
+ margin: 0.2em 0 0 0;
}
ol.LC_primary_menu a {
@@ -6153,7 +6656,7 @@ ol.LC_docs_parameters li.LC_docs_paramet
}
ul#LC_secondary_menu {
- clear: both;
+ clear: right;
color: $fontmenu;
background: $tabbg;
list-style: none;
@@ -6161,15 +6664,52 @@ ul#LC_secondary_menu {
margin: 0;
width: 100%;
text-align: left;
+ float: left;
}
ul#LC_secondary_menu li {
font-weight: bold;
line-height: 1.8em;
+ border-right: 1px solid black;
+ float: left;
+}
+
+ul#LC_secondary_menu li.LC_hoverable:hover, ul#LC_secondary_menu li.hover {
+ background-color: $data_table_light;
+}
+
+ul#LC_secondary_menu li a {
padding: 0 0.8em;
+}
+
+ul#LC_secondary_menu li ul {
+ display: none;
+}
+
+ul#LC_secondary_menu li:hover ul, ul#LC_secondary_menu li.hover ul {
+ display: block;
+ position: absolute;
+ margin: 0;
+ padding: 0;
+ list-style:none;
+ float: none;
+ background-color: $data_table_light;
+ z-index: 2;
+ margin-left: -1px;
+}
+
+ul#LC_secondary_menu li ul li {
+ font-size: 90%;
+ vertical-align: top;
+ border-left: 1px solid black;
border-right: 1px solid black;
- display: inline;
- vertical-align: middle;
+ background-color: $data_table_light
+ list-style:none;
+ float: none;
+}
+
+ul#LC_secondary_menu li ul li:hover, ul#LC_secondary_menu li ul li.hover {
+ background-color: $data_table_dark;
}
ul.LC_TabContent {
@@ -6177,7 +6717,7 @@ ul.LC_TabContent {
background: $sidebg;
border-bottom: solid 1px $lg_border_color;
list-style:none;
- margin: 0 -10px;
+ margin: -1px -10px 0 -10px;
padding: 0;
}
@@ -6200,7 +6740,7 @@ ul.LC_TabContent li {
padding: 0 16px 0 10px;
background-color:$tabbg;
border-bottom:solid 1px $lg_border_color;
- border-right: solid 1px $font;
+ border-left: solid 1px $font;
}
ul.LC_TabContent .right {
@@ -6240,6 +6780,12 @@ ul.LC_TabContent li.active a {
background:#FFFFFF;
outline: none;
}
+
+ul.LC_TabContent li.goback {
+ float: left;
+ border-left: none;
+}
+
#maincoursedoc {
clear:both;
}
@@ -6299,11 +6845,10 @@ ul.LC_TabContentBigger li.active b {
ul.LC_CourseBreadcrumbs {
background: $sidebg;
- line-height: 32px;
+ height: 2em;
padding-left: 10px;
- margin: 0 0 10px 0;
+ margin: 0;
list-style-position: inside;
-
}
ol#LC_MenuBreadcrumbs,
@@ -6345,6 +6890,11 @@ ol#LC_PathBreadcrumbs li a {
padding: 0 10px 10px 10px;
}
+.LC_DocsBox {
+ border: solid 1px $lg_border_color;
+ padding: 0 0 10px 10px;
+}
+
.LC_AboutMe_Image {
float:left;
margin-right:10px;
@@ -6485,6 +7035,10 @@ a#LC_content_toolbar_changefolder_toggle
background-image:url(/res/adm/pages/open-all-folders.gif);
}
+a#LC_content_toolbar_edittoplevel {
+ background-image:url(/res/adm/pages/edittoplevel.gif);
+}
+
ul#LC_toolbar li a:hover {
background-position: bottom center;
}
@@ -6495,6 +7049,7 @@ ul#LC_toolbar {
list-style:none;
position:relative;
background-color:white;
+ overflow: auto;
}
ul#LC_toolbar li {
@@ -6504,6 +7059,7 @@ ul#LC_toolbar li {
float: left;
display:inline;
vertical-align:middle;
+ white-space: nowrap;
}
@@ -6553,6 +7109,74 @@ ul.LC_funclist li {
display: none;
}
+.LCmodal-overlay {
+ position:fixed;
+ top:0;
+ right:0;
+ bottom:0;
+ left:0;
+ height:100%;
+ width:100%;
+ margin:0;
+ padding:0;
+ background:#999;
+ opacity:.75;
+ filter: alpha(opacity=75);
+ -moz-opacity: 0.75;
+ z-index:101;
+}
+
+* html .LCmodal-overlay {
+ position: absolute;
+ height: expression(document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px');
+}
+
+.LCmodal-window {
+ position:fixed;
+ top:50%;
+ left:50%;
+ margin:0;
+ padding:0;
+ z-index:102;
+ }
+
+* html .LCmodal-window {
+ position:absolute;
+}
+
+.LCclose-window {
+ position:absolute;
+ width:32px;
+ height:32px;
+ right:8px;
+ top:8px;
+ background:transparent url('/res/adm/pages/process-stop.png') no-repeat scroll right top;
+ text-indent:-99999px;
+ overflow:hidden;
+ cursor:pointer;
+}
+
+/*
+ styles used by TTH when "Default set of options to pass to tth/m
+ when converting TeX" in course settings has been set
+
+ option passed: -t
+
+*/
+
+td div.comp { margin-top: -0.6ex; margin-bottom: -1ex;}
+td div.comb { margin-top: -0.6ex; margin-bottom: -.6ex;}
+td div.hrcomp { line-height: 0.9; margin-top: -0.8ex; margin-bottom: -1ex;}
+td div.norm {line-height:normal;}
+
+/*
+ option passed -y3
+*/
+
+span.roman {font-family: serif; font-style: normal; font-weight: normal;}
+span.overacc2 {position: relative; left: .8em; top: -1.2ex;}
+span.overacc1 {position: relative; left: .6em; top: -1.2ex;}
+
END
}
@@ -6601,6 +7225,8 @@ sub headtag {
'
'.
&font_settings();
+ my $inhibitprint = &print_suppression();
+
if (!$args->{'frameset'}) {
$result .= &Apache::lonhtmlcommon::htmlareaheaders();
}
@@ -6611,8 +7237,24 @@ sub headtag {
&& !$args->{'only_body'}
&& !$args->{'frameset'}) {
$result .= &help_menu_js();
+ $result.=&modal_window();
+ $result.=&togglebox_script();
+ $result.=&wishlist_window();
+ $result.=&LCprogressbarUpdate_script();
+ } else {
+ if ($args->{'add_modal'}) {
+ $result.=&modal_window();
+ }
+ if ($args->{'add_wishlist'}) {
+ $result.=&wishlist_window();
+ }
+ if ($args->{'add_togglebox'}) {
+ $result.=&togglebox_script();
+ }
+ if ($args->{'add_progressbar'}) {
+ $result.=&LCprogressbarUpdate_script();
+ }
}
-
if (ref($args->{'redirect'})) {
my ($time,$url,$inhibit_continue) = @{$args->{'redirect'}};
$url = &Apache::lonenc::check_encrypt($url);
@@ -6630,6 +7272,7 @@ ADDMETA
if (!$args->{'no_auto_mt_title'}) { $title = &mt($title); }
$result .= '