--- loncom/interface/loncommon.pm 2011/05/27 18:36:51 1.1006
+++ loncom/interface/loncommon.pm 2013/07/10 22:07:37 1.1137
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# a pile of common routines
#
-# $Id: loncommon.pm,v 1.1006 2011/05/27 18:36:51 raeburn Exp $
+# $Id: loncommon.pm,v 1.1137 2013/07/10 22:07:37 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);
}
@@ -475,7 +488,7 @@ sub selectstudent_link {
&mt('Select User').'';
}
if ($env{'request.role'}=~/^(au|dc|su)/) {
- $callargs .= ",1";
+ $callargs .= ",'',1";
return ''.
''.
&mt('Select User').' ';
@@ -518,7 +531,8 @@ ENDAUTHORBRW
}
sub coursebrowser_javascript {
- my ($domainfilter,$sec_element,$formname,$role_element,$crstype) = @_;
+ my ($domainfilter,$sec_element,$formname,$role_element,$crstype,
+ $credits_element) = @_;
my $wintitle = 'Course_Browser';
if ($crstype eq 'Community') {
$wintitle = 'Community_Browser';
@@ -581,8 +595,9 @@ sub coursebrowser_javascript {
}
$id_functions
ENDSTDBRW
- if (($sec_element ne '') || ($role_element ne '')) {
- $output .= &setsec_javascript($sec_element,$formname,$role_element);
+ if (($sec_element ne '') || ($role_element ne '') || ($credits_element ne '')) {
+ $output .= &setsec_javascript($sec_element,$formname,$role_element,
+ $credits_element);
}
$output .= '
// ]]>
@@ -632,6 +647,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";
@@ -694,7 +754,7 @@ ENDUSERBRW
}
sub setsec_javascript {
- my ($sec_element,$formname,$role_element) = @_;
+ my ($sec_element,$formname,$role_element,$credits_element) = @_;
my (@courserolenames,@communityrolenames,$rolestr,$courserolestr,
$communityrolestr);
if ($role_element ne '') {
@@ -789,6 +849,14 @@ function setRole(crstype) {
}
|;
}
+ if ($credits_element) {
+ $setsections .= qq|
+function setCredits(defaultcredits) {
+ document.$formname.$credits_element.value = defaultcredits;
+ return;
+}
+|;
+ }
return $setsections;
}
@@ -802,6 +870,9 @@ sub selectcourse_link {
} elsif ($selecttype eq 'Course/Community') {
$linktext = &mt('Select Course/Community');
$type = '';
+ } elsif ($selecttype eq 'Select') {
+ $linktext = &mt('Select');
+ $type = '';
}
return ''
."
END
# output the initial values for the selection lists
- $result .= "\n";
+ $result .= "\n";
my @order = sort(keys(%{$hashref}));
if (ref($menuorder) eq 'ARRAY') {
@order = @{$menuorder};
@@ -1089,7 +1200,11 @@ END
$result .= " \n";
my %select2 = %{$hashref->{$firstdefault}->{'select2'}};
$result .= $middletext;
- $result .= "\n";
+ $result .= "{$firstdefault}->{'default'};
my @secondorder = sort(keys(%select2));
@@ -1138,7 +1253,7 @@ sub help_open_topic {
my ($topic, $text, $stayOnPage, $width, $height, $imgid) = @_;
$text = "" if (not defined $text);
$stayOnPage = 0 if (not defined $stayOnPage);
- $width = 350 if (not defined $width);
+ $width = 500 if (not defined $width);
$height = 400 if (not defined $height);
my $filename = $topic;
$filename =~ s/ /_/g;
@@ -1149,7 +1264,9 @@ sub help_open_topic {
$topic=~s/\W/\_/g;
if (!$stayOnPage) {
- $link = "javascript:void(open('/adm/help/${filename}.hlp', 'Help_for_$topic', 'menubar=0,toolbar=1,scrollbars=1,width=$width,height=$height,resizable=yes'))";
+ $link = "javascript:openMyModal('/adm/help/${filename}.hlp',$width,$height,'yes');";
+ } elsif ($stayOnPage eq 'popup') {
+ $link = "javascript:void(open('/adm/help/${filename}.hlp', 'Help_for_$topic', 'menubar=0,toolbar=1,scrollbars=1,width=$width,height=$height,resizable=yes'))";
} else {
$link = "/adm/help/${filename}.hlp";
}
@@ -1182,27 +1299,22 @@ sub help_open_topic {
# This is a quicky function for Latex cheatsheet editing, since it
# appears in at least four places
sub helpLatexCheatsheet {
- my ($topic,$text,$not_author) = @_;
+ my ($topic,$text,$not_author,$stayOnPage) = @_;
my $out;
my $addOther = '';
if ($topic) {
- $addOther = ''.&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 +1435,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 +1809,7 @@ Inputs: $workbook
Returns: $format, a hash reference.
+
=cut
###############################################################
@@ -1758,7 +1871,7 @@ sub create_workbook {
return (undef);
}
#
- $workbook->set_tempdir('/home/httpd/perl/tmp');
+ $workbook->set_tempdir(LONCAPA::tempdir());
#
my $format = &Apache::loncommon::define_excel_formats($workbook);
return ($workbook,$filename,$format);
@@ -1929,19 +2042,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 {
@@ -1985,7 +2191,7 @@ sub select_level_form {
=pod
-=item * &select_dom_form($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms)
+=item * &select_dom_form($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms,$excdoms)
Returns a string containing a form to
allow a user to select the domain to preform an operation in.
@@ -1998,25 +2204,31 @@ If the $showdomdesc flag is set, the dom
The optional $onchange argument specifies what should occur if the domain selector is changed, e.g., 'this.form.submit()' if the form is to be automatically submitted.
-The optional $incdoms is a reference to an array of domains which will be the only available options.
+The optional $incdoms is a reference to an array of domains which will be the only available options.
+
+The optional $excdoms is a reference to an array of domains which will be excluded from the available options.
=cut
#-------------------------------------------
sub select_dom_form {
- my ($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms) = @_;
+ my ($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms,$excdoms) = @_;
if ($onchange) {
$onchange = ' onchange="'.$onchange.'"';
}
- my @domains;
+ my (@domains,%exclude);
if (ref($incdoms) eq 'ARRAY') {
@domains = sort {lc($a) cmp lc($b)} (@{$incdoms});
} else {
@domains = sort {lc($a) cmp lc($b)} (&Apache::lonnet::all_domains());
}
if ($includeempty) { @domains=('',@domains); }
+ if (ref($excdoms) eq 'ARRAY') {
+ map { $exclude{$_} = 1; } @{$excdoms};
+ }
my $selectdomain = "\n";
foreach my $dom (@domains) {
+ next if ($exclude{$dom});
$selectdomain.="'.$dom;
if ($showdomdesc) {
@@ -2137,6 +2349,8 @@ Outputs:
=item * $clientos
+=item * $clientmobile
+
=back
=back
@@ -2155,6 +2369,7 @@ sub decode_user_agent {
my $clientversion='0';
my $clientmathml='';
my $clientunicode='0';
+ my $clientmobile=0;
for (my $i=0;$i<=$#browsertype;$i++) {
my ($bname,$match,$notmatch,$vreg,$minv,$univ)=split(/\:/,$browsertype[$i]);
if (($httpbrowser=~/$match/i) && ($httpbrowser!~/$notmatch/i)) {
@@ -2177,8 +2392,11 @@ sub decode_user_agent {
($httpbrowser=~/powerpc/i)) { $clientos='mac'; }
if ($httpbrowser=~/win/i) { $clientos='win'; }
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);
+ }
return ($httpbrowser,$clientbrowser,$clientversion,$clientmathml,
- $clientunicode,$clientos,);
+ $clientunicode,$clientos,$clientmobile);
}
###############################################################
@@ -2330,7 +2548,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 +2557,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 +2648,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 +2686,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 +2722,7 @@ sub authform_internal{
if (defined($in{'mode'})) {
if ($in{'mode'} eq 'modifycourse') {
if ($authnum == 1) {
- $authtype = ' ';
+ $authtype = ' ';
}
}
}
@@ -2523,14 +2741,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 +2777,7 @@ sub authform_local{
if (defined($in{'mode'})) {
if ($in{'mode'} eq 'modifycourse') {
if ($authnum == 1) {
- $authtype = ' ';
+ $authtype = ' ';
}
}
}
@@ -2577,14 +2795,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 +2828,7 @@ sub authform_filesystem{
if (defined($in{'mode'})) {
if ($in{'mode'} eq 'modifycourse') {
if ($authnum == 1) {
- $authtype = ' ';
+ $authtype = ' ';
}
}
}
@@ -2805,6 +3023,7 @@ database which holds them.
Uses global $thesaurus_db_file.
+
=cut
###############################################################
@@ -2840,6 +3059,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
@@ -2847,6 +3105,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
@@ -3076,12 +3359,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 +3465,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 +3495,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
@@ -3459,6 +3789,7 @@ sub get_previous_attempt {
my $data=$parts[-1];
next if ($data eq 'foilorder');
pop(@parts);
+ $prevattempts.=''.&mt('Part ').join('.',@parts).' '.$data.' ';
if ($data eq 'type') {
unless ($showsurv) {
my $id = join(',',@parts);
@@ -3467,10 +3798,7 @@ sub get_previous_attempt {
$lasthidden{$ign.'.'.$id} = 1;
}
}
- delete($lasthash{$key});
- } else {
- $prevattempts.=''.&mt('Part ').join('.',@parts).' '.$data.' ';
- }
+ }
} else {
if ($#parts == 0) {
$prevattempts.=''.$parts[0].' ';
@@ -3587,7 +3915,7 @@ sub get_previous_attempt {
sub format_previous_attempt_value {
my ($key,$value) = @_;
- if ($key =~ /timestamp/) {
+ if (($key =~ /timestamp/) || ($key=~/duedate/)) {
$value = &Apache::lonlocal::locallocaltime($value);
} elsif (ref($value) eq 'ARRAY') {
$value = '('.join(', ', @{ $value }).')';
@@ -3892,9 +4220,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,
@@ -3919,18 +4245,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)) {
@@ -3948,11 +4281,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;
}
}
}
@@ -3963,7 +4304,7 @@ sub findallcourses {
###############################################
sub blockcheck {
- my ($setters,$activity,$uname,$udom) = @_;
+ my ($setters,$activity,$uname,$udom,$url) = @_;
if (!defined($udom)) {
$udom = $env{'user.domain'};
@@ -3975,13 +4316,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.,
@@ -4045,34 +4387,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 {
@@ -4092,46 +4438,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,
+ };
+ }
+ }
}
}
}
}
- return ($startblock,$endblock);
+ 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,$triggerblock);
}
sub parse_block_record {
@@ -4155,39 +4594,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";
@@ -4198,7 +4648,7 @@ END_MYBLOCK
END_BLOCK
- return ($blocked, $output);
+ return ($blocked, $output);
}
###############################################
@@ -4308,8 +4758,7 @@ sub get_domainconf {
if (ref($domconfig{'login'}{$key}) eq 'HASH') {
if ($key eq 'loginvia') {
if (ref($domconfig{'login'}{'loginvia'}) eq 'HASH') {
- my @ids = &Apache::lonnet::current_machine_ids();
- foreach my $hostname (@ids) {
+ 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'};
@@ -4318,7 +4767,7 @@ sub get_domainconf {
$designhash{$udom.'.login.loginvia_'.$hostname} = $server.':'.$domconfig{'login'}{'loginvia'}{$hostname}{'custompath'};
} else {
- $designhash{$udom.'.login.loginvia_'.$hostname} = $server.':'.$domconfig{'login'}{'loginvia'}{$hostname}{'serverpath'};
+ $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'};
@@ -4401,7 +4850,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;
@@ -4459,7 +4908,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};
@@ -4484,27 +4936,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 Authoring 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'};
}
- return '/priv/'.$caname.'/';
+ if (($caname ne '') && ($cadom ne '')) {
+ return "/priv/$cadom/$caname/";
+ }
+ return;
}
##############################################
@@ -4532,20 +4996,29 @@ 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
+ To be included on Authoring Space pages
=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,10 +5032,10 @@ sub CSTR_pageheader {
my $output =
''
.&Apache::loncommon::help_open_menu('','',3,'Authoring') #FIXME: Broken? Where is it?
- .'
'.&mt('Construction Space:').' '
+ .'
'.&mt('Authoring Space:').' '
.'
';
+ }
$endbodytag=&Apache::lontexconvert::jsMath_process()."\n".$endbodytag;
if ( exists( $env{'internal.head.redirect'} ) ) {
if (!(ref($args) eq 'HASH' && $args->{'noredirectlink'})) {
@@ -4874,7 +5355,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';
@@ -4914,7 +5395,6 @@ body {
a:focus,
a:focus img {
color: red;
- background: yellow;
}
form, .inline {
@@ -4929,6 +5409,14 @@ form, .inline {
vertical-align:middle;
}
+.LC_floatleft {
+ float: left;
+}
+
+.LC_floatright {
+ float: right;
+}
+
.LC_400Box {
width:400px;
}
@@ -4961,12 +5449,18 @@ form, .inline {
text-decoration:none;
}
+.LC_setting {
+ text-decoration:underline;
+}
+
.LC_error {
color: red;
- font-size: larger;
}
-.LC_warning,
+.LC_warning {
+ color: darkorange;
+}
+
.LC_diff_removed {
color: red;
}
@@ -5005,35 +5499,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 {
@@ -5128,11 +5623,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;
}
@@ -5155,7 +5650,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;
}
@@ -5205,14 +5700,6 @@ table.LC_nested {
width: 100%;
}
-.ui-accordion,
-.ui-accordion table.LC_data_table,
-.ui-accordion table.LC_nested_outer{
- border: 0px;
- border-spacing: 0px;
- margin: 3px;
-}
-
table.LC_data_table tr th,
table.LC_calendar tr th,
table.LC_prior_tries tr th,
@@ -5273,7 +5760,8 @@ table.LC_nested tr.LC_empty_row td {
padding: 8px;
}
-table.LC_data_table tr.LC_empty_row td {
+table.LC_data_table tr.LC_empty_row td,
+table.LC_data_table tr.LC_footer_row td {
background-color: $sidebg;
}
@@ -5328,22 +5816,6 @@ table.LC_nested tr td.LC_right_item {
text-align: right;
}
-.ui-accordion table.LC_nested tr.LC_odd_row td.LC_left_item,
-.ui-accordion table.LC_nested tr.LC_even_row td.LC_left_item {
- text-align: right;
- width: 40%;
- padding-right:10px;
- vertical-align: top;
- padding: 5px;
-}
-
-.ui-accordion table.LC_nested tr.LC_odd_row td.LC_right_item,
-.ui-accordion table.LC_nested tr.LC_even_row td.LC_right_item {
- text-align: left;
- width: 60%;
- padding: 2px 4px;
-}
-
table.LC_nested tr.LC_odd_row td {
background-color: #EEEEEE;
}
@@ -5475,6 +5947,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;
}
@@ -5846,7 +6323,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;
}
@@ -5976,6 +6452,7 @@ div.LC_edit_problem_footer {
font-weight: normal;
font-size: medium;
margin: 2px;
+ background-color: $sidebg;
}
div.LC_edit_problem_header,
@@ -5992,6 +6469,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 {
@@ -6009,6 +6487,11 @@ div.LC_edit_problem_saves {
padding-bottom: 5px;
}
+.LC_edit_opt {
+ padding-left: 1em;
+ white-space: nowrap;
+}
+
img.stift {
border-width: 0;
vertical-align: middle;
@@ -6023,13 +6506,13 @@ div.LC_createcourse {
}
.LC_dccid {
+ float: right;
margin: 0.2em 0 0 0;
padding: 0;
font-size: 90%;
display:none;
}
-a:hover,
ol.LC_primary_menu a:hover,
ol#LC_MenuBreadcrumbs a:hover,
ol#LC_PathBreadcrumbs a:hover,
@@ -6121,8 +6604,8 @@ fieldset > legend {
}
ol.LC_primary_menu {
- float: right;
margin: 0;
+ padding: 0;
background-color: $pgbg_or_bgcolor;
}
@@ -6131,14 +6614,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 {
@@ -6176,7 +6700,7 @@ ol.LC_docs_parameters li.LC_docs_paramet
}
ul#LC_secondary_menu {
- clear: both;
+ clear: right;
color: $fontmenu;
background: $tabbg;
list-style: none;
@@ -6184,15 +6708,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 {
@@ -6200,7 +6761,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;
}
@@ -6223,7 +6784,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 {
@@ -6263,6 +6824,12 @@ ul.LC_TabContent li.active a {
background:#FFFFFF;
outline: none;
}
+
+ul.LC_TabContent li.goback {
+ float: left;
+ border-left: none;
+}
+
#maincoursedoc {
clear:both;
}
@@ -6322,11 +6889,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,
@@ -6368,6 +6934,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;
@@ -6508,6 +7079,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;
}
@@ -6518,6 +7093,7 @@ ul#LC_toolbar {
list-style:none;
position:relative;
background-color:white;
+ overflow: auto;
}
ul#LC_toolbar li {
@@ -6527,6 +7103,7 @@ ul#LC_toolbar li {
float: left;
display:inline;
vertical-align:middle;
+ white-space: nowrap;
}
@@ -6572,16 +7149,78 @@ ul.LC_funclist li {
line-height: 150%;
}
-.ui-accordion .LC_advanced_toggle {
- float: right;
- font-size: 90%;
- padding: 0px 4px
-}
-
.LC_hidden {
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
}
@@ -6630,6 +7269,8 @@ sub headtag {
'
'.
&font_settings();
+ my $inhibitprint = &print_suppression();
+
if (!$args->{'frameset'}) {
$result .= &Apache::lonhtmlcommon::htmlareaheaders();
}
@@ -6640,8 +7281,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);
@@ -6659,7 +7316,13 @@ ADDMETA
if (!$args->{'no_auto_mt_title'}) { $title = &mt($title); }
$result .= '
LON-CAPA '.$title.' '
.' '
+ .$inhibitprint
.$head_extra;
+ if ($env{'browser.mobile'}) {
+ $result .= '
+
+ ';
+ }
return $result.'';
}
@@ -6684,6 +7347,82 @@ sub font_settings {
=pod
+=item * &print_suppression()
+
+In course context returns css which causes the body to be blank when media="print",
+if printout generation is unavailable for the current resource.
+
+This could be because:
+
+(a) printstartdate is in the future
+
+(b) printenddate is in the past
+
+(c) there is an active exam block with "printout"
+functionality blocked
+
+Users with pav, pfo or evb privileges are exempt.
+
+Inputs: none
+
+=cut
+
+
+sub print_suppression {
+ my $noprint;
+ if ($env{'request.course.id'}) {
+ my $scope = $env{'request.course.id'};
+ if ((&Apache::lonnet::allowed('pav',$scope)) ||
+ (&Apache::lonnet::allowed('pfo',$scope))) {
+ return;
+ }
+ if ($env{'request.course.sec'} ne '') {
+ $scope .= "/$env{'request.course.sec'}";
+ if ((&Apache::lonnet::allowed('pav',$scope)) ||
+ (&Apache::lonnet::allowed('pfo',$scope))) {
+ return;
+ }
+ }
+ my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+ my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+ my $blocked = &blocking_status('printout',$cnum,$cdom);
+ if ($blocked) {
+ my $checkrole = "cm./$cdom/$cnum";
+ if ($env{'request.course.sec'} ne '') {
+ $checkrole .= "/$env{'request.course.sec'}";
+ }
+ unless ((&Apache::lonnet::allowed('evb',undef,undef,$checkrole)) &&
+ ($env{'request.role'} !~ m{^st\./$cdom/$cnum})) {
+ $noprint = 1;
+ }
+ }
+ unless ($noprint) {
+ my $symb = &Apache::lonnet::symbread();
+ if ($symb ne '') {
+ my $navmap = Apache::lonnavmaps::navmap->new();
+ if (ref($navmap)) {
+ my $res = $navmap->getBySymb($symb);
+ if (ref($res)) {
+ if (!$res->resprintable()) {
+ $noprint = 1;
+ }
+ }
+ }
+ }
+ }
+ if ($noprint) {
+ return <<"ENDSTYLE";
+
+ENDSTYLE
+ }
+ }
+ return;
+}
+
+=pod
+
=item * &xml_begin()
Returns the needed doctype and
@@ -6756,6 +7495,8 @@ $args - additional optional args support
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
+ specific group
=back
@@ -6766,32 +7507,12 @@ $args - additional optional args support
sub start_page {
my ($title,$head_extra,$args) = @_;
#&Apache::lonnet::logthis("start_page ".join(':',caller(0)));
-#SD
-#I don't see why we copy certain elements of %$args to %head_args
-#head args is passed to headtag() and this routine only reads those
-#keys that are needed. There doesn't happen any writes or any processing
-#of other keys.
-#proposal: just pass $args to headtag instead of \%head_args and delete
-#marked lines
-#<- MARK
- my %head_args;
- foreach my $arg ('redirect','force_register','domain','function',
- 'bgcolor','frameset','no_nav_bar','only_body',
- 'no_auto_mt_title') {
- if (defined($args->{$arg})) {
- $head_args{$arg} = $args->{$arg};
- }
- }
-#MARK ->
$env{'internal.start_page'}++;
- my $result;
+ my ($result,@advtools);
if (! exists($args->{'skip_phases'}{'head'}) ) {
- $result .=
- &xml_begin() . &headtag($title,$head_extra,\%head_args);
-#replace prev line by
-# &xml_begin() . &headtag($title, $head_extra, $args);
+ $result .= &xml_begin() . &headtag($title, $head_extra, $args);
}
if (! exists($args->{'skip_phases'}{'body'}) ) {
@@ -6805,7 +7526,8 @@ sub start_page {
$args->{'function'}, $args->{'add_entries'},
$args->{'only_body'}, $args->{'domain'},
$args->{'force_register'}, $args->{'no_nav_bar'},
- $args->{'bgcolor'}, $args);
+ $args->{'bgcolor'}, $args,
+ \@advtools);
}
}
@@ -6834,6 +7556,10 @@ sub start_page {
&Apache::lonhtmlcommon::add_breadcrumb($crumb);
}
}
+ # if @advtools array contains items add then to the breadcrumbs
+ if (@advtools > 0) {
+ &Apache::lonmenu::advtools_crumbs(@advtools);
+ }
#if bread_crumbs_component exists show it as headline else show only the breadcrumbs
if(exists($args->{'bread_crumbs_component'})){
@@ -6857,13 +7583,14 @@ sub end_page {
}
$result .= &Apache::lonxml::xmlend($target,$parser);
}
-
if ($args->{'frameset'}) {
$result .= '';
} else {
$result .= &endbodytag($args);
}
- $result .= "\n";
+ unless ($args->{'notbody'}) {
+ $result .= "\n