--- loncom/interface/lonparmset.pm 2022/03/23 17:29:29 1.522.2.28.4.3 +++ loncom/interface/lonparmset.pm 2023/12/29 20:45:18 1.522.2.28.4.11 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Handler to set parameters for assessments # -# $Id: lonparmset.pm,v 1.522.2.28.4.3 2022/03/23 17:29:29 raeburn Exp $ +# $Id: lonparmset.pm,v 1.522.2.28.4.11 2023/12/29 20:45:18 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -945,10 +945,14 @@ function validateParms() { var dlKeyRegExp = /^deeplink_key_/; var dlMenusRegExp = /^deeplink_menus_/; var dlCollsRegExp = /^deeplink_colls_/; + var dlTargetRegExp = /^deeplink_target_/; + var dlExitRegExp = /^deeplink_exit_/; + var dlExitTextRegExp = /^deeplink_exittext_/; var patternIP = /[\[\]\*\.a-zA-Z\d\-]+/; - if ((document.parmform.elements.length != 'undefined') && (document.parmform.elements.length) != 'null') { - if (document.parmform.elements.length) { - for (i=0; i 0) { + var linktarget = document.parmform.elements[i].options[idx].value + linktarget = linktarget.replace(/^\s+|\s+$/g,''); + if (document.parmform.elements['set_'+identifier].value) { + linktarget = ','+linktarget; + } + document.parmform.elements['set_'+identifier].value += linktarget; + } + } else if (dlExitRegExp.test(name)) { + if (document.parmform.elements[i].checked) { + var identifier = name.replace(dlExitRegExp,''); + var posslinkexit = document.parmform.elements[i].value; + posslinkexit = posslinkexit.replace(/^\s+|\s+$/g,''); + if (document.parmform.elements['set_'+identifier].value) { + posslinkexit = ','+posslinkexit; + } + document.parmform.elements['set_'+identifier].value += posslinkexit; + } + } else if (dlExitTextRegExp.test(name)) { + var identifier = name.replace(dlExitTextRegExp,''); + if ((isRadioSet('deeplink_exit_'+identifier,'yes')) || + (isRadioSet('deeplink_exit_'+identifier,'url'))) { + var posstext = document.parmform.elements[i].value; + posstext = posstext.replace(/^\s+|\s+$/g,''); + var origlength = posstext.length; + posstext = posstext.replace(/[:;'",]/g,''); + var newlength = posstext.length; + if (newlength > 0) { + var change = origlength - newlength; + if (change) { + alert(change+' disallowed character(s) removed from Exit Button text'); + } + if (posstext !== 'Exit Tool') { + posstext = ':'+posstext; + document.parmform.elements['set_'+identifier].value += posstext; + } + } else { + document.parmform.elements['set_'+identifier].value = ''; + if (newlength < origlength) { + alert("An exit link type of 'In use' was selected but the button text value was blank, after removing disallowed characters.\nDisallowed characters are ,\":;'"); + } else { + alert("An exit link type of 'In use' was selected but the button text value was blank.\nPlease enter the text to use."); + } + return false; + } + } } } } @@ -1129,6 +1183,8 @@ END } sub done_proctor_js { + my $defaultdone = &mt('Done'); + &js_escape(\$defaultdone); return <<"END"; function toggleSecret(form,radio,key) { var radios = form[radio+key]; @@ -1145,6 +1201,15 @@ function toggleSecret(form,radio,key) { document.getElementById('done_'+key+'_proctorkey').value=''; } } + if (document.getElementById('done_'+key+'_buttontext')) { + if (radios[i].value == '') { + document.getElementById('done_'+key+'_buttontext').value = ''; + } else { + if (document.getElementById('done_'+key+'_buttontext').value == '') { + document.getElementById('done_'+key+'_buttontext').value = '$defaultdone'; + } + } + } } } } @@ -1207,6 +1272,24 @@ function toggleDeepLink(form,item,key) { keybox.type = 'hidden'; } } + } else if (item == 'exit') { + if (document.getElementById('deeplinkdiv_'+item+'_'+key)) { + if (radios[i].value == 'no') { + document.getElementById('deeplinkdiv_'+item+'_'+key).style.display = 'none'; + if (document.getElementById('deeplink_exittext_'+key)) { + if (document.getElementById('deeplink_exittext_'+key).value != '') { + document.getElementById('deeplink_exittext_'+key).value = ''; + } + } + } else { + document.getElementById('deeplinkdiv_'+item+'_'+key).style.display = 'inline-block'; + if (document.getElementById('deeplink_exittext_'+key)) { + if (document.getElementById('deeplink_exittext_'+key).value == '') { + document.getElementById('deeplink_exittext_'+key).value = 'Exit Tool'; + } + } + } + } } } } @@ -1325,7 +1408,7 @@ sub print_row { $extra = 'ltid_'.$domltistr; } } - my %courselti = &Apache::lonnet::get_course_lti($cnum,$cdom); + my %courselti = &Apache::lonnet::get_course_lti($cnum,$cdom,'provider'); if (keys(%courselti)) { foreach my $item (sort { $a <=> $b } keys(%courselti)) { if (($item =~ /^\d+$/) && (ref($courselti{$item}) eq 'HASH')) { @@ -1557,23 +1640,27 @@ sub extractResourceInformation { my $srcf=$resource->src(); $srcf=~/\.(\w+)$/; $$typep{$id}=$1; + my $toolsymb; + if ($srcf =~ /ext\.tool$/) { + $toolsymb = $resource->symb(); + } $$keyp{$id}=''; $$uris{$id}=$srcf; - foreach my $key (split(/\,/,&Apache::lonnet::metadata($srcf,'allpossiblekeys'))) { + foreach my $key (split(/\,/,&Apache::lonnet::metadata($srcf,'allpossiblekeys',$toolsymb))) { next if ($key!~/^parameter_/); # Hidden parameters - next if (&Apache::lonnet::metadata($srcf,$key.'.hidden') eq 'parm'); + next if (&Apache::lonnet::metadata($srcf,$key.'.hidden',$toolsymb) eq 'parm'); # # allparms is a hash of parameter names # - my $name=&Apache::lonnet::metadata($srcf,$key.'.name'); + my $name=&Apache::lonnet::metadata($srcf,$key.'.name',$toolsymb); if (!exists($$allparms{$name}) || $$allparms{$name} =~ m/^\s*$/ ) { my ($display,$parmdis); $display = &standard_parameter_names($name); if ($display eq '') { - $display= &Apache::lonnet::metadata($srcf,$key.'.display'); + $display= &Apache::lonnet::metadata($srcf,$key.'.display',$toolsymb); $parmdis = $display; $parmdis =~ s/\s*\[Part.*$//g; } else { @@ -1582,14 +1669,14 @@ sub extractResourceInformation { $$allparms{$name}=$parmdis; if (ref($defkeytype)) { $$defkeytype{$name}= - &Apache::lonnet::metadata($srcf,$key.'.type'); + &Apache::lonnet::metadata($srcf,$key.'.type',$toolsymb); } } # # allparts is a hash of all parts # - my $part= &Apache::lonnet::metadata($srcf,$key.'.part'); + my $part= &Apache::lonnet::metadata($srcf,$key.'.part',$toolsymb); $$allparts{$part} = &mt('Part: [_1]',$part); # # Remember all keys going with this resource @@ -1793,6 +1880,7 @@ sub lookUpTableParameter { 'lenient' => 'grading', 'retrypartial' => 'tries', 'discussvote' => 'misc', + 'texdisplay' => 'misc', 'examcode' => 'high_level_randomization', ); } @@ -2110,7 +2198,7 @@ sub displaymenu { } sub mapmenu { - my ($r,$allmaps,$pschp,$maptitles,$symbp)=@_; + my ($r,$allmaps,$pschp,$maptitles,$symbp,$parmlev)=@_; my %allmaps_inverted = reverse %$allmaps; my $navmap = Apache::lonnavmaps::navmap->new(); my $tree=[]; @@ -2158,7 +2246,11 @@ sub mapmenu { } } # Show it ... - $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Enclosing Map or Folder'),'','',' id="mapmenu"')); + my $rowattr = ' id="mapmenu"'; + if ($parmlev eq 'general') { + $rowattr .= ' style="display:none"'; + } + $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Enclosing Map or Folder'),'','',$rowattr)); if ((ref($tree) eq 'ARRAY') && (ref($treeinfo) eq 'HASH')) { my $icon = ''; my $whitespace = @@ -2799,7 +2891,7 @@ sub assessparms { 'date_interval','int','float','string','string_lenient', 'string_examcode','string_deeplink','string_discussvote', 'string_useslots','string_problemstatus','string_ip', - 'string_questiontype') { + 'string_questiontype','string_tex') { $r->print(''). '" name="recent_'.$item.'" />'); @@ -2807,13 +2899,20 @@ sub assessparms { # ----- Start Parameter Selection - # Hide parm selection? + # Hide parm selection and possibly table? + my ($tablejs,$tabledivsty); + if (((($env{'form.uname'} ne '') || ($env{'form.id'} ne '')) && ($uname eq '')) && + ($env{'form.dis'}) && ($pssymb eq '')) { + $tablejs = 'document.getElementById('."'parmtable'".').style.display = "";'; + $tabledivsty = ' style="display:none"'; + } $r->print(< // @@ -2839,7 +2938,7 @@ ENDPARMSELSCRIPT $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel')); &levelmenu($r,\%alllevs,$parmlev); $r->print(&Apache::lonhtmlcommon::row_closure()); - &mapmenu($r,\%allmaps,$pschp,\%maptitles, \%symbp); + &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp,$parmlev); $r->print(&Apache::lonhtmlcommon::row_closure()); $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View'))); &partmenu($r,\%allparts,\@psprt); @@ -2925,6 +3024,7 @@ ENDPARMSELSCRIPT if ($parm_permission->{'edit'}) { undef($readonly); } + $r->print('
'); if ($parmlev eq 'full') { # @@ -3044,20 +3144,24 @@ ENDTABLEHEADFOUR my %type= (); my %default=(); my $uri=&Apache::lonnet::declutter($uris{$rid}); + my $toolsymb; + if ($uri =~ /ext\.tool$/) { + $toolsymb = $symbp{$rid}; + } my $filter=$env{'form.filter'}; foreach (&keysplit($keyp{$rid})) { my $tempkeyp = $_; if (grep $_ eq $tempkeyp, @catmarker) { - my $parmname=&Apache::lonnet::metadata($uri,$_.'.name'); + my $parmname=&Apache::lonnet::metadata($uri,$_.'.name',$toolsymb); # We may only want certain parameters listed if ($filter) { unless ($filter=~/\Q$parmname\E/) { next; } } $name{$_}=$parmname; - $part{$_}=&Apache::lonnet::metadata($uri,$_.'.part'); + $part{$_}=&Apache::lonnet::metadata($uri,$_.'.part',$toolsymb); - my $parmdis=&Apache::lonnet::metadata($uri,$_.'.display'); + my $parmdis=&Apache::lonnet::metadata($uri,$_.'.display',$toolsymb); if ($allparms{$name{$_}} ne '') { my $identifier; if ($parmdis =~ /(\s*\[Part.*)$/) { @@ -3069,9 +3173,9 @@ ENDTABLEHEADFOUR } unless ($display{$_}) { $display{$_}=''; } $display{$_}.=' ('.$name{$_}.')'; - $default{$_}=&Apache::lonnet::metadata($uri,$_); - $type{$_}=&Apache::lonnet::metadata($uri,$_.'.type'); - $thistitle=&Apache::lonnet::metadata($uri,$_.'.title'); + $default{$_}=&Apache::lonnet::metadata($uri,$_,$toolsymb); + $type{$_}=&Apache::lonnet::metadata($uri,$_.'.type',$toolsymb); + $thistitle=&Apache::lonnet::metadata($uri,$_.'.title',$toolsymb); } } my $totalparms=scalar keys %name; @@ -3134,7 +3238,7 @@ ENDTABLEHEADFOUR #-------------------------------------------- for each map, gather information my $mapid; - foreach $mapid (sort {$maplist{$a} cmp $maplist{$b}} keys %maplist) { + foreach $mapid (sort { $a <=> $b } keys(%maplist)) { my $maptitle = $maplist{$mapid}; #----------------------- loop through ids and get all parameter types for map @@ -3156,6 +3260,10 @@ ENDTABLEHEADFOUR if ($map eq $mapid) { my $uri=&Apache::lonnet::declutter($uris{$rid}); + my $toolsymb; + if ($uri =~ /ext\.tool$/) { + $toolsymb = $symbp{$rid}; + } # $r->print("Keys: $keyp{$rid}
\n"); #-------------------------------------------------------------------- @@ -3172,8 +3280,8 @@ ENDTABLEHEADFOUR if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) { $part{$tempkeyp}="0"; - $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name'); - my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display'); + $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb); + my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb); if ($allparms{$name{$tempkeyp}} ne '') { my $identifier; if ($parmdis =~ /(\s*\[Part.*)$/) { @@ -3186,8 +3294,8 @@ ENDTABLEHEADFOUR unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; } $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')'; $display{$tempkeyp} =~ s/_\w+_/_0_/; - $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp); - $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type'); + $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb); + $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb); } } # end loop through keys } @@ -3261,6 +3369,10 @@ ENDTABLEHEADFOUR my $rid = $_; my $uri=&Apache::lonnet::declutter($uris{$rid}); + my $toolsymb; + if ($uri =~ /ext\.tool$/) { + $toolsymb = $symbp{$rid}; + } #-------------------------------------------------------------------- # @catmarker contains list of all possible parameters including part #s @@ -3275,8 +3387,8 @@ ENDTABLEHEADFOUR $tempkeyp =~ s/_\w+_/_0_/; if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) { $part{$tempkeyp}="0"; - $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name'); - my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display'); + $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb); + my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb); if ($allparms{$name{$tempkeyp}} ne '') { my $identifier; if ($parmdis =~ /(\s*\[Part.*)$/) { @@ -3289,8 +3401,8 @@ ENDTABLEHEADFOUR unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; } $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')'; $display{$tempkeyp} =~ s/_\w+_/_0_/; - $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp); - $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type'); + $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb); + $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb); } } # end loop through keys } # end loop through ids @@ -3333,6 +3445,7 @@ ENDMAPONE .'' ); } # end of $parmlev eq general + $r->print('
'); } $r->print(''); $r->print(&Apache::loncommon::end_page()); @@ -3460,6 +3573,8 @@ sub storedata { if ($thiskey =~ /\.retrypartial$/) { $name = 'retrypartial'; } + } elsif ($typeof eq 'string_tex') { + $name = 'texdisplay'; } } elsif ($cmd eq 'datepointer') { $data=&Apache::lonhtmlcommon::get_date_from_form($env{$key}); @@ -3591,7 +3706,7 @@ sub parse_listdata_key { } sub listdata { - my ($r,$resourcedata,$listdata,$sortorder,$caller,$classlist,$readonly)=@_; + my ($r,$resourcedata,$listdata,$sortorder,$caller,$classlist,$readonly,$parmlev)=@_; # Start list output my $oldsection=''; @@ -3703,6 +3818,7 @@ sub listdata { $realm=''.&mt('Folder/Map').': '.&Apache::lonnet::gettitle($1).'
('.$1.')
'; } elsif ($middle) { my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle); + next if (($url =~ /\.(page|sequence)$/) && ($parmlev eq 'full') && ($caller eq 'newoverview')); $realm=''.&mt('Resource').': '.&Apache::lonnet::gettitle($middle).'
('.$url.' in '.$map.' id: '.$id.')
'; } if ($sortorder eq 'realmstudent') { @@ -3808,6 +3924,11 @@ sub date_interval_selector { $showval %= $factor; my %select = ((map {$_ => $_} (0..$max)), 'select_form_order' => [0..$max]); + if ($currval eq '') { + unshift(@{$select{'select_form_order'}},''); + $select{''} = ''; + $amount = ''; + } $result .= &Apache::loncommon::select_form($amount,$name.'_'.$thiskey, \%select,'',$readonly); $result .= ' '.&mt($name); @@ -3815,6 +3936,7 @@ sub date_interval_selector { if ($pname eq 'interval') { unless ($skipval{'done'}) { my $checkedon = ''; + my $checkedoff = ''; my $checkedproc = ''; my $currproctorkey = ''; my $currprocdisplay = 'hidden'; @@ -3822,22 +3944,22 @@ sub date_interval_selector { my $checkedoff = ' checked="checked"'; if ($currval =~ /^(?:\d+)_done$/) { $checkedon = ' checked="checked"'; - $checkedoff = ''; } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:$/) { $currdonetext = $1; $checkedon = ' checked="checked"'; - $checkedoff = ''; } elsif ($currval =~ /^(?:\d+)_done_proctor_(.+)$/) { $currproctorkey = $1; $checkedproc = ' checked="checked"'; - $checkedoff = ''; $currprocdisplay = 'text'; } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:_proctor_(.+)$/) { $currdonetext = $1; $currproctorkey = $2; $checkedproc = ' checked="checked"'; - $checkedoff = ''; $currprocdisplay = 'text'; + } elsif ($currval ne '') { + $checkedoff = ' checked="checked"'; + } else { + $currdonetext = ''; } my $onclick = ' onclick="toggleSecret(this.form,'."'done_','$thiskey'".');"'; my $disabled; @@ -3854,7 +3976,8 @@ sub date_interval_selector { '&').'"'.$disabled.' />
'. ''.&mt('Button text').': '. - '&').'"'.$disabled.' />'; + '&').'"'.$disabled.' />'; } } unless ($readonly) { @@ -3867,15 +3990,36 @@ sub date_interval_selector { sub get_date_interval_from_form { my ($key) = @_; my $seconds = 0; + my $numnotnull = 0; foreach my $which (['days', 86400], ['hours', 3600], ['minutes', 60], ['seconds', 1]) { my ($name, $factor) = @{ $which }; if (defined($env{'form.'.$name.'_'.$key})) { - $seconds += $env{'form.'.$name.'_'.$key} * $factor; + unless ($env{'form.'.$name.'_'.$key} eq '') { + $numnotnull ++; + $seconds += $env{'form.'.$name.'_'.$key} * $factor; + } + } } + if (($key =~ /\.interval$/) && + (($env{'form.done_'.$key} eq '_done') || ($env{'form.done_'.$key} eq '_done_proctor'))) { + if ($env{'form.done_'.$key.'_buttontext'}) { + $env{'form.done_'.$key.'_buttontext'} =~ s/\://g; + $seconds .= '_done:'.$env{'form.done_'.$key.'_buttontext'}.':'; + if ($env{'form.done_'.$key} eq '_done_proctor') { + $seconds .= '_proctor'; + } + } else { + $seconds .= $env{'form.done_'.$key}; + } + if (($env{'form.done_'.$key} eq '_done_proctor') && + ($env{'form.done_'.$key.'_proctorkey'})) { + $seconds .= '_'.$env{'form.done_'.$key.'_proctorkey'}; + } } + return if (!$numnotnull); return $seconds; } @@ -3951,9 +4095,13 @@ sub string_ip_selector { sub string_deeplink_selector { my ($thiskey, $showval, $readonly) = @_; - my (@components,%values,@current,%titles,%options,%optiontext,%defaults, - %selectnull,%domlti,%crslti,@possmenus); - @components = ('state','others','listing','scope','protect','menus'); + my (@tables,%values,@current,%titles,%options,%optiontext,%defaults, + %selectnull,%domlti,%crslti,@possmenus,%components); + @tables = ('upper','lower'); + %components = ( + upper => ['state','others','listing','scope'], + lower => ['protect','menus','target','exit'], + ); %titles = &Apache::lonlocal::texthash ( state => 'Access status', others => 'Hide other resources', @@ -3961,6 +4109,8 @@ sub string_deeplink_selector { scope => 'Access scope for link', protect => 'Link protection', menus => 'Menu Items Displayed', + target => 'Embedded?', + exit => 'Exit Tool Button?', ); %options = ( state => ['only','off','both'], @@ -3969,6 +4119,8 @@ sub string_deeplink_selector { scope => ['res','map','rec'], protect => ['none','key','ltid','ltic'], menus => ['std','colls'], + target => ['_self','_top'], + exit => ['no','yes','url'], ); %optiontext = &Apache::lonlocal::texthash ( only => 'deep only', @@ -3990,6 +4142,11 @@ sub string_deeplink_selector { ltid => 'LTI access (domain)' , std => 'Standard (all menus)', colls => 'Numbered collection', + _self => 'Embedded', + _top => 'Not embedded', + no => 'Not in use', + yes => 'In use, no URL redirect', + url => 'In use, redirect to URL', ); %selectnull = &Apache::lonlocal::texthash ( ltic => 'Select Launcher', @@ -4005,6 +4162,8 @@ sub string_deeplink_selector { ($values{'scope'}) = ($current[3] =~ /^(res|map|rec)$/); ($values{'protect'}) = ($current[4] =~ /^(key:[a-zA-Z\d_.!\@#\$%^&*()+=-]+|ltic:\d+|ltid:\d+)$/); ($values{'menus'}) = ($current[5] =~ /^(\d+)$/); + ($values{'target'}) = ($current[6] =~ /^(_self|_top)$/); + ($values{'exit'}) = ($current[7] =~ /^((?:(?:yes|url)(?:|\:[^:;"',]+))|no)$/); } else { $defaults{'state'} = 'off', $defaults{'others'} = 'unhide', @@ -4012,6 +4171,8 @@ sub string_deeplink_selector { $defaults{'scope'} = 'res'; $defaults{'protect'} = 'none'; $defaults{'menus'} = '0'; + $defaults{'target'} = '_top'; + $defaults{'exit'} = 'yes'; } my $disabled; if ($readonly) { @@ -4019,7 +4180,8 @@ sub string_deeplink_selector { } my %courselti = &Apache::lonnet::get_course_lti($env{'course.'.$env{'request.course.id'}.'.num'}, - $env{'course.'.$env{'request.course.id'}.'.domain'}); + $env{'course.'.$env{'request.course.id'}.'.domain'}, + 'provider'); foreach my $item (keys(%courselti)) { if (ref($courselti{$item}) eq 'HASH') { $crslti{$item} = $courselti{$item}{'name'}; @@ -4042,119 +4204,144 @@ sub string_deeplink_selector { } } - my $output = ''; - foreach my $item (@components) { - $output .= ''; - } - $output .= ''; - foreach my $item (@components) { - $output .= ''; } - $output .= '
'.$titles{$item}.'
'; - if (($item eq 'protect') || ($item eq 'menus')) { - my $selected = $values{$item}; - foreach my $option (@{$options{$item}}) { - if ($item eq 'protect') { - if ($option eq 'ltid') { - next unless (keys(%domlti)); - } elsif ($option eq 'ltic') { - next unless (keys(%crslti)); - } - } elsif (($item eq 'menus') && ($option eq 'colls')) { - next unless (@possmenus); - } - my $checked; - if ($item eq 'menus') { - if (($selected =~ /^\d+$/) && (@possmenus) && - (grep(/^\Q$selected\E$/,@possmenus))) { - if ($option eq 'colls') { + my $output = ''; + foreach my $table ('upper','lower') { + next unless (ref($components{$table}) eq 'ARRAY'); + $output .= ''; + foreach my $item (@{$components{$table}}) { + $output .= ''; + } + $output .= ''; + foreach my $item (@{$components{$table}}) { + $output .= ''; + } + $output .= '
'.$titles{$item}.'
'; + if (($item eq 'protect') || ($item eq 'menus') || ($item eq 'exit')) { + my $selected = $values{$item}; + foreach my $option (@{$options{$item}}) { + if ($item eq 'protect') { + if ($option eq 'ltid') { + next unless (keys(%domlti)); + } elsif ($option eq 'ltic') { + next unless (keys(%crslti)); + } + } elsif (($item eq 'menus') && ($option eq 'colls')) { + next unless (@possmenus); + } + my $checked; + if ($item eq 'menus') { + if (($selected =~ /^\d+$/) && (@possmenus) && + (grep(/^\Q$selected\E$/,@possmenus))) { + if ($option eq 'colls') { + $checked = ' checked="checked"'; + } + } elsif (($option eq 'std') && ($selected == 0) && ($selected ne '')) { $checked = ' checked="checked"'; } - } elsif (($option eq 'std') && ($selected == 0) && ($selected ne '')) { + } elsif ($selected =~ /^\Q$option\E/) { $checked = ' checked="checked"'; } - } elsif ($selected =~ /^\Q$option\E/) { - $checked = ' checked="checked"'; - } - my $onclick; - unless ($readonly) { - my $esc_key = &js_escape($thiskey); - $onclick = ' onclick="toggleDeepLink(this.form,'."'$item','$esc_key'".');"'; - } - $output .= ''; - if (($item eq 'protect') && ($option eq 'key')) { - my $visibility="hidden"; - my $currkey; - if ($checked) { - $visibility = "text"; - $currkey = (split(/\:/,$values{$item}))[1]; - } - $output .= ' '. - ''; - } elsif (($option eq 'ltic') || ($option eq 'ltid') || ($option eq 'colls')) { - my $display="none"; - my ($current,$blankcheck,@possibles); - if ($checked) { - $display = 'inline-block'; - if (($option eq 'ltic') || ($option eq 'ltid')) { - $current = (split(/\:/,$selected))[1]; - } else { - $current = $selected; + my $onclick; + unless ($readonly) { + my $esc_key = &js_escape($thiskey); + $onclick = ' onclick="toggleDeepLink(this.form,'."'$item','$esc_key'".');"'; + } + $output .= ''; + if (($item eq 'protect') && ($option eq 'key')) { + my $visibility="hidden"; + my $currkey; + if ($checked) { + $visibility = "text"; + $currkey = (split(/\:/,$values{$item}))[1]; } - } else { - $blankcheck = ' selected="selected"'; - } - if ($option eq 'ltid') { - @possibles = keys(%domlti); - } elsif ($option eq 'ltic') { - @possibles = keys(%crslti); - } else { - @possibles = @possmenus; - } - $output .= '
 '; + } elsif (($option eq 'ltic') || ($option eq 'ltid') || ($option eq 'colls')) { + my $display="none"; + my ($current,$blankcheck,@possibles); + if ($checked) { + $display = 'inline-block'; + if (($option eq 'ltic') || ($option eq 'ltid')) { + $current = (split(/\:/,$selected))[1]; + } else { + $current = $selected; + } + } else { + $blankcheck = ' selected="selected"'; } - my $shown = $poss; if ($option eq 'ltid') { - $shown = $domlti{$poss}; + @possibles = keys(%domlti); } elsif ($option eq 'ltic') { - $shown = $crslti{$poss}; + @possibles = keys(%crslti); + } else { + @possibles = @possmenus; } - $output .= ''; + $output .= '
 
'; } - $output .= '
'; + $output .= '
'; } - $output .= '
'; - } - } else { - my $selected = $values{$item}; - my $defsel; - if ($selected eq '') { - $defsel = ' selected="selected"'; - } - $output .= ''; } - $output .= '>'.$optiontext{$option}.''; - } - $output .= ''; + } else { + my $selected = $values{$item}; + my $defsel; + if ($selected eq '') { + $defsel = ' selected="selected"'; + } + $output .= ''; + } + $output .= '
'."\n"; + if ($table eq 'upper') { + $output .= '
'; } - $output .= '
'."\n"; return $output; } @@ -4191,7 +4378,10 @@ my %strings = => [['_allowfrom_','Hostname(s), or IP(s) from which access is allowed'], ['_denyfrom_','Hostname(s) or IP(s) from which access is disallowed']], 'string_deeplink' - => [['on','Set choices for link protection, resource listing, access scope, and shown menu items']], + => [['on','Set choices for link protection, resource listing, access scope, shown menu items, embedding, and exit link']], + 'string_tex' + => [['tth', 'tth (TeX to HTML)'], + ['mathjax', 'MathJax']], ); my %stringmatches = ( @@ -4199,7 +4389,7 @@ my %stringmatches = ( => [['_allowfrom_','[^\!]+'], ['_denyfrom_','\!']], 'string_deeplink' - => [['on','^(only|off|both)\,(hide|unhide)\,(full|absent|grades|details|datestatus)\,(res|map|rec)\,(none|key\:\w+|ltic\:\d+|ltid\:\d+)\,(\d+|)$']], + => [['on','^(only|off|both)\,(hide|unhide)\,(full|absent|grades|details|datestatus)\,(res|map|rec)\,(none|key\:\w+|ltic\:\d+|ltid\:\d+)\,(\d+|)\,_(self|top),(yes|url|no)(|:[^:;\'",]+)$']], ); my %stringtypes = ( @@ -4210,6 +4400,7 @@ my %stringtypes = ( examcode => 'string_examcode', acc => 'string_ip', deeplink => 'string_deeplink', + texdisplay => 'string_tex', ); sub standard_string_options { @@ -4440,6 +4631,8 @@ sub newoverview { '. &Apache::lonhtmlcommon::resize_scrollbox_js('params')."\n". &showhide_js()."\n". + &validateparms_js()."\n". + &ipacc_boxes_js()."\n". &done_proctor_js()."\n". &deeplink_js()."\n". '// ]]> @@ -4450,7 +4643,7 @@ sub newoverview { my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview'); $r->print($start_page.$breadcrumbs); $r->print(< +
ENDOVER my @ids=(); my %typep=(); @@ -4516,10 +4709,8 @@ ENDOVER $r->print('
'); $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel')); &levelmenu($r,\%alllevs,$parmlev); - if ($parmlev ne 'general') { - $r->print(&Apache::lonhtmlcommon::row_closure()); - &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp); - } + $r->print(&Apache::lonhtmlcommon::row_closure()); + &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp,$parmlev); $r->print(&Apache::lonhtmlcommon::row_closure(1)); $r->print(&Apache::lonhtmlcommon::end_pick_box()); $r->print('
'); @@ -4582,7 +4773,7 @@ ENDOVER # List data - &listdata($r,$resourcedata,$listdata,$sortorder,'newoverview',undef,$readonly); + &listdata($r,$resourcedata,$listdata,$sortorder,'newoverview',undef,$readonly,$parmlev); } $r->print(&tableend()); unless ($readonly) { @@ -4635,6 +4826,8 @@ sub overview { my $js = ''."\n"; @@ -4647,7 +4840,7 @@ sub overview { my $start_page=&Apache::loncommon::start_page('Modify Parameters',$js); my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview'); $r->print($start_page.$breadcrumbs); - $r->print(''); + $r->print(''); # Store modified unless ($readonly) { @@ -5754,7 +5947,11 @@ sub parm_change_log { $parmitem = &mt($parmitem); $output .= &mt('Type: [_1]',$parmitem); } else { - my ($level,@all)=&parmval_by_symb($what,$middle,&Apache::lonnet::metadata($middle,$what), + my $toolsymb; + if ($middle =~ /ext\.tool$/) { + $toolsymb = $middle; + } + my ($level,@all)=&parmval_by_symb($what,$middle,&Apache::lonnet::metadata($middle,$what,$toolsymb), $uname,$udom,$issection,$issection,$courseopt); my $showvalue = $value; if ($istype{$parmname} eq '') {