--- loncom/interface/loncommon.pm 2011/12/21 21:25:40 1.1044
+++ loncom/interface/loncommon.pm 2013/01/09 03:56:27 1.1110
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# a pile of common routines
#
-# $Id: loncommon.pm,v 1.1044 2011/12/21 21:25:40 www Exp $
+# $Id: loncommon.pm,v 1.1110 2013/01/09 03:56:27 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -67,9 +67,14 @@ use Apache::lonhtmlcommon();
use Apache::loncoursedata();
use Apache::lontexconvert();
use Apache::lonclonecourse();
+use Apache::lonuserutils();
+use Apache::lonuserstate();
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 +159,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 +194,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);
}
@@ -651,7 +664,7 @@ if (!Array.prototype.indexOf) {
var n = 0;
if (arguments.length > 0) {
n = Number(arguments[1]);
- if (n !== n) { // shortcut for verifying if it's NaN
+ 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));
@@ -879,10 +892,14 @@ sub check_uncheck_jscript {
function checkAll(field) {
if (field.length > 0) {
for (i = 0; i < field.length; i++) {
- field[i].checked = true ;
+ if (!field[i].disabled) {
+ field[i].checked = true;
+ }
}
} else {
- field.checked = true
+ if (!field.disabled) {
+ field.checked = true;
+ }
}
}
@@ -989,6 +1006,33 @@ sub select_language {
=pod
+
+=item * &list_languages()
+
+Returns an array reference that is suitable for use in language prompters.
+Each array element is itself a two element array. The first element
+is the language code. The second element a descsriptiuon of the
+language itself. This is suitable for use in e.g.
+&Apache::edit::select_arg (once dereferenced that is).
+
+=cut
+
+sub list_languages {
+ my @lang_choices;
+
+ foreach my $id (&languageids()) {
+ my $code = &supportedlanguagecode($id);
+ if ($code) {
+ my $selector = $supported_codes{$id};
+ my $description = &plainlanguagedescription($id);
+ push (@lang_choices, [$selector, $description]);
+ }
+ }
+ return \@lang_choices;
+}
+
+=pod
+
=item * &linked_select_forms(...)
linked_select_forms returns a string containing a block
@@ -1368,7 +1412,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()
}
@@ -1742,6 +1786,7 @@ Inputs: $workbook
Returns: $format, a hash reference.
+
=cut
###############################################################
@@ -1974,19 +2019,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 {
@@ -2375,7 +2513,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 '.
@@ -2384,16 +2522,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 = ' ';
}
}
}
@@ -2475,9 +2613,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] '.
@@ -2513,14 +2651,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'}) {
@@ -2549,7 +2687,7 @@ sub authform_internal{
if (defined($in{'mode'})) {
if ($in{'mode'} eq 'modifycourse') {
if ($authnum == 1) {
- $authtype = ' ';
+ $authtype = ' ';
}
}
}
@@ -2568,14 +2706,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'}) {
@@ -2604,7 +2742,7 @@ sub authform_local{
if (defined($in{'mode'})) {
if ($in{'mode'} eq 'modifycourse') {
if ($authnum == 1) {
- $authtype = ' ';
+ $authtype = ' ';
}
}
}
@@ -2622,14 +2760,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'}) {
@@ -2655,7 +2793,7 @@ sub authform_filesystem{
if (defined($in{'mode'})) {
if ($in{'mode'} eq 'modifycourse') {
if ($authnum == 1) {
- $authtype = ' ';
+ $authtype = ' ';
}
}
}
@@ -2850,6 +2988,7 @@ database which holds them.
Uses global $thesaurus_db_file.
+
=cut
###############################################################
@@ -2885,6 +3024,45 @@ 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
@@ -2892,6 +3070,31 @@ sub get_related_words {
=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
@@ -3121,12 +3324,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
@@ -3227,11 +3430,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};
@@ -3239,6 +3460,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
@@ -3935,9 +4185,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,
@@ -3962,18 +4210,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)) {
@@ -3991,11 +4246,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;
}
}
}
@@ -4006,7 +4269,7 @@ sub findallcourses {
###############################################
sub blockcheck {
- my ($setters,$activity,$uname,$udom) = @_;
+ my ($setters,$activity,$uname,$udom,$url) = @_;
if (!defined($udom)) {
$udom = $env{'user.domain'};
@@ -4018,13 +4281,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.,
@@ -4088,34 +4352,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 {
@@ -4135,46 +4403,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 {
@@ -4198,39 +4559,50 @@ sub parse_block_record {
}
sub blocking_status {
- my ($activity,$uname,$udom) = @_;
- my %setters;
-
- # check for active blocking
- my ($startblock,$endblock)=&blockcheck(\%setters,$activity,$uname,$udom);
-
- my $blocked = $startblock && $endblock ? 1 : 0;
+ my ($activity,$uname,$udom,$url) = @_;
+ my %setters;
- # 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";
@@ -4241,7 +4613,7 @@ END_MYBLOCK
END_BLOCK
- return ($blocked, $output);
+ return ($blocked, $output);
}
###############################################
@@ -4690,6 +5062,10 @@ Inputs:
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
+ breadcrumbs.
+
=back
Returns: A uniform header for LON-CAPA web pages.
@@ -4701,7 +5077,7 @@ other decorations will be returned.
sub bodytag {
my ($title,$function,$addentries,$bodyonly,$domain,$forcereg,
- $no_nav_bar,$bgcolor,$args)=@_;
+ $no_nav_bar,$bgcolor,$args,$advtoolsref)=@_;
my $public;
if ((($env{'user.name'} eq 'public') && ($env{'user.domain'} eq 'public'))
@@ -4758,7 +5134,8 @@ sub bodytag {
if ($public) {
undef($role);
} else {
- $name = &aboutmewrapper($name,$env{'user.name'},$env{'user.domain'});
+ $name = &aboutmewrapper($name,$env{'user.name'},$env{'user.domain'},
+ undef,'LC_menubuttons_link');
}
my $titleinfo = ''.$title.' ';
@@ -4819,8 +5196,15 @@ sub bodytag {
if ($env{'request.state'} eq 'construct') {
$bodytag .= &Apache::lonmenu::innerregister($forcereg,
$args->{'bread_crumbs'});
- } elsif ($forcereg) {
- $bodytag .= &Apache::lonmenu::innerregister($forcereg);
+ } elsif ($forcereg) {
+ $bodytag .= &Apache::lonmenu::innerregister($forcereg,undef,
+ $args->{'group'});
+ } else {
+ $bodytag .=
+ &Apache::lonmenu::prepare_functions($env{'request.noversionuri'},
+ $forcereg,$args->{'group'},
+ $args->{'bread_crumbs'},
+ $advtoolsref);
}
}else{
# this is to seperate menu from content when there's no secondary
@@ -4835,7 +5219,7 @@ sub bodytag {
sub dc_courseid_toggle {
my ($dc_info) = @_;
return ' '.
- ''.
+ ' '.
''.$dc_info.'
';
}
@@ -4892,7 +5276,10 @@ i.e., $env{'internal.head.redirect'} exi
sub endbodytag {
my ($args) = @_;
- my $endbodytag='
';
+ 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'})) {
@@ -4940,7 +5327,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';
@@ -4980,7 +5367,6 @@ body {
a:focus,
a:focus img {
color: red;
- background: yellow;
}
form, .inline {
@@ -5033,10 +5419,12 @@ form, .inline {
.LC_error {
color: red;
- font-size: larger;
}
-.LC_warning,
+.LC_warning {
+ color: darkorange;
+}
+
.LC_diff_removed {
color: red;
}
@@ -5075,35 +5463,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 {
@@ -5198,11 +5587,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;
}
@@ -5225,7 +5614,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;
}
@@ -5897,7 +6286,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;
}
@@ -6027,6 +6415,7 @@ div.LC_edit_problem_footer {
font-weight: normal;
font-size: medium;
margin: 2px;
+ background-color: $sidebg;
}
div.LC_edit_problem_header,
@@ -6043,6 +6432,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 {
@@ -6080,7 +6470,6 @@ div.LC_createcourse {
display:none;
}
-a:hover,
ol.LC_primary_menu a:hover,
ol#LC_MenuBreadcrumbs a:hover,
ol#LC_PathBreadcrumbs a:hover,
@@ -6174,6 +6563,7 @@ fieldset > legend {
ol.LC_primary_menu {
float: right;
margin: 0;
+ padding: 0;
background-color: $pgbg_or_bgcolor;
}
@@ -6182,14 +6572,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 {
@@ -6227,7 +6658,7 @@ ol.LC_docs_parameters li.LC_docs_paramet
}
ul#LC_secondary_menu {
- clear: both;
+ clear: right;
color: $fontmenu;
background: $tabbg;
list-style: none;
@@ -6235,15 +6666,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 {
@@ -6314,6 +6782,12 @@ ul.LC_TabContent li.active a {
background:#FFFFFF;
outline: none;
}
+
+ul.LC_TabContent li.goback {
+ float: left;
+ border-left: none;
+}
+
#maincoursedoc {
clear:both;
}
@@ -6577,6 +7051,7 @@ ul#LC_toolbar {
list-style:none;
position:relative;
background-color:white;
+ overflow: auto;
}
ul#LC_toolbar li {
@@ -6586,6 +7061,7 @@ ul#LC_toolbar li {
float: left;
display:inline;
vertical-align:middle;
+ white-space: nowrap;
}
@@ -6682,6 +7158,27 @@ ul.LC_funclist li {
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
}
@@ -6730,6 +7227,8 @@ sub headtag {
'
'.
&font_settings();
+ my $inhibitprint = &print_suppression();
+
if (!$args->{'frameset'}) {
$result .= &Apache::lonhtmlcommon::htmlareaheaders();
}
@@ -6775,6 +7274,7 @@ ADDMETA
if (!$args->{'no_auto_mt_title'}) { $title = &mt($title); }
$result .= '